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