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