xref: /freebsd/contrib/llvm-project/clang/utils/TableGen/RISCVVEmitter.cpp (revision a8089ea5aee578e08acab2438e82fc9a9ae50ed8)
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   uint32_t 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   case 'y':
155     return BasicType::BFloat16;
156     break;
157   default:
158     return BasicType::Unknown;
159   }
160 }
161 
162 static VectorTypeModifier getTupleVTM(unsigned NF) {
163   assert(2 <= NF && NF <= 8 && "2 <= NF <= 8");
164   return static_cast<VectorTypeModifier>(
165       static_cast<uint8_t>(VectorTypeModifier::Tuple2) + (NF - 2));
166 }
167 
168 void emitCodeGenSwitchBody(const RVVIntrinsic *RVVI, raw_ostream &OS) {
169   if (!RVVI->getIRName().empty())
170     OS << "  ID = Intrinsic::riscv_" + RVVI->getIRName() + ";\n";
171   if (RVVI->getNF() >= 2)
172     OS << "  NF = " + utostr(RVVI->getNF()) + ";\n";
173 
174   OS << "  PolicyAttrs = " << RVVI->getPolicyAttrsBits() << ";\n";
175 
176   if (RVVI->hasManualCodegen()) {
177     OS << "IsMasked = " << (RVVI->isMasked() ? "true" : "false") << ";\n";
178     OS << RVVI->getManualCodegen();
179     OS << "break;\n";
180     return;
181   }
182 
183   for (const auto &I : enumerate(RVVI->getInputTypes())) {
184     if (I.value()->isPointer()) {
185       assert(RVVI->getIntrinsicTypes().front() == -1 &&
186              "RVVI should be vector load intrinsic.");
187     }
188   }
189 
190   if (RVVI->isMasked()) {
191     if (RVVI->hasVL()) {
192       OS << "  std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);\n";
193       if (RVVI->hasPolicyOperand())
194         OS << "  Ops.push_back(ConstantInt::get(Ops.back()->getType(),"
195               " PolicyAttrs));\n";
196       if (RVVI->hasMaskedOffOperand() && RVVI->getPolicyAttrs().isTAMAPolicy())
197         OS << "  Ops.insert(Ops.begin(), "
198               "llvm::PoisonValue::get(ResultType));\n";
199       // Masked reduction cases.
200       if (!RVVI->hasMaskedOffOperand() && RVVI->hasPassthruOperand() &&
201           RVVI->getPolicyAttrs().isTAMAPolicy())
202         OS << "  Ops.insert(Ops.begin(), "
203               "llvm::PoisonValue::get(ResultType));\n";
204     } else {
205       OS << "  std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end());\n";
206     }
207   } else {
208     if (RVVI->hasPolicyOperand())
209       OS << "  Ops.push_back(ConstantInt::get(Ops.back()->getType(), "
210             "PolicyAttrs));\n";
211     else if (RVVI->hasPassthruOperand() && RVVI->getPolicyAttrs().isTAPolicy())
212       OS << "  Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));\n";
213   }
214 
215   OS << "  IntrinsicTypes = {";
216   ListSeparator LS;
217   for (const auto &Idx : RVVI->getIntrinsicTypes()) {
218     if (Idx == -1)
219       OS << LS << "ResultType";
220     else
221       OS << LS << "Ops[" << Idx << "]->getType()";
222   }
223 
224   // VL could be i64 or i32, need to encode it in IntrinsicTypes. VL is
225   // always last operand.
226   if (RVVI->hasVL())
227     OS << ", Ops.back()->getType()";
228   OS << "};\n";
229   OS << "  break;\n";
230 }
231 
232 //===----------------------------------------------------------------------===//
233 // SemaSignatureTable implementation
234 //===----------------------------------------------------------------------===//
235 void SemaSignatureTable::init(ArrayRef<SemaRecord> SemaRecords) {
236   // Sort signature entries by length, let longer signature insert first, to
237   // make it more possible to reuse table entries, that can reduce ~10% table
238   // size.
239   struct Compare {
240     bool operator()(const SmallVector<PrototypeDescriptor> &A,
241                     const SmallVector<PrototypeDescriptor> &B) const {
242       if (A.size() != B.size())
243         return A.size() > B.size();
244 
245       size_t Len = A.size();
246       for (size_t i = 0; i < Len; ++i) {
247         if (A[i] != B[i])
248           return A[i] < B[i];
249       }
250 
251       return false;
252     }
253   };
254 
255   std::set<SmallVector<PrototypeDescriptor>, Compare> Signatures;
256   auto InsertToSignatureSet =
257       [&](const SmallVector<PrototypeDescriptor> &Signature) {
258         if (Signature.empty())
259           return;
260 
261         Signatures.insert(Signature);
262       };
263 
264   assert(!SemaRecords.empty());
265 
266   for (const SemaRecord &SR : SemaRecords) {
267     InsertToSignatureSet(SR.Prototype);
268     InsertToSignatureSet(SR.Suffix);
269     InsertToSignatureSet(SR.OverloadedSuffix);
270   }
271 
272   for (auto &Sig : Signatures)
273     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 : {BasicType::Float16, BasicType::Float32,
392                        BasicType::Float64, BasicType::BFloat16}) {
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                                 (BT == BasicType::BFloat16
402                                      ? TypeModifier::BFloat
403                                      : TypeModifier::Float)));
404         if (TupleT)
405           printType(*TupleT);
406       }
407     }
408   }
409 
410   OS << "#define __riscv_v_intrinsic_overloading 1\n";
411 
412   OS << "\n#ifdef __cplusplus\n";
413   OS << "}\n";
414   OS << "#endif // __cplusplus\n";
415   OS << "#endif // __RISCV_VECTOR_H\n";
416 }
417 
418 void RVVEmitter::createBuiltins(raw_ostream &OS) {
419   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
420   createRVVIntrinsics(Defs);
421 
422   // Map to keep track of which builtin names have already been emitted.
423   StringMap<RVVIntrinsic *> BuiltinMap;
424 
425   OS << "#if defined(TARGET_BUILTIN) && !defined(RISCVV_BUILTIN)\n";
426   OS << "#define RISCVV_BUILTIN(ID, TYPE, ATTRS) TARGET_BUILTIN(ID, TYPE, "
427         "ATTRS, \"zve32x\")\n";
428   OS << "#endif\n";
429   for (auto &Def : Defs) {
430     auto P =
431         BuiltinMap.insert(std::make_pair(Def->getBuiltinName(), Def.get()));
432     if (!P.second) {
433       // Verf that this would have produced the same builtin definition.
434       if (P.first->second->hasBuiltinAlias() != Def->hasBuiltinAlias())
435         PrintFatalError("Builtin with same name has different hasAutoDef");
436       else if (!Def->hasBuiltinAlias() &&
437                P.first->second->getBuiltinTypeStr() != Def->getBuiltinTypeStr())
438         PrintFatalError("Builtin with same name has different type string");
439       continue;
440     }
441     OS << "RISCVV_BUILTIN(__builtin_rvv_" << Def->getBuiltinName() << ",\"";
442     if (!Def->hasBuiltinAlias())
443       OS << Def->getBuiltinTypeStr();
444     OS << "\", \"n\")\n";
445   }
446   OS << "#undef RISCVV_BUILTIN\n";
447 }
448 
449 void RVVEmitter::createCodeGen(raw_ostream &OS) {
450   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
451   createRVVIntrinsics(Defs);
452   // IR name could be empty, use the stable sort preserves the relative order.
453   llvm::stable_sort(Defs, [](const std::unique_ptr<RVVIntrinsic> &A,
454                              const std::unique_ptr<RVVIntrinsic> &B) {
455     if (A->getIRName() == B->getIRName())
456       return (A->getPolicyAttrs() < B->getPolicyAttrs());
457     return (A->getIRName() < B->getIRName());
458   });
459 
460   // Map to keep track of which builtin names have already been emitted.
461   StringMap<RVVIntrinsic *> BuiltinMap;
462 
463   // Print switch body when the ir name, ManualCodegen or policy changes from
464   // previous iteration.
465   RVVIntrinsic *PrevDef = Defs.begin()->get();
466   for (auto &Def : Defs) {
467     StringRef CurIRName = Def->getIRName();
468     if (CurIRName != PrevDef->getIRName() ||
469         (Def->getManualCodegen() != PrevDef->getManualCodegen()) ||
470         (Def->getPolicyAttrs() != PrevDef->getPolicyAttrs())) {
471       emitCodeGenSwitchBody(PrevDef, OS);
472     }
473     PrevDef = Def.get();
474 
475     auto P =
476         BuiltinMap.insert(std::make_pair(Def->getBuiltinName(), Def.get()));
477     if (P.second) {
478       OS << "case RISCVVector::BI__builtin_rvv_" << Def->getBuiltinName()
479          << ":\n";
480       continue;
481     }
482 
483     if (P.first->second->getIRName() != Def->getIRName())
484       PrintFatalError("Builtin with same name has different IRName");
485     else if (P.first->second->getManualCodegen() != Def->getManualCodegen())
486       PrintFatalError("Builtin with same name has different ManualCodegen");
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 =
657           StringSwitch<RVVRequire>(RequiredFeature)
658               .Case("RV64", RVV_REQ_RV64)
659               .Case("Zvfhmin", RVV_REQ_Zvfhmin)
660               .Case("Xsfvcp", RVV_REQ_Xsfvcp)
661               .Case("Xsfvfnrclipxfqf", RVV_REQ_Xsfvfnrclipxfqf)
662               .Case("Xsfvfwmaccqqq", RVV_REQ_Xsfvfwmaccqqq)
663               .Case("Xsfvqmaccdod", RVV_REQ_Xsfvqmaccdod)
664               .Case("Xsfvqmaccqoq", RVV_REQ_Xsfvqmaccqoq)
665               .Case("Zvbb", RVV_REQ_Zvbb)
666               .Case("Zvbc", RVV_REQ_Zvbc)
667               .Case("Zvkb", RVV_REQ_Zvkb)
668               .Case("Zvkg", RVV_REQ_Zvkg)
669               .Case("Zvkned", RVV_REQ_Zvkned)
670               .Case("Zvknha", RVV_REQ_Zvknha)
671               .Case("Zvknhb", RVV_REQ_Zvknhb)
672               .Case("Zvksed", RVV_REQ_Zvksed)
673               .Case("Zvksh", RVV_REQ_Zvksh)
674               .Case("Experimental", RVV_REQ_Experimental)
675               .Default(RVV_REQ_None);
676       assert(RequireExt != RVV_REQ_None && "Unrecognized required feature?");
677       SR.RequiredExtensions |= RequireExt;
678     }
679 
680     SR.NF = NF;
681     SR.HasMasked = HasMasked;
682     SR.HasVL = HasVL;
683     SR.HasMaskedOffOperand = HasMaskedOffOperand;
684     SR.HasTailPolicy = HasTailPolicy;
685     SR.HasMaskPolicy = HasMaskPolicy;
686     SR.UnMaskedPolicyScheme = static_cast<uint8_t>(UnMaskedPolicyScheme);
687     SR.MaskedPolicyScheme = static_cast<uint8_t>(MaskedPolicyScheme);
688     SR.Prototype = std::move(BasicPrototype);
689     SR.Suffix = parsePrototypes(SuffixProto);
690     SR.OverloadedSuffix = parsePrototypes(OverloadedSuffixProto);
691     SR.IsTuple = IsTuple;
692     SR.HasFRMRoundModeOp = HasFRMRoundModeOp;
693 
694     SemaRecords->push_back(SR);
695   }
696 }
697 
698 void RVVEmitter::printHeaderCode(raw_ostream &OS) {
699   std::vector<Record *> RVVHeaders =
700       Records.getAllDerivedDefinitions("RVVHeader");
701   for (auto *R : RVVHeaders) {
702     StringRef HeaderCodeStr = R->getValueAsString("HeaderCode");
703     OS << HeaderCodeStr.str();
704   }
705 }
706 
707 void RVVEmitter::createRVVIntrinsicRecords(std::vector<RVVIntrinsicRecord> &Out,
708                                            SemaSignatureTable &SST,
709                                            ArrayRef<SemaRecord> SemaRecords) {
710   SST.init(SemaRecords);
711 
712   for (const auto &SR : SemaRecords) {
713     Out.emplace_back(RVVIntrinsicRecord());
714     RVVIntrinsicRecord &R = Out.back();
715     R.Name = SR.Name.c_str();
716     R.OverloadedName = SR.OverloadedName.c_str();
717     R.PrototypeIndex = SST.getIndex(SR.Prototype);
718     R.SuffixIndex = SST.getIndex(SR.Suffix);
719     R.OverloadedSuffixIndex = SST.getIndex(SR.OverloadedSuffix);
720     R.PrototypeLength = SR.Prototype.size();
721     R.SuffixLength = SR.Suffix.size();
722     R.OverloadedSuffixSize = SR.OverloadedSuffix.size();
723     R.RequiredExtensions = SR.RequiredExtensions;
724     R.TypeRangeMask = SR.TypeRangeMask;
725     R.Log2LMULMask = SR.Log2LMULMask;
726     R.NF = SR.NF;
727     R.HasMasked = SR.HasMasked;
728     R.HasVL = SR.HasVL;
729     R.HasMaskedOffOperand = SR.HasMaskedOffOperand;
730     R.HasTailPolicy = SR.HasTailPolicy;
731     R.HasMaskPolicy = SR.HasMaskPolicy;
732     R.UnMaskedPolicyScheme = SR.UnMaskedPolicyScheme;
733     R.MaskedPolicyScheme = SR.MaskedPolicyScheme;
734     R.IsTuple = SR.IsTuple;
735     R.HasFRMRoundModeOp = SR.HasFRMRoundModeOp;
736 
737     assert(R.PrototypeIndex !=
738            static_cast<uint16_t>(SemaSignatureTable::INVALID_INDEX));
739     assert(R.SuffixIndex !=
740            static_cast<uint16_t>(SemaSignatureTable::INVALID_INDEX));
741     assert(R.OverloadedSuffixIndex !=
742            static_cast<uint16_t>(SemaSignatureTable::INVALID_INDEX));
743   }
744 }
745 
746 void RVVEmitter::createSema(raw_ostream &OS) {
747   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
748   std::vector<RVVIntrinsicRecord> RVVIntrinsicRecords;
749   SemaSignatureTable SST;
750   std::vector<SemaRecord> SemaRecords;
751 
752   createRVVIntrinsics(Defs, &SemaRecords);
753 
754   createRVVIntrinsicRecords(RVVIntrinsicRecords, SST, SemaRecords);
755 
756   // Emit signature table for SemaRISCVVectorLookup.cpp.
757   OS << "#ifdef DECL_SIGNATURE_TABLE\n";
758   SST.print(OS);
759   OS << "#endif\n";
760 
761   // Emit RVVIntrinsicRecords for SemaRISCVVectorLookup.cpp.
762   OS << "#ifdef DECL_INTRINSIC_RECORDS\n";
763   for (const RVVIntrinsicRecord &Record : RVVIntrinsicRecords)
764     OS << Record;
765   OS << "#endif\n";
766 }
767 
768 namespace clang {
769 void EmitRVVHeader(RecordKeeper &Records, raw_ostream &OS) {
770   RVVEmitter(Records).createHeader(OS);
771 }
772 
773 void EmitRVVBuiltins(RecordKeeper &Records, raw_ostream &OS) {
774   RVVEmitter(Records).createBuiltins(OS);
775 }
776 
777 void EmitRVVBuiltinCG(RecordKeeper &Records, raw_ostream &OS) {
778   RVVEmitter(Records).createCodeGen(OS);
779 }
780 
781 void EmitRVVBuiltinSema(RecordKeeper &Records, raw_ostream &OS) {
782   RVVEmitter(Records).createSema(OS);
783 }
784 
785 } // End namespace clang
786