xref: /freebsd/contrib/llvm-project/clang/lib/Support/RISCVVIntrinsicUtils.cpp (revision 9c77fb6aaa366cbabc80ee1b834bcfe4df135491)
1 //===- RISCVVIntrinsicUtils.cpp - RISC-V Vector Intrinsic Utils -*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "clang/Support/RISCVVIntrinsicUtils.h"
10 #include "llvm/ADT/ArrayRef.h"
11 #include "llvm/ADT/StringExtras.h"
12 #include "llvm/ADT/Twine.h"
13 #include "llvm/Support/ErrorHandling.h"
14 #include "llvm/Support/raw_ostream.h"
15 #include <optional>
16 
17 using namespace llvm;
18 
19 namespace clang {
20 namespace RISCV {
21 
22 const PrototypeDescriptor PrototypeDescriptor::Mask = PrototypeDescriptor(
23     BaseTypeModifier::Vector, VectorTypeModifier::MaskVector);
24 const PrototypeDescriptor PrototypeDescriptor::VL =
25     PrototypeDescriptor(BaseTypeModifier::SizeT);
26 const PrototypeDescriptor PrototypeDescriptor::Vector =
27     PrototypeDescriptor(BaseTypeModifier::Vector);
28 
29 //===----------------------------------------------------------------------===//
30 // Type implementation
31 //===----------------------------------------------------------------------===//
32 
33 LMULType::LMULType(int NewLog2LMUL) {
34   // Check Log2LMUL is -3, -2, -1, 0, 1, 2, 3
35   assert(NewLog2LMUL <= 3 && NewLog2LMUL >= -3 && "Bad LMUL number!");
36   Log2LMUL = NewLog2LMUL;
37 }
38 
39 std::string LMULType::str() const {
40   if (Log2LMUL < 0)
41     return "mf" + utostr(1ULL << (-Log2LMUL));
42   return "m" + utostr(1ULL << Log2LMUL);
43 }
44 
45 VScaleVal LMULType::getScale(unsigned ElementBitwidth) const {
46   int Log2ScaleResult = 0;
47   switch (ElementBitwidth) {
48   default:
49     break;
50   case 8:
51     Log2ScaleResult = Log2LMUL + 3;
52     break;
53   case 16:
54     Log2ScaleResult = Log2LMUL + 2;
55     break;
56   case 32:
57     Log2ScaleResult = Log2LMUL + 1;
58     break;
59   case 64:
60     Log2ScaleResult = Log2LMUL;
61     break;
62   }
63   // Illegal vscale result would be less than 1
64   if (Log2ScaleResult < 0)
65     return std::nullopt;
66   return 1 << Log2ScaleResult;
67 }
68 
69 void LMULType::MulLog2LMUL(int log2LMUL) { Log2LMUL += log2LMUL; }
70 
71 RVVType::RVVType(BasicType BT, int Log2LMUL,
72                  const PrototypeDescriptor &prototype)
73     : BT(BT), LMUL(LMULType(Log2LMUL)) {
74   applyBasicType();
75   applyModifier(prototype);
76   Valid = verifyType();
77   if (Valid) {
78     initBuiltinStr();
79     initTypeStr();
80     if (isVector()) {
81       initClangBuiltinStr();
82     }
83   }
84 }
85 
86 // clang-format off
87 // boolean type are encoded the ratio of n (SEW/LMUL)
88 // SEW/LMUL | 1         | 2         | 4         | 8        | 16        | 32        | 64
89 // c type   | vbool64_t | vbool32_t | vbool16_t | vbool8_t | vbool4_t  | vbool2_t  | vbool1_t
90 // IR type  | nxv1i1    | nxv2i1    | nxv4i1    | nxv8i1   | nxv16i1   | nxv32i1   | nxv64i1
91 
92 // type\lmul | 1/8    | 1/4      | 1/2     | 1       | 2        | 4        | 8
93 // --------  |------  | -------- | ------- | ------- | -------- | -------- | --------
94 // i64       | N/A    | N/A      | N/A     | nxv1i64 | nxv2i64  | nxv4i64  | nxv8i64
95 // i32       | N/A    | N/A      | nxv1i32 | nxv2i32 | nxv4i32  | nxv8i32  | nxv16i32
96 // i16       | N/A    | nxv1i16  | nxv2i16 | nxv4i16 | nxv8i16  | nxv16i16 | nxv32i16
97 // i8        | nxv1i8 | nxv2i8   | nxv4i8  | nxv8i8  | nxv16i8  | nxv32i8  | nxv64i8
98 // double    | N/A    | N/A      | N/A     | nxv1f64 | nxv2f64  | nxv4f64  | nxv8f64
99 // float     | N/A    | N/A      | nxv1f32 | nxv2f32 | nxv4f32  | nxv8f32  | nxv16f32
100 // half      | N/A    | nxv1f16  | nxv2f16 | nxv4f16 | nxv8f16  | nxv16f16 | nxv32f16
101 // bfloat16  | N/A    | nxv1bf16 | nxv2bf16| nxv4bf16| nxv8bf16 | nxv16bf16| nxv32bf16
102 // clang-format on
103 
104 bool RVVType::verifyType() const {
105   if (ScalarType == Invalid)
106     return false;
107   if (isScalar())
108     return true;
109   if (!Scale)
110     return false;
111   if (isFloat() && ElementBitwidth == 8)
112     return false;
113   if (isBFloat() && ElementBitwidth != 16)
114     return false;
115   if (IsTuple && (NF == 1 || NF > 8))
116     return false;
117   if (IsTuple && (1 << std::max(0, LMUL.Log2LMUL)) * NF > 8)
118     return false;
119   unsigned V = *Scale;
120   switch (ElementBitwidth) {
121   case 1:
122   case 8:
123     // Check Scale is 1,2,4,8,16,32,64
124     return (V <= 64 && isPowerOf2_32(V));
125   case 16:
126     // Check Scale is 1,2,4,8,16,32
127     return (V <= 32 && isPowerOf2_32(V));
128   case 32:
129     // Check Scale is 1,2,4,8,16
130     return (V <= 16 && isPowerOf2_32(V));
131   case 64:
132     // Check Scale is 1,2,4,8
133     return (V <= 8 && isPowerOf2_32(V));
134   }
135   return false;
136 }
137 
138 void RVVType::initBuiltinStr() {
139   assert(isValid() && "RVVType is invalid");
140   switch (ScalarType) {
141   case ScalarTypeKind::Void:
142     BuiltinStr = "v";
143     return;
144   case ScalarTypeKind::Size_t:
145     BuiltinStr = "z";
146     if (IsImmediate)
147       BuiltinStr = "I" + BuiltinStr;
148     if (IsPointer)
149       BuiltinStr += "*";
150     return;
151   case ScalarTypeKind::Ptrdiff_t:
152     BuiltinStr = "Y";
153     return;
154   case ScalarTypeKind::UnsignedLong:
155     BuiltinStr = "ULi";
156     return;
157   case ScalarTypeKind::SignedLong:
158     BuiltinStr = "Li";
159     return;
160   case ScalarTypeKind::Boolean:
161     assert(ElementBitwidth == 1);
162     BuiltinStr += "b";
163     break;
164   case ScalarTypeKind::SignedInteger:
165   case ScalarTypeKind::UnsignedInteger:
166     switch (ElementBitwidth) {
167     case 8:
168       BuiltinStr += "c";
169       break;
170     case 16:
171       BuiltinStr += "s";
172       break;
173     case 32:
174       BuiltinStr += "i";
175       break;
176     case 64:
177       BuiltinStr += "Wi";
178       break;
179     default:
180       llvm_unreachable("Unhandled ElementBitwidth!");
181     }
182     if (isSignedInteger())
183       BuiltinStr = "S" + BuiltinStr;
184     else
185       BuiltinStr = "U" + BuiltinStr;
186     break;
187   case ScalarTypeKind::Float:
188     switch (ElementBitwidth) {
189     case 16:
190       BuiltinStr += "x";
191       break;
192     case 32:
193       BuiltinStr += "f";
194       break;
195     case 64:
196       BuiltinStr += "d";
197       break;
198     default:
199       llvm_unreachable("Unhandled ElementBitwidth!");
200     }
201     break;
202   case ScalarTypeKind::BFloat:
203     BuiltinStr += "y";
204     break;
205   default:
206     llvm_unreachable("ScalarType is invalid!");
207   }
208   if (IsImmediate)
209     BuiltinStr = "I" + BuiltinStr;
210   if (isScalar()) {
211     if (IsConstant)
212       BuiltinStr += "C";
213     if (IsPointer)
214       BuiltinStr += "*";
215     return;
216   }
217   BuiltinStr = "q" + utostr(*Scale) + BuiltinStr;
218   // Pointer to vector types. Defined for segment load intrinsics.
219   // segment load intrinsics have pointer type arguments to store the loaded
220   // vector values.
221   if (IsPointer)
222     BuiltinStr += "*";
223 
224   if (IsTuple)
225     BuiltinStr = "T" + utostr(NF) + BuiltinStr;
226 }
227 
228 void RVVType::initClangBuiltinStr() {
229   assert(isValid() && "RVVType is invalid");
230   assert(isVector() && "Handle Vector type only");
231 
232   ClangBuiltinStr = "__rvv_";
233   switch (ScalarType) {
234   case ScalarTypeKind::Boolean:
235     ClangBuiltinStr += "bool" + utostr(64 / *Scale) + "_t";
236     return;
237   case ScalarTypeKind::Float:
238     ClangBuiltinStr += "float";
239     break;
240   case ScalarTypeKind::BFloat:
241     ClangBuiltinStr += "bfloat";
242     break;
243   case ScalarTypeKind::SignedInteger:
244     ClangBuiltinStr += "int";
245     break;
246   case ScalarTypeKind::UnsignedInteger:
247     ClangBuiltinStr += "uint";
248     break;
249   default:
250     llvm_unreachable("ScalarTypeKind is invalid");
251   }
252   ClangBuiltinStr += utostr(ElementBitwidth) + LMUL.str() +
253                      (IsTuple ? "x" + utostr(NF) : "") + "_t";
254 }
255 
256 void RVVType::initTypeStr() {
257   assert(isValid() && "RVVType is invalid");
258 
259   if (IsConstant)
260     Str += "const ";
261 
262   auto getTypeString = [&](StringRef TypeStr) {
263     if (isScalar())
264       return Twine(TypeStr + Twine(ElementBitwidth) + "_t").str();
265     return Twine("v" + TypeStr + Twine(ElementBitwidth) + LMUL.str() +
266                  (IsTuple ? "x" + utostr(NF) : "") + "_t")
267         .str();
268   };
269 
270   switch (ScalarType) {
271   case ScalarTypeKind::Void:
272     Str = "void";
273     return;
274   case ScalarTypeKind::Size_t:
275     Str = "size_t";
276     if (IsPointer)
277       Str += " *";
278     return;
279   case ScalarTypeKind::Ptrdiff_t:
280     Str = "ptrdiff_t";
281     return;
282   case ScalarTypeKind::UnsignedLong:
283     Str = "unsigned long";
284     return;
285   case ScalarTypeKind::SignedLong:
286     Str = "long";
287     return;
288   case ScalarTypeKind::Boolean:
289     if (isScalar())
290       Str += "bool";
291     else
292       // Vector bool is special case, the formulate is
293       // `vbool<N>_t = MVT::nxv<64/N>i1` ex. vbool16_t = MVT::4i1
294       Str += "vbool" + utostr(64 / *Scale) + "_t";
295     break;
296   case ScalarTypeKind::Float:
297     if (isScalar()) {
298       if (ElementBitwidth == 64)
299         Str += "double";
300       else if (ElementBitwidth == 32)
301         Str += "float";
302       else if (ElementBitwidth == 16)
303         Str += "_Float16";
304       else
305         llvm_unreachable("Unhandled floating type.");
306     } else
307       Str += getTypeString("float");
308     break;
309   case ScalarTypeKind::BFloat:
310     if (isScalar()) {
311       if (ElementBitwidth == 16)
312         Str += "__bf16";
313       else
314         llvm_unreachable("Unhandled floating type.");
315     } else
316       Str += getTypeString("bfloat");
317     break;
318   case ScalarTypeKind::SignedInteger:
319     Str += getTypeString("int");
320     break;
321   case ScalarTypeKind::UnsignedInteger:
322     Str += getTypeString("uint");
323     break;
324   default:
325     llvm_unreachable("ScalarType is invalid!");
326   }
327   if (IsPointer)
328     Str += " *";
329 }
330 
331 void RVVType::initShortStr() {
332   switch (ScalarType) {
333   case ScalarTypeKind::Boolean:
334     assert(isVector());
335     ShortStr = "b" + utostr(64 / *Scale);
336     return;
337   case ScalarTypeKind::Float:
338     ShortStr = "f" + utostr(ElementBitwidth);
339     break;
340   case ScalarTypeKind::BFloat:
341     ShortStr = "bf" + utostr(ElementBitwidth);
342     break;
343   case ScalarTypeKind::SignedInteger:
344     ShortStr = "i" + utostr(ElementBitwidth);
345     break;
346   case ScalarTypeKind::UnsignedInteger:
347     ShortStr = "u" + utostr(ElementBitwidth);
348     break;
349   default:
350     llvm_unreachable("Unhandled case!");
351   }
352   if (isVector())
353     ShortStr += LMUL.str();
354   if (isTuple())
355     ShortStr += "x" + utostr(NF);
356 }
357 
358 static VectorTypeModifier getTupleVTM(unsigned NF) {
359   assert(2 <= NF && NF <= 8 && "2 <= NF <= 8");
360   return static_cast<VectorTypeModifier>(
361       static_cast<uint8_t>(VectorTypeModifier::Tuple2) + (NF - 2));
362 }
363 
364 void RVVType::applyBasicType() {
365   switch (BT) {
366   case BasicType::Int8:
367     ElementBitwidth = 8;
368     ScalarType = ScalarTypeKind::SignedInteger;
369     break;
370   case BasicType::Int16:
371     ElementBitwidth = 16;
372     ScalarType = ScalarTypeKind::SignedInteger;
373     break;
374   case BasicType::Int32:
375     ElementBitwidth = 32;
376     ScalarType = ScalarTypeKind::SignedInteger;
377     break;
378   case BasicType::Int64:
379     ElementBitwidth = 64;
380     ScalarType = ScalarTypeKind::SignedInteger;
381     break;
382   case BasicType::Float16:
383     ElementBitwidth = 16;
384     ScalarType = ScalarTypeKind::Float;
385     break;
386   case BasicType::Float32:
387     ElementBitwidth = 32;
388     ScalarType = ScalarTypeKind::Float;
389     break;
390   case BasicType::Float64:
391     ElementBitwidth = 64;
392     ScalarType = ScalarTypeKind::Float;
393     break;
394   case BasicType::BFloat16:
395     ElementBitwidth = 16;
396     ScalarType = ScalarTypeKind::BFloat;
397     break;
398   default:
399     llvm_unreachable("Unhandled type code!");
400   }
401   assert(ElementBitwidth != 0 && "Bad element bitwidth!");
402 }
403 
404 std::optional<PrototypeDescriptor>
405 PrototypeDescriptor::parsePrototypeDescriptor(
406     llvm::StringRef PrototypeDescriptorStr) {
407   PrototypeDescriptor PD;
408   BaseTypeModifier PT = BaseTypeModifier::Invalid;
409   VectorTypeModifier VTM = VectorTypeModifier::NoModifier;
410 
411   if (PrototypeDescriptorStr.empty())
412     return PD;
413 
414   // Handle base type modifier
415   auto PType = PrototypeDescriptorStr.back();
416   switch (PType) {
417   case 'e':
418     PT = BaseTypeModifier::Scalar;
419     break;
420   case 'v':
421     PT = BaseTypeModifier::Vector;
422     break;
423   case 'w':
424     PT = BaseTypeModifier::Vector;
425     VTM = VectorTypeModifier::Widening2XVector;
426     break;
427   case 'q':
428     PT = BaseTypeModifier::Vector;
429     VTM = VectorTypeModifier::Widening4XVector;
430     break;
431   case 'o':
432     PT = BaseTypeModifier::Vector;
433     VTM = VectorTypeModifier::Widening8XVector;
434     break;
435   case 'm':
436     PT = BaseTypeModifier::Vector;
437     VTM = VectorTypeModifier::MaskVector;
438     break;
439   case '0':
440     PT = BaseTypeModifier::Void;
441     break;
442   case 'z':
443     PT = BaseTypeModifier::SizeT;
444     break;
445   case 't':
446     PT = BaseTypeModifier::Ptrdiff;
447     break;
448   case 'u':
449     PT = BaseTypeModifier::UnsignedLong;
450     break;
451   case 'l':
452     PT = BaseTypeModifier::SignedLong;
453     break;
454   case 'f':
455     PT = BaseTypeModifier::Float32;
456     break;
457   default:
458     llvm_unreachable("Illegal primitive type transformers!");
459   }
460   PD.PT = static_cast<uint8_t>(PT);
461   PrototypeDescriptorStr = PrototypeDescriptorStr.drop_back();
462 
463   // Compute the vector type transformers, it can only appear one time.
464   if (PrototypeDescriptorStr.starts_with("(")) {
465     assert(VTM == VectorTypeModifier::NoModifier &&
466            "VectorTypeModifier should only have one modifier");
467     size_t Idx = PrototypeDescriptorStr.find(')');
468     assert(Idx != StringRef::npos);
469     StringRef ComplexType = PrototypeDescriptorStr.slice(1, Idx);
470     PrototypeDescriptorStr = PrototypeDescriptorStr.drop_front(Idx + 1);
471     assert(!PrototypeDescriptorStr.contains('(') &&
472            "Only allow one vector type modifier");
473 
474     auto ComplexTT = ComplexType.split(":");
475     if (ComplexTT.first == "Log2EEW") {
476       uint32_t Log2EEW;
477       if (ComplexTT.second.getAsInteger(10, Log2EEW)) {
478         llvm_unreachable("Invalid Log2EEW value!");
479         return std::nullopt;
480       }
481       switch (Log2EEW) {
482       case 3:
483         VTM = VectorTypeModifier::Log2EEW3;
484         break;
485       case 4:
486         VTM = VectorTypeModifier::Log2EEW4;
487         break;
488       case 5:
489         VTM = VectorTypeModifier::Log2EEW5;
490         break;
491       case 6:
492         VTM = VectorTypeModifier::Log2EEW6;
493         break;
494       default:
495         llvm_unreachable("Invalid Log2EEW value, should be [3-6]");
496         return std::nullopt;
497       }
498     } else if (ComplexTT.first == "FixedSEW") {
499       uint32_t NewSEW;
500       if (ComplexTT.second.getAsInteger(10, NewSEW)) {
501         llvm_unreachable("Invalid FixedSEW value!");
502         return std::nullopt;
503       }
504       switch (NewSEW) {
505       case 8:
506         VTM = VectorTypeModifier::FixedSEW8;
507         break;
508       case 16:
509         VTM = VectorTypeModifier::FixedSEW16;
510         break;
511       case 32:
512         VTM = VectorTypeModifier::FixedSEW32;
513         break;
514       case 64:
515         VTM = VectorTypeModifier::FixedSEW64;
516         break;
517       default:
518         llvm_unreachable("Invalid FixedSEW value, should be 8, 16, 32 or 64");
519         return std::nullopt;
520       }
521     } else if (ComplexTT.first == "LFixedLog2LMUL") {
522       int32_t Log2LMUL;
523       if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
524         llvm_unreachable("Invalid LFixedLog2LMUL value!");
525         return std::nullopt;
526       }
527       switch (Log2LMUL) {
528       case -3:
529         VTM = VectorTypeModifier::LFixedLog2LMULN3;
530         break;
531       case -2:
532         VTM = VectorTypeModifier::LFixedLog2LMULN2;
533         break;
534       case -1:
535         VTM = VectorTypeModifier::LFixedLog2LMULN1;
536         break;
537       case 0:
538         VTM = VectorTypeModifier::LFixedLog2LMUL0;
539         break;
540       case 1:
541         VTM = VectorTypeModifier::LFixedLog2LMUL1;
542         break;
543       case 2:
544         VTM = VectorTypeModifier::LFixedLog2LMUL2;
545         break;
546       case 3:
547         VTM = VectorTypeModifier::LFixedLog2LMUL3;
548         break;
549       default:
550         llvm_unreachable("Invalid LFixedLog2LMUL value, should be [-3, 3]");
551         return std::nullopt;
552       }
553     } else if (ComplexTT.first == "SFixedLog2LMUL") {
554       int32_t Log2LMUL;
555       if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
556         llvm_unreachable("Invalid SFixedLog2LMUL value!");
557         return std::nullopt;
558       }
559       switch (Log2LMUL) {
560       case -3:
561         VTM = VectorTypeModifier::SFixedLog2LMULN3;
562         break;
563       case -2:
564         VTM = VectorTypeModifier::SFixedLog2LMULN2;
565         break;
566       case -1:
567         VTM = VectorTypeModifier::SFixedLog2LMULN1;
568         break;
569       case 0:
570         VTM = VectorTypeModifier::SFixedLog2LMUL0;
571         break;
572       case 1:
573         VTM = VectorTypeModifier::SFixedLog2LMUL1;
574         break;
575       case 2:
576         VTM = VectorTypeModifier::SFixedLog2LMUL2;
577         break;
578       case 3:
579         VTM = VectorTypeModifier::SFixedLog2LMUL3;
580         break;
581       default:
582         llvm_unreachable("Invalid LFixedLog2LMUL value, should be [-3, 3]");
583         return std::nullopt;
584       }
585 
586     } else if (ComplexTT.first == "SEFixedLog2LMUL") {
587       int32_t Log2LMUL;
588       if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
589         llvm_unreachable("Invalid SEFixedLog2LMUL value!");
590         return std::nullopt;
591       }
592       switch (Log2LMUL) {
593       case -3:
594         VTM = VectorTypeModifier::SEFixedLog2LMULN3;
595         break;
596       case -2:
597         VTM = VectorTypeModifier::SEFixedLog2LMULN2;
598         break;
599       case -1:
600         VTM = VectorTypeModifier::SEFixedLog2LMULN1;
601         break;
602       case 0:
603         VTM = VectorTypeModifier::SEFixedLog2LMUL0;
604         break;
605       case 1:
606         VTM = VectorTypeModifier::SEFixedLog2LMUL1;
607         break;
608       case 2:
609         VTM = VectorTypeModifier::SEFixedLog2LMUL2;
610         break;
611       case 3:
612         VTM = VectorTypeModifier::SEFixedLog2LMUL3;
613         break;
614       default:
615         llvm_unreachable("Invalid LFixedLog2LMUL value, should be [-3, 3]");
616         return std::nullopt;
617       }
618     } else if (ComplexTT.first == "Tuple") {
619       unsigned NF = 0;
620       if (ComplexTT.second.getAsInteger(10, NF)) {
621         llvm_unreachable("Invalid NF value!");
622         return std::nullopt;
623       }
624       VTM = getTupleVTM(NF);
625     } else {
626       llvm_unreachable("Illegal complex type transformers!");
627     }
628   }
629   PD.VTM = static_cast<uint8_t>(VTM);
630 
631   // Compute the remain type transformers
632   TypeModifier TM = TypeModifier::NoModifier;
633   for (char I : PrototypeDescriptorStr) {
634     switch (I) {
635     case 'P':
636       if ((TM & TypeModifier::Const) == TypeModifier::Const)
637         llvm_unreachable("'P' transformer cannot be used after 'C'");
638       if ((TM & TypeModifier::Pointer) == TypeModifier::Pointer)
639         llvm_unreachable("'P' transformer cannot be used twice");
640       TM |= TypeModifier::Pointer;
641       break;
642     case 'C':
643       TM |= TypeModifier::Const;
644       break;
645     case 'K':
646       TM |= TypeModifier::Immediate;
647       break;
648     case 'U':
649       TM |= TypeModifier::UnsignedInteger;
650       break;
651     case 'I':
652       TM |= TypeModifier::SignedInteger;
653       break;
654     case 'F':
655       TM |= TypeModifier::Float;
656       break;
657     case 'S':
658       TM |= TypeModifier::LMUL1;
659       break;
660     default:
661       llvm_unreachable("Illegal non-primitive type transformer!");
662     }
663   }
664   PD.TM = static_cast<uint8_t>(TM);
665 
666   return PD;
667 }
668 
669 void RVVType::applyModifier(const PrototypeDescriptor &Transformer) {
670   // Handle primitive type transformer
671   switch (static_cast<BaseTypeModifier>(Transformer.PT)) {
672   case BaseTypeModifier::Scalar:
673     Scale = 0;
674     break;
675   case BaseTypeModifier::Vector:
676     Scale = LMUL.getScale(ElementBitwidth);
677     break;
678   case BaseTypeModifier::Void:
679     ScalarType = ScalarTypeKind::Void;
680     break;
681   case BaseTypeModifier::SizeT:
682     ScalarType = ScalarTypeKind::Size_t;
683     break;
684   case BaseTypeModifier::Ptrdiff:
685     ScalarType = ScalarTypeKind::Ptrdiff_t;
686     break;
687   case BaseTypeModifier::UnsignedLong:
688     ScalarType = ScalarTypeKind::UnsignedLong;
689     break;
690   case BaseTypeModifier::SignedLong:
691     ScalarType = ScalarTypeKind::SignedLong;
692     break;
693   case BaseTypeModifier::Float32:
694     ElementBitwidth = 32;
695     ScalarType = ScalarTypeKind::Float;
696     break;
697   case BaseTypeModifier::Invalid:
698     ScalarType = ScalarTypeKind::Invalid;
699     return;
700   }
701 
702   switch (static_cast<VectorTypeModifier>(Transformer.VTM)) {
703   case VectorTypeModifier::Widening2XVector:
704     ElementBitwidth *= 2;
705     LMUL.MulLog2LMUL(1);
706     Scale = LMUL.getScale(ElementBitwidth);
707     break;
708   case VectorTypeModifier::Widening4XVector:
709     ElementBitwidth *= 4;
710     LMUL.MulLog2LMUL(2);
711     Scale = LMUL.getScale(ElementBitwidth);
712     break;
713   case VectorTypeModifier::Widening8XVector:
714     ElementBitwidth *= 8;
715     LMUL.MulLog2LMUL(3);
716     Scale = LMUL.getScale(ElementBitwidth);
717     break;
718   case VectorTypeModifier::MaskVector:
719     ScalarType = ScalarTypeKind::Boolean;
720     Scale = LMUL.getScale(ElementBitwidth);
721     ElementBitwidth = 1;
722     break;
723   case VectorTypeModifier::Log2EEW3:
724     applyLog2EEW(3);
725     break;
726   case VectorTypeModifier::Log2EEW4:
727     applyLog2EEW(4);
728     break;
729   case VectorTypeModifier::Log2EEW5:
730     applyLog2EEW(5);
731     break;
732   case VectorTypeModifier::Log2EEW6:
733     applyLog2EEW(6);
734     break;
735   case VectorTypeModifier::FixedSEW8:
736     applyFixedSEW(8);
737     break;
738   case VectorTypeModifier::FixedSEW16:
739     applyFixedSEW(16);
740     break;
741   case VectorTypeModifier::FixedSEW32:
742     applyFixedSEW(32);
743     break;
744   case VectorTypeModifier::FixedSEW64:
745     applyFixedSEW(64);
746     break;
747   case VectorTypeModifier::LFixedLog2LMULN3:
748     applyFixedLog2LMUL(-3, FixedLMULType::LargerThan);
749     break;
750   case VectorTypeModifier::LFixedLog2LMULN2:
751     applyFixedLog2LMUL(-2, FixedLMULType::LargerThan);
752     break;
753   case VectorTypeModifier::LFixedLog2LMULN1:
754     applyFixedLog2LMUL(-1, FixedLMULType::LargerThan);
755     break;
756   case VectorTypeModifier::LFixedLog2LMUL0:
757     applyFixedLog2LMUL(0, FixedLMULType::LargerThan);
758     break;
759   case VectorTypeModifier::LFixedLog2LMUL1:
760     applyFixedLog2LMUL(1, FixedLMULType::LargerThan);
761     break;
762   case VectorTypeModifier::LFixedLog2LMUL2:
763     applyFixedLog2LMUL(2, FixedLMULType::LargerThan);
764     break;
765   case VectorTypeModifier::LFixedLog2LMUL3:
766     applyFixedLog2LMUL(3, FixedLMULType::LargerThan);
767     break;
768   case VectorTypeModifier::SFixedLog2LMULN3:
769     applyFixedLog2LMUL(-3, FixedLMULType::SmallerThan);
770     break;
771   case VectorTypeModifier::SFixedLog2LMULN2:
772     applyFixedLog2LMUL(-2, FixedLMULType::SmallerThan);
773     break;
774   case VectorTypeModifier::SFixedLog2LMULN1:
775     applyFixedLog2LMUL(-1, FixedLMULType::SmallerThan);
776     break;
777   case VectorTypeModifier::SFixedLog2LMUL0:
778     applyFixedLog2LMUL(0, FixedLMULType::SmallerThan);
779     break;
780   case VectorTypeModifier::SFixedLog2LMUL1:
781     applyFixedLog2LMUL(1, FixedLMULType::SmallerThan);
782     break;
783   case VectorTypeModifier::SFixedLog2LMUL2:
784     applyFixedLog2LMUL(2, FixedLMULType::SmallerThan);
785     break;
786   case VectorTypeModifier::SFixedLog2LMUL3:
787     applyFixedLog2LMUL(3, FixedLMULType::SmallerThan);
788     break;
789   case VectorTypeModifier::SEFixedLog2LMULN3:
790     applyFixedLog2LMUL(-3, FixedLMULType::SmallerOrEqual);
791     break;
792   case VectorTypeModifier::SEFixedLog2LMULN2:
793     applyFixedLog2LMUL(-2, FixedLMULType::SmallerOrEqual);
794     break;
795   case VectorTypeModifier::SEFixedLog2LMULN1:
796     applyFixedLog2LMUL(-1, FixedLMULType::SmallerOrEqual);
797     break;
798   case VectorTypeModifier::SEFixedLog2LMUL0:
799     applyFixedLog2LMUL(0, FixedLMULType::SmallerOrEqual);
800     break;
801   case VectorTypeModifier::SEFixedLog2LMUL1:
802     applyFixedLog2LMUL(1, FixedLMULType::SmallerOrEqual);
803     break;
804   case VectorTypeModifier::SEFixedLog2LMUL2:
805     applyFixedLog2LMUL(2, FixedLMULType::SmallerOrEqual);
806     break;
807   case VectorTypeModifier::SEFixedLog2LMUL3:
808     applyFixedLog2LMUL(3, FixedLMULType::SmallerOrEqual);
809     break;
810   case VectorTypeModifier::Tuple2:
811   case VectorTypeModifier::Tuple3:
812   case VectorTypeModifier::Tuple4:
813   case VectorTypeModifier::Tuple5:
814   case VectorTypeModifier::Tuple6:
815   case VectorTypeModifier::Tuple7:
816   case VectorTypeModifier::Tuple8: {
817     IsTuple = true;
818     NF = 2 + static_cast<uint8_t>(Transformer.VTM) -
819          static_cast<uint8_t>(VectorTypeModifier::Tuple2);
820     break;
821   }
822   case VectorTypeModifier::NoModifier:
823     break;
824   }
825 
826   // Early return if the current type modifier is already invalid.
827   if (ScalarType == Invalid)
828     return;
829 
830   for (unsigned TypeModifierMaskShift = 0;
831        TypeModifierMaskShift <= static_cast<unsigned>(TypeModifier::MaxOffset);
832        ++TypeModifierMaskShift) {
833     unsigned TypeModifierMask = 1 << TypeModifierMaskShift;
834     if ((static_cast<unsigned>(Transformer.TM) & TypeModifierMask) !=
835         TypeModifierMask)
836       continue;
837     switch (static_cast<TypeModifier>(TypeModifierMask)) {
838     case TypeModifier::Pointer:
839       IsPointer = true;
840       break;
841     case TypeModifier::Const:
842       IsConstant = true;
843       break;
844     case TypeModifier::Immediate:
845       IsImmediate = true;
846       IsConstant = true;
847       break;
848     case TypeModifier::UnsignedInteger:
849       ScalarType = ScalarTypeKind::UnsignedInteger;
850       break;
851     case TypeModifier::SignedInteger:
852       ScalarType = ScalarTypeKind::SignedInteger;
853       break;
854     case TypeModifier::Float:
855       ScalarType = ScalarTypeKind::Float;
856       break;
857     case TypeModifier::BFloat:
858       ScalarType = ScalarTypeKind::BFloat;
859       break;
860     case TypeModifier::LMUL1:
861       LMUL = LMULType(0);
862       // Update ElementBitwidth need to update Scale too.
863       Scale = LMUL.getScale(ElementBitwidth);
864       break;
865     default:
866       llvm_unreachable("Unknown type modifier mask!");
867     }
868   }
869 }
870 
871 void RVVType::applyLog2EEW(unsigned Log2EEW) {
872   // update new elmul = (eew/sew) * lmul
873   LMUL.MulLog2LMUL(Log2EEW - Log2_32(ElementBitwidth));
874   // update new eew
875   ElementBitwidth = 1 << Log2EEW;
876   ScalarType = ScalarTypeKind::SignedInteger;
877   Scale = LMUL.getScale(ElementBitwidth);
878 }
879 
880 void RVVType::applyFixedSEW(unsigned NewSEW) {
881   // Set invalid type if src and dst SEW are same.
882   if (ElementBitwidth == NewSEW) {
883     ScalarType = ScalarTypeKind::Invalid;
884     return;
885   }
886   // Update new SEW
887   ElementBitwidth = NewSEW;
888   Scale = LMUL.getScale(ElementBitwidth);
889 }
890 
891 void RVVType::applyFixedLog2LMUL(int Log2LMUL, enum FixedLMULType Type) {
892   switch (Type) {
893   case FixedLMULType::LargerThan:
894     if (Log2LMUL <= LMUL.Log2LMUL) {
895       ScalarType = ScalarTypeKind::Invalid;
896       return;
897     }
898     break;
899   case FixedLMULType::SmallerThan:
900     if (Log2LMUL >= LMUL.Log2LMUL) {
901       ScalarType = ScalarTypeKind::Invalid;
902       return;
903     }
904     break;
905   case FixedLMULType::SmallerOrEqual:
906     if (Log2LMUL > LMUL.Log2LMUL) {
907       ScalarType = ScalarTypeKind::Invalid;
908       return;
909     }
910     break;
911   }
912 
913   // Update new LMUL
914   LMUL = LMULType(Log2LMUL);
915   Scale = LMUL.getScale(ElementBitwidth);
916 }
917 
918 std::optional<RVVTypes>
919 RVVTypeCache::computeTypes(BasicType BT, int Log2LMUL, unsigned NF,
920                            ArrayRef<PrototypeDescriptor> Prototype) {
921   RVVTypes Types;
922   for (const PrototypeDescriptor &Proto : Prototype) {
923     auto T = computeType(BT, Log2LMUL, Proto);
924     if (!T)
925       return std::nullopt;
926     // Record legal type index
927     Types.push_back(*T);
928   }
929   return Types;
930 }
931 
932 // Compute the hash value of RVVType, used for cache the result of computeType.
933 static uint64_t computeRVVTypeHashValue(BasicType BT, int Log2LMUL,
934                                         PrototypeDescriptor Proto) {
935   // Layout of hash value:
936   // 0               8    16          24        32          40
937   // | Log2LMUL + 3  | BT  | Proto.PT | Proto.TM | Proto.VTM |
938   assert(Log2LMUL >= -3 && Log2LMUL <= 3);
939   return (Log2LMUL + 3) | (static_cast<uint64_t>(BT) & 0xff) << 8 |
940          ((uint64_t)(Proto.PT & 0xff) << 16) |
941          ((uint64_t)(Proto.TM & 0xff) << 24) |
942          ((uint64_t)(Proto.VTM & 0xff) << 32);
943 }
944 
945 std::optional<RVVTypePtr> RVVTypeCache::computeType(BasicType BT, int Log2LMUL,
946                                                     PrototypeDescriptor Proto) {
947   uint64_t Idx = computeRVVTypeHashValue(BT, Log2LMUL, Proto);
948   // Search first
949   auto It = LegalTypes.find(Idx);
950   if (It != LegalTypes.end())
951     return &(It->second);
952 
953   if (IllegalTypes.count(Idx))
954     return std::nullopt;
955 
956   // Compute type and record the result.
957   RVVType T(BT, Log2LMUL, Proto);
958   if (T.isValid()) {
959     // Record legal type index and value.
960     std::pair<std::unordered_map<uint64_t, RVVType>::iterator, bool>
961         InsertResult = LegalTypes.insert({Idx, T});
962     return &(InsertResult.first->second);
963   }
964   // Record illegal type index.
965   IllegalTypes.insert(Idx);
966   return std::nullopt;
967 }
968 
969 //===----------------------------------------------------------------------===//
970 // RVVIntrinsic implementation
971 //===----------------------------------------------------------------------===//
972 RVVIntrinsic::RVVIntrinsic(
973     StringRef NewName, StringRef Suffix, StringRef NewOverloadedName,
974     StringRef OverloadedSuffix, StringRef IRName, bool IsMasked,
975     bool HasMaskedOffOperand, bool HasVL, PolicyScheme Scheme,
976     bool SupportOverloading, bool HasBuiltinAlias, StringRef ManualCodegen,
977     const RVVTypes &OutInTypes, const std::vector<int64_t> &NewIntrinsicTypes,
978     unsigned NF, Policy NewPolicyAttrs, bool HasFRMRoundModeOp)
979     : IRName(IRName), IsMasked(IsMasked),
980       HasMaskedOffOperand(HasMaskedOffOperand), HasVL(HasVL), Scheme(Scheme),
981       SupportOverloading(SupportOverloading), HasBuiltinAlias(HasBuiltinAlias),
982       ManualCodegen(ManualCodegen.str()), NF(NF), PolicyAttrs(NewPolicyAttrs) {
983 
984   // Init BuiltinName, Name and OverloadedName
985   BuiltinName = NewName.str();
986   Name = BuiltinName;
987   if (NewOverloadedName.empty())
988     OverloadedName = NewName.split("_").first.str();
989   else
990     OverloadedName = NewOverloadedName.str();
991   if (!Suffix.empty())
992     Name += "_" + Suffix.str();
993   if (!OverloadedSuffix.empty())
994     OverloadedName += "_" + OverloadedSuffix.str();
995 
996   updateNamesAndPolicy(IsMasked, hasPolicy(), Name, BuiltinName, OverloadedName,
997                        PolicyAttrs, HasFRMRoundModeOp);
998 
999   // Init OutputType and InputTypes
1000   OutputType = OutInTypes[0];
1001   InputTypes.assign(OutInTypes.begin() + 1, OutInTypes.end());
1002 
1003   // IntrinsicTypes is unmasked TA version index. Need to update it
1004   // if there is merge operand (It is always in first operand).
1005   IntrinsicTypes = NewIntrinsicTypes;
1006   if ((IsMasked && hasMaskedOffOperand()) ||
1007       (!IsMasked && hasPassthruOperand())) {
1008     for (auto &I : IntrinsicTypes) {
1009       if (I >= 0)
1010         I += 1;
1011     }
1012   }
1013 }
1014 
1015 std::string RVVIntrinsic::getBuiltinTypeStr() const {
1016   std::string S;
1017   S += OutputType->getBuiltinStr();
1018   for (const auto &T : InputTypes) {
1019     S += T->getBuiltinStr();
1020   }
1021   return S;
1022 }
1023 
1024 std::string RVVIntrinsic::getSuffixStr(
1025     RVVTypeCache &TypeCache, BasicType Type, int Log2LMUL,
1026     llvm::ArrayRef<PrototypeDescriptor> PrototypeDescriptors) {
1027   SmallVector<std::string> SuffixStrs;
1028   for (auto PD : PrototypeDescriptors) {
1029     auto T = TypeCache.computeType(Type, Log2LMUL, PD);
1030     SuffixStrs.push_back((*T)->getShortStr());
1031   }
1032   return join(SuffixStrs, "_");
1033 }
1034 
1035 llvm::SmallVector<PrototypeDescriptor> RVVIntrinsic::computeBuiltinTypes(
1036     llvm::ArrayRef<PrototypeDescriptor> Prototype, bool IsMasked,
1037     bool HasMaskedOffOperand, bool HasVL, unsigned NF,
1038     PolicyScheme DefaultScheme, Policy PolicyAttrs, bool IsTuple) {
1039   SmallVector<PrototypeDescriptor> NewPrototype(Prototype);
1040   bool HasPassthruOp = DefaultScheme == PolicyScheme::HasPassthruOperand;
1041   if (IsMasked) {
1042     // If HasMaskedOffOperand, insert result type as first input operand if
1043     // need.
1044     if (HasMaskedOffOperand && !PolicyAttrs.isTAMAPolicy()) {
1045       if (NF == 1) {
1046         NewPrototype.insert(NewPrototype.begin() + 1, NewPrototype[0]);
1047       } else if (NF > 1) {
1048         if (IsTuple) {
1049           PrototypeDescriptor BasePtrOperand = Prototype[1];
1050           PrototypeDescriptor MaskoffType = PrototypeDescriptor(
1051               static_cast<uint8_t>(BaseTypeModifier::Vector),
1052               static_cast<uint8_t>(getTupleVTM(NF)),
1053               BasePtrOperand.TM & ~static_cast<uint8_t>(TypeModifier::Pointer));
1054           NewPrototype.insert(NewPrototype.begin() + 1, MaskoffType);
1055         } else {
1056           // Convert
1057           // (void, op0 address, op1 address, ...)
1058           // to
1059           // (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...)
1060           PrototypeDescriptor MaskoffType = NewPrototype[1];
1061           MaskoffType.TM &= ~static_cast<uint8_t>(TypeModifier::Pointer);
1062           NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType);
1063         }
1064       }
1065     }
1066     if (HasMaskedOffOperand && NF > 1) {
1067       // Convert
1068       // (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...)
1069       // to
1070       // (void, op0 address, op1 address, ..., mask, maskedoff0, maskedoff1,
1071       // ...)
1072       if (IsTuple)
1073         NewPrototype.insert(NewPrototype.begin() + 1,
1074                             PrototypeDescriptor::Mask);
1075       else
1076         NewPrototype.insert(NewPrototype.begin() + NF + 1,
1077                             PrototypeDescriptor::Mask);
1078     } else {
1079       // If IsMasked, insert PrototypeDescriptor:Mask as first input operand.
1080       NewPrototype.insert(NewPrototype.begin() + 1, PrototypeDescriptor::Mask);
1081     }
1082   } else {
1083     if (NF == 1) {
1084       if (PolicyAttrs.isTUPolicy() && HasPassthruOp)
1085         NewPrototype.insert(NewPrototype.begin(), NewPrototype[0]);
1086     } else if (PolicyAttrs.isTUPolicy() && HasPassthruOp) {
1087       if (IsTuple) {
1088         PrototypeDescriptor BasePtrOperand = Prototype[0];
1089         PrototypeDescriptor MaskoffType = PrototypeDescriptor(
1090             static_cast<uint8_t>(BaseTypeModifier::Vector),
1091             static_cast<uint8_t>(getTupleVTM(NF)),
1092             BasePtrOperand.TM & ~static_cast<uint8_t>(TypeModifier::Pointer));
1093         NewPrototype.insert(NewPrototype.begin(), MaskoffType);
1094       } else {
1095         // NF > 1 cases for segment load operations.
1096         // Convert
1097         // (void, op0 address, op1 address, ...)
1098         // to
1099         // (void, op0 address, op1 address, maskedoff0, maskedoff1, ...)
1100         PrototypeDescriptor MaskoffType = Prototype[1];
1101         MaskoffType.TM &= ~static_cast<uint8_t>(TypeModifier::Pointer);
1102         NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType);
1103       }
1104     }
1105  }
1106 
1107   // If HasVL, append PrototypeDescriptor:VL to last operand
1108   if (HasVL)
1109     NewPrototype.push_back(PrototypeDescriptor::VL);
1110 
1111   return NewPrototype;
1112 }
1113 
1114 llvm::SmallVector<Policy> RVVIntrinsic::getSupportedUnMaskedPolicies() {
1115   return {Policy(Policy::PolicyType::Undisturbed)}; // TU
1116 }
1117 
1118 llvm::SmallVector<Policy>
1119 RVVIntrinsic::getSupportedMaskedPolicies(bool HasTailPolicy,
1120                                          bool HasMaskPolicy) {
1121   if (HasTailPolicy && HasMaskPolicy)
1122     return {Policy(Policy::PolicyType::Undisturbed,
1123                    Policy::PolicyType::Agnostic), // TUM
1124             Policy(Policy::PolicyType::Undisturbed,
1125                    Policy::PolicyType::Undisturbed), // TUMU
1126             Policy(Policy::PolicyType::Agnostic,
1127                    Policy::PolicyType::Undisturbed)}; // MU
1128   if (HasTailPolicy && !HasMaskPolicy)
1129     return {Policy(Policy::PolicyType::Undisturbed,
1130                    Policy::PolicyType::Agnostic)}; // TU
1131   if (!HasTailPolicy && HasMaskPolicy)
1132     return {Policy(Policy::PolicyType::Agnostic,
1133                    Policy::PolicyType::Undisturbed)}; // MU
1134   llvm_unreachable("An RVV instruction should not be without both tail policy "
1135                    "and mask policy");
1136 }
1137 
1138 void RVVIntrinsic::updateNamesAndPolicy(
1139     bool IsMasked, bool HasPolicy, std::string &Name, std::string &BuiltinName,
1140     std::string &OverloadedName, Policy &PolicyAttrs, bool HasFRMRoundModeOp) {
1141 
1142   auto appendPolicySuffix = [&](const std::string &suffix) {
1143     Name += suffix;
1144     BuiltinName += suffix;
1145     OverloadedName += suffix;
1146   };
1147 
1148   if (HasFRMRoundModeOp) {
1149     Name += "_rm";
1150     BuiltinName += "_rm";
1151   }
1152 
1153   if (IsMasked) {
1154     if (PolicyAttrs.isTUMUPolicy())
1155       appendPolicySuffix("_tumu");
1156     else if (PolicyAttrs.isTUMAPolicy())
1157       appendPolicySuffix("_tum");
1158     else if (PolicyAttrs.isTAMUPolicy())
1159       appendPolicySuffix("_mu");
1160     else if (PolicyAttrs.isTAMAPolicy()) {
1161       Name += "_m";
1162       BuiltinName += "_m";
1163     } else
1164       llvm_unreachable("Unhandled policy condition");
1165   } else {
1166     if (PolicyAttrs.isTUPolicy())
1167       appendPolicySuffix("_tu");
1168     else if (PolicyAttrs.isTAPolicy()) // no suffix needed
1169       return;
1170     else
1171       llvm_unreachable("Unhandled policy condition");
1172   }
1173 }
1174 
1175 SmallVector<PrototypeDescriptor> parsePrototypes(StringRef Prototypes) {
1176   SmallVector<PrototypeDescriptor> PrototypeDescriptors;
1177   const StringRef Primaries("evwqom0ztulf");
1178   while (!Prototypes.empty()) {
1179     size_t Idx = 0;
1180     // Skip over complex prototype because it could contain primitive type
1181     // character.
1182     if (Prototypes[0] == '(')
1183       Idx = Prototypes.find_first_of(')');
1184     Idx = Prototypes.find_first_of(Primaries, Idx);
1185     assert(Idx != StringRef::npos);
1186     auto PD = PrototypeDescriptor::parsePrototypeDescriptor(
1187         Prototypes.slice(0, Idx + 1));
1188     if (!PD)
1189       llvm_unreachable("Error during parsing prototype.");
1190     PrototypeDescriptors.push_back(*PD);
1191     Prototypes = Prototypes.drop_front(Idx + 1);
1192   }
1193   return PrototypeDescriptors;
1194 }
1195 
1196 #define STRINGIFY(NAME)                                                        \
1197   case NAME:                                                                   \
1198     OS << #NAME;                                                               \
1199     break;
1200 
1201 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, enum PolicyScheme PS) {
1202   switch (PS) {
1203     STRINGIFY(SchemeNone)
1204     STRINGIFY(HasPassthruOperand)
1205     STRINGIFY(HasPolicyOperand)
1206   }
1207   return OS;
1208 }
1209 
1210 #undef STRINGIFY
1211 
1212 raw_ostream &operator<<(raw_ostream &OS, const RVVIntrinsicRecord &Record) {
1213   OS << "{";
1214   OS << "/*Name=*/\"" << Record.Name << "\", ";
1215   if (Record.OverloadedName == nullptr ||
1216       StringRef(Record.OverloadedName).empty())
1217     OS << "/*OverloadedName=*/nullptr, ";
1218   else
1219     OS << "/*OverloadedName=*/\"" << Record.OverloadedName << "\", ";
1220   OS << "/*RequiredExtensions=*/\"" << Record.RequiredExtensions << "\", ";
1221   OS << "/*PrototypeIndex=*/" << Record.PrototypeIndex << ", ";
1222   OS << "/*SuffixIndex=*/" << Record.SuffixIndex << ", ";
1223   OS << "/*OverloadedSuffixIndex=*/" << Record.OverloadedSuffixIndex << ", ";
1224   OS << "/*PrototypeLength=*/" << (int)Record.PrototypeLength << ", ";
1225   OS << "/*SuffixLength=*/" << (int)Record.SuffixLength << ", ";
1226   OS << "/*OverloadedSuffixSize=*/" << (int)Record.OverloadedSuffixSize << ", ";
1227   OS << "/*TypeRangeMask=*/" << (int)Record.TypeRangeMask << ", ";
1228   OS << "/*Log2LMULMask=*/" << (int)Record.Log2LMULMask << ", ";
1229   OS << "/*NF=*/" << (int)Record.NF << ", ";
1230   OS << "/*HasMasked=*/" << (int)Record.HasMasked << ", ";
1231   OS << "/*HasVL=*/" << (int)Record.HasVL << ", ";
1232   OS << "/*HasMaskedOffOperand=*/" << (int)Record.HasMaskedOffOperand << ", ";
1233   OS << "/*HasTailPolicy=*/" << (int)Record.HasTailPolicy << ", ";
1234   OS << "/*HasMaskPolicy=*/" << (int)Record.HasMaskPolicy << ", ";
1235   OS << "/*HasFRMRoundModeOp=*/" << (int)Record.HasFRMRoundModeOp << ", ";
1236   OS << "/*IsTuple=*/" << (int)Record.IsTuple << ", ";
1237   OS << "/*UnMaskedPolicyScheme=*/" << (PolicyScheme)Record.UnMaskedPolicyScheme
1238      << ", ";
1239   OS << "/*MaskedPolicyScheme=*/" << (PolicyScheme)Record.MaskedPolicyScheme
1240      << ", ";
1241   OS << "},\n";
1242   return OS;
1243 }
1244 
1245 } // end namespace RISCV
1246 } // end namespace clang
1247