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 and
10 // riscv_vector_generic.h, which includes a declaration and definition of each
11 // intrinsic fucntions specified 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 class LMULType {
35 private:
36   int Log2LMUL;
37 
38 public:
39   LMULType(int Log2LMUL);
40   // Return the C/C++ string representation of LMUL
41   std::string str() const;
42   Optional<unsigned> getScale(unsigned ElementBitwidth) const;
43   LMULType &operator*=(unsigned RHS);
44 };
45 
46 // This class is compact representation of a valid and invalid RVVType.
47 class RVVType {
48   enum ScalarTypeKind : uint32_t {
49     Void,
50     Size_t,
51     Ptrdiff_t,
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 buitlin 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() const { return ShortStr; }
93 
94   bool isValid() const { return Valid; }
95   bool isScalar() const { return Scale.hasValue() && Scale.getValue() == 0; }
96   bool isVector() const { return Scale.hasValue() && Scale.getValue() != 0; }
97   bool isFloat() const { return ScalarType == ScalarTypeKind::Float; }
98   bool isSignedInteger() const {
99     return ScalarType == ScalarTypeKind::SignedInteger;
100   }
101   bool isFloatVector(unsigned Width) const {
102     return isVector() && isFloat() && ElementBitwidth == Width;
103   }
104 
105 private:
106   // Verify RVV vector type and set Valid.
107   bool verifyType() const;
108 
109   // Creates a type based on basic types of TypeRange
110   void applyBasicType();
111 
112   // Applies a prototype modifier to the current type. The result maybe an
113   // invalid type.
114   void applyModifier(StringRef prototype);
115 
116   // Compute and record a string for legal type.
117   void initBuiltinStr();
118   // Compute and record a builtin RVV vector type string.
119   void initClangBuiltinStr();
120   // Compute and record a type string for used in the header.
121   void initTypeStr();
122   // Compute and record a short name of a type for C/C++ name suffix.
123   void initShortStr();
124 };
125 
126 using RVVTypePtr = RVVType *;
127 using RVVTypes = std::vector<RVVTypePtr>;
128 
129 enum RISCVExtension : uint8_t {
130   Basic = 0,
131   F = 1 << 1,
132   D = 1 << 2,
133   Zfh = 1 << 3
134 };
135 
136 // TODO refactor RVVIntrinsic class design after support all intrinsic
137 // combination. This represents an instantiation of an intrinsic with a
138 // particular type and prototype
139 class RVVIntrinsic {
140 
141 private:
142   std::string Name; // Builtin name
143   std::string MangledName;
144   std::string IRName;
145   bool HasSideEffects;
146   bool HasMaskedOffOperand;
147   bool HasVL;
148   bool HasGeneric;
149   bool HasAutoDef; // There is automiatic definition in header
150   std::string ManualCodegen;
151   RVVTypePtr OutputType; // Builtin output type
152   RVVTypes InputTypes;   // Builtin input types
153   // The types we use to obtain the specific LLVM intrinsic. They are index of
154   // InputTypes. -1 means the return type.
155   std::vector<int64_t> IntrinsicTypes;
156   // C/C++ intrinsic operand order is different to builtin operand order. Record
157   // the mapping of InputTypes index.
158   SmallVector<unsigned> CTypeOrder;
159   uint8_t RISCVExtensions = 0;
160 
161 public:
162   RVVIntrinsic(StringRef Name, StringRef Suffix, StringRef MangledName,
163                StringRef IRName, bool HasSideEffects, bool IsMask,
164                bool HasMaskedOffOperand, bool HasVL, bool HasGeneric,
165                bool HasAutoDef, StringRef ManualCodegen, const RVVTypes &Types,
166                const std::vector<int64_t> &IntrinsicTypes,
167                const std::vector<int64_t> &PermuteOperands);
168   ~RVVIntrinsic() = default;
169 
170   StringRef getName() const { return Name; }
171   StringRef getMangledName() const { return MangledName; }
172   bool hasSideEffects() const { return HasSideEffects; }
173   bool hasMaskedOffOperand() const { return HasMaskedOffOperand; }
174   bool hasVL() const { return HasVL; }
175   bool hasGeneric() const { return HasGeneric; }
176   bool hasManualCodegen() const { return !ManualCodegen.empty(); }
177   bool hasAutoDef() const { return HasAutoDef; }
178   size_t getNumOperand() const { return InputTypes.size(); }
179   StringRef getIRName() const { return IRName; }
180   uint8_t getRISCVExtensions() const { return RISCVExtensions; }
181 
182   // Return the type string for a BUILTIN() macro in Builtins.def.
183   std::string getBuiltinTypeStr() const;
184 
185   // Emit the code block for switch body in EmitRISCVBuiltinExpr, it should
186   // init the RVVIntrinsic ID and IntrinsicTypes.
187   void emitCodeGenSwitchBody(raw_ostream &o) const;
188 
189   // Emit the macros for mapping C/C++ intrinsic function to builtin functions.
190   void emitIntrinsicMacro(raw_ostream &o) const;
191 
192   // Emit the mangled function definition.
193   void emitMangledFuncDef(raw_ostream &o) const;
194 };
195 
196 class RVVEmitter {
197 private:
198   RecordKeeper &Records;
199   std::string HeaderCode;
200   // Concat BasicType, LMUL and Proto as key
201   StringMap<RVVType> LegalTypes;
202   StringSet<> IllegalTypes;
203 
204 public:
205   RVVEmitter(RecordKeeper &R) : Records(R) {}
206 
207   /// Emit riscv_vector.h
208   void createHeader(raw_ostream &o);
209 
210   /// Emit riscv_generic.h
211   void createGenericHeader(raw_ostream &o);
212 
213   /// Emit all the __builtin prototypes and code needed by Sema.
214   void createBuiltins(raw_ostream &o);
215 
216   /// Emit all the information needed to map builtin -> LLVM IR intrinsic.
217   void createCodeGen(raw_ostream &o);
218 
219 private:
220   /// Create all intrinsics and add them to \p Out
221   void createRVVIntrinsics(std::vector<std::unique_ptr<RVVIntrinsic>> &Out);
222   /// Compute output and input types by applying different config (basic type
223   /// and LMUL with type transformers). It also record result of type in legal
224   /// or illegal set to avoid compute the  same config again. The result maybe
225   /// have illegal RVVType.
226   Optional<RVVTypes> computeTypes(BasicType BT, int Log2LMUL,
227                                   ArrayRef<std::string> PrototypeSeq);
228   Optional<RVVTypePtr> computeType(BasicType BT, int Log2LMUL, StringRef Proto);
229 
230   /// Emit Acrh predecessor definitions and body
231   void emitArchMacroAndBody(
232       std::vector<std::unique_ptr<RVVIntrinsic>> &Defs, raw_ostream &o,
233       std::function<void(raw_ostream &, const RVVIntrinsic &)>);
234 
235   // Emit the architecture preprocessor definitions. Return true when emits
236   // non-empty string.
237   bool emitExtDefStr(uint8_t Extensions, raw_ostream &o);
238 };
239 
240 } // namespace
241 
242 //===----------------------------------------------------------------------===//
243 // Type implementation
244 //===----------------------------------------------------------------------===//
245 
246 LMULType::LMULType(int NewLog2LMUL) {
247   // Check Log2LMUL is -3, -2, -1, 0, 1, 2, 3
248   assert(NewLog2LMUL <= 3 && NewLog2LMUL >= -3 && "Bad LMUL number!");
249   Log2LMUL = NewLog2LMUL;
250 }
251 
252 std::string LMULType::str() const {
253   if (Log2LMUL < 0)
254     return "mf" + utostr(1ULL << (-Log2LMUL));
255   return "m" + utostr(1ULL << Log2LMUL);
256 }
257 
258 VScaleVal LMULType::getScale(unsigned ElementBitwidth) const {
259   int Log2ScaleResult = 0;
260   switch (ElementBitwidth) {
261   default:
262     break;
263   case 8:
264     Log2ScaleResult = Log2LMUL + 3;
265     break;
266   case 16:
267     Log2ScaleResult = Log2LMUL + 2;
268     break;
269   case 32:
270     Log2ScaleResult = Log2LMUL + 1;
271     break;
272   case 64:
273     Log2ScaleResult = Log2LMUL;
274     break;
275   }
276   // Illegal vscale result would be less than 1
277   if (Log2ScaleResult < 0)
278     return None;
279   return 1 << Log2ScaleResult;
280 }
281 
282 LMULType &LMULType::operator*=(uint32_t RHS) {
283   assert(isPowerOf2_32(RHS));
284   this->Log2LMUL = this->Log2LMUL + Log2_32(RHS);
285   return *this;
286 }
287 
288 RVVType::RVVType(BasicType BT, int Log2LMUL, StringRef prototype)
289     : BT(BT), LMUL(LMULType(Log2LMUL)) {
290   applyBasicType();
291   applyModifier(prototype);
292   Valid = verifyType();
293   if (Valid) {
294     initBuiltinStr();
295     initTypeStr();
296     if (isVector()) {
297       initClangBuiltinStr();
298       initShortStr();
299     }
300   }
301 }
302 
303 // clang-format off
304 // boolean type are encoded the ratio of n (SEW/LMUL)
305 // SEW/LMUL | 1         | 2         | 4         | 8        | 16        | 32        | 64
306 // c type   | vbool64_t | vbool32_t | vbool16_t | vbool8_t | vbool4_t  | vbool2_t  | vbool1_t
307 // IR type  | nxv1i1    | nxv2i1    | nxv4i1    | nxv8i1   | nxv16i1   | nxv32i1   | nxv64i1
308 
309 // type\lmul | 1/8    | 1/4      | 1/2     | 1       | 2        | 4        | 8
310 // --------  |------  | -------- | ------- | ------- | -------- | -------- | --------
311 // i64       | N/A    | N/A      | N/A     | nxv1i64 | nxv2i64  | nxv4i64  | nxv8i64
312 // i32       | N/A    | N/A      | nxv1i32 | nxv2i32 | nxv4i32  | nxv8i32  | nxv16i32
313 // i16       | N/A    | nxv1i16  | nxv2i16 | nxv4i16 | nxv8i16  | nxv16i16 | nxv32i16
314 // i8        | nxv1i8 | nxv2i8   | nxv4i8  | nxv8i8  | nxv16i8  | nxv32i8  | nxv64i8
315 // double    | N/A    | N/A      | N/A     | nxv1f64 | nxv2f64  | nxv4f64  | nxv8f64
316 // float     | N/A    | N/A      | nxv1f32 | nxv2f32 | nxv4f32  | nxv8f32  | nxv16f32
317 // half      | N/A    | nxv1f16  | nxv2f16 | nxv4f16 | nxv8f16  | nxv16f16 | nxv32f16
318 // clang-format on
319 
320 bool RVVType::verifyType() const {
321   if (isScalar())
322     return true;
323   if (!Scale.hasValue())
324     return false;
325   if (isFloat() && ElementBitwidth == 8)
326     return false;
327   unsigned V = Scale.getValue();
328   switch (ElementBitwidth) {
329   case 1:
330   case 8:
331     // Check Scale is 1,2,4,8,16,32,64
332     return (V <= 64 && isPowerOf2_32(V));
333   case 16:
334     // Check Scale is 1,2,4,8,16,32
335     return (V <= 32 && isPowerOf2_32(V));
336   case 32:
337     // Check Scale is 1,2,4,8,16
338     return (V <= 16 && isPowerOf2_32(V));
339   case 64:
340     // Check Scale is 1,2,4,8
341     return (V <= 8 && isPowerOf2_32(V));
342   }
343   return false;
344 }
345 
346 void RVVType::initBuiltinStr() {
347   assert(isValid() && "RVVType is invalid");
348   switch (ScalarType) {
349   case ScalarTypeKind::Void:
350     BuiltinStr = "v";
351     return;
352   case ScalarTypeKind::Size_t:
353     BuiltinStr = "z";
354     if (IsImmediate)
355       BuiltinStr = "I" + BuiltinStr;
356     return;
357   case ScalarTypeKind::Ptrdiff_t:
358     BuiltinStr = "Y";
359     return;
360   case ScalarTypeKind::Boolean:
361     assert(ElementBitwidth == 1);
362     BuiltinStr += "b";
363     break;
364   case ScalarTypeKind::SignedInteger:
365   case ScalarTypeKind::UnsignedInteger:
366     switch (ElementBitwidth) {
367     case 8:
368       BuiltinStr += "c";
369       break;
370     case 16:
371       BuiltinStr += "s";
372       break;
373     case 32:
374       BuiltinStr += "i";
375       break;
376     case 64:
377       BuiltinStr += "Wi";
378       break;
379     default:
380       llvm_unreachable("Unhandled ElementBitwidth!");
381     }
382     if (isSignedInteger())
383       BuiltinStr = "S" + BuiltinStr;
384     else
385       BuiltinStr = "U" + BuiltinStr;
386     break;
387   case ScalarTypeKind::Float:
388     switch (ElementBitwidth) {
389     case 16:
390       BuiltinStr += "h";
391       break;
392     case 32:
393       BuiltinStr += "f";
394       break;
395     case 64:
396       BuiltinStr += "d";
397       break;
398     default:
399       llvm_unreachable("Unhandled ElementBitwidth!");
400     }
401     break;
402   default:
403     llvm_unreachable("ScalarType is invalid!");
404   }
405   if (IsImmediate)
406     BuiltinStr = "I" + BuiltinStr;
407   if (isScalar()) {
408     if (IsConstant)
409       BuiltinStr += "C";
410     if (IsPointer)
411       BuiltinStr += "*";
412     return;
413   }
414   BuiltinStr = "q" + utostr(Scale.getValue()) + BuiltinStr;
415 }
416 
417 void RVVType::initClangBuiltinStr() {
418   assert(isValid() && "RVVType is invalid");
419   assert(isVector() && "Handle Vector type only");
420 
421   ClangBuiltinStr = "__rvv_";
422   switch (ScalarType) {
423   case ScalarTypeKind::Boolean:
424     ClangBuiltinStr += "bool" + utostr(64 / Scale.getValue()) + "_t";
425     return;
426   case ScalarTypeKind::Float:
427     ClangBuiltinStr += "float";
428     break;
429   case ScalarTypeKind::SignedInteger:
430     ClangBuiltinStr += "int";
431     break;
432   case ScalarTypeKind::UnsignedInteger:
433     ClangBuiltinStr += "uint";
434     break;
435   default:
436     llvm_unreachable("ScalarTypeKind is invalid");
437   }
438   ClangBuiltinStr += utostr(ElementBitwidth) + LMUL.str() + "_t";
439 }
440 
441 void RVVType::initTypeStr() {
442   assert(isValid() && "RVVType is invalid");
443 
444   if (IsConstant)
445     Str += "const ";
446 
447   auto getTypeString = [&](StringRef TypeStr) {
448     if (isScalar())
449       return Twine(TypeStr + Twine(ElementBitwidth) + "_t").str();
450     return Twine("v" + TypeStr + Twine(ElementBitwidth) + LMUL.str() + "_t")
451         .str();
452   };
453 
454   switch (ScalarType) {
455   case ScalarTypeKind::Void:
456     Str = "void";
457     return;
458   case ScalarTypeKind::Size_t:
459     Str = "size_t";
460     return;
461   case ScalarTypeKind::Ptrdiff_t:
462     Str = "ptrdiff_t";
463     return;
464   case ScalarTypeKind::Boolean:
465     if (isScalar())
466       Str += "bool";
467     else
468       // Vector bool is special case, the formulate is
469       // `vbool<N>_t = MVT::nxv<64/N>i1` ex. vbool16_t = MVT::4i1
470       Str += "vbool" + utostr(64 / Scale.getValue()) + "_t";
471     break;
472   case ScalarTypeKind::Float:
473     if (isScalar()) {
474       if (ElementBitwidth == 64)
475         Str += "double";
476       else if (ElementBitwidth == 32)
477         Str += "float";
478       assert((ElementBitwidth == 32 || ElementBitwidth == 64) &&
479              "Unhandled floating type");
480     } else
481       Str += getTypeString("float");
482     break;
483   case ScalarTypeKind::SignedInteger:
484     Str += getTypeString("int");
485     break;
486   case ScalarTypeKind::UnsignedInteger:
487     Str += getTypeString("uint");
488     break;
489   default:
490     llvm_unreachable("ScalarType is invalid!");
491   }
492   if (IsPointer)
493     Str += " *";
494 }
495 
496 void RVVType::initShortStr() {
497   assert(isVector() && "only handle vector type");
498   switch (ScalarType) {
499   case ScalarTypeKind::Boolean:
500     ShortStr = "b" + utostr(64 / Scale.getValue());
501     break;
502   case ScalarTypeKind::Float:
503     ShortStr = "f" + utostr(ElementBitwidth) + LMUL.str();
504     break;
505   case ScalarTypeKind::SignedInteger:
506     ShortStr = "i" + utostr(ElementBitwidth) + LMUL.str();
507     break;
508   case ScalarTypeKind::UnsignedInteger:
509     ShortStr = "u" + utostr(ElementBitwidth) + LMUL.str();
510     break;
511   default:
512     llvm_unreachable("Unhandled case!");
513   }
514 }
515 
516 void RVVType::applyBasicType() {
517   switch (BT) {
518   case 'c':
519     ElementBitwidth = 8;
520     ScalarType = ScalarTypeKind::SignedInteger;
521     break;
522   case 's':
523     ElementBitwidth = 16;
524     ScalarType = ScalarTypeKind::SignedInteger;
525     break;
526   case 'i':
527     ElementBitwidth = 32;
528     ScalarType = ScalarTypeKind::SignedInteger;
529     break;
530   case 'l':
531     ElementBitwidth = 64;
532     ScalarType = ScalarTypeKind::SignedInteger;
533     break;
534   case 'h':
535     ElementBitwidth = 16;
536     ScalarType = ScalarTypeKind::Float;
537     break;
538   case 'f':
539     ElementBitwidth = 32;
540     ScalarType = ScalarTypeKind::Float;
541     break;
542   case 'd':
543     ElementBitwidth = 64;
544     ScalarType = ScalarTypeKind::Float;
545     break;
546   default:
547     PrintFatalError("Unhandled type code!");
548   }
549   assert(ElementBitwidth != 0 && "Bad element bitwidth!");
550 }
551 
552 void RVVType::applyModifier(StringRef Transformer) {
553   if (Transformer.empty())
554     return;
555   // Handle primitive type transformer
556   switch (Transformer.back()) {
557   case 'e':
558     Scale = 0;
559     break;
560   case 'v':
561     Scale = LMUL.getScale(ElementBitwidth);
562     break;
563   case 'w':
564     ElementBitwidth *= 2;
565     LMUL *= 2;
566     Scale = LMUL.getScale(ElementBitwidth);
567     break;
568   case 'q':
569     ElementBitwidth *= 4;
570     LMUL *= 4;
571     Scale = LMUL.getScale(ElementBitwidth);
572     break;
573   case 'o':
574     ElementBitwidth *= 8;
575     LMUL *= 8;
576     Scale = LMUL.getScale(ElementBitwidth);
577     break;
578   case 'm':
579     ScalarType = ScalarTypeKind::Boolean;
580     Scale = LMUL.getScale(ElementBitwidth);
581     ElementBitwidth = 1;
582     break;
583   case '0':
584     ScalarType = ScalarTypeKind::Void;
585     break;
586   case 'z':
587     ScalarType = ScalarTypeKind::Size_t;
588     break;
589   case 't':
590     ScalarType = ScalarTypeKind::Ptrdiff_t;
591     break;
592   case 'c': // uint8_t
593     ScalarType = ScalarTypeKind::UnsignedInteger;
594     ElementBitwidth = 8;
595     Scale = 0;
596     break;
597   default:
598     PrintFatalError("Illegal primitive type transformers!");
599   }
600   Transformer = Transformer.drop_back();
601 
602   // Compute type transformers
603   for (char I : Transformer) {
604     switch (I) {
605     case 'P':
606       if (IsConstant)
607         PrintFatalError("'P' transformer cannot be used after 'C'");
608       if (IsPointer)
609         PrintFatalError("'P' transformer cannot be used twice");
610       IsPointer = true;
611       break;
612     case 'C':
613       if (IsConstant)
614         PrintFatalError("'C' transformer cannot be used twice");
615       IsConstant = true;
616       break;
617     case 'K':
618       IsImmediate = true;
619       break;
620     case 'U':
621       ScalarType = ScalarTypeKind::UnsignedInteger;
622       break;
623     case 'I':
624       ScalarType = ScalarTypeKind::SignedInteger;
625       break;
626     case 'F':
627       ScalarType = ScalarTypeKind::Float;
628       break;
629     case 'S':
630       LMUL = LMULType(0);
631       // Update ElementBitwidth need to update Scale too.
632       Scale = LMUL.getScale(ElementBitwidth);
633       break;
634     default:
635       PrintFatalError("Illegal non-primitive type transformer!");
636     }
637   }
638 }
639 
640 //===----------------------------------------------------------------------===//
641 // RVVIntrinsic implementation
642 //===----------------------------------------------------------------------===//
643 RVVIntrinsic::RVVIntrinsic(StringRef NewName, StringRef Suffix,
644                            StringRef NewMangledName, StringRef IRName,
645                            bool HasSideEffects, bool IsMask,
646                            bool HasMaskedOffOperand, bool HasVL,
647                            bool HasGeneric, bool HasAutoDef,
648                            StringRef ManualCodegen, const RVVTypes &OutInTypes,
649                            const std::vector<int64_t> &NewIntrinsicTypes,
650                            const std::vector<int64_t> &PermuteOperands)
651     : IRName(IRName), HasSideEffects(HasSideEffects),
652       HasMaskedOffOperand(HasMaskedOffOperand), HasVL(HasVL),
653       HasGeneric(HasGeneric), HasAutoDef(HasAutoDef),
654       ManualCodegen(ManualCodegen.str()) {
655 
656   // Init Name and MangledName
657   Name = NewName.str();
658   if (NewMangledName.empty())
659     MangledName = NewName.split("_").first.str();
660   else
661     MangledName = NewMangledName.str();
662   if (!Suffix.empty())
663     Name += "_" + Suffix.str();
664   if (IsMask) {
665     Name += "_m";
666     MangledName += "_m";
667   }
668   // Init RISC-V extensions
669   for (const auto &T : OutInTypes) {
670     if (T->isFloatVector(16))
671       RISCVExtensions |= RISCVExtension::Zfh;
672     else if (T->isFloatVector(32))
673       RISCVExtensions |= RISCVExtension::F;
674     else if (T->isFloatVector(64))
675       RISCVExtensions |= RISCVExtension::D;
676   }
677 
678   // Init OutputType and InputTypes
679   OutputType = OutInTypes[0];
680   InputTypes.assign(OutInTypes.begin() + 1, OutInTypes.end());
681   CTypeOrder.resize(InputTypes.size());
682   std::iota(CTypeOrder.begin(), CTypeOrder.end(), 0);
683   // Update default order if we need permutate.
684   if (!PermuteOperands.empty()) {
685     // PermuteOperands is nonmasked version index. Update index when there is
686     // maskedoff operand which is always in first operand.
687 
688     unsigned Skew = HasMaskedOffOperand ? 1 : 0;
689     for (unsigned i = 0; i < PermuteOperands.size(); ++i) {
690       if (i != PermuteOperands[i])
691         CTypeOrder[i] = PermuteOperands[i] + Skew;
692     }
693     // Verify the result of CTypeOrder has legal value.
694     if (*std::max_element(CTypeOrder.begin(), CTypeOrder.end()) >=
695         CTypeOrder.size())
696       PrintFatalError(
697           "The index of PermuteOperand is bigger than the operand number");
698     SmallSet<unsigned, 8> Seen;
699     for (auto Idx : CTypeOrder) {
700       if (!Seen.insert(Idx).second)
701         PrintFatalError(
702             "The different element in PermuteOperand could not be equal");
703     }
704   }
705 
706   if (IsMask) {
707     if (HasVL)
708       // Builtin type order: op0, op1, ..., mask, vl
709       // C type order: mask, op0, op1, ..., vl
710       std::rotate(CTypeOrder.begin(), CTypeOrder.end() - 2,
711                   CTypeOrder.end() - 1);
712     else
713       // Builtin type order: op0, op1, ..., mask
714       // C type order: mask, op0, op1, ...,
715       std::rotate(CTypeOrder.begin(), CTypeOrder.end() - 1, CTypeOrder.end());
716   }
717   // IntrinsicTypes is nonmasked version index. Need to update it
718   // if there is maskedoff operand (It is always in first operand).
719   IntrinsicTypes = NewIntrinsicTypes;
720   if (IsMask && HasMaskedOffOperand) {
721     for (auto &I : IntrinsicTypes) {
722       if (I >= 0)
723         I += 1;
724     }
725   }
726 }
727 
728 std::string RVVIntrinsic::getBuiltinTypeStr() const {
729   std::string S;
730   S += OutputType->getBuiltinStr();
731   for (const auto &T : InputTypes) {
732     S += T->getBuiltinStr();
733   }
734   return S;
735 }
736 
737 void RVVIntrinsic::emitCodeGenSwitchBody(raw_ostream &OS) const {
738 
739   OS << "  ID = Intrinsic::riscv_" + getIRName() + ";\n";
740   if (hasManualCodegen()) {
741     OS << ManualCodegen;
742     OS << "break;\n";
743     return;
744   }
745   OS << "  IntrinsicTypes = {";
746   ListSeparator LS;
747   for (const auto &Idx : IntrinsicTypes) {
748     if (Idx == -1)
749       OS << LS << "ResultType";
750     else
751       OS << LS << "Ops[" << Idx << "]->getType()";
752   }
753 
754   // VL could be i64 or i32, need to encode it in IntrinsicTypes. VL is
755   // always last operand.
756   if (hasVL())
757     OS << ", Ops[" << getNumOperand() - 1 << "]->getType()";
758   OS << "};\n";
759   OS << "  break;\n";
760 }
761 
762 void RVVIntrinsic::emitIntrinsicMacro(raw_ostream &OS) const {
763   OS << "#define " << getName() << "(";
764   if (getNumOperand() > 0) {
765     ListSeparator LS;
766     for (const auto &I : CTypeOrder)
767       OS << LS << "op" << I;
768   }
769   OS << ") \\\n";
770   OS << "__builtin_rvv_" << getName() << "(";
771   if (getNumOperand() > 0) {
772     ListSeparator LS;
773     for (unsigned i = 0; i < InputTypes.size(); ++i)
774       OS << LS << "(" << InputTypes[i]->getTypeStr() << ")(op" << i << ")";
775   }
776   OS << ")\n";
777 }
778 
779 void RVVIntrinsic::emitMangledFuncDef(raw_ostream &OS) const {
780   OS << OutputType->getTypeStr() << " " << getMangledName() << "(";
781   // Emit function arguments
782   if (getNumOperand() > 0) {
783     ListSeparator LS;
784     for (unsigned i = 0; i < CTypeOrder.size(); ++i)
785       OS << LS << InputTypes[CTypeOrder[i]]->getTypeStr() << " op" << i;
786   }
787   OS << "){\n";
788   OS << "  return " << getName() << "(";
789   // Emit parameter variables
790   if (getNumOperand() > 0) {
791     ListSeparator LS;
792     for (unsigned i = 0; i < CTypeOrder.size(); ++i)
793       OS << LS << "op" << i;
794   }
795   OS << ");\n";
796   OS << "}\n\n";
797 }
798 
799 //===----------------------------------------------------------------------===//
800 // RVVEmitter implementation
801 //===----------------------------------------------------------------------===//
802 void RVVEmitter::createHeader(raw_ostream &OS) {
803 
804   OS << "/*===---- riscv_vector.h - RISC-V V-extension RVVIntrinsics "
805         "-------------------===\n"
806         " *\n"
807         " *\n"
808         " * Part of the LLVM Project, under the Apache License v2.0 with LLVM "
809         "Exceptions.\n"
810         " * See https://llvm.org/LICENSE.txt for license information.\n"
811         " * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n"
812         " *\n"
813         " *===-----------------------------------------------------------------"
814         "------===\n"
815         " */\n\n";
816 
817   OS << "#ifndef __RISCV_VECTOR_H\n";
818   OS << "#define __RISCV_VECTOR_H\n\n";
819 
820   OS << "#include <stdint.h>\n";
821   OS << "#include <stddef.h>\n\n";
822 
823   OS << "#ifndef __riscv_vector\n";
824   OS << "#error \"Vector intrinsics require the vector extension.\"\n";
825   OS << "#endif\n\n";
826 
827   OS << "#ifdef __cplusplus\n";
828   OS << "extern \"C\" {\n";
829   OS << "#endif\n\n";
830 
831   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
832   createRVVIntrinsics(Defs);
833 
834   // Print header code
835   if (!HeaderCode.empty()) {
836     OS << HeaderCode;
837   }
838 
839   auto printType = [&](auto T) {
840     OS << "typedef " << T->getClangBuiltinStr() << " " << T->getTypeStr()
841        << ";\n";
842   };
843 
844   constexpr int Log2LMULs[] = {-3, -2, -1, 0, 1, 2, 3};
845   // Print RVV boolean types.
846   for (int Log2LMUL : Log2LMULs) {
847     auto T = computeType('c', Log2LMUL, "m");
848     if (T.hasValue())
849       printType(T.getValue());
850   }
851   // Print RVV int/float types.
852   for (char I : StringRef("csil")) {
853     for (int Log2LMUL : Log2LMULs) {
854       auto T = computeType(I, Log2LMUL, "v");
855       if (T.hasValue()) {
856         printType(T.getValue());
857         auto UT = computeType(I, Log2LMUL, "Uv");
858         printType(UT.getValue());
859       }
860     }
861   }
862   OS << "#if defined(__riscv_zfh)\n";
863   for (int Log2LMUL : Log2LMULs) {
864     auto T = computeType('h', Log2LMUL, "v");
865     if (T.hasValue())
866       printType(T.getValue());
867   }
868   OS << "#endif\n";
869 
870   OS << "#if defined(__riscv_f)\n";
871   for (int Log2LMUL : Log2LMULs) {
872     auto T = computeType('f', Log2LMUL, "v");
873     if (T.hasValue())
874       printType(T.getValue());
875   }
876   OS << "#endif\n";
877 
878   OS << "#if defined(__riscv_d)\n";
879   for (int ELMul : Log2LMULs) {
880     auto T = computeType('d', ELMul, "v");
881     if (T.hasValue())
882       printType(T.getValue());
883   }
884   OS << "#endif\n\n";
885 
886   // Print intrinsic functions with macro
887   emitArchMacroAndBody(Defs, OS, [](raw_ostream &OS, const RVVIntrinsic &Inst) {
888     Inst.emitIntrinsicMacro(OS);
889   });
890 
891   OS << "\n#ifdef __cplusplus\n";
892   OS << "}\n";
893   OS << "#endif // __riscv_vector\n";
894   OS << "#endif // __RISCV_VECTOR_H\n";
895 }
896 
897 void RVVEmitter::createGenericHeader(raw_ostream &OS) {
898   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
899   createRVVIntrinsics(Defs);
900 
901   OS << "#include <riscv_vector.h>\n\n";
902   // Print intrinsic functions macro
903   emitArchMacroAndBody(Defs, OS, [](raw_ostream &OS, const RVVIntrinsic &Inst) {
904     if (!Inst.hasGeneric())
905       return;
906     OS << "static inline __attribute__((__always_inline__, __nodebug__, "
907           "__overloadable__))\n";
908     Inst.emitMangledFuncDef(OS);
909   });
910 }
911 
912 void RVVEmitter::createBuiltins(raw_ostream &OS) {
913   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
914   createRVVIntrinsics(Defs);
915 
916   OS << "#if defined(TARGET_BUILTIN) && !defined(RISCVV_BUILTIN)\n";
917   OS << "#define RISCVV_BUILTIN(ID, TYPE, ATTRS) TARGET_BUILTIN(ID, TYPE, "
918         "ATTRS, \"experimental-v\")\n";
919   OS << "#endif\n";
920   for (auto &Def : Defs) {
921     OS << "RISCVV_BUILTIN(__builtin_rvv_" << Def->getName() << ",\""
922        << Def->getBuiltinTypeStr() << "\", ";
923     if (!Def->hasSideEffects())
924       OS << "\"n\")\n";
925     else
926       OS << "\"\")\n";
927   }
928   OS << "#undef RISCVV_BUILTIN\n";
929 }
930 
931 void RVVEmitter::createCodeGen(raw_ostream &OS) {
932   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
933   createRVVIntrinsics(Defs);
934 
935   // The same intrinsic IR name has the same switch body.
936   std::stable_sort(Defs.begin(), Defs.end(),
937                    [](const std::unique_ptr<RVVIntrinsic> &A,
938                       const std::unique_ptr<RVVIntrinsic> &B) {
939                      return A->getIRName() < B->getIRName();
940                    });
941   // Print switch body when the ir name changes from previous iteration.
942   RVVIntrinsic *PrevDef = Defs.begin()->get();
943   for (auto &Def : Defs) {
944     StringRef CurIRName = Def->getIRName();
945     if (CurIRName != PrevDef->getIRName()) {
946       PrevDef->emitCodeGenSwitchBody(OS);
947     }
948     PrevDef = Def.get();
949     OS << "case RISCV::BI__builtin_rvv_" << Def->getName() << ":\n";
950   }
951   Defs.back()->emitCodeGenSwitchBody(OS);
952   OS << "\n";
953 }
954 
955 void RVVEmitter::createRVVIntrinsics(
956     std::vector<std::unique_ptr<RVVIntrinsic>> &Out) {
957   std::vector<Record *> RV = Records.getAllDerivedDefinitions("RVVBuiltin");
958   for (auto *R : RV) {
959     StringRef Name = R->getValueAsString("Name");
960     StringRef Suffix = R->getValueAsString("Suffix");
961     StringRef MangledName = R->getValueAsString("MangledName");
962     StringRef Prototypes = R->getValueAsString("Prototype");
963     StringRef TypeRange = R->getValueAsString("TypeRange");
964     bool HasMask = R->getValueAsBit("HasMask");
965     bool HasMaskedOffOperand = R->getValueAsBit("HasMaskedOffOperand");
966     bool HasVL = R->getValueAsBit("HasVL");
967     bool HasGeneric = R->getValueAsBit("HasGeneric");
968     bool HasSideEffects = R->getValueAsBit("HasSideEffects");
969     std::vector<int64_t> Log2LMULList = R->getValueAsListOfInts("Log2LMUL");
970     StringRef ManualCodegen = R->getValueAsString("ManualCodegen");
971     StringRef ManualCodegenMask = R->getValueAsString("ManualCodegenMask");
972     std::vector<int64_t> IntrinsicTypes =
973         R->getValueAsListOfInts("IntrinsicTypes");
974     std::vector<int64_t> PermuteOperands =
975         R->getValueAsListOfInts("PermuteOperands");
976     StringRef IRName = R->getValueAsString("IRName");
977     StringRef IRNameMask = R->getValueAsString("IRNameMask");
978 
979     StringRef HeaderCodeStr = R->getValueAsString("HeaderCode");
980     bool HasAutoDef = HeaderCodeStr.empty();
981     if (!HeaderCodeStr.empty()) {
982       HeaderCode += HeaderCodeStr.str();
983     }
984     // Parse prototype and create a list of primitive type with transformers
985     // (operand) in ProtoSeq. ProtoSeq[0] is output operand.
986     SmallVector<std::string, 8> ProtoSeq;
987     const StringRef Primaries("evwqom0ztc");
988     while (!Prototypes.empty()) {
989       auto Idx = Prototypes.find_first_of(Primaries);
990       assert(Idx != StringRef::npos);
991       ProtoSeq.push_back(Prototypes.slice(0, Idx + 1).str());
992       Prototypes = Prototypes.drop_front(Idx + 1);
993     }
994 
995     // Compute Builtin types
996     SmallVector<std::string, 8> ProtoMaskSeq = ProtoSeq;
997     if (HasMask) {
998       // If HasMask, append 'm' to last operand.
999       ProtoMaskSeq.push_back("m");
1000       // If HasMaskedOffOperand, insert result type as first input operand.
1001       if (HasMaskedOffOperand)
1002         ProtoMaskSeq.insert(ProtoMaskSeq.begin() + 1, ProtoSeq[0]);
1003     }
1004     // If HasVL, append 'z' to last operand
1005     if (HasVL) {
1006       ProtoSeq.push_back("z");
1007       ProtoMaskSeq.push_back("z");
1008     }
1009 
1010     // Create Intrinsics for each type and LMUL.
1011     for (char I : TypeRange) {
1012       for (int Log2LMUL : Log2LMULList) {
1013         Optional<RVVTypes> Types = computeTypes(I, Log2LMUL, ProtoSeq);
1014         // Ignored to create new intrinsic if there are any illegal types.
1015         if (!Types.hasValue())
1016           continue;
1017 
1018         auto SuffixStr =
1019             computeType(I, Log2LMUL, Suffix).getValue()->getShortStr();
1020         // Create a non-mask intrinsic
1021         Out.push_back(std::make_unique<RVVIntrinsic>(
1022             Name, SuffixStr, MangledName, IRName, HasSideEffects,
1023             /*IsMask=*/false, /*HasMaskedOffOperand=*/false, HasVL, HasGeneric,
1024             HasAutoDef, ManualCodegen, Types.getValue(), IntrinsicTypes,
1025             PermuteOperands));
1026         if (HasMask) {
1027           // Create a mask intrinsic
1028           Optional<RVVTypes> MaskTypes =
1029               computeTypes(I, Log2LMUL, ProtoMaskSeq);
1030           Out.push_back(std::make_unique<RVVIntrinsic>(
1031               Name, SuffixStr, MangledName, IRNameMask, HasSideEffects,
1032               /*IsMask=*/true, HasMaskedOffOperand, HasVL, HasGeneric,
1033               HasAutoDef, ManualCodegenMask, MaskTypes.getValue(),
1034               IntrinsicTypes, PermuteOperands));
1035         }
1036       } // end for Log2LMULList
1037     }   // end for TypeRange
1038   }
1039 }
1040 
1041 Optional<RVVTypes>
1042 RVVEmitter::computeTypes(BasicType BT, int Log2LMUL,
1043                          ArrayRef<std::string> PrototypeSeq) {
1044   RVVTypes Types;
1045   for (const std::string &Proto : PrototypeSeq) {
1046     auto T = computeType(BT, Log2LMUL, Proto);
1047     if (!T.hasValue())
1048       return llvm::None;
1049     // Record legal type index
1050     Types.push_back(T.getValue());
1051   }
1052   return Types;
1053 }
1054 
1055 Optional<RVVTypePtr> RVVEmitter::computeType(BasicType BT, int Log2LMUL,
1056                                              StringRef Proto) {
1057   std::string Idx = Twine(Twine(BT) + Twine(Log2LMUL) + Proto).str();
1058   // Search first
1059   auto It = LegalTypes.find(Idx);
1060   if (It != LegalTypes.end())
1061     return &(It->second);
1062   if (IllegalTypes.count(Idx))
1063     return llvm::None;
1064   // Compute type and record the result.
1065   RVVType T(BT, Log2LMUL, Proto);
1066   if (T.isValid()) {
1067     // Record legal type index and value.
1068     LegalTypes.insert({Idx, T});
1069     return &(LegalTypes[Idx]);
1070   }
1071   // Record illegal type index.
1072   IllegalTypes.insert(Idx);
1073   return llvm::None;
1074 }
1075 
1076 void RVVEmitter::emitArchMacroAndBody(
1077     std::vector<std::unique_ptr<RVVIntrinsic>> &Defs, raw_ostream &OS,
1078     std::function<void(raw_ostream &, const RVVIntrinsic &)> PrintBody) {
1079 
1080   // The same extension include in the same arch guard marco.
1081   std::stable_sort(Defs.begin(), Defs.end(),
1082                    [](const std::unique_ptr<RVVIntrinsic> &A,
1083                       const std::unique_ptr<RVVIntrinsic> &B) {
1084                      return A->getRISCVExtensions() < B->getRISCVExtensions();
1085                    });
1086   uint8_t PrevExt = (*Defs.begin())->getRISCVExtensions();
1087   bool NeedEndif = emitExtDefStr(PrevExt, OS);
1088   for (auto &Def : Defs) {
1089     uint8_t CurExt = Def->getRISCVExtensions();
1090     if (CurExt != PrevExt) {
1091       if (NeedEndif)
1092         OS << "#endif\n\n";
1093       NeedEndif = emitExtDefStr(CurExt, OS);
1094       PrevExt = CurExt;
1095     }
1096     if (Def->hasAutoDef())
1097       PrintBody(OS, *Def);
1098   }
1099   if (NeedEndif)
1100     OS << "#endif\n\n";
1101 }
1102 
1103 bool RVVEmitter::emitExtDefStr(uint8_t Extents, raw_ostream &OS) {
1104   if (Extents == RISCVExtension::Basic)
1105     return false;
1106   OS << "#if ";
1107   ListSeparator LS(" || ");
1108   if (Extents & RISCVExtension::F)
1109     OS << LS << "defined(__riscv_f)";
1110   if (Extents & RISCVExtension::D)
1111     OS << LS << "defined(__riscv_d)";
1112   if (Extents & RISCVExtension::Zfh)
1113     OS << LS << "defined(__riscv_zfh)";
1114   OS << "\n";
1115   return true;
1116 }
1117 
1118 namespace clang {
1119 void EmitRVVHeader(RecordKeeper &Records, raw_ostream &OS) {
1120   RVVEmitter(Records).createHeader(OS);
1121 }
1122 
1123 void EmitRVVGenericHeader(RecordKeeper &Records, raw_ostream &OS) {
1124   RVVEmitter(Records).createGenericHeader(OS);
1125 }
1126 
1127 void EmitRVVBuiltins(RecordKeeper &Records, raw_ostream &OS) {
1128   RVVEmitter(Records).createBuiltins(OS);
1129 }
1130 
1131 void EmitRVVBuiltinCG(RecordKeeper &Records, raw_ostream &OS) {
1132   RVVEmitter(Records).createCodeGen(OS);
1133 }
1134 
1135 } // End namespace clang
1136