xref: /freebsd/contrib/llvm-project/clang/utils/TableGen/RISCVVEmitter.cpp (revision 1165fc9a526630487a1feb63daef65c5aee1a583)
1 //===- RISCVVEmitter.cpp - Generate riscv_vector.h for use with clang -----===//
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 // This tablegen backend is responsible for emitting riscv_vector.h which
10 // includes a declaration and definition of each intrinsic functions specified
11 // in https://github.com/riscv/rvv-intrinsic-doc.
12 //
13 // See also the documentation in include/clang/Basic/riscv_vector.td.
14 //
15 //===----------------------------------------------------------------------===//
16 
17 #include "llvm/ADT/ArrayRef.h"
18 #include "llvm/ADT/SmallSet.h"
19 #include "llvm/ADT/StringExtras.h"
20 #include "llvm/ADT/StringMap.h"
21 #include "llvm/ADT/StringSet.h"
22 #include "llvm/ADT/Twine.h"
23 #include "llvm/TableGen/Error.h"
24 #include "llvm/TableGen/Record.h"
25 #include <numeric>
26 
27 using namespace llvm;
28 using BasicType = char;
29 using VScaleVal = Optional<unsigned>;
30 
31 namespace {
32 
33 // Exponential LMUL
34 struct LMULType {
35   int Log2LMUL;
36   LMULType(int Log2LMUL);
37   // Return the C/C++ string representation of LMUL
38   std::string str() const;
39   Optional<unsigned> getScale(unsigned ElementBitwidth) const;
40   void MulLog2LMUL(int Log2LMUL);
41   LMULType &operator*=(uint32_t RHS);
42 };
43 
44 // This class is compact representation of a valid and invalid RVVType.
45 class RVVType {
46   enum ScalarTypeKind : uint32_t {
47     Void,
48     Size_t,
49     Ptrdiff_t,
50     UnsignedLong,
51     SignedLong,
52     Boolean,
53     SignedInteger,
54     UnsignedInteger,
55     Float,
56     Invalid,
57   };
58   BasicType BT;
59   ScalarTypeKind ScalarType = Invalid;
60   LMULType LMUL;
61   bool IsPointer = false;
62   // IsConstant indices are "int", but have the constant expression.
63   bool IsImmediate = false;
64   // Const qualifier for pointer to const object or object of const type.
65   bool IsConstant = false;
66   unsigned ElementBitwidth = 0;
67   VScaleVal Scale = 0;
68   bool Valid;
69 
70   std::string BuiltinStr;
71   std::string ClangBuiltinStr;
72   std::string Str;
73   std::string ShortStr;
74 
75 public:
76   RVVType() : RVVType(BasicType(), 0, StringRef()) {}
77   RVVType(BasicType BT, int Log2LMUL, StringRef prototype);
78 
79   // Return the string representation of a type, which is an encoded string for
80   // passing to the BUILTIN() macro in Builtins.def.
81   const std::string &getBuiltinStr() const { return BuiltinStr; }
82 
83   // Return the clang builtin type for RVV vector type which are used in the
84   // riscv_vector.h header file.
85   const std::string &getClangBuiltinStr() const { return ClangBuiltinStr; }
86 
87   // Return the C/C++ string representation of a type for use in the
88   // riscv_vector.h header file.
89   const std::string &getTypeStr() const { return Str; }
90 
91   // Return the short name of a type for C/C++ name suffix.
92   const std::string &getShortStr() {
93     // Not all types are used in short name, so compute the short name by
94     // demanded.
95     if (ShortStr.empty())
96       initShortStr();
97     return ShortStr;
98   }
99 
100   bool isValid() const { return Valid; }
101   bool isScalar() const { return Scale.hasValue() && Scale.getValue() == 0; }
102   bool isVector() const { return Scale.hasValue() && Scale.getValue() != 0; }
103   bool isVector(unsigned Width) const {
104     return isVector() && ElementBitwidth == Width;
105   }
106   bool isFloat() const { return ScalarType == ScalarTypeKind::Float; }
107   bool isSignedInteger() const {
108     return ScalarType == ScalarTypeKind::SignedInteger;
109   }
110   bool isFloatVector(unsigned Width) const {
111     return isVector() && isFloat() && ElementBitwidth == Width;
112   }
113   bool isFloat(unsigned Width) const {
114     return isFloat() && ElementBitwidth == Width;
115   }
116 
117 private:
118   // Verify RVV vector type and set Valid.
119   bool verifyType() const;
120 
121   // Creates a type based on basic types of TypeRange
122   void applyBasicType();
123 
124   // Applies a prototype modifier to the current type. The result maybe an
125   // invalid type.
126   void applyModifier(StringRef prototype);
127 
128   // Compute and record a string for legal type.
129   void initBuiltinStr();
130   // Compute and record a builtin RVV vector type string.
131   void initClangBuiltinStr();
132   // Compute and record a type string for used in the header.
133   void initTypeStr();
134   // Compute and record a short name of a type for C/C++ name suffix.
135   void initShortStr();
136 };
137 
138 using RVVTypePtr = RVVType *;
139 using RVVTypes = std::vector<RVVTypePtr>;
140 using RISCVPredefinedMacroT = uint8_t;
141 
142 enum RISCVPredefinedMacro : RISCVPredefinedMacroT {
143   Basic = 0,
144   V = 1 << 1,
145   Zfh = 1 << 2,
146   RV64 = 1 << 3,
147   VectorMaxELen64 = 1 << 4,
148   VectorMaxELenFp32 = 1 << 5,
149   VectorMaxELenFp64 = 1 << 6,
150 };
151 
152 // TODO refactor RVVIntrinsic class design after support all intrinsic
153 // combination. This represents an instantiation of an intrinsic with a
154 // particular type and prototype
155 class RVVIntrinsic {
156 
157 private:
158   std::string BuiltinName; // Builtin name
159   std::string Name;        // C intrinsic name.
160   std::string MangledName;
161   std::string IRName;
162   bool IsMask;
163   bool HasVL;
164   bool HasPolicy;
165   bool HasNoMaskedOverloaded;
166   bool HasAutoDef; // There is automiatic definition in header
167   std::string ManualCodegen;
168   RVVTypePtr OutputType; // Builtin output type
169   RVVTypes InputTypes;   // Builtin input types
170   // The types we use to obtain the specific LLVM intrinsic. They are index of
171   // InputTypes. -1 means the return type.
172   std::vector<int64_t> IntrinsicTypes;
173   RISCVPredefinedMacroT RISCVPredefinedMacros = 0;
174   unsigned NF = 1;
175 
176 public:
177   RVVIntrinsic(StringRef Name, StringRef Suffix, StringRef MangledName,
178                StringRef MangledSuffix, StringRef IRName, bool IsMask,
179                bool HasMaskedOffOperand, bool HasVL, bool HasPolicy,
180                bool HasNoMaskedOverloaded, bool HasAutoDef,
181                StringRef ManualCodegen, const RVVTypes &Types,
182                const std::vector<int64_t> &IntrinsicTypes,
183                const std::vector<StringRef> &RequiredFeatures, unsigned NF);
184   ~RVVIntrinsic() = default;
185 
186   StringRef getBuiltinName() const { return BuiltinName; }
187   StringRef getName() const { return Name; }
188   StringRef getMangledName() const { return MangledName; }
189   bool hasVL() const { return HasVL; }
190   bool hasPolicy() const { return HasPolicy; }
191   bool hasNoMaskedOverloaded() const { return HasNoMaskedOverloaded; }
192   bool hasManualCodegen() const { return !ManualCodegen.empty(); }
193   bool hasAutoDef() const { return HasAutoDef; }
194   bool isMask() const { return IsMask; }
195   StringRef getIRName() const { return IRName; }
196   StringRef getManualCodegen() const { return ManualCodegen; }
197   RISCVPredefinedMacroT getRISCVPredefinedMacros() const {
198     return RISCVPredefinedMacros;
199   }
200   unsigned getNF() const { return NF; }
201   const std::vector<int64_t> &getIntrinsicTypes() const {
202     return IntrinsicTypes;
203   }
204 
205   // Return the type string for a BUILTIN() macro in Builtins.def.
206   std::string getBuiltinTypeStr() const;
207 
208   // Emit the code block for switch body in EmitRISCVBuiltinExpr, it should
209   // init the RVVIntrinsic ID and IntrinsicTypes.
210   void emitCodeGenSwitchBody(raw_ostream &o) const;
211 
212   // Emit the macros for mapping C/C++ intrinsic function to builtin functions.
213   void emitIntrinsicFuncDef(raw_ostream &o) const;
214 
215   // Emit the mangled function definition.
216   void emitMangledFuncDef(raw_ostream &o) const;
217 };
218 
219 class RVVEmitter {
220 private:
221   RecordKeeper &Records;
222   std::string HeaderCode;
223   // Concat BasicType, LMUL and Proto as key
224   StringMap<RVVType> LegalTypes;
225   StringSet<> IllegalTypes;
226 
227 public:
228   RVVEmitter(RecordKeeper &R) : Records(R) {}
229 
230   /// Emit riscv_vector.h
231   void createHeader(raw_ostream &o);
232 
233   /// Emit all the __builtin prototypes and code needed by Sema.
234   void createBuiltins(raw_ostream &o);
235 
236   /// Emit all the information needed to map builtin -> LLVM IR intrinsic.
237   void createCodeGen(raw_ostream &o);
238 
239   std::string getSuffixStr(char Type, int Log2LMUL, StringRef Prototypes);
240 
241 private:
242   /// Create all intrinsics and add them to \p Out
243   void createRVVIntrinsics(std::vector<std::unique_ptr<RVVIntrinsic>> &Out);
244   /// Create Headers and add them to \p Out
245   void createRVVHeaders(raw_ostream &OS);
246   /// Compute output and input types by applying different config (basic type
247   /// and LMUL with type transformers). It also record result of type in legal
248   /// or illegal set to avoid compute the  same config again. The result maybe
249   /// have illegal RVVType.
250   Optional<RVVTypes> computeTypes(BasicType BT, int Log2LMUL, unsigned NF,
251                                   ArrayRef<std::string> PrototypeSeq);
252   Optional<RVVTypePtr> computeType(BasicType BT, int Log2LMUL, StringRef Proto);
253 
254   /// Emit Acrh predecessor definitions and body, assume the element of Defs are
255   /// sorted by extension.
256   void emitArchMacroAndBody(
257       std::vector<std::unique_ptr<RVVIntrinsic>> &Defs, raw_ostream &o,
258       std::function<void(raw_ostream &, const RVVIntrinsic &)>);
259 
260   // Emit the architecture preprocessor definitions. Return true when emits
261   // non-empty string.
262   bool emitMacroRestrictionStr(RISCVPredefinedMacroT PredefinedMacros,
263                                raw_ostream &o);
264   // Slice Prototypes string into sub prototype string and process each sub
265   // prototype string individually in the Handler.
266   void parsePrototypes(StringRef Prototypes,
267                        std::function<void(StringRef)> Handler);
268 };
269 
270 } // namespace
271 
272 //===----------------------------------------------------------------------===//
273 // Type implementation
274 //===----------------------------------------------------------------------===//
275 
276 LMULType::LMULType(int NewLog2LMUL) {
277   // Check Log2LMUL is -3, -2, -1, 0, 1, 2, 3
278   assert(NewLog2LMUL <= 3 && NewLog2LMUL >= -3 && "Bad LMUL number!");
279   Log2LMUL = NewLog2LMUL;
280 }
281 
282 std::string LMULType::str() const {
283   if (Log2LMUL < 0)
284     return "mf" + utostr(1ULL << (-Log2LMUL));
285   return "m" + utostr(1ULL << Log2LMUL);
286 }
287 
288 VScaleVal LMULType::getScale(unsigned ElementBitwidth) const {
289   int Log2ScaleResult = 0;
290   switch (ElementBitwidth) {
291   default:
292     break;
293   case 8:
294     Log2ScaleResult = Log2LMUL + 3;
295     break;
296   case 16:
297     Log2ScaleResult = Log2LMUL + 2;
298     break;
299   case 32:
300     Log2ScaleResult = Log2LMUL + 1;
301     break;
302   case 64:
303     Log2ScaleResult = Log2LMUL;
304     break;
305   }
306   // Illegal vscale result would be less than 1
307   if (Log2ScaleResult < 0)
308     return None;
309   return 1 << Log2ScaleResult;
310 }
311 
312 void LMULType::MulLog2LMUL(int log2LMUL) { Log2LMUL += log2LMUL; }
313 
314 LMULType &LMULType::operator*=(uint32_t RHS) {
315   assert(isPowerOf2_32(RHS));
316   this->Log2LMUL = this->Log2LMUL + Log2_32(RHS);
317   return *this;
318 }
319 
320 RVVType::RVVType(BasicType BT, int Log2LMUL, StringRef prototype)
321     : BT(BT), LMUL(LMULType(Log2LMUL)) {
322   applyBasicType();
323   applyModifier(prototype);
324   Valid = verifyType();
325   if (Valid) {
326     initBuiltinStr();
327     initTypeStr();
328     if (isVector()) {
329       initClangBuiltinStr();
330     }
331   }
332 }
333 
334 // clang-format off
335 // boolean type are encoded the ratio of n (SEW/LMUL)
336 // SEW/LMUL | 1         | 2         | 4         | 8        | 16        | 32        | 64
337 // c type   | vbool64_t | vbool32_t | vbool16_t | vbool8_t | vbool4_t  | vbool2_t  | vbool1_t
338 // IR type  | nxv1i1    | nxv2i1    | nxv4i1    | nxv8i1   | nxv16i1   | nxv32i1   | nxv64i1
339 
340 // type\lmul | 1/8    | 1/4      | 1/2     | 1       | 2        | 4        | 8
341 // --------  |------  | -------- | ------- | ------- | -------- | -------- | --------
342 // i64       | N/A    | N/A      | N/A     | nxv1i64 | nxv2i64  | nxv4i64  | nxv8i64
343 // i32       | N/A    | N/A      | nxv1i32 | nxv2i32 | nxv4i32  | nxv8i32  | nxv16i32
344 // i16       | N/A    | nxv1i16  | nxv2i16 | nxv4i16 | nxv8i16  | nxv16i16 | nxv32i16
345 // i8        | nxv1i8 | nxv2i8   | nxv4i8  | nxv8i8  | nxv16i8  | nxv32i8  | nxv64i8
346 // double    | N/A    | N/A      | N/A     | nxv1f64 | nxv2f64  | nxv4f64  | nxv8f64
347 // float     | N/A    | N/A      | nxv1f32 | nxv2f32 | nxv4f32  | nxv8f32  | nxv16f32
348 // half      | N/A    | nxv1f16  | nxv2f16 | nxv4f16 | nxv8f16  | nxv16f16 | nxv32f16
349 // clang-format on
350 
351 bool RVVType::verifyType() const {
352   if (ScalarType == Invalid)
353     return false;
354   if (isScalar())
355     return true;
356   if (!Scale.hasValue())
357     return false;
358   if (isFloat() && ElementBitwidth == 8)
359     return false;
360   unsigned V = Scale.getValue();
361   switch (ElementBitwidth) {
362   case 1:
363   case 8:
364     // Check Scale is 1,2,4,8,16,32,64
365     return (V <= 64 && isPowerOf2_32(V));
366   case 16:
367     // Check Scale is 1,2,4,8,16,32
368     return (V <= 32 && isPowerOf2_32(V));
369   case 32:
370     // Check Scale is 1,2,4,8,16
371     return (V <= 16 && isPowerOf2_32(V));
372   case 64:
373     // Check Scale is 1,2,4,8
374     return (V <= 8 && isPowerOf2_32(V));
375   }
376   return false;
377 }
378 
379 void RVVType::initBuiltinStr() {
380   assert(isValid() && "RVVType is invalid");
381   switch (ScalarType) {
382   case ScalarTypeKind::Void:
383     BuiltinStr = "v";
384     return;
385   case ScalarTypeKind::Size_t:
386     BuiltinStr = "z";
387     if (IsImmediate)
388       BuiltinStr = "I" + BuiltinStr;
389     if (IsPointer)
390       BuiltinStr += "*";
391     return;
392   case ScalarTypeKind::Ptrdiff_t:
393     BuiltinStr = "Y";
394     return;
395   case ScalarTypeKind::UnsignedLong:
396     BuiltinStr = "ULi";
397     return;
398   case ScalarTypeKind::SignedLong:
399     BuiltinStr = "Li";
400     return;
401   case ScalarTypeKind::Boolean:
402     assert(ElementBitwidth == 1);
403     BuiltinStr += "b";
404     break;
405   case ScalarTypeKind::SignedInteger:
406   case ScalarTypeKind::UnsignedInteger:
407     switch (ElementBitwidth) {
408     case 8:
409       BuiltinStr += "c";
410       break;
411     case 16:
412       BuiltinStr += "s";
413       break;
414     case 32:
415       BuiltinStr += "i";
416       break;
417     case 64:
418       BuiltinStr += "Wi";
419       break;
420     default:
421       llvm_unreachable("Unhandled ElementBitwidth!");
422     }
423     if (isSignedInteger())
424       BuiltinStr = "S" + BuiltinStr;
425     else
426       BuiltinStr = "U" + BuiltinStr;
427     break;
428   case ScalarTypeKind::Float:
429     switch (ElementBitwidth) {
430     case 16:
431       BuiltinStr += "x";
432       break;
433     case 32:
434       BuiltinStr += "f";
435       break;
436     case 64:
437       BuiltinStr += "d";
438       break;
439     default:
440       llvm_unreachable("Unhandled ElementBitwidth!");
441     }
442     break;
443   default:
444     llvm_unreachable("ScalarType is invalid!");
445   }
446   if (IsImmediate)
447     BuiltinStr = "I" + BuiltinStr;
448   if (isScalar()) {
449     if (IsConstant)
450       BuiltinStr += "C";
451     if (IsPointer)
452       BuiltinStr += "*";
453     return;
454   }
455   BuiltinStr = "q" + utostr(Scale.getValue()) + BuiltinStr;
456   // Pointer to vector types. Defined for segment load intrinsics.
457   // segment load intrinsics have pointer type arguments to store the loaded
458   // vector values.
459   if (IsPointer)
460     BuiltinStr += "*";
461 }
462 
463 void RVVType::initClangBuiltinStr() {
464   assert(isValid() && "RVVType is invalid");
465   assert(isVector() && "Handle Vector type only");
466 
467   ClangBuiltinStr = "__rvv_";
468   switch (ScalarType) {
469   case ScalarTypeKind::Boolean:
470     ClangBuiltinStr += "bool" + utostr(64 / Scale.getValue()) + "_t";
471     return;
472   case ScalarTypeKind::Float:
473     ClangBuiltinStr += "float";
474     break;
475   case ScalarTypeKind::SignedInteger:
476     ClangBuiltinStr += "int";
477     break;
478   case ScalarTypeKind::UnsignedInteger:
479     ClangBuiltinStr += "uint";
480     break;
481   default:
482     llvm_unreachable("ScalarTypeKind is invalid");
483   }
484   ClangBuiltinStr += utostr(ElementBitwidth) + LMUL.str() + "_t";
485 }
486 
487 void RVVType::initTypeStr() {
488   assert(isValid() && "RVVType is invalid");
489 
490   if (IsConstant)
491     Str += "const ";
492 
493   auto getTypeString = [&](StringRef TypeStr) {
494     if (isScalar())
495       return Twine(TypeStr + Twine(ElementBitwidth) + "_t").str();
496     return Twine("v" + TypeStr + Twine(ElementBitwidth) + LMUL.str() + "_t")
497         .str();
498   };
499 
500   switch (ScalarType) {
501   case ScalarTypeKind::Void:
502     Str = "void";
503     return;
504   case ScalarTypeKind::Size_t:
505     Str = "size_t";
506     if (IsPointer)
507       Str += " *";
508     return;
509   case ScalarTypeKind::Ptrdiff_t:
510     Str = "ptrdiff_t";
511     return;
512   case ScalarTypeKind::UnsignedLong:
513     Str = "unsigned long";
514     return;
515   case ScalarTypeKind::SignedLong:
516     Str = "long";
517     return;
518   case ScalarTypeKind::Boolean:
519     if (isScalar())
520       Str += "bool";
521     else
522       // Vector bool is special case, the formulate is
523       // `vbool<N>_t = MVT::nxv<64/N>i1` ex. vbool16_t = MVT::4i1
524       Str += "vbool" + utostr(64 / Scale.getValue()) + "_t";
525     break;
526   case ScalarTypeKind::Float:
527     if (isScalar()) {
528       if (ElementBitwidth == 64)
529         Str += "double";
530       else if (ElementBitwidth == 32)
531         Str += "float";
532       else if (ElementBitwidth == 16)
533         Str += "_Float16";
534       else
535         llvm_unreachable("Unhandled floating type.");
536     } else
537       Str += getTypeString("float");
538     break;
539   case ScalarTypeKind::SignedInteger:
540     Str += getTypeString("int");
541     break;
542   case ScalarTypeKind::UnsignedInteger:
543     Str += getTypeString("uint");
544     break;
545   default:
546     llvm_unreachable("ScalarType is invalid!");
547   }
548   if (IsPointer)
549     Str += " *";
550 }
551 
552 void RVVType::initShortStr() {
553   switch (ScalarType) {
554   case ScalarTypeKind::Boolean:
555     assert(isVector());
556     ShortStr = "b" + utostr(64 / Scale.getValue());
557     return;
558   case ScalarTypeKind::Float:
559     ShortStr = "f" + utostr(ElementBitwidth);
560     break;
561   case ScalarTypeKind::SignedInteger:
562     ShortStr = "i" + utostr(ElementBitwidth);
563     break;
564   case ScalarTypeKind::UnsignedInteger:
565     ShortStr = "u" + utostr(ElementBitwidth);
566     break;
567   default:
568     PrintFatalError("Unhandled case!");
569   }
570   if (isVector())
571     ShortStr += LMUL.str();
572 }
573 
574 void RVVType::applyBasicType() {
575   switch (BT) {
576   case 'c':
577     ElementBitwidth = 8;
578     ScalarType = ScalarTypeKind::SignedInteger;
579     break;
580   case 's':
581     ElementBitwidth = 16;
582     ScalarType = ScalarTypeKind::SignedInteger;
583     break;
584   case 'i':
585     ElementBitwidth = 32;
586     ScalarType = ScalarTypeKind::SignedInteger;
587     break;
588   case 'l':
589     ElementBitwidth = 64;
590     ScalarType = ScalarTypeKind::SignedInteger;
591     break;
592   case 'x':
593     ElementBitwidth = 16;
594     ScalarType = ScalarTypeKind::Float;
595     break;
596   case 'f':
597     ElementBitwidth = 32;
598     ScalarType = ScalarTypeKind::Float;
599     break;
600   case 'd':
601     ElementBitwidth = 64;
602     ScalarType = ScalarTypeKind::Float;
603     break;
604   default:
605     PrintFatalError("Unhandled type code!");
606   }
607   assert(ElementBitwidth != 0 && "Bad element bitwidth!");
608 }
609 
610 void RVVType::applyModifier(StringRef Transformer) {
611   if (Transformer.empty())
612     return;
613   // Handle primitive type transformer
614   auto PType = Transformer.back();
615   switch (PType) {
616   case 'e':
617     Scale = 0;
618     break;
619   case 'v':
620     Scale = LMUL.getScale(ElementBitwidth);
621     break;
622   case 'w':
623     ElementBitwidth *= 2;
624     LMUL *= 2;
625     Scale = LMUL.getScale(ElementBitwidth);
626     break;
627   case 'q':
628     ElementBitwidth *= 4;
629     LMUL *= 4;
630     Scale = LMUL.getScale(ElementBitwidth);
631     break;
632   case 'o':
633     ElementBitwidth *= 8;
634     LMUL *= 8;
635     Scale = LMUL.getScale(ElementBitwidth);
636     break;
637   case 'm':
638     ScalarType = ScalarTypeKind::Boolean;
639     Scale = LMUL.getScale(ElementBitwidth);
640     ElementBitwidth = 1;
641     break;
642   case '0':
643     ScalarType = ScalarTypeKind::Void;
644     break;
645   case 'z':
646     ScalarType = ScalarTypeKind::Size_t;
647     break;
648   case 't':
649     ScalarType = ScalarTypeKind::Ptrdiff_t;
650     break;
651   case 'u':
652     ScalarType = ScalarTypeKind::UnsignedLong;
653     break;
654   case 'l':
655     ScalarType = ScalarTypeKind::SignedLong;
656     break;
657   default:
658     PrintFatalError("Illegal primitive type transformers!");
659   }
660   Transformer = Transformer.drop_back();
661 
662   // Extract and compute complex type transformer. It can only appear one time.
663   if (Transformer.startswith("(")) {
664     size_t Idx = Transformer.find(')');
665     assert(Idx != StringRef::npos);
666     StringRef ComplexType = Transformer.slice(1, Idx);
667     Transformer = Transformer.drop_front(Idx + 1);
668     assert(!Transformer.contains('(') &&
669            "Only allow one complex type transformer");
670 
671     auto UpdateAndCheckComplexProto = [&]() {
672       Scale = LMUL.getScale(ElementBitwidth);
673       const StringRef VectorPrototypes("vwqom");
674       if (!VectorPrototypes.contains(PType))
675         PrintFatalError("Complex type transformer only supports vector type!");
676       if (Transformer.find_first_of("PCKWS") != StringRef::npos)
677         PrintFatalError(
678             "Illegal type transformer for Complex type transformer");
679     };
680     auto ComputeFixedLog2LMUL =
681         [&](StringRef Value,
682             std::function<bool(const int32_t &, const int32_t &)> Compare) {
683           int32_t Log2LMUL;
684           Value.getAsInteger(10, Log2LMUL);
685           if (!Compare(Log2LMUL, LMUL.Log2LMUL)) {
686             ScalarType = Invalid;
687             return false;
688           }
689           // Update new LMUL
690           LMUL = LMULType(Log2LMUL);
691           UpdateAndCheckComplexProto();
692           return true;
693         };
694     auto ComplexTT = ComplexType.split(":");
695     if (ComplexTT.first == "Log2EEW") {
696       uint32_t Log2EEW;
697       ComplexTT.second.getAsInteger(10, Log2EEW);
698       // update new elmul = (eew/sew) * lmul
699       LMUL.MulLog2LMUL(Log2EEW - Log2_32(ElementBitwidth));
700       // update new eew
701       ElementBitwidth = 1 << Log2EEW;
702       ScalarType = ScalarTypeKind::SignedInteger;
703       UpdateAndCheckComplexProto();
704     } else if (ComplexTT.first == "FixedSEW") {
705       uint32_t NewSEW;
706       ComplexTT.second.getAsInteger(10, NewSEW);
707       // Set invalid type if src and dst SEW are same.
708       if (ElementBitwidth == NewSEW) {
709         ScalarType = Invalid;
710         return;
711       }
712       // Update new SEW
713       ElementBitwidth = NewSEW;
714       UpdateAndCheckComplexProto();
715     } else if (ComplexTT.first == "LFixedLog2LMUL") {
716       // New LMUL should be larger than old
717       if (!ComputeFixedLog2LMUL(ComplexTT.second, std::greater<int32_t>()))
718         return;
719     } else if (ComplexTT.first == "SFixedLog2LMUL") {
720       // New LMUL should be smaller than old
721       if (!ComputeFixedLog2LMUL(ComplexTT.second, std::less<int32_t>()))
722         return;
723     } else {
724       PrintFatalError("Illegal complex type transformers!");
725     }
726   }
727 
728   // Compute the remain type transformers
729   for (char I : Transformer) {
730     switch (I) {
731     case 'P':
732       if (IsConstant)
733         PrintFatalError("'P' transformer cannot be used after 'C'");
734       if (IsPointer)
735         PrintFatalError("'P' transformer cannot be used twice");
736       IsPointer = true;
737       break;
738     case 'C':
739       if (IsConstant)
740         PrintFatalError("'C' transformer cannot be used twice");
741       IsConstant = true;
742       break;
743     case 'K':
744       IsImmediate = true;
745       break;
746     case 'U':
747       ScalarType = ScalarTypeKind::UnsignedInteger;
748       break;
749     case 'I':
750       ScalarType = ScalarTypeKind::SignedInteger;
751       break;
752     case 'F':
753       ScalarType = ScalarTypeKind::Float;
754       break;
755     case 'S':
756       LMUL = LMULType(0);
757       // Update ElementBitwidth need to update Scale too.
758       Scale = LMUL.getScale(ElementBitwidth);
759       break;
760     default:
761       PrintFatalError("Illegal non-primitive type transformer!");
762     }
763   }
764 }
765 
766 //===----------------------------------------------------------------------===//
767 // RVVIntrinsic implementation
768 //===----------------------------------------------------------------------===//
769 RVVIntrinsic::RVVIntrinsic(StringRef NewName, StringRef Suffix,
770                            StringRef NewMangledName, StringRef MangledSuffix,
771                            StringRef IRName, bool IsMask,
772                            bool HasMaskedOffOperand, bool HasVL, bool HasPolicy,
773                            bool HasNoMaskedOverloaded, bool HasAutoDef,
774                            StringRef ManualCodegen, const RVVTypes &OutInTypes,
775                            const std::vector<int64_t> &NewIntrinsicTypes,
776                            const std::vector<StringRef> &RequiredFeatures,
777                            unsigned NF)
778     : IRName(IRName), IsMask(IsMask), HasVL(HasVL), HasPolicy(HasPolicy),
779       HasNoMaskedOverloaded(HasNoMaskedOverloaded), HasAutoDef(HasAutoDef),
780       ManualCodegen(ManualCodegen.str()), NF(NF) {
781 
782   // Init BuiltinName, Name and MangledName
783   BuiltinName = NewName.str();
784   Name = BuiltinName;
785   if (NewMangledName.empty())
786     MangledName = NewName.split("_").first.str();
787   else
788     MangledName = NewMangledName.str();
789   if (!Suffix.empty())
790     Name += "_" + Suffix.str();
791   if (!MangledSuffix.empty())
792     MangledName += "_" + MangledSuffix.str();
793   if (IsMask) {
794     BuiltinName += "_m";
795     Name += "_m";
796   }
797 
798   // Init RISC-V extensions
799   for (const auto &T : OutInTypes) {
800     if (T->isFloatVector(16) || T->isFloat(16))
801       RISCVPredefinedMacros |= RISCVPredefinedMacro::Zfh;
802     if (T->isFloatVector(32))
803       RISCVPredefinedMacros |= RISCVPredefinedMacro::VectorMaxELenFp32;
804     if (T->isFloatVector(64))
805       RISCVPredefinedMacros |= RISCVPredefinedMacro::VectorMaxELenFp64;
806     if (T->isVector(64))
807       RISCVPredefinedMacros |= RISCVPredefinedMacro::VectorMaxELen64;
808   }
809   for (auto Feature : RequiredFeatures) {
810     if (Feature == "RV64")
811       RISCVPredefinedMacros |= RISCVPredefinedMacro::RV64;
812     // Note: Full multiply instruction (mulh, mulhu, mulhsu, smul) for EEW=64
813     // require V.
814     if (Feature == "FullMultiply" &&
815         (RISCVPredefinedMacros & RISCVPredefinedMacro::VectorMaxELen64))
816       RISCVPredefinedMacros |= RISCVPredefinedMacro::V;
817   }
818 
819   // Init OutputType and InputTypes
820   OutputType = OutInTypes[0];
821   InputTypes.assign(OutInTypes.begin() + 1, OutInTypes.end());
822 
823   // IntrinsicTypes is nonmasked version index. Need to update it
824   // if there is maskedoff operand (It is always in first operand).
825   IntrinsicTypes = NewIntrinsicTypes;
826   if (IsMask && HasMaskedOffOperand) {
827     for (auto &I : IntrinsicTypes) {
828       if (I >= 0)
829         I += NF;
830     }
831   }
832 }
833 
834 std::string RVVIntrinsic::getBuiltinTypeStr() const {
835   std::string S;
836   S += OutputType->getBuiltinStr();
837   for (const auto &T : InputTypes) {
838     S += T->getBuiltinStr();
839   }
840   return S;
841 }
842 
843 void RVVIntrinsic::emitCodeGenSwitchBody(raw_ostream &OS) const {
844   if (!getIRName().empty())
845     OS << "  ID = Intrinsic::riscv_" + getIRName() + ";\n";
846   if (NF >= 2)
847     OS << "  NF = " + utostr(getNF()) + ";\n";
848   if (hasManualCodegen()) {
849     OS << ManualCodegen;
850     OS << "break;\n";
851     return;
852   }
853 
854   if (isMask()) {
855     if (hasVL()) {
856       OS << "  std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);\n";
857       if (hasPolicy())
858         OS << "  Ops.push_back(ConstantInt::get(Ops.back()->getType(),"
859                                " TAIL_UNDISTURBED));\n";
860     } else {
861       OS << "  std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end());\n";
862     }
863   }
864 
865   OS << "  IntrinsicTypes = {";
866   ListSeparator LS;
867   for (const auto &Idx : IntrinsicTypes) {
868     if (Idx == -1)
869       OS << LS << "ResultType";
870     else
871       OS << LS << "Ops[" << Idx << "]->getType()";
872   }
873 
874   // VL could be i64 or i32, need to encode it in IntrinsicTypes. VL is
875   // always last operand.
876   if (hasVL())
877     OS << ", Ops.back()->getType()";
878   OS << "};\n";
879   OS << "  break;\n";
880 }
881 
882 void RVVIntrinsic::emitIntrinsicFuncDef(raw_ostream &OS) const {
883   OS << "__attribute__((__clang_builtin_alias__(";
884   OS << "__builtin_rvv_" << getBuiltinName() << ")))\n";
885   OS << OutputType->getTypeStr() << " " << getName() << "(";
886   // Emit function arguments
887   if (!InputTypes.empty()) {
888     ListSeparator LS;
889     for (unsigned i = 0; i < InputTypes.size(); ++i)
890       OS << LS << InputTypes[i]->getTypeStr();
891   }
892   OS << ");\n";
893 }
894 
895 void RVVIntrinsic::emitMangledFuncDef(raw_ostream &OS) const {
896   OS << "__attribute__((__clang_builtin_alias__(";
897   OS << "__builtin_rvv_" << getBuiltinName() << ")))\n";
898   OS << OutputType->getTypeStr() << " " << getMangledName() << "(";
899   // Emit function arguments
900   if (!InputTypes.empty()) {
901     ListSeparator LS;
902     for (unsigned i = 0; i < InputTypes.size(); ++i)
903       OS << LS << InputTypes[i]->getTypeStr();
904   }
905   OS << ");\n";
906 }
907 
908 //===----------------------------------------------------------------------===//
909 // RVVEmitter implementation
910 //===----------------------------------------------------------------------===//
911 void RVVEmitter::createHeader(raw_ostream &OS) {
912 
913   OS << "/*===---- riscv_vector.h - RISC-V V-extension RVVIntrinsics "
914         "-------------------===\n"
915         " *\n"
916         " *\n"
917         " * Part of the LLVM Project, under the Apache License v2.0 with LLVM "
918         "Exceptions.\n"
919         " * See https://llvm.org/LICENSE.txt for license information.\n"
920         " * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n"
921         " *\n"
922         " *===-----------------------------------------------------------------"
923         "------===\n"
924         " */\n\n";
925 
926   OS << "#ifndef __RISCV_VECTOR_H\n";
927   OS << "#define __RISCV_VECTOR_H\n\n";
928 
929   OS << "#include <stdint.h>\n";
930   OS << "#include <stddef.h>\n\n";
931 
932   OS << "#ifndef __riscv_vector\n";
933   OS << "#error \"Vector intrinsics require the vector extension.\"\n";
934   OS << "#endif\n\n";
935 
936   OS << "#ifdef __cplusplus\n";
937   OS << "extern \"C\" {\n";
938   OS << "#endif\n\n";
939 
940   createRVVHeaders(OS);
941 
942   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
943   createRVVIntrinsics(Defs);
944 
945   // Print header code
946   if (!HeaderCode.empty()) {
947     OS << HeaderCode;
948   }
949 
950   auto printType = [&](auto T) {
951     OS << "typedef " << T->getClangBuiltinStr() << " " << T->getTypeStr()
952        << ";\n";
953   };
954 
955   constexpr int Log2LMULs[] = {-3, -2, -1, 0, 1, 2, 3};
956   // Print RVV boolean types.
957   for (int Log2LMUL : Log2LMULs) {
958     auto T = computeType('c', Log2LMUL, "m");
959     if (T.hasValue())
960       printType(T.getValue());
961   }
962   // Print RVV int/float types.
963   for (char I : StringRef("csil")) {
964     for (int Log2LMUL : Log2LMULs) {
965       auto T = computeType(I, Log2LMUL, "v");
966       if (T.hasValue()) {
967         printType(T.getValue());
968         auto UT = computeType(I, Log2LMUL, "Uv");
969         printType(UT.getValue());
970       }
971     }
972   }
973   OS << "#if defined(__riscv_zfh)\n";
974   for (int Log2LMUL : Log2LMULs) {
975     auto T = computeType('x', Log2LMUL, "v");
976     if (T.hasValue())
977       printType(T.getValue());
978   }
979   OS << "#endif\n";
980 
981   OS << "#if defined(__riscv_f)\n";
982   for (int Log2LMUL : Log2LMULs) {
983     auto T = computeType('f', Log2LMUL, "v");
984     if (T.hasValue())
985       printType(T.getValue());
986   }
987   OS << "#endif\n";
988 
989   OS << "#if defined(__riscv_d)\n";
990   for (int Log2LMUL : Log2LMULs) {
991     auto T = computeType('d', Log2LMUL, "v");
992     if (T.hasValue())
993       printType(T.getValue());
994   }
995   OS << "#endif\n\n";
996 
997   // The same extension include in the same arch guard marco.
998   llvm::stable_sort(Defs, [](const std::unique_ptr<RVVIntrinsic> &A,
999                              const std::unique_ptr<RVVIntrinsic> &B) {
1000     return A->getRISCVPredefinedMacros() < B->getRISCVPredefinedMacros();
1001   });
1002 
1003   OS << "#define __rvv_ai static __inline__\n";
1004 
1005   // Print intrinsic functions with macro
1006   emitArchMacroAndBody(Defs, OS, [](raw_ostream &OS, const RVVIntrinsic &Inst) {
1007     OS << "__rvv_ai ";
1008     Inst.emitIntrinsicFuncDef(OS);
1009   });
1010 
1011   OS << "#undef __rvv_ai\n\n";
1012 
1013   OS << "#define __riscv_v_intrinsic_overloading 1\n";
1014 
1015   // Print Overloaded APIs
1016   OS << "#define __rvv_aio static __inline__ "
1017         "__attribute__((__overloadable__))\n";
1018 
1019   emitArchMacroAndBody(Defs, OS, [](raw_ostream &OS, const RVVIntrinsic &Inst) {
1020     if (!Inst.isMask() && !Inst.hasNoMaskedOverloaded())
1021       return;
1022     OS << "__rvv_aio ";
1023     Inst.emitMangledFuncDef(OS);
1024   });
1025 
1026   OS << "#undef __rvv_aio\n";
1027 
1028   OS << "\n#ifdef __cplusplus\n";
1029   OS << "}\n";
1030   OS << "#endif // __cplusplus\n";
1031   OS << "#endif // __RISCV_VECTOR_H\n";
1032 }
1033 
1034 void RVVEmitter::createBuiltins(raw_ostream &OS) {
1035   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
1036   createRVVIntrinsics(Defs);
1037 
1038   // Map to keep track of which builtin names have already been emitted.
1039   StringMap<RVVIntrinsic *> BuiltinMap;
1040 
1041   OS << "#if defined(TARGET_BUILTIN) && !defined(RISCVV_BUILTIN)\n";
1042   OS << "#define RISCVV_BUILTIN(ID, TYPE, ATTRS) TARGET_BUILTIN(ID, TYPE, "
1043         "ATTRS, \"zve32x|v\")\n";
1044   OS << "#endif\n";
1045   for (auto &Def : Defs) {
1046     auto P =
1047         BuiltinMap.insert(std::make_pair(Def->getBuiltinName(), Def.get()));
1048     if (!P.second) {
1049       // Verify that this would have produced the same builtin definition.
1050       if (P.first->second->hasAutoDef() != Def->hasAutoDef()) {
1051         PrintFatalError("Builtin with same name has different hasAutoDef");
1052       } else if (!Def->hasAutoDef() && P.first->second->getBuiltinTypeStr() !=
1053                                            Def->getBuiltinTypeStr()) {
1054         PrintFatalError("Builtin with same name has different type string");
1055       }
1056       continue;
1057     }
1058 
1059     OS << "RISCVV_BUILTIN(__builtin_rvv_" << Def->getBuiltinName() << ",\"";
1060     if (!Def->hasAutoDef())
1061       OS << Def->getBuiltinTypeStr();
1062     OS << "\", \"n\")\n";
1063   }
1064   OS << "#undef RISCVV_BUILTIN\n";
1065 }
1066 
1067 void RVVEmitter::createCodeGen(raw_ostream &OS) {
1068   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
1069   createRVVIntrinsics(Defs);
1070   // IR name could be empty, use the stable sort preserves the relative order.
1071   llvm::stable_sort(Defs, [](const std::unique_ptr<RVVIntrinsic> &A,
1072                              const std::unique_ptr<RVVIntrinsic> &B) {
1073     return A->getIRName() < B->getIRName();
1074   });
1075 
1076   // Map to keep track of which builtin names have already been emitted.
1077   StringMap<RVVIntrinsic *> BuiltinMap;
1078 
1079   // Print switch body when the ir name or ManualCodegen changes from previous
1080   // iteration.
1081   RVVIntrinsic *PrevDef = Defs.begin()->get();
1082   for (auto &Def : Defs) {
1083     StringRef CurIRName = Def->getIRName();
1084     if (CurIRName != PrevDef->getIRName() ||
1085         (Def->getManualCodegen() != PrevDef->getManualCodegen())) {
1086       PrevDef->emitCodeGenSwitchBody(OS);
1087     }
1088     PrevDef = Def.get();
1089 
1090     auto P =
1091         BuiltinMap.insert(std::make_pair(Def->getBuiltinName(), Def.get()));
1092     if (P.second) {
1093       OS << "case RISCVVector::BI__builtin_rvv_" << Def->getBuiltinName()
1094          << ":\n";
1095       continue;
1096     }
1097 
1098     if (P.first->second->getIRName() != Def->getIRName())
1099       PrintFatalError("Builtin with same name has different IRName");
1100     else if (P.first->second->getManualCodegen() != Def->getManualCodegen())
1101       PrintFatalError("Builtin with same name has different ManualCodegen");
1102     else if (P.first->second->getNF() != Def->getNF())
1103       PrintFatalError("Builtin with same name has different NF");
1104     else if (P.first->second->isMask() != Def->isMask())
1105       PrintFatalError("Builtin with same name has different isMask");
1106     else if (P.first->second->hasVL() != Def->hasVL())
1107       PrintFatalError("Builtin with same name has different HasPolicy");
1108     else if (P.first->second->hasPolicy() != Def->hasPolicy())
1109       PrintFatalError("Builtin with same name has different HasPolicy");
1110     else if (P.first->second->getIntrinsicTypes() != Def->getIntrinsicTypes())
1111       PrintFatalError("Builtin with same name has different IntrinsicTypes");
1112   }
1113   Defs.back()->emitCodeGenSwitchBody(OS);
1114   OS << "\n";
1115 }
1116 
1117 void RVVEmitter::parsePrototypes(StringRef Prototypes,
1118                                  std::function<void(StringRef)> Handler) {
1119   const StringRef Primaries("evwqom0ztul");
1120   while (!Prototypes.empty()) {
1121     size_t Idx = 0;
1122     // Skip over complex prototype because it could contain primitive type
1123     // character.
1124     if (Prototypes[0] == '(')
1125       Idx = Prototypes.find_first_of(')');
1126     Idx = Prototypes.find_first_of(Primaries, Idx);
1127     assert(Idx != StringRef::npos);
1128     Handler(Prototypes.slice(0, Idx + 1));
1129     Prototypes = Prototypes.drop_front(Idx + 1);
1130   }
1131 }
1132 
1133 std::string RVVEmitter::getSuffixStr(char Type, int Log2LMUL,
1134                                      StringRef Prototypes) {
1135   SmallVector<std::string> SuffixStrs;
1136   parsePrototypes(Prototypes, [&](StringRef Proto) {
1137     auto T = computeType(Type, Log2LMUL, Proto);
1138     SuffixStrs.push_back(T.getValue()->getShortStr());
1139   });
1140   return join(SuffixStrs, "_");
1141 }
1142 
1143 void RVVEmitter::createRVVIntrinsics(
1144     std::vector<std::unique_ptr<RVVIntrinsic>> &Out) {
1145   std::vector<Record *> RV = Records.getAllDerivedDefinitions("RVVBuiltin");
1146   for (auto *R : RV) {
1147     StringRef Name = R->getValueAsString("Name");
1148     StringRef SuffixProto = R->getValueAsString("Suffix");
1149     StringRef MangledName = R->getValueAsString("MangledName");
1150     StringRef MangledSuffixProto = R->getValueAsString("MangledSuffix");
1151     StringRef Prototypes = R->getValueAsString("Prototype");
1152     StringRef TypeRange = R->getValueAsString("TypeRange");
1153     bool HasMask = R->getValueAsBit("HasMask");
1154     bool HasMaskedOffOperand = R->getValueAsBit("HasMaskedOffOperand");
1155     bool HasVL = R->getValueAsBit("HasVL");
1156     bool HasPolicy = R->getValueAsBit("HasPolicy");
1157     bool HasNoMaskedOverloaded = R->getValueAsBit("HasNoMaskedOverloaded");
1158     std::vector<int64_t> Log2LMULList = R->getValueAsListOfInts("Log2LMUL");
1159     StringRef ManualCodegen = R->getValueAsString("ManualCodegen");
1160     StringRef ManualCodegenMask = R->getValueAsString("ManualCodegenMask");
1161     std::vector<int64_t> IntrinsicTypes =
1162         R->getValueAsListOfInts("IntrinsicTypes");
1163     std::vector<StringRef> RequiredFeatures =
1164         R->getValueAsListOfStrings("RequiredFeatures");
1165     StringRef IRName = R->getValueAsString("IRName");
1166     StringRef IRNameMask = R->getValueAsString("IRNameMask");
1167     unsigned NF = R->getValueAsInt("NF");
1168 
1169     StringRef HeaderCodeStr = R->getValueAsString("HeaderCode");
1170     bool HasAutoDef = HeaderCodeStr.empty();
1171     if (!HeaderCodeStr.empty()) {
1172       HeaderCode += HeaderCodeStr.str();
1173     }
1174     // Parse prototype and create a list of primitive type with transformers
1175     // (operand) in ProtoSeq. ProtoSeq[0] is output operand.
1176     SmallVector<std::string> ProtoSeq;
1177     parsePrototypes(Prototypes, [&ProtoSeq](StringRef Proto) {
1178       ProtoSeq.push_back(Proto.str());
1179     });
1180 
1181     // Compute Builtin types
1182     SmallVector<std::string> ProtoMaskSeq = ProtoSeq;
1183     if (HasMask) {
1184       // If HasMaskedOffOperand, insert result type as first input operand.
1185       if (HasMaskedOffOperand) {
1186         if (NF == 1) {
1187           ProtoMaskSeq.insert(ProtoMaskSeq.begin() + 1, ProtoSeq[0]);
1188         } else {
1189           // Convert
1190           // (void, op0 address, op1 address, ...)
1191           // to
1192           // (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...)
1193           for (unsigned I = 0; I < NF; ++I)
1194             ProtoMaskSeq.insert(
1195                 ProtoMaskSeq.begin() + NF + 1,
1196                 ProtoSeq[1].substr(1)); // Use substr(1) to skip '*'
1197         }
1198       }
1199       if (HasMaskedOffOperand && NF > 1) {
1200         // Convert
1201         // (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...)
1202         // to
1203         // (void, op0 address, op1 address, ..., mask, maskedoff0, maskedoff1,
1204         // ...)
1205         ProtoMaskSeq.insert(ProtoMaskSeq.begin() + NF + 1, "m");
1206       } else {
1207         // If HasMask, insert 'm' as first input operand.
1208         ProtoMaskSeq.insert(ProtoMaskSeq.begin() + 1, "m");
1209       }
1210     }
1211     // If HasVL, append 'z' to last operand
1212     if (HasVL) {
1213       ProtoSeq.push_back("z");
1214       ProtoMaskSeq.push_back("z");
1215     }
1216 
1217     // Create Intrinsics for each type and LMUL.
1218     for (char I : TypeRange) {
1219       for (int Log2LMUL : Log2LMULList) {
1220         Optional<RVVTypes> Types = computeTypes(I, Log2LMUL, NF, ProtoSeq);
1221         // Ignored to create new intrinsic if there are any illegal types.
1222         if (!Types.hasValue())
1223           continue;
1224 
1225         auto SuffixStr = getSuffixStr(I, Log2LMUL, SuffixProto);
1226         auto MangledSuffixStr = getSuffixStr(I, Log2LMUL, MangledSuffixProto);
1227         // Create a non-mask intrinsic
1228         Out.push_back(std::make_unique<RVVIntrinsic>(
1229             Name, SuffixStr, MangledName, MangledSuffixStr, IRName,
1230             /*IsMask=*/false, /*HasMaskedOffOperand=*/false, HasVL, HasPolicy,
1231             HasNoMaskedOverloaded, HasAutoDef, ManualCodegen, Types.getValue(),
1232             IntrinsicTypes, RequiredFeatures, NF));
1233         if (HasMask) {
1234           // Create a mask intrinsic
1235           Optional<RVVTypes> MaskTypes =
1236               computeTypes(I, Log2LMUL, NF, ProtoMaskSeq);
1237           Out.push_back(std::make_unique<RVVIntrinsic>(
1238               Name, SuffixStr, MangledName, MangledSuffixStr, IRNameMask,
1239               /*IsMask=*/true, HasMaskedOffOperand, HasVL, HasPolicy,
1240               HasNoMaskedOverloaded, HasAutoDef, ManualCodegenMask,
1241               MaskTypes.getValue(), IntrinsicTypes, RequiredFeatures, NF));
1242         }
1243       } // end for Log2LMULList
1244     }   // end for TypeRange
1245   }
1246 }
1247 
1248 void RVVEmitter::createRVVHeaders(raw_ostream &OS) {
1249   std::vector<Record *> RVVHeaders =
1250       Records.getAllDerivedDefinitions("RVVHeader");
1251   for (auto *R : RVVHeaders) {
1252     StringRef HeaderCodeStr = R->getValueAsString("HeaderCode");
1253     OS << HeaderCodeStr.str();
1254   }
1255 }
1256 
1257 Optional<RVVTypes>
1258 RVVEmitter::computeTypes(BasicType BT, int Log2LMUL, unsigned NF,
1259                          ArrayRef<std::string> PrototypeSeq) {
1260   // LMUL x NF must be less than or equal to 8.
1261   if ((Log2LMUL >= 1) && (1 << Log2LMUL) * NF > 8)
1262     return llvm::None;
1263 
1264   RVVTypes Types;
1265   for (const std::string &Proto : PrototypeSeq) {
1266     auto T = computeType(BT, Log2LMUL, Proto);
1267     if (!T.hasValue())
1268       return llvm::None;
1269     // Record legal type index
1270     Types.push_back(T.getValue());
1271   }
1272   return Types;
1273 }
1274 
1275 Optional<RVVTypePtr> RVVEmitter::computeType(BasicType BT, int Log2LMUL,
1276                                              StringRef Proto) {
1277   std::string Idx = Twine(Twine(BT) + Twine(Log2LMUL) + Proto).str();
1278   // Search first
1279   auto It = LegalTypes.find(Idx);
1280   if (It != LegalTypes.end())
1281     return &(It->second);
1282   if (IllegalTypes.count(Idx))
1283     return llvm::None;
1284   // Compute type and record the result.
1285   RVVType T(BT, Log2LMUL, Proto);
1286   if (T.isValid()) {
1287     // Record legal type index and value.
1288     LegalTypes.insert({Idx, T});
1289     return &(LegalTypes[Idx]);
1290   }
1291   // Record illegal type index.
1292   IllegalTypes.insert(Idx);
1293   return llvm::None;
1294 }
1295 
1296 void RVVEmitter::emitArchMacroAndBody(
1297     std::vector<std::unique_ptr<RVVIntrinsic>> &Defs, raw_ostream &OS,
1298     std::function<void(raw_ostream &, const RVVIntrinsic &)> PrintBody) {
1299   RISCVPredefinedMacroT PrevMacros =
1300       (*Defs.begin())->getRISCVPredefinedMacros();
1301   bool NeedEndif = emitMacroRestrictionStr(PrevMacros, OS);
1302   for (auto &Def : Defs) {
1303     RISCVPredefinedMacroT CurMacros = Def->getRISCVPredefinedMacros();
1304     if (CurMacros != PrevMacros) {
1305       if (NeedEndif)
1306         OS << "#endif\n\n";
1307       NeedEndif = emitMacroRestrictionStr(CurMacros, OS);
1308       PrevMacros = CurMacros;
1309     }
1310     if (Def->hasAutoDef())
1311       PrintBody(OS, *Def);
1312   }
1313   if (NeedEndif)
1314     OS << "#endif\n\n";
1315 }
1316 
1317 bool RVVEmitter::emitMacroRestrictionStr(RISCVPredefinedMacroT PredefinedMacros,
1318                                          raw_ostream &OS) {
1319   if (PredefinedMacros == RISCVPredefinedMacro::Basic)
1320     return false;
1321   OS << "#if ";
1322   ListSeparator LS(" && ");
1323   if (PredefinedMacros & RISCVPredefinedMacro::V)
1324     OS << LS << "defined(__riscv_v)";
1325   if (PredefinedMacros & RISCVPredefinedMacro::Zfh)
1326     OS << LS << "defined(__riscv_zfh)";
1327   if (PredefinedMacros & RISCVPredefinedMacro::RV64)
1328     OS << LS << "(__riscv_xlen == 64)";
1329   if (PredefinedMacros & RISCVPredefinedMacro::VectorMaxELen64)
1330     OS << LS << "(__riscv_v_elen >= 64)";
1331   if (PredefinedMacros & RISCVPredefinedMacro::VectorMaxELenFp32)
1332     OS << LS << "(__riscv_v_elen_fp >= 32)";
1333   if (PredefinedMacros & RISCVPredefinedMacro::VectorMaxELenFp64)
1334     OS << LS << "(__riscv_v_elen_fp >= 64)";
1335   OS << "\n";
1336   return true;
1337 }
1338 
1339 namespace clang {
1340 void EmitRVVHeader(RecordKeeper &Records, raw_ostream &OS) {
1341   RVVEmitter(Records).createHeader(OS);
1342 }
1343 
1344 void EmitRVVBuiltins(RecordKeeper &Records, raw_ostream &OS) {
1345   RVVEmitter(Records).createBuiltins(OS);
1346 }
1347 
1348 void EmitRVVBuiltinCG(RecordKeeper &Records, raw_ostream &OS) {
1349   RVVEmitter(Records).createCodeGen(OS);
1350 }
1351 
1352 } // End namespace clang
1353