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