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