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