xref: /llvm-project/clang/utils/TableGen/RISCVVEmitter.cpp (revision 05b3d26181ade32f5988d2be4939f605a5225782)
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 "clang/Support/RISCVVIntrinsicUtils.h"
18 #include "llvm/ADT/ArrayRef.h"
19 #include "llvm/ADT/StringExtras.h"
20 #include "llvm/ADT/StringMap.h"
21 #include "llvm/ADT/StringSwitch.h"
22 #include "llvm/ADT/Twine.h"
23 #include "llvm/TableGen/Error.h"
24 #include "llvm/TableGen/Record.h"
25 #include <optional>
26 
27 using namespace llvm;
28 using namespace clang::RISCV;
29 
30 namespace {
31 struct SemaRecord {
32   // Intrinsic name, e.g. vadd_vv
33   std::string Name;
34 
35   // Overloaded intrinsic name, could be empty if can be computed from Name
36   // e.g. vadd
37   std::string OverloadedName;
38 
39   // Supported type, mask of BasicType.
40   unsigned TypeRangeMask;
41 
42   // Supported LMUL.
43   unsigned Log2LMULMask;
44 
45   // Required extensions for this intrinsic.
46   uint32_t RequiredExtensions;
47 
48   // Prototype for this intrinsic.
49   SmallVector<PrototypeDescriptor> Prototype;
50 
51   // Suffix of intrinsic name.
52   SmallVector<PrototypeDescriptor> Suffix;
53 
54   // Suffix of overloaded intrinsic name.
55   SmallVector<PrototypeDescriptor> OverloadedSuffix;
56 
57   // Number of field, large than 1 if it's segment load/store.
58   unsigned NF;
59 
60   bool HasMasked :1;
61   bool HasVL :1;
62   bool HasMaskedOffOperand :1;
63   bool HasTailPolicy : 1;
64   bool HasMaskPolicy : 1;
65   bool HasFRMRoundModeOp : 1;
66   bool IsTuple : 1;
67   LLVM_PREFERRED_TYPE(PolicyScheme)
68   uint8_t UnMaskedPolicyScheme : 2;
69   LLVM_PREFERRED_TYPE(PolicyScheme)
70   uint8_t MaskedPolicyScheme : 2;
71 };
72 
73 // Compressed function signature table.
74 class SemaSignatureTable {
75 private:
76   std::vector<PrototypeDescriptor> SignatureTable;
77 
78   void insert(ArrayRef<PrototypeDescriptor> Signature);
79 
80 public:
81   static constexpr unsigned INVALID_INDEX = ~0U;
82 
83   // Create compressed signature table from SemaRecords.
84   void init(ArrayRef<SemaRecord> SemaRecords);
85 
86   // Query the Signature, return INVALID_INDEX if not found.
87   unsigned getIndex(ArrayRef<PrototypeDescriptor> Signature);
88 
89   /// Print signature table in RVVHeader Record to \p OS
90   void print(raw_ostream &OS);
91 };
92 
93 class RVVEmitter {
94 private:
95   const RecordKeeper &Records;
96   RVVTypeCache TypeCache;
97 
98 public:
99   RVVEmitter(const RecordKeeper &R) : Records(R) {}
100 
101   /// Emit riscv_vector.h
102   void createHeader(raw_ostream &o);
103 
104   /// Emit all the __builtin prototypes and code needed by Sema.
105   void createBuiltins(raw_ostream &o);
106 
107   /// Emit all the information needed to map builtin -> LLVM IR intrinsic.
108   void createCodeGen(raw_ostream &o);
109 
110   /// Emit all the information needed by SemaRISCVVectorLookup.cpp.
111   /// We've large number of intrinsic function for RVV, creating a customized
112   /// could speed up the compilation time.
113   void createSema(raw_ostream &o);
114 
115 private:
116   /// Create all intrinsics and add them to \p Out and SemaRecords.
117   void createRVVIntrinsics(std::vector<std::unique_ptr<RVVIntrinsic>> &Out,
118                            std::vector<SemaRecord> *SemaRecords = nullptr);
119   /// Create all intrinsic records and SemaSignatureTable from SemaRecords.
120   void createRVVIntrinsicRecords(std::vector<RVVIntrinsicRecord> &Out,
121                                  SemaSignatureTable &SST,
122                                  ArrayRef<SemaRecord> SemaRecords);
123 
124   /// Print HeaderCode in RVVHeader Record to \p Out
125   void printHeaderCode(raw_ostream &OS);
126 };
127 
128 } // namespace
129 
130 static BasicType ParseBasicType(char c) {
131   switch (c) {
132   case 'c':
133     return BasicType::Int8;
134     break;
135   case 's':
136     return BasicType::Int16;
137     break;
138   case 'i':
139     return BasicType::Int32;
140     break;
141   case 'l':
142     return BasicType::Int64;
143     break;
144   case 'x':
145     return BasicType::Float16;
146     break;
147   case 'f':
148     return BasicType::Float32;
149     break;
150   case 'd':
151     return BasicType::Float64;
152     break;
153   case 'y':
154     return BasicType::BFloat16;
155     break;
156   default:
157     return BasicType::Unknown;
158   }
159 }
160 
161 static VectorTypeModifier getTupleVTM(unsigned NF) {
162   assert(2 <= NF && NF <= 8 && "2 <= NF <= 8");
163   return static_cast<VectorTypeModifier>(
164       static_cast<uint8_t>(VectorTypeModifier::Tuple2) + (NF - 2));
165 }
166 
167 static unsigned getIndexedLoadStorePtrIdx(const RVVIntrinsic *RVVI) {
168   // We need a special rule for segment load/store since the data width is not
169   // encoded in the intrinsic name itself.
170   const StringRef IRName = RVVI->getIRName();
171   constexpr unsigned RVV_VTA = 0x1;
172   constexpr unsigned RVV_VMA = 0x2;
173 
174   if (IRName.starts_with("vloxseg") || IRName.starts_with("vluxseg")) {
175     bool NoPassthru =
176         (RVVI->isMasked() && (RVVI->getPolicyAttrsBits() & RVV_VTA) &&
177          (RVVI->getPolicyAttrsBits() & RVV_VMA)) ||
178         (!RVVI->isMasked() && (RVVI->getPolicyAttrsBits() & RVV_VTA));
179     return RVVI->isMasked() ? NoPassthru ? 1 : 2 : NoPassthru ? 0 : 1;
180   }
181   if (IRName.starts_with("vsoxseg") || IRName.starts_with("vsuxseg"))
182     return RVVI->isMasked() ? 1 : 0;
183 
184   return (unsigned)-1;
185 }
186 
187 // This function is used to get the log2SEW of each segment load/store, this
188 // prevent to add a member to RVVIntrinsic.
189 static unsigned getSegInstLog2SEW(StringRef InstName) {
190   // clang-format off
191   // We need a special rule for indexed segment load/store since the data width
192   // is not encoded in the intrinsic name itself.
193   if (InstName.starts_with("vloxseg") || InstName.starts_with("vluxseg") ||
194       InstName.starts_with("vsoxseg") || InstName.starts_with("vsuxseg"))
195     return (unsigned)-1;
196 
197 #define KEY_VAL(KEY, VAL) {#KEY, VAL}
198 #define KEY_VAL_ALL_W_POLICY(KEY, VAL) \
199   KEY_VAL(KEY, VAL),                   \
200   KEY_VAL(KEY ## _tu, VAL),            \
201   KEY_VAL(KEY ## _tum, VAL),           \
202   KEY_VAL(KEY ## _tumu, VAL),          \
203   KEY_VAL(KEY ## _mu, VAL)
204 
205 #define KEY_VAL_ALL_NF_BASE(MACRO_NAME, NAME, SEW, LOG2SEW, FF) \
206   MACRO_NAME(NAME ## 2e ## SEW ## FF, LOG2SEW), \
207   MACRO_NAME(NAME ## 3e ## SEW ## FF, LOG2SEW), \
208   MACRO_NAME(NAME ## 4e ## SEW ## FF, LOG2SEW), \
209   MACRO_NAME(NAME ## 5e ## SEW ## FF, LOG2SEW), \
210   MACRO_NAME(NAME ## 6e ## SEW ## FF, LOG2SEW), \
211   MACRO_NAME(NAME ## 7e ## SEW ## FF, LOG2SEW), \
212   MACRO_NAME(NAME ## 8e ## SEW ## FF, LOG2SEW)
213 
214 #define KEY_VAL_ALL_NF(NAME, SEW, LOG2SEW) \
215   KEY_VAL_ALL_NF_BASE(KEY_VAL_ALL_W_POLICY, NAME, SEW, LOG2SEW,)
216 
217 #define KEY_VAL_FF_ALL_NF(NAME, SEW, LOG2SEW) \
218   KEY_VAL_ALL_NF_BASE(KEY_VAL_ALL_W_POLICY, NAME, SEW, LOG2SEW, ff)
219 
220 #define KEY_VAL_ALL_NF_SEW_BASE(MACRO_NAME, NAME) \
221   MACRO_NAME(NAME, 8, 3),  \
222   MACRO_NAME(NAME, 16, 4), \
223   MACRO_NAME(NAME, 32, 5), \
224   MACRO_NAME(NAME, 64, 6)
225 
226 #define KEY_VAL_ALL_NF_SEW(NAME) \
227   KEY_VAL_ALL_NF_SEW_BASE(KEY_VAL_ALL_NF, NAME)
228 
229 #define KEY_VAL_FF_ALL_NF_SEW(NAME) \
230   KEY_VAL_ALL_NF_SEW_BASE(KEY_VAL_FF_ALL_NF, NAME)
231   // clang-format on
232 
233   static StringMap<unsigned> SegInsts = {
234       KEY_VAL_ALL_NF_SEW(vlseg), KEY_VAL_FF_ALL_NF_SEW(vlseg),
235       KEY_VAL_ALL_NF_SEW(vlsseg), KEY_VAL_ALL_NF_SEW(vsseg),
236       KEY_VAL_ALL_NF_SEW(vssseg)};
237 
238 #undef KEY_VAL_ALL_NF_SEW
239 #undef KEY_VAL_ALL_NF
240 #undef KEY_VAL
241 
242   return SegInsts.lookup(InstName);
243 }
244 
245 void emitCodeGenSwitchBody(const RVVIntrinsic *RVVI, raw_ostream &OS) {
246   if (!RVVI->getIRName().empty())
247     OS << "  ID = Intrinsic::riscv_" + RVVI->getIRName() + ";\n";
248 
249   OS << "  PolicyAttrs = " << RVVI->getPolicyAttrsBits() << ";\n";
250   OS << "  SegInstSEW = " << getSegInstLog2SEW(RVVI->getOverloadedName())
251      << ";\n";
252 
253   if (RVVI->hasManualCodegen()) {
254     OS << "IsMasked = " << (RVVI->isMasked() ? "true" : "false") << ";\n";
255 
256     // Skip the non-indexed load/store and compatible header load/store.
257     OS << "if (SegInstSEW == (unsigned)-1) {\n";
258     OS << "  auto PointeeType = E->getArg(" << getIndexedLoadStorePtrIdx(RVVI)
259        << "      )->getType()->getPointeeType();\n";
260     OS << "  SegInstSEW = "
261           "      llvm::Log2_64(getContext().getTypeSize(PointeeType));\n}\n";
262 
263     OS << RVVI->getManualCodegen();
264     OS << "break;\n";
265     return;
266   }
267 
268   for (const auto &I : enumerate(RVVI->getInputTypes())) {
269     if (I.value()->isPointer()) {
270       assert(RVVI->getIntrinsicTypes().front() == -1 &&
271              "RVVI should be vector load intrinsic.");
272     }
273   }
274 
275   if (RVVI->isMasked()) {
276     if (RVVI->hasVL()) {
277       OS << "  std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);\n";
278       if (RVVI->hasPolicyOperand())
279         OS << "  Ops.push_back(ConstantInt::get(Ops.back()->getType(),"
280               " PolicyAttrs));\n";
281       if (RVVI->hasMaskedOffOperand() && RVVI->getPolicyAttrs().isTAMAPolicy())
282         OS << "  Ops.insert(Ops.begin(), "
283               "llvm::PoisonValue::get(ResultType));\n";
284       // Masked reduction cases.
285       if (!RVVI->hasMaskedOffOperand() && RVVI->hasPassthruOperand() &&
286           RVVI->getPolicyAttrs().isTAMAPolicy())
287         OS << "  Ops.insert(Ops.begin(), "
288               "llvm::PoisonValue::get(ResultType));\n";
289     } else {
290       OS << "  std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end());\n";
291     }
292   } else {
293     if (RVVI->hasPolicyOperand())
294       OS << "  Ops.push_back(ConstantInt::get(Ops.back()->getType(), "
295             "PolicyAttrs));\n";
296     else if (RVVI->hasPassthruOperand() && RVVI->getPolicyAttrs().isTAPolicy())
297       OS << "  Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));\n";
298   }
299 
300   OS << "  IntrinsicTypes = {";
301   ListSeparator LS;
302   for (const auto &Idx : RVVI->getIntrinsicTypes()) {
303     if (Idx == -1)
304       OS << LS << "ResultType";
305     else
306       OS << LS << "Ops[" << Idx << "]->getType()";
307   }
308 
309   // VL could be i64 or i32, need to encode it in IntrinsicTypes. VL is
310   // always last operand.
311   if (RVVI->hasVL())
312     OS << ", Ops.back()->getType()";
313   OS << "};\n";
314   OS << "  break;\n";
315 }
316 
317 //===----------------------------------------------------------------------===//
318 // SemaSignatureTable implementation
319 //===----------------------------------------------------------------------===//
320 void SemaSignatureTable::init(ArrayRef<SemaRecord> SemaRecords) {
321   // Sort signature entries by length, let longer signature insert first, to
322   // make it more possible to reuse table entries, that can reduce ~10% table
323   // size.
324   struct Compare {
325     bool operator()(const SmallVector<PrototypeDescriptor> &A,
326                     const SmallVector<PrototypeDescriptor> &B) const {
327       if (A.size() != B.size())
328         return A.size() > B.size();
329 
330       size_t Len = A.size();
331       for (size_t i = 0; i < Len; ++i) {
332         if (A[i] != B[i])
333           return A[i] < B[i];
334       }
335 
336       return false;
337     }
338   };
339 
340   std::set<SmallVector<PrototypeDescriptor>, Compare> Signatures;
341   auto InsertToSignatureSet =
342       [&](const SmallVector<PrototypeDescriptor> &Signature) {
343         if (Signature.empty())
344           return;
345 
346         Signatures.insert(Signature);
347       };
348 
349   assert(!SemaRecords.empty());
350 
351   for (const SemaRecord &SR : SemaRecords) {
352     InsertToSignatureSet(SR.Prototype);
353     InsertToSignatureSet(SR.Suffix);
354     InsertToSignatureSet(SR.OverloadedSuffix);
355   }
356 
357   for (auto &Sig : Signatures)
358     insert(Sig);
359 }
360 
361 void SemaSignatureTable::insert(ArrayRef<PrototypeDescriptor> Signature) {
362   if (getIndex(Signature) != INVALID_INDEX)
363     return;
364 
365   // Insert Signature into SignatureTable if not found in the table.
366   SignatureTable.insert(SignatureTable.begin(), Signature.begin(),
367                         Signature.end());
368 }
369 
370 unsigned SemaSignatureTable::getIndex(ArrayRef<PrototypeDescriptor> Signature) {
371   // Empty signature could be point into any index since there is length
372   // field when we use, so just always point it to 0.
373   if (Signature.empty())
374     return 0;
375 
376   // Checking Signature already in table or not.
377   if (Signature.size() <= SignatureTable.size()) {
378     size_t Bound = SignatureTable.size() - Signature.size() + 1;
379     for (size_t Index = 0; Index < Bound; ++Index) {
380       if (equal(Signature.begin(), Signature.end(),
381                 SignatureTable.begin() + Index))
382         return Index;
383     }
384   }
385 
386   return INVALID_INDEX;
387 }
388 
389 void SemaSignatureTable::print(raw_ostream &OS) {
390   for (const auto &Sig : SignatureTable)
391     OS << "PrototypeDescriptor(" << static_cast<int>(Sig.PT) << ", "
392        << static_cast<int>(Sig.VTM) << ", " << static_cast<int>(Sig.TM)
393        << "),\n";
394 }
395 
396 //===----------------------------------------------------------------------===//
397 // RVVEmitter implementation
398 //===----------------------------------------------------------------------===//
399 void RVVEmitter::createHeader(raw_ostream &OS) {
400 
401   OS << "/*===---- riscv_vector.h - RISC-V V-extension RVVIntrinsics "
402         "-------------------===\n"
403         " *\n"
404         " *\n"
405         " * Part of the LLVM Project, under the Apache License v2.0 with LLVM "
406         "Exceptions.\n"
407         " * See https://llvm.org/LICENSE.txt for license information.\n"
408         " * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n"
409         " *\n"
410         " *===-----------------------------------------------------------------"
411         "------===\n"
412         " */\n\n";
413 
414   OS << "#ifndef __RISCV_VECTOR_H\n";
415   OS << "#define __RISCV_VECTOR_H\n\n";
416 
417   OS << "#include <stdint.h>\n";
418   OS << "#include <stddef.h>\n\n";
419 
420   OS << "#ifdef __cplusplus\n";
421   OS << "extern \"C\" {\n";
422   OS << "#endif\n\n";
423 
424   OS << "#pragma clang riscv intrinsic vector\n\n";
425 
426   printHeaderCode(OS);
427 
428   auto printType = [&](auto T) {
429     OS << "typedef " << T->getClangBuiltinStr() << " " << T->getTypeStr()
430        << ";\n";
431   };
432 
433   constexpr int Log2LMULs[] = {-3, -2, -1, 0, 1, 2, 3};
434   // Print RVV boolean types.
435   for (int Log2LMUL : Log2LMULs) {
436     auto T = TypeCache.computeType(BasicType::Int8, Log2LMUL,
437                                    PrototypeDescriptor::Mask);
438     if (T)
439       printType(*T);
440   }
441   // Print RVV int/float types.
442   for (char I : StringRef("csil")) {
443     BasicType BT = ParseBasicType(I);
444     for (int Log2LMUL : Log2LMULs) {
445       auto T = TypeCache.computeType(BT, Log2LMUL, PrototypeDescriptor::Vector);
446       if (T) {
447         printType(*T);
448         auto UT = TypeCache.computeType(
449             BT, Log2LMUL,
450             PrototypeDescriptor(BaseTypeModifier::Vector,
451                                 VectorTypeModifier::NoModifier,
452                                 TypeModifier::UnsignedInteger));
453         printType(*UT);
454       }
455       for (int NF = 2; NF <= 8; ++NF) {
456         auto TupleT = TypeCache.computeType(
457             BT, Log2LMUL,
458             PrototypeDescriptor(BaseTypeModifier::Vector, getTupleVTM(NF),
459                                 TypeModifier::SignedInteger));
460         auto TupleUT = TypeCache.computeType(
461             BT, Log2LMUL,
462             PrototypeDescriptor(BaseTypeModifier::Vector, getTupleVTM(NF),
463                                 TypeModifier::UnsignedInteger));
464         if (TupleT)
465           printType(*TupleT);
466         if (TupleUT)
467           printType(*TupleUT);
468       }
469     }
470   }
471 
472   for (BasicType BT : {BasicType::Float16, BasicType::Float32,
473                        BasicType::Float64, BasicType::BFloat16}) {
474     for (int Log2LMUL : Log2LMULs) {
475       auto T = TypeCache.computeType(BT, Log2LMUL, PrototypeDescriptor::Vector);
476       if (T)
477         printType(*T);
478       for (int NF = 2; NF <= 8; ++NF) {
479         auto TupleT = TypeCache.computeType(
480             BT, Log2LMUL,
481             PrototypeDescriptor(BaseTypeModifier::Vector, getTupleVTM(NF),
482                                 (BT == BasicType::BFloat16
483                                      ? TypeModifier::BFloat
484                                      : TypeModifier::Float)));
485         if (TupleT)
486           printType(*TupleT);
487       }
488     }
489   }
490 
491   OS << "\n#ifdef __cplusplus\n";
492   OS << "}\n";
493   OS << "#endif // __cplusplus\n";
494   OS << "#endif // __RISCV_VECTOR_H\n";
495 }
496 
497 void RVVEmitter::createBuiltins(raw_ostream &OS) {
498   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
499   createRVVIntrinsics(Defs);
500 
501   // Map to keep track of which builtin names have already been emitted.
502   StringMap<RVVIntrinsic *> BuiltinMap;
503 
504   OS << "#if defined(TARGET_BUILTIN) && !defined(RISCVV_BUILTIN)\n";
505   OS << "#define RISCVV_BUILTIN(ID, TYPE, ATTRS) TARGET_BUILTIN(ID, TYPE, "
506         "ATTRS, \"zve32x\")\n";
507   OS << "#endif\n";
508   for (auto &Def : Defs) {
509     auto P =
510         BuiltinMap.insert(std::make_pair(Def->getBuiltinName(), Def.get()));
511     if (!P.second) {
512       // Verf that this would have produced the same builtin definition.
513       if (P.first->second->hasBuiltinAlias() != Def->hasBuiltinAlias())
514         PrintFatalError("Builtin with same name has different hasAutoDef");
515       else if (!Def->hasBuiltinAlias() &&
516                P.first->second->getBuiltinTypeStr() != Def->getBuiltinTypeStr())
517         PrintFatalError("Builtin with same name has different type string");
518       continue;
519     }
520     OS << "RISCVV_BUILTIN(__builtin_rvv_" << Def->getBuiltinName() << ",\"";
521     if (!Def->hasBuiltinAlias())
522       OS << Def->getBuiltinTypeStr();
523     OS << "\", \"n\")\n";
524   }
525   OS << "#undef RISCVV_BUILTIN\n";
526 }
527 
528 void RVVEmitter::createCodeGen(raw_ostream &OS) {
529   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
530   createRVVIntrinsics(Defs);
531   // IR name could be empty, use the stable sort preserves the relative order.
532   stable_sort(Defs, [](const std::unique_ptr<RVVIntrinsic> &A,
533                        const std::unique_ptr<RVVIntrinsic> &B) {
534     if (A->getIRName() == B->getIRName())
535       return (A->getPolicyAttrs() < B->getPolicyAttrs());
536     return (A->getIRName() < B->getIRName());
537   });
538 
539   // Map to keep track of which builtin names have already been emitted.
540   StringMap<RVVIntrinsic *> BuiltinMap;
541 
542   // Print switch body when the ir name, ManualCodegen, policy or log2sew
543   // changes from previous iteration.
544   RVVIntrinsic *PrevDef = Defs.begin()->get();
545   for (auto &Def : Defs) {
546     StringRef CurIRName = Def->getIRName();
547     if (CurIRName != PrevDef->getIRName() ||
548         (Def->getManualCodegen() != PrevDef->getManualCodegen()) ||
549         (Def->getPolicyAttrs() != PrevDef->getPolicyAttrs()) ||
550         (getSegInstLog2SEW(Def->getOverloadedName()) !=
551          getSegInstLog2SEW(PrevDef->getOverloadedName()))) {
552       emitCodeGenSwitchBody(PrevDef, OS);
553     }
554     PrevDef = Def.get();
555 
556     auto P =
557         BuiltinMap.insert(std::make_pair(Def->getBuiltinName(), Def.get()));
558     if (P.second) {
559       OS << "case RISCVVector::BI__builtin_rvv_" << Def->getBuiltinName()
560          << ":\n";
561       continue;
562     }
563 
564     if (P.first->second->getIRName() != Def->getIRName())
565       PrintFatalError("Builtin with same name has different IRName");
566     else if (P.first->second->getManualCodegen() != Def->getManualCodegen())
567       PrintFatalError("Builtin with same name has different ManualCodegen");
568     else if (P.first->second->isMasked() != Def->isMasked())
569       PrintFatalError("Builtin with same name has different isMasked");
570     else if (P.first->second->hasVL() != Def->hasVL())
571       PrintFatalError("Builtin with same name has different hasVL");
572     else if (P.first->second->getPolicyScheme() != Def->getPolicyScheme())
573       PrintFatalError("Builtin with same name has different getPolicyScheme");
574     else if (P.first->second->getIntrinsicTypes() != Def->getIntrinsicTypes())
575       PrintFatalError("Builtin with same name has different IntrinsicTypes");
576   }
577   emitCodeGenSwitchBody(Defs.back().get(), OS);
578   OS << "\n";
579 }
580 
581 void RVVEmitter::createRVVIntrinsics(
582     std::vector<std::unique_ptr<RVVIntrinsic>> &Out,
583     std::vector<SemaRecord> *SemaRecords) {
584   for (const Record *R : Records.getAllDerivedDefinitions("RVVBuiltin")) {
585     StringRef Name = R->getValueAsString("Name");
586     StringRef SuffixProto = R->getValueAsString("Suffix");
587     StringRef OverloadedName = R->getValueAsString("OverloadedName");
588     StringRef OverloadedSuffixProto = R->getValueAsString("OverloadedSuffix");
589     StringRef Prototypes = R->getValueAsString("Prototype");
590     StringRef TypeRange = R->getValueAsString("TypeRange");
591     bool HasMasked = R->getValueAsBit("HasMasked");
592     bool HasMaskedOffOperand = R->getValueAsBit("HasMaskedOffOperand");
593     bool HasVL = R->getValueAsBit("HasVL");
594     const Record *MPSRecord = R->getValueAsDef("MaskedPolicyScheme");
595     auto MaskedPolicyScheme =
596         static_cast<PolicyScheme>(MPSRecord->getValueAsInt("Value"));
597     const Record *UMPSRecord = R->getValueAsDef("UnMaskedPolicyScheme");
598     auto UnMaskedPolicyScheme =
599         static_cast<PolicyScheme>(UMPSRecord->getValueAsInt("Value"));
600     std::vector<int64_t> Log2LMULList = R->getValueAsListOfInts("Log2LMUL");
601     bool HasTailPolicy = R->getValueAsBit("HasTailPolicy");
602     bool HasMaskPolicy = R->getValueAsBit("HasMaskPolicy");
603     bool SupportOverloading = R->getValueAsBit("SupportOverloading");
604     bool HasBuiltinAlias = R->getValueAsBit("HasBuiltinAlias");
605     StringRef ManualCodegen = R->getValueAsString("ManualCodegen");
606     std::vector<int64_t> IntrinsicTypes =
607         R->getValueAsListOfInts("IntrinsicTypes");
608     std::vector<StringRef> RequiredFeatures =
609         R->getValueAsListOfStrings("RequiredFeatures");
610     StringRef IRName = R->getValueAsString("IRName");
611     StringRef MaskedIRName = R->getValueAsString("MaskedIRName");
612     unsigned NF = R->getValueAsInt("NF");
613     bool IsTuple = R->getValueAsBit("IsTuple");
614     bool HasFRMRoundModeOp = R->getValueAsBit("HasFRMRoundModeOp");
615 
616     const Policy DefaultPolicy;
617     SmallVector<Policy> SupportedUnMaskedPolicies =
618         RVVIntrinsic::getSupportedUnMaskedPolicies();
619     SmallVector<Policy> SupportedMaskedPolicies =
620         RVVIntrinsic::getSupportedMaskedPolicies(HasTailPolicy, HasMaskPolicy);
621 
622     // Parse prototype and create a list of primitive type with transformers
623     // (operand) in Prototype. Prototype[0] is output operand.
624     SmallVector<PrototypeDescriptor> BasicPrototype =
625         parsePrototypes(Prototypes);
626 
627     SmallVector<PrototypeDescriptor> SuffixDesc = parsePrototypes(SuffixProto);
628     SmallVector<PrototypeDescriptor> OverloadedSuffixDesc =
629         parsePrototypes(OverloadedSuffixProto);
630 
631     // Compute Builtin types
632     auto Prototype = RVVIntrinsic::computeBuiltinTypes(
633         BasicPrototype, /*IsMasked=*/false,
634         /*HasMaskedOffOperand=*/false, HasVL, NF, UnMaskedPolicyScheme,
635         DefaultPolicy, IsTuple);
636     SmallVector<PrototypeDescriptor> MaskedPrototype;
637     if (HasMasked)
638       MaskedPrototype = RVVIntrinsic::computeBuiltinTypes(
639           BasicPrototype, /*IsMasked=*/true, HasMaskedOffOperand, HasVL, NF,
640           MaskedPolicyScheme, DefaultPolicy, IsTuple);
641 
642     // Create Intrinsics for each type and LMUL.
643     for (char I : TypeRange) {
644       for (int Log2LMUL : Log2LMULList) {
645         BasicType BT = ParseBasicType(I);
646         std::optional<RVVTypes> Types =
647             TypeCache.computeTypes(BT, Log2LMUL, NF, Prototype);
648         // Ignored to create new intrinsic if there are any illegal types.
649         if (!Types)
650           continue;
651 
652         auto SuffixStr =
653             RVVIntrinsic::getSuffixStr(TypeCache, BT, Log2LMUL, SuffixDesc);
654         auto OverloadedSuffixStr = RVVIntrinsic::getSuffixStr(
655             TypeCache, BT, Log2LMUL, OverloadedSuffixDesc);
656         // Create a unmasked intrinsic
657         Out.push_back(std::make_unique<RVVIntrinsic>(
658             Name, SuffixStr, OverloadedName, OverloadedSuffixStr, IRName,
659             /*IsMasked=*/false, /*HasMaskedOffOperand=*/false, HasVL,
660             UnMaskedPolicyScheme, SupportOverloading, HasBuiltinAlias,
661             ManualCodegen, *Types, IntrinsicTypes, NF, DefaultPolicy,
662             HasFRMRoundModeOp));
663         if (UnMaskedPolicyScheme != PolicyScheme::SchemeNone)
664           for (auto P : SupportedUnMaskedPolicies) {
665             SmallVector<PrototypeDescriptor> PolicyPrototype =
666                 RVVIntrinsic::computeBuiltinTypes(
667                     BasicPrototype, /*IsMasked=*/false,
668                     /*HasMaskedOffOperand=*/false, HasVL, NF,
669                     UnMaskedPolicyScheme, P, IsTuple);
670             std::optional<RVVTypes> PolicyTypes =
671                 TypeCache.computeTypes(BT, Log2LMUL, NF, PolicyPrototype);
672             Out.push_back(std::make_unique<RVVIntrinsic>(
673                 Name, SuffixStr, OverloadedName, OverloadedSuffixStr, IRName,
674                 /*IsMask=*/false, /*HasMaskedOffOperand=*/false, HasVL,
675                 UnMaskedPolicyScheme, SupportOverloading, HasBuiltinAlias,
676                 ManualCodegen, *PolicyTypes, IntrinsicTypes, NF, P,
677                 HasFRMRoundModeOp));
678           }
679         if (!HasMasked)
680           continue;
681         // Create a masked intrinsic
682         std::optional<RVVTypes> MaskTypes =
683             TypeCache.computeTypes(BT, Log2LMUL, NF, MaskedPrototype);
684         Out.push_back(std::make_unique<RVVIntrinsic>(
685             Name, SuffixStr, OverloadedName, OverloadedSuffixStr, MaskedIRName,
686             /*IsMasked=*/true, HasMaskedOffOperand, HasVL, MaskedPolicyScheme,
687             SupportOverloading, HasBuiltinAlias, ManualCodegen, *MaskTypes,
688             IntrinsicTypes, NF, DefaultPolicy, HasFRMRoundModeOp));
689         if (MaskedPolicyScheme == PolicyScheme::SchemeNone)
690           continue;
691         for (auto P : SupportedMaskedPolicies) {
692           SmallVector<PrototypeDescriptor> PolicyPrototype =
693               RVVIntrinsic::computeBuiltinTypes(
694                   BasicPrototype, /*IsMasked=*/true, HasMaskedOffOperand, HasVL,
695                   NF, MaskedPolicyScheme, P, IsTuple);
696           std::optional<RVVTypes> PolicyTypes =
697               TypeCache.computeTypes(BT, Log2LMUL, NF, PolicyPrototype);
698           Out.push_back(std::make_unique<RVVIntrinsic>(
699               Name, SuffixStr, OverloadedName, OverloadedSuffixStr,
700               MaskedIRName, /*IsMasked=*/true, HasMaskedOffOperand, HasVL,
701               MaskedPolicyScheme, SupportOverloading, HasBuiltinAlias,
702               ManualCodegen, *PolicyTypes, IntrinsicTypes, NF, P,
703               HasFRMRoundModeOp));
704         }
705       } // End for Log2LMULList
706     }   // End for TypeRange
707 
708     // We don't emit vsetvli and vsetvlimax for SemaRecord.
709     // They are written in riscv_vector.td and will emit those marco define in
710     // riscv_vector.h
711     if (Name == "vsetvli" || Name == "vsetvlimax")
712       continue;
713 
714     if (!SemaRecords)
715       continue;
716 
717     // Create SemaRecord
718     SemaRecord SR;
719     SR.Name = Name.str();
720     SR.OverloadedName = OverloadedName.str();
721     BasicType TypeRangeMask = BasicType::Unknown;
722     for (char I : TypeRange)
723       TypeRangeMask |= ParseBasicType(I);
724 
725     SR.TypeRangeMask = static_cast<unsigned>(TypeRangeMask);
726 
727     unsigned Log2LMULMask = 0;
728     for (int Log2LMUL : Log2LMULList)
729       Log2LMULMask |= 1 << (Log2LMUL + 3);
730 
731     SR.Log2LMULMask = Log2LMULMask;
732 
733     SR.RequiredExtensions = 0;
734     for (auto RequiredFeature : RequiredFeatures) {
735       RVVRequire RequireExt =
736           StringSwitch<RVVRequire>(RequiredFeature)
737               .Case("RV64", RVV_REQ_RV64)
738               .Case("Zvfhmin", RVV_REQ_Zvfhmin)
739               .Case("Xsfvcp", RVV_REQ_Xsfvcp)
740               .Case("Xsfvfnrclipxfqf", RVV_REQ_Xsfvfnrclipxfqf)
741               .Case("Xsfvfwmaccqqq", RVV_REQ_Xsfvfwmaccqqq)
742               .Case("Xsfvqmaccdod", RVV_REQ_Xsfvqmaccdod)
743               .Case("Xsfvqmaccqoq", RVV_REQ_Xsfvqmaccqoq)
744               .Case("Zvbb", RVV_REQ_Zvbb)
745               .Case("Zvbc", RVV_REQ_Zvbc)
746               .Case("Zvkb", RVV_REQ_Zvkb)
747               .Case("Zvkg", RVV_REQ_Zvkg)
748               .Case("Zvkned", RVV_REQ_Zvkned)
749               .Case("Zvknha", RVV_REQ_Zvknha)
750               .Case("Zvknhb", RVV_REQ_Zvknhb)
751               .Case("Zvksed", RVV_REQ_Zvksed)
752               .Case("Zvksh", RVV_REQ_Zvksh)
753               .Case("Zvfbfwma", RVV_REQ_Zvfbfwma)
754               .Case("Zvfbfmin", RVV_REQ_Zvfbfmin)
755               .Case("Zvfh", RVV_REQ_Zvfh)
756               .Case("Experimental", RVV_REQ_Experimental)
757               .Default(RVV_REQ_None);
758       assert(RequireExt != RVV_REQ_None && "Unrecognized required feature?");
759       SR.RequiredExtensions |= RequireExt;
760     }
761 
762     SR.NF = NF;
763     SR.HasMasked = HasMasked;
764     SR.HasVL = HasVL;
765     SR.HasMaskedOffOperand = HasMaskedOffOperand;
766     SR.HasTailPolicy = HasTailPolicy;
767     SR.HasMaskPolicy = HasMaskPolicy;
768     SR.UnMaskedPolicyScheme = static_cast<uint8_t>(UnMaskedPolicyScheme);
769     SR.MaskedPolicyScheme = static_cast<uint8_t>(MaskedPolicyScheme);
770     SR.Prototype = std::move(BasicPrototype);
771     SR.Suffix = parsePrototypes(SuffixProto);
772     SR.OverloadedSuffix = parsePrototypes(OverloadedSuffixProto);
773     SR.IsTuple = IsTuple;
774     SR.HasFRMRoundModeOp = HasFRMRoundModeOp;
775 
776     SemaRecords->push_back(SR);
777   }
778 }
779 
780 void RVVEmitter::printHeaderCode(raw_ostream &OS) {
781   for (const Record *R : Records.getAllDerivedDefinitions("RVVHeader")) {
782     StringRef HeaderCodeStr = R->getValueAsString("HeaderCode");
783     OS << HeaderCodeStr.str();
784   }
785 }
786 
787 void RVVEmitter::createRVVIntrinsicRecords(std::vector<RVVIntrinsicRecord> &Out,
788                                            SemaSignatureTable &SST,
789                                            ArrayRef<SemaRecord> SemaRecords) {
790   SST.init(SemaRecords);
791 
792   for (const auto &SR : SemaRecords) {
793     Out.emplace_back(RVVIntrinsicRecord());
794     RVVIntrinsicRecord &R = Out.back();
795     R.Name = SR.Name.c_str();
796     R.OverloadedName = SR.OverloadedName.c_str();
797     R.PrototypeIndex = SST.getIndex(SR.Prototype);
798     R.SuffixIndex = SST.getIndex(SR.Suffix);
799     R.OverloadedSuffixIndex = SST.getIndex(SR.OverloadedSuffix);
800     R.PrototypeLength = SR.Prototype.size();
801     R.SuffixLength = SR.Suffix.size();
802     R.OverloadedSuffixSize = SR.OverloadedSuffix.size();
803     R.RequiredExtensions = SR.RequiredExtensions;
804     R.TypeRangeMask = SR.TypeRangeMask;
805     R.Log2LMULMask = SR.Log2LMULMask;
806     R.NF = SR.NF;
807     R.HasMasked = SR.HasMasked;
808     R.HasVL = SR.HasVL;
809     R.HasMaskedOffOperand = SR.HasMaskedOffOperand;
810     R.HasTailPolicy = SR.HasTailPolicy;
811     R.HasMaskPolicy = SR.HasMaskPolicy;
812     R.UnMaskedPolicyScheme = SR.UnMaskedPolicyScheme;
813     R.MaskedPolicyScheme = SR.MaskedPolicyScheme;
814     R.IsTuple = SR.IsTuple;
815     R.HasFRMRoundModeOp = SR.HasFRMRoundModeOp;
816 
817     assert(R.PrototypeIndex !=
818            static_cast<uint16_t>(SemaSignatureTable::INVALID_INDEX));
819     assert(R.SuffixIndex !=
820            static_cast<uint16_t>(SemaSignatureTable::INVALID_INDEX));
821     assert(R.OverloadedSuffixIndex !=
822            static_cast<uint16_t>(SemaSignatureTable::INVALID_INDEX));
823   }
824 }
825 
826 void RVVEmitter::createSema(raw_ostream &OS) {
827   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
828   std::vector<RVVIntrinsicRecord> RVVIntrinsicRecords;
829   SemaSignatureTable SST;
830   std::vector<SemaRecord> SemaRecords;
831 
832   createRVVIntrinsics(Defs, &SemaRecords);
833 
834   createRVVIntrinsicRecords(RVVIntrinsicRecords, SST, SemaRecords);
835 
836   // Emit signature table for SemaRISCVVectorLookup.cpp.
837   OS << "#ifdef DECL_SIGNATURE_TABLE\n";
838   SST.print(OS);
839   OS << "#endif\n";
840 
841   // Emit RVVIntrinsicRecords for SemaRISCVVectorLookup.cpp.
842   OS << "#ifdef DECL_INTRINSIC_RECORDS\n";
843   for (const RVVIntrinsicRecord &Record : RVVIntrinsicRecords)
844     OS << Record;
845   OS << "#endif\n";
846 }
847 
848 namespace clang {
849 void EmitRVVHeader(const RecordKeeper &Records, raw_ostream &OS) {
850   RVVEmitter(Records).createHeader(OS);
851 }
852 
853 void EmitRVVBuiltins(const RecordKeeper &Records, raw_ostream &OS) {
854   RVVEmitter(Records).createBuiltins(OS);
855 }
856 
857 void EmitRVVBuiltinCG(const RecordKeeper &Records, raw_ostream &OS) {
858   RVVEmitter(Records).createCodeGen(OS);
859 }
860 
861 void EmitRVVBuiltinSema(const RecordKeeper &Records, raw_ostream &OS) {
862   RVVEmitter(Records).createSema(OS);
863 }
864 
865 } // End namespace clang
866