xref: /llvm-project/clang/utils/TableGen/RISCVVEmitter.cpp (revision 05b3d26181ade32f5988d2be4939f605a5225782)
1*63aa8cf6SRahul Joshi //===-- RISCVVEmitter.cpp - Generate riscv_vector.h for use with clang ----===//
2d6a0560bSZakk Chen //
3d6a0560bSZakk Chen // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4d6a0560bSZakk Chen // See https://llvm.org/LICENSE.txt for license information.
5d6a0560bSZakk Chen // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6d6a0560bSZakk Chen //
7d6a0560bSZakk Chen //===----------------------------------------------------------------------===//
8d6a0560bSZakk Chen //
9821547caSZakk Chen // This tablegen backend is responsible for emitting riscv_vector.h which
10821547caSZakk Chen // includes a declaration and definition of each intrinsic functions specified
11821547caSZakk Chen // in https://github.com/riscv/rvv-intrinsic-doc.
12d6a0560bSZakk Chen //
13d6a0560bSZakk Chen // See also the documentation in include/clang/Basic/riscv_vector.td.
14d6a0560bSZakk Chen //
15d6a0560bSZakk Chen //===----------------------------------------------------------------------===//
16d6a0560bSZakk Chen 
17f26c41e8SKito Cheng #include "clang/Support/RISCVVIntrinsicUtils.h"
18d6a0560bSZakk Chen #include "llvm/ADT/ArrayRef.h"
19d6a0560bSZakk Chen #include "llvm/ADT/StringExtras.h"
20d6a0560bSZakk Chen #include "llvm/ADT/StringMap.h"
217a5cb15eSKito Cheng #include "llvm/ADT/StringSwitch.h"
22d6a0560bSZakk Chen #include "llvm/ADT/Twine.h"
239773cad5SCraig Topper #include "llvm/TableGen/Error.h"
24d6a0560bSZakk Chen #include "llvm/TableGen/Record.h"
259cf4419eSKazu Hirata #include <optional>
26d6a0560bSZakk Chen 
27d6a0560bSZakk Chen using namespace llvm;
28f26c41e8SKito Cheng using namespace clang::RISCV;
29d6a0560bSZakk Chen 
30d6a0560bSZakk Chen namespace {
317a5cb15eSKito Cheng struct SemaRecord {
327a5cb15eSKito Cheng   // Intrinsic name, e.g. vadd_vv
337a5cb15eSKito Cheng   std::string Name;
347a5cb15eSKito Cheng 
357a5cb15eSKito Cheng   // Overloaded intrinsic name, could be empty if can be computed from Name
367a5cb15eSKito Cheng   // e.g. vadd
377a5cb15eSKito Cheng   std::string OverloadedName;
387a5cb15eSKito Cheng 
397a5cb15eSKito Cheng   // Supported type, mask of BasicType.
407a5cb15eSKito Cheng   unsigned TypeRangeMask;
417a5cb15eSKito Cheng 
427a5cb15eSKito Cheng   // Supported LMUL.
437a5cb15eSKito Cheng   unsigned Log2LMULMask;
447a5cb15eSKito Cheng 
457a5cb15eSKito Cheng   // Required extensions for this intrinsic.
4609058654SEric Biggers   uint32_t RequiredExtensions;
477a5cb15eSKito Cheng 
487a5cb15eSKito Cheng   // Prototype for this intrinsic.
497a5cb15eSKito Cheng   SmallVector<PrototypeDescriptor> Prototype;
507a5cb15eSKito Cheng 
517a5cb15eSKito Cheng   // Suffix of intrinsic name.
527a5cb15eSKito Cheng   SmallVector<PrototypeDescriptor> Suffix;
537a5cb15eSKito Cheng 
547a5cb15eSKito Cheng   // Suffix of overloaded intrinsic name.
557a5cb15eSKito Cheng   SmallVector<PrototypeDescriptor> OverloadedSuffix;
567a5cb15eSKito Cheng 
577a5cb15eSKito Cheng   // Number of field, large than 1 if it's segment load/store.
587a5cb15eSKito Cheng   unsigned NF;
5993f8657cSZakk Chen 
6093f8657cSZakk Chen   bool HasMasked :1;
6193f8657cSZakk Chen   bool HasVL :1;
6293f8657cSZakk Chen   bool HasMaskedOffOperand :1;
6371fd6616SZakk Chen   bool HasTailPolicy : 1;
6471fd6616SZakk Chen   bool HasMaskPolicy : 1;
6576482078SeopXD   bool HasFRMRoundModeOp : 1;
660019226cSeopXD   bool IsTuple : 1;
6723bdca2cSVlad Serebrennikov   LLVM_PREFERRED_TYPE(PolicyScheme)
6871fd6616SZakk Chen   uint8_t UnMaskedPolicyScheme : 2;
6923bdca2cSVlad Serebrennikov   LLVM_PREFERRED_TYPE(PolicyScheme)
7071fd6616SZakk Chen   uint8_t MaskedPolicyScheme : 2;
717a5cb15eSKito Cheng };
727a5cb15eSKito Cheng 
737a5cb15eSKito Cheng // Compressed function signature table.
747a5cb15eSKito Cheng class SemaSignatureTable {
757a5cb15eSKito Cheng private:
767a5cb15eSKito Cheng   std::vector<PrototypeDescriptor> SignatureTable;
777a5cb15eSKito Cheng 
787a5cb15eSKito Cheng   void insert(ArrayRef<PrototypeDescriptor> Signature);
797a5cb15eSKito Cheng 
807a5cb15eSKito Cheng public:
817a5cb15eSKito Cheng   static constexpr unsigned INVALID_INDEX = ~0U;
827a5cb15eSKito Cheng 
837a5cb15eSKito Cheng   // Create compressed signature table from SemaRecords.
847a5cb15eSKito Cheng   void init(ArrayRef<SemaRecord> SemaRecords);
857a5cb15eSKito Cheng 
867a5cb15eSKito Cheng   // Query the Signature, return INVALID_INDEX if not found.
877a5cb15eSKito Cheng   unsigned getIndex(ArrayRef<PrototypeDescriptor> Signature);
887a5cb15eSKito Cheng 
897a5cb15eSKito Cheng   /// Print signature table in RVVHeader Record to \p OS
907a5cb15eSKito Cheng   void print(raw_ostream &OS);
917a5cb15eSKito Cheng };
927a5cb15eSKito Cheng 
93d6a0560bSZakk Chen class RVVEmitter {
94d6a0560bSZakk Chen private:
95974fa852SRahul Joshi   const RecordKeeper &Records;
963fe89be8SKito Cheng   RVVTypeCache TypeCache;
97d6a0560bSZakk Chen 
98d6a0560bSZakk Chen public:
99974fa852SRahul Joshi   RVVEmitter(const RecordKeeper &R) : Records(R) {}
100d6a0560bSZakk Chen 
101d6a0560bSZakk Chen   /// Emit riscv_vector.h
102d6a0560bSZakk Chen   void createHeader(raw_ostream &o);
103d6a0560bSZakk Chen 
104d6a0560bSZakk Chen   /// Emit all the __builtin prototypes and code needed by Sema.
105d6a0560bSZakk Chen   void createBuiltins(raw_ostream &o);
106d6a0560bSZakk Chen 
107d6a0560bSZakk Chen   /// Emit all the information needed to map builtin -> LLVM IR intrinsic.
108d6a0560bSZakk Chen   void createCodeGen(raw_ostream &o);
109d6a0560bSZakk Chen 
1107a5cb15eSKito Cheng   /// Emit all the information needed by SemaRISCVVectorLookup.cpp.
1117a5cb15eSKito Cheng   /// We've large number of intrinsic function for RVV, creating a customized
1127a5cb15eSKito Cheng   /// could speed up the compilation time.
1137a5cb15eSKito Cheng   void createSema(raw_ostream &o);
1147a5cb15eSKito Cheng 
115d6a0560bSZakk Chen private:
1167a5cb15eSKito Cheng   /// Create all intrinsics and add them to \p Out and SemaRecords.
1177a5cb15eSKito Cheng   void createRVVIntrinsics(std::vector<std::unique_ptr<RVVIntrinsic>> &Out,
1187a5cb15eSKito Cheng                            std::vector<SemaRecord> *SemaRecords = nullptr);
1197a5cb15eSKito Cheng   /// Create all intrinsic records and SemaSignatureTable from SemaRecords.
1207a5cb15eSKito Cheng   void createRVVIntrinsicRecords(std::vector<RVVIntrinsicRecord> &Out,
1217a5cb15eSKito Cheng                                  SemaSignatureTable &SST,
1227a5cb15eSKito Cheng                                  ArrayRef<SemaRecord> SemaRecords);
1237a5cb15eSKito Cheng 
12423d60ce1SZakk Chen   /// Print HeaderCode in RVVHeader Record to \p Out
12523d60ce1SZakk Chen   void printHeaderCode(raw_ostream &OS);
126d6a0560bSZakk Chen };
127d6a0560bSZakk Chen 
128d6a0560bSZakk Chen } // namespace
129d6a0560bSZakk Chen 
1307ff0bf57SKito Cheng static BasicType ParseBasicType(char c) {
1317ff0bf57SKito Cheng   switch (c) {
1327ff0bf57SKito Cheng   case 'c':
1337ff0bf57SKito Cheng     return BasicType::Int8;
1347ff0bf57SKito Cheng     break;
1357ff0bf57SKito Cheng   case 's':
1367ff0bf57SKito Cheng     return BasicType::Int16;
1377ff0bf57SKito Cheng     break;
1387ff0bf57SKito Cheng   case 'i':
1397ff0bf57SKito Cheng     return BasicType::Int32;
1407ff0bf57SKito Cheng     break;
1417ff0bf57SKito Cheng   case 'l':
1427ff0bf57SKito Cheng     return BasicType::Int64;
1437ff0bf57SKito Cheng     break;
1447ff0bf57SKito Cheng   case 'x':
1457ff0bf57SKito Cheng     return BasicType::Float16;
1467ff0bf57SKito Cheng     break;
1477ff0bf57SKito Cheng   case 'f':
1487ff0bf57SKito Cheng     return BasicType::Float32;
1497ff0bf57SKito Cheng     break;
1507ff0bf57SKito Cheng   case 'd':
1517ff0bf57SKito Cheng     return BasicType::Float64;
1527ff0bf57SKito Cheng     break;
153fa8347fbSMichael Maitland   case 'y':
154fbdf6e27SShao-Ce SUN     return BasicType::BFloat16;
155fbdf6e27SShao-Ce SUN     break;
1567ff0bf57SKito Cheng   default:
1577ff0bf57SKito Cheng     return BasicType::Unknown;
1587ff0bf57SKito Cheng   }
1597ff0bf57SKito Cheng }
1607ff0bf57SKito Cheng 
1615847ec4dSeopXD static VectorTypeModifier getTupleVTM(unsigned NF) {
1625847ec4dSeopXD   assert(2 <= NF && NF <= 8 && "2 <= NF <= 8");
1635847ec4dSeopXD   return static_cast<VectorTypeModifier>(
1645847ec4dSeopXD       static_cast<uint8_t>(VectorTypeModifier::Tuple2) + (NF - 2));
1655847ec4dSeopXD }
1665847ec4dSeopXD 
16746f953d1SBrandon Wu static unsigned getIndexedLoadStorePtrIdx(const RVVIntrinsic *RVVI) {
16846f953d1SBrandon Wu   // We need a special rule for segment load/store since the data width is not
169922992a2SJay Foad   // encoded in the intrinsic name itself.
17046f953d1SBrandon Wu   const StringRef IRName = RVVI->getIRName();
17146f953d1SBrandon Wu   constexpr unsigned RVV_VTA = 0x1;
17246f953d1SBrandon Wu   constexpr unsigned RVV_VMA = 0x2;
17346f953d1SBrandon Wu 
17446f953d1SBrandon Wu   if (IRName.starts_with("vloxseg") || IRName.starts_with("vluxseg")) {
17546f953d1SBrandon Wu     bool NoPassthru =
17646f953d1SBrandon Wu         (RVVI->isMasked() && (RVVI->getPolicyAttrsBits() & RVV_VTA) &&
17746f953d1SBrandon Wu          (RVVI->getPolicyAttrsBits() & RVV_VMA)) ||
17846f953d1SBrandon Wu         (!RVVI->isMasked() && (RVVI->getPolicyAttrsBits() & RVV_VTA));
17946f953d1SBrandon Wu     return RVVI->isMasked() ? NoPassthru ? 1 : 2 : NoPassthru ? 0 : 1;
18046f953d1SBrandon Wu   }
18146f953d1SBrandon Wu   if (IRName.starts_with("vsoxseg") || IRName.starts_with("vsuxseg"))
18246f953d1SBrandon Wu     return RVVI->isMasked() ? 1 : 0;
18346f953d1SBrandon Wu 
18446f953d1SBrandon Wu   return (unsigned)-1;
18546f953d1SBrandon Wu }
18646f953d1SBrandon Wu 
187239127d7SBrandon Wu // This function is used to get the log2SEW of each segment load/store, this
188239127d7SBrandon Wu // prevent to add a member to RVVIntrinsic.
189239127d7SBrandon Wu static unsigned getSegInstLog2SEW(StringRef InstName) {
190239127d7SBrandon Wu   // clang-format off
19146f953d1SBrandon Wu   // We need a special rule for indexed segment load/store since the data width
192922992a2SJay Foad   // is not encoded in the intrinsic name itself.
19346f953d1SBrandon Wu   if (InstName.starts_with("vloxseg") || InstName.starts_with("vluxseg") ||
19446f953d1SBrandon Wu       InstName.starts_with("vsoxseg") || InstName.starts_with("vsuxseg"))
19546f953d1SBrandon Wu     return (unsigned)-1;
19646f953d1SBrandon Wu 
197239127d7SBrandon Wu #define KEY_VAL(KEY, VAL) {#KEY, VAL}
198239127d7SBrandon Wu #define KEY_VAL_ALL_W_POLICY(KEY, VAL) \
199239127d7SBrandon Wu   KEY_VAL(KEY, VAL),                   \
200239127d7SBrandon Wu   KEY_VAL(KEY ## _tu, VAL),            \
201239127d7SBrandon Wu   KEY_VAL(KEY ## _tum, VAL),           \
202239127d7SBrandon Wu   KEY_VAL(KEY ## _tumu, VAL),          \
203239127d7SBrandon Wu   KEY_VAL(KEY ## _mu, VAL)
204239127d7SBrandon Wu 
20546f953d1SBrandon Wu #define KEY_VAL_ALL_NF_BASE(MACRO_NAME, NAME, SEW, LOG2SEW, FF) \
20646f953d1SBrandon Wu   MACRO_NAME(NAME ## 2e ## SEW ## FF, LOG2SEW), \
20746f953d1SBrandon Wu   MACRO_NAME(NAME ## 3e ## SEW ## FF, LOG2SEW), \
20846f953d1SBrandon Wu   MACRO_NAME(NAME ## 4e ## SEW ## FF, LOG2SEW), \
20946f953d1SBrandon Wu   MACRO_NAME(NAME ## 5e ## SEW ## FF, LOG2SEW), \
21046f953d1SBrandon Wu   MACRO_NAME(NAME ## 6e ## SEW ## FF, LOG2SEW), \
21146f953d1SBrandon Wu   MACRO_NAME(NAME ## 7e ## SEW ## FF, LOG2SEW), \
21246f953d1SBrandon Wu   MACRO_NAME(NAME ## 8e ## SEW ## FF, LOG2SEW)
213239127d7SBrandon Wu 
214239127d7SBrandon Wu #define KEY_VAL_ALL_NF(NAME, SEW, LOG2SEW) \
215239127d7SBrandon Wu   KEY_VAL_ALL_NF_BASE(KEY_VAL_ALL_W_POLICY, NAME, SEW, LOG2SEW,)
216239127d7SBrandon Wu 
217239127d7SBrandon Wu #define KEY_VAL_FF_ALL_NF(NAME, SEW, LOG2SEW) \
21846f953d1SBrandon Wu   KEY_VAL_ALL_NF_BASE(KEY_VAL_ALL_W_POLICY, NAME, SEW, LOG2SEW, ff)
219239127d7SBrandon Wu 
220239127d7SBrandon Wu #define KEY_VAL_ALL_NF_SEW_BASE(MACRO_NAME, NAME) \
221239127d7SBrandon Wu   MACRO_NAME(NAME, 8, 3),  \
222239127d7SBrandon Wu   MACRO_NAME(NAME, 16, 4), \
223239127d7SBrandon Wu   MACRO_NAME(NAME, 32, 5), \
224239127d7SBrandon Wu   MACRO_NAME(NAME, 64, 6)
225239127d7SBrandon Wu 
226239127d7SBrandon Wu #define KEY_VAL_ALL_NF_SEW(NAME) \
227239127d7SBrandon Wu   KEY_VAL_ALL_NF_SEW_BASE(KEY_VAL_ALL_NF, NAME)
228239127d7SBrandon Wu 
229239127d7SBrandon Wu #define KEY_VAL_FF_ALL_NF_SEW(NAME) \
230239127d7SBrandon Wu   KEY_VAL_ALL_NF_SEW_BASE(KEY_VAL_FF_ALL_NF, NAME)
231239127d7SBrandon Wu   // clang-format on
232239127d7SBrandon Wu 
233239127d7SBrandon Wu   static StringMap<unsigned> SegInsts = {
234239127d7SBrandon Wu       KEY_VAL_ALL_NF_SEW(vlseg), KEY_VAL_FF_ALL_NF_SEW(vlseg),
23546f953d1SBrandon Wu       KEY_VAL_ALL_NF_SEW(vlsseg), KEY_VAL_ALL_NF_SEW(vsseg),
23646f953d1SBrandon Wu       KEY_VAL_ALL_NF_SEW(vssseg)};
237239127d7SBrandon Wu 
238239127d7SBrandon Wu #undef KEY_VAL_ALL_NF_SEW
239239127d7SBrandon Wu #undef KEY_VAL_ALL_NF
240239127d7SBrandon Wu #undef KEY_VAL
241239127d7SBrandon Wu 
242239127d7SBrandon Wu   return SegInsts.lookup(InstName);
243239127d7SBrandon Wu }
244239127d7SBrandon Wu 
245f26c41e8SKito Cheng void emitCodeGenSwitchBody(const RVVIntrinsic *RVVI, raw_ostream &OS) {
246f26c41e8SKito Cheng   if (!RVVI->getIRName().empty())
247f26c41e8SKito Cheng     OS << "  ID = Intrinsic::riscv_" + RVVI->getIRName() + ";\n";
2485a1c6ec1SeopXD 
2491deb6bceSeopXD   OS << "  PolicyAttrs = " << RVVI->getPolicyAttrsBits() << ";\n";
250239127d7SBrandon Wu   OS << "  SegInstSEW = " << getSegInstLog2SEW(RVVI->getOverloadedName())
251239127d7SBrandon Wu      << ";\n";
25271fd6616SZakk Chen 
253f26c41e8SKito Cheng   if (RVVI->hasManualCodegen()) {
2545a1c6ec1SeopXD     OS << "IsMasked = " << (RVVI->isMasked() ? "true" : "false") << ";\n";
25546f953d1SBrandon Wu 
25646f953d1SBrandon Wu     // Skip the non-indexed load/store and compatible header load/store.
25746f953d1SBrandon Wu     OS << "if (SegInstSEW == (unsigned)-1) {\n";
25846f953d1SBrandon Wu     OS << "  auto PointeeType = E->getArg(" << getIndexedLoadStorePtrIdx(RVVI)
25946f953d1SBrandon Wu        << "      )->getType()->getPointeeType();\n";
26046f953d1SBrandon Wu     OS << "  SegInstSEW = "
26146f953d1SBrandon Wu           "      llvm::Log2_64(getContext().getTypeSize(PointeeType));\n}\n";
26246f953d1SBrandon Wu 
263f26c41e8SKito Cheng     OS << RVVI->getManualCodegen();
26495c0125fSZakk Chen     OS << "break;\n";
26595c0125fSZakk Chen     return;
26695c0125fSZakk Chen   }
267cfe3b000SCraig Topper 
268939352b6SYeting Kuo   for (const auto &I : enumerate(RVVI->getInputTypes())) {
269939352b6SYeting Kuo     if (I.value()->isPointer()) {
270939352b6SYeting Kuo       assert(RVVI->getIntrinsicTypes().front() == -1 &&
271939352b6SYeting Kuo              "RVVI should be vector load intrinsic.");
272939352b6SYeting Kuo     }
273939352b6SYeting Kuo   }
274939352b6SYeting Kuo 
275f26c41e8SKito Cheng   if (RVVI->isMasked()) {
276f26c41e8SKito Cheng     if (RVVI->hasVL()) {
277cfe3b000SCraig Topper       OS << "  std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);\n";
278f26c41e8SKito Cheng       if (RVVI->hasPolicyOperand())
2795158cfefSHsiangkai Wang         OS << "  Ops.push_back(ConstantInt::get(Ops.back()->getType(),"
2801deb6bceSeopXD               " PolicyAttrs));\n";
2811deb6bceSeopXD       if (RVVI->hasMaskedOffOperand() && RVVI->getPolicyAttrs().isTAMAPolicy())
2821972fb23SeopXD         OS << "  Ops.insert(Ops.begin(), "
2831972fb23SeopXD               "llvm::PoisonValue::get(ResultType));\n";
284dffdca85SZakk Chen       // Masked reduction cases.
285dffdca85SZakk Chen       if (!RVVI->hasMaskedOffOperand() && RVVI->hasPassthruOperand() &&
2861deb6bceSeopXD           RVVI->getPolicyAttrs().isTAMAPolicy())
2871972fb23SeopXD         OS << "  Ops.insert(Ops.begin(), "
2881972fb23SeopXD               "llvm::PoisonValue::get(ResultType));\n";
289cfe3b000SCraig Topper     } else {
290cfe3b000SCraig Topper       OS << "  std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end());\n";
291cfe3b000SCraig Topper     }
292ca783124SZakk Chen   } else {
293f26c41e8SKito Cheng     if (RVVI->hasPolicyOperand())
294ca783124SZakk Chen       OS << "  Ops.push_back(ConstantInt::get(Ops.back()->getType(), "
2951deb6bceSeopXD             "PolicyAttrs));\n";
2961deb6bceSeopXD     else if (RVVI->hasPassthruOperand() && RVVI->getPolicyAttrs().isTAPolicy())
2971972fb23SeopXD       OS << "  Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));\n";
298ca783124SZakk Chen   }
299cfe3b000SCraig Topper 
300d6a0560bSZakk Chen   OS << "  IntrinsicTypes = {";
301d6a0560bSZakk Chen   ListSeparator LS;
302f26c41e8SKito Cheng   for (const auto &Idx : RVVI->getIntrinsicTypes()) {
303d6a0560bSZakk Chen     if (Idx == -1)
304d6a0560bSZakk Chen       OS << LS << "ResultType";
305d6a0560bSZakk Chen     else
306d6a0560bSZakk Chen       OS << LS << "Ops[" << Idx << "]->getType()";
307d6a0560bSZakk Chen   }
308d6a0560bSZakk Chen 
309d6a0560bSZakk Chen   // VL could be i64 or i32, need to encode it in IntrinsicTypes. VL is
310d6a0560bSZakk Chen   // always last operand.
311f26c41e8SKito Cheng   if (RVVI->hasVL())
312cfe3b000SCraig Topper     OS << ", Ops.back()->getType()";
313d6a0560bSZakk Chen   OS << "};\n";
314d6a0560bSZakk Chen   OS << "  break;\n";
315d6a0560bSZakk Chen }
316d6a0560bSZakk Chen 
3177a5cb15eSKito Cheng //===----------------------------------------------------------------------===//
3187a5cb15eSKito Cheng // SemaSignatureTable implementation
3197a5cb15eSKito Cheng //===----------------------------------------------------------------------===//
3207a5cb15eSKito Cheng void SemaSignatureTable::init(ArrayRef<SemaRecord> SemaRecords) {
3217a5cb15eSKito Cheng   // Sort signature entries by length, let longer signature insert first, to
3227a5cb15eSKito Cheng   // make it more possible to reuse table entries, that can reduce ~10% table
3237a5cb15eSKito Cheng   // size.
3247a5cb15eSKito Cheng   struct Compare {
3257a5cb15eSKito Cheng     bool operator()(const SmallVector<PrototypeDescriptor> &A,
3267a5cb15eSKito Cheng                     const SmallVector<PrototypeDescriptor> &B) const {
3277a5cb15eSKito Cheng       if (A.size() != B.size())
3287a5cb15eSKito Cheng         return A.size() > B.size();
3297a5cb15eSKito Cheng 
3307a5cb15eSKito Cheng       size_t Len = A.size();
3317a5cb15eSKito Cheng       for (size_t i = 0; i < Len; ++i) {
3327a5cb15eSKito Cheng         if (A[i] != B[i])
3337a5cb15eSKito Cheng           return A[i] < B[i];
334d6a0560bSZakk Chen       }
335d6a0560bSZakk Chen 
3367a5cb15eSKito Cheng       return false;
337d6a0560bSZakk Chen     }
3387a5cb15eSKito Cheng   };
3397a5cb15eSKito Cheng 
3407a5cb15eSKito Cheng   std::set<SmallVector<PrototypeDescriptor>, Compare> Signatures;
3417a5cb15eSKito Cheng   auto InsertToSignatureSet =
3427a5cb15eSKito Cheng       [&](const SmallVector<PrototypeDescriptor> &Signature) {
3437a5cb15eSKito Cheng         if (Signature.empty())
3447a5cb15eSKito Cheng           return;
3457a5cb15eSKito Cheng 
3467a5cb15eSKito Cheng         Signatures.insert(Signature);
3477a5cb15eSKito Cheng       };
3487a5cb15eSKito Cheng 
3497a5cb15eSKito Cheng   assert(!SemaRecords.empty());
3507a5cb15eSKito Cheng 
35127bba42fSKazu Hirata   for (const SemaRecord &SR : SemaRecords) {
3527a5cb15eSKito Cheng     InsertToSignatureSet(SR.Prototype);
3537a5cb15eSKito Cheng     InsertToSignatureSet(SR.Suffix);
3547a5cb15eSKito Cheng     InsertToSignatureSet(SR.OverloadedSuffix);
35527bba42fSKazu Hirata   }
3567a5cb15eSKito Cheng 
35727bba42fSKazu Hirata   for (auto &Sig : Signatures)
35827bba42fSKazu Hirata     insert(Sig);
3597a5cb15eSKito Cheng }
3607a5cb15eSKito Cheng 
3617a5cb15eSKito Cheng void SemaSignatureTable::insert(ArrayRef<PrototypeDescriptor> Signature) {
3627a5cb15eSKito Cheng   if (getIndex(Signature) != INVALID_INDEX)
3637a5cb15eSKito Cheng     return;
3647a5cb15eSKito Cheng 
3657a5cb15eSKito Cheng   // Insert Signature into SignatureTable if not found in the table.
3667a5cb15eSKito Cheng   SignatureTable.insert(SignatureTable.begin(), Signature.begin(),
3677a5cb15eSKito Cheng                         Signature.end());
3687a5cb15eSKito Cheng }
3697a5cb15eSKito Cheng 
3707a5cb15eSKito Cheng unsigned SemaSignatureTable::getIndex(ArrayRef<PrototypeDescriptor> Signature) {
3717a5cb15eSKito Cheng   // Empty signature could be point into any index since there is length
3727a5cb15eSKito Cheng   // field when we use, so just always point it to 0.
3737a5cb15eSKito Cheng   if (Signature.empty())
3747a5cb15eSKito Cheng     return 0;
3757a5cb15eSKito Cheng 
3767a5cb15eSKito Cheng   // Checking Signature already in table or not.
377bccf2c84SJianjian Guan   if (Signature.size() <= SignatureTable.size()) {
3787a5cb15eSKito Cheng     size_t Bound = SignatureTable.size() - Signature.size() + 1;
3797a5cb15eSKito Cheng     for (size_t Index = 0; Index < Bound; ++Index) {
3807a5cb15eSKito Cheng       if (equal(Signature.begin(), Signature.end(),
3817a5cb15eSKito Cheng                 SignatureTable.begin() + Index))
3827a5cb15eSKito Cheng         return Index;
3837a5cb15eSKito Cheng     }
3847a5cb15eSKito Cheng   }
3857a5cb15eSKito Cheng 
3867a5cb15eSKito Cheng   return INVALID_INDEX;
3877a5cb15eSKito Cheng }
3887a5cb15eSKito Cheng 
3897a5cb15eSKito Cheng void SemaSignatureTable::print(raw_ostream &OS) {
3907a5cb15eSKito Cheng   for (const auto &Sig : SignatureTable)
3917a5cb15eSKito Cheng     OS << "PrototypeDescriptor(" << static_cast<int>(Sig.PT) << ", "
3927a5cb15eSKito Cheng        << static_cast<int>(Sig.VTM) << ", " << static_cast<int>(Sig.TM)
3937a5cb15eSKito Cheng        << "),\n";
394d8fa5ef6SHsiangkai Wang }
395d6a0560bSZakk Chen 
396d6a0560bSZakk Chen //===----------------------------------------------------------------------===//
397d6a0560bSZakk Chen // RVVEmitter implementation
398d6a0560bSZakk Chen //===----------------------------------------------------------------------===//
399d6a0560bSZakk Chen void RVVEmitter::createHeader(raw_ostream &OS) {
400d6a0560bSZakk Chen 
401d6a0560bSZakk Chen   OS << "/*===---- riscv_vector.h - RISC-V V-extension RVVIntrinsics "
402d6a0560bSZakk Chen         "-------------------===\n"
403d6a0560bSZakk Chen         " *\n"
404d6a0560bSZakk Chen         " *\n"
405d6a0560bSZakk Chen         " * Part of the LLVM Project, under the Apache License v2.0 with LLVM "
406d6a0560bSZakk Chen         "Exceptions.\n"
407d6a0560bSZakk Chen         " * See https://llvm.org/LICENSE.txt for license information.\n"
408d6a0560bSZakk Chen         " * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n"
409d6a0560bSZakk Chen         " *\n"
410d6a0560bSZakk Chen         " *===-----------------------------------------------------------------"
411d6a0560bSZakk Chen         "------===\n"
412d6a0560bSZakk Chen         " */\n\n";
413d6a0560bSZakk Chen 
414d6a0560bSZakk Chen   OS << "#ifndef __RISCV_VECTOR_H\n";
415d6a0560bSZakk Chen   OS << "#define __RISCV_VECTOR_H\n\n";
416d6a0560bSZakk Chen 
417d6a0560bSZakk Chen   OS << "#include <stdint.h>\n";
418d6a0560bSZakk Chen   OS << "#include <stddef.h>\n\n";
419d6a0560bSZakk Chen 
420d6a0560bSZakk Chen   OS << "#ifdef __cplusplus\n";
421d6a0560bSZakk Chen   OS << "extern \"C\" {\n";
422d6a0560bSZakk Chen   OS << "#endif\n\n";
423d6a0560bSZakk Chen 
4247a5cb15eSKito Cheng   OS << "#pragma clang riscv intrinsic vector\n\n";
4255158cfefSHsiangkai Wang 
4267a5cb15eSKito Cheng   printHeaderCode(OS);
427d6a0560bSZakk Chen 
428d6a0560bSZakk Chen   auto printType = [&](auto T) {
429d6a0560bSZakk Chen     OS << "typedef " << T->getClangBuiltinStr() << " " << T->getTypeStr()
430d6a0560bSZakk Chen        << ";\n";
431d6a0560bSZakk Chen   };
432d6a0560bSZakk Chen 
433d6a0560bSZakk Chen   constexpr int Log2LMULs[] = {-3, -2, -1, 0, 1, 2, 3};
434d6a0560bSZakk Chen   // Print RVV boolean types.
435d6a0560bSZakk Chen   for (int Log2LMUL : Log2LMULs) {
4363fe89be8SKito Cheng     auto T = TypeCache.computeType(BasicType::Int8, Log2LMUL,
4377ff0bf57SKito Cheng                                    PrototypeDescriptor::Mask);
43897afce08SKazu Hirata     if (T)
439fc6ca0d0SFangrui Song       printType(*T);
440d6a0560bSZakk Chen   }
441d6a0560bSZakk Chen   // Print RVV int/float types.
442d6a0560bSZakk Chen   for (char I : StringRef("csil")) {
4437ff0bf57SKito Cheng     BasicType BT = ParseBasicType(I);
444d6a0560bSZakk Chen     for (int Log2LMUL : Log2LMULs) {
4453fe89be8SKito Cheng       auto T = TypeCache.computeType(BT, Log2LMUL, PrototypeDescriptor::Vector);
44697afce08SKazu Hirata       if (T) {
447fc6ca0d0SFangrui Song         printType(*T);
4483fe89be8SKito Cheng         auto UT = TypeCache.computeType(
4497ff0bf57SKito Cheng             BT, Log2LMUL,
4507ff0bf57SKito Cheng             PrototypeDescriptor(BaseTypeModifier::Vector,
4517ff0bf57SKito Cheng                                 VectorTypeModifier::NoModifier,
4527ff0bf57SKito Cheng                                 TypeModifier::UnsignedInteger));
453fc6ca0d0SFangrui Song         printType(*UT);
454d6a0560bSZakk Chen       }
4555847ec4dSeopXD       for (int NF = 2; NF <= 8; ++NF) {
4560019226cSeopXD         auto TupleT = TypeCache.computeType(
4570019226cSeopXD             BT, Log2LMUL,
4585847ec4dSeopXD             PrototypeDescriptor(BaseTypeModifier::Vector, getTupleVTM(NF),
4590019226cSeopXD                                 TypeModifier::SignedInteger));
4605847ec4dSeopXD         auto TupleUT = TypeCache.computeType(
4615847ec4dSeopXD             BT, Log2LMUL,
4625847ec4dSeopXD             PrototypeDescriptor(BaseTypeModifier::Vector, getTupleVTM(NF),
4635847ec4dSeopXD                                 TypeModifier::UnsignedInteger));
4640019226cSeopXD         if (TupleT)
4650019226cSeopXD           printType(*TupleT);
4665847ec4dSeopXD         if (TupleUT)
4675847ec4dSeopXD           printType(*TupleUT);
4680019226cSeopXD       }
469d6a0560bSZakk Chen     }
470d6a0560bSZakk Chen   }
471235e90c1SeopXD 
472fbdf6e27SShao-Ce SUN   for (BasicType BT : {BasicType::Float16, BasicType::Float32,
473fbdf6e27SShao-Ce SUN                        BasicType::Float64, BasicType::BFloat16}) {
474d6a0560bSZakk Chen     for (int Log2LMUL : Log2LMULs) {
4759efa4cdbSeopXD       auto T = TypeCache.computeType(BT, Log2LMUL, PrototypeDescriptor::Vector);
47697afce08SKazu Hirata       if (T)
477fc6ca0d0SFangrui Song         printType(*T);
4785847ec4dSeopXD       for (int NF = 2; NF <= 8; ++NF) {
4795847ec4dSeopXD         auto TupleT = TypeCache.computeType(
4805847ec4dSeopXD             BT, Log2LMUL,
4815847ec4dSeopXD             PrototypeDescriptor(BaseTypeModifier::Vector, getTupleVTM(NF),
4821c937819SYueh-Ting (eop) Chen                                 (BT == BasicType::BFloat16
4831c937819SYueh-Ting (eop) Chen                                      ? TypeModifier::BFloat
4841c937819SYueh-Ting (eop) Chen                                      : TypeModifier::Float)));
4855847ec4dSeopXD         if (TupleT)
4865847ec4dSeopXD           printType(*TupleT);
4875847ec4dSeopXD       }
488d6a0560bSZakk Chen     }
489d6a0560bSZakk Chen   }
490d6a0560bSZakk Chen 
491d6a0560bSZakk Chen   OS << "\n#ifdef __cplusplus\n";
492d6a0560bSZakk Chen   OS << "}\n";
493477f5f4fSjacquesguan   OS << "#endif // __cplusplus\n";
494d6a0560bSZakk Chen   OS << "#endif // __RISCV_VECTOR_H\n";
495d6a0560bSZakk Chen }
496d6a0560bSZakk Chen 
497d6a0560bSZakk Chen void RVVEmitter::createBuiltins(raw_ostream &OS) {
498d6a0560bSZakk Chen   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
499d6a0560bSZakk Chen   createRVVIntrinsics(Defs);
500d6a0560bSZakk Chen 
501e2b7aabbSCraig Topper   // Map to keep track of which builtin names have already been emitted.
502e2b7aabbSCraig Topper   StringMap<RVVIntrinsic *> BuiltinMap;
503e2b7aabbSCraig Topper 
504d6a0560bSZakk Chen   OS << "#if defined(TARGET_BUILTIN) && !defined(RISCVV_BUILTIN)\n";
505d6a0560bSZakk Chen   OS << "#define RISCVV_BUILTIN(ID, TYPE, ATTRS) TARGET_BUILTIN(ID, TYPE, "
506bfb4c0c3Sjacquesguan         "ATTRS, \"zve32x\")\n";
507d6a0560bSZakk Chen   OS << "#endif\n";
508d6a0560bSZakk Chen   for (auto &Def : Defs) {
509e2b7aabbSCraig Topper     auto P =
510e2b7aabbSCraig Topper         BuiltinMap.insert(std::make_pair(Def->getBuiltinName(), Def.get()));
511e2b7aabbSCraig Topper     if (!P.second) {
51223d60ce1SZakk Chen       // Verf that this would have produced the same builtin definition.
51323d60ce1SZakk Chen       if (P.first->second->hasBuiltinAlias() != Def->hasBuiltinAlias())
514e2b7aabbSCraig Topper         PrintFatalError("Builtin with same name has different hasAutoDef");
51523d60ce1SZakk Chen       else if (!Def->hasBuiltinAlias() &&
51623d60ce1SZakk Chen                P.first->second->getBuiltinTypeStr() != Def->getBuiltinTypeStr())
517e2b7aabbSCraig Topper         PrintFatalError("Builtin with same name has different type string");
518e2b7aabbSCraig Topper       continue;
519e2b7aabbSCraig Topper     }
520e2b7aabbSCraig Topper     OS << "RISCVV_BUILTIN(__builtin_rvv_" << Def->getBuiltinName() << ",\"";
52123d60ce1SZakk Chen     if (!Def->hasBuiltinAlias())
522e2b7aabbSCraig Topper       OS << Def->getBuiltinTypeStr();
523e2b7aabbSCraig Topper     OS << "\", \"n\")\n";
524d6a0560bSZakk Chen   }
525d6a0560bSZakk Chen   OS << "#undef RISCVV_BUILTIN\n";
526d6a0560bSZakk Chen }
527d6a0560bSZakk Chen 
528d6a0560bSZakk Chen void RVVEmitter::createCodeGen(raw_ostream &OS) {
529d6a0560bSZakk Chen   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
530d6a0560bSZakk Chen   createRVVIntrinsics(Defs);
5318f683366SZakk Chen   // IR name could be empty, use the stable sort preserves the relative order.
5320e948bfdSRahul Joshi   stable_sort(Defs, [](const std::unique_ptr<RVVIntrinsic> &A,
533d6a0560bSZakk Chen                        const std::unique_ptr<RVVIntrinsic> &B) {
53471fd6616SZakk Chen     if (A->getIRName() == B->getIRName())
5351deb6bceSeopXD       return (A->getPolicyAttrs() < B->getPolicyAttrs());
53671fd6616SZakk Chen     return (A->getIRName() < B->getIRName());
537d6a0560bSZakk Chen   });
538e2b7aabbSCraig Topper 
539e2b7aabbSCraig Topper   // Map to keep track of which builtin names have already been emitted.
540e2b7aabbSCraig Topper   StringMap<RVVIntrinsic *> BuiltinMap;
541e2b7aabbSCraig Topper 
542239127d7SBrandon Wu   // Print switch body when the ir name, ManualCodegen, policy or log2sew
543239127d7SBrandon Wu   // changes from previous iteration.
544d6a0560bSZakk Chen   RVVIntrinsic *PrevDef = Defs.begin()->get();
545d6a0560bSZakk Chen   for (auto &Def : Defs) {
546d6a0560bSZakk Chen     StringRef CurIRName = Def->getIRName();
5478f683366SZakk Chen     if (CurIRName != PrevDef->getIRName() ||
54871fd6616SZakk Chen         (Def->getManualCodegen() != PrevDef->getManualCodegen()) ||
549239127d7SBrandon Wu         (Def->getPolicyAttrs() != PrevDef->getPolicyAttrs()) ||
550239127d7SBrandon Wu         (getSegInstLog2SEW(Def->getOverloadedName()) !=
551239127d7SBrandon Wu          getSegInstLog2SEW(PrevDef->getOverloadedName()))) {
552f26c41e8SKito Cheng       emitCodeGenSwitchBody(PrevDef, OS);
553d6a0560bSZakk Chen     }
554d6a0560bSZakk Chen     PrevDef = Def.get();
555e2b7aabbSCraig Topper 
556e2b7aabbSCraig Topper     auto P =
557e2b7aabbSCraig Topper         BuiltinMap.insert(std::make_pair(Def->getBuiltinName(), Def.get()));
558e2b7aabbSCraig Topper     if (P.second) {
559e2b7aabbSCraig Topper       OS << "case RISCVVector::BI__builtin_rvv_" << Def->getBuiltinName()
560e2b7aabbSCraig Topper          << ":\n";
561e2b7aabbSCraig Topper       continue;
562e2b7aabbSCraig Topper     }
563e2b7aabbSCraig Topper 
564e2b7aabbSCraig Topper     if (P.first->second->getIRName() != Def->getIRName())
565e2b7aabbSCraig Topper       PrintFatalError("Builtin with same name has different IRName");
566e2b7aabbSCraig Topper     else if (P.first->second->getManualCodegen() != Def->getManualCodegen())
567e2b7aabbSCraig Topper       PrintFatalError("Builtin with same name has different ManualCodegen");
56823d60ce1SZakk Chen     else if (P.first->second->isMasked() != Def->isMasked())
56923d60ce1SZakk Chen       PrintFatalError("Builtin with same name has different isMasked");
570e2b7aabbSCraig Topper     else if (P.first->second->hasVL() != Def->hasVL())
57123d60ce1SZakk Chen       PrintFatalError("Builtin with same name has different hasVL");
57223d60ce1SZakk Chen     else if (P.first->second->getPolicyScheme() != Def->getPolicyScheme())
57323d60ce1SZakk Chen       PrintFatalError("Builtin with same name has different getPolicyScheme");
574e2b7aabbSCraig Topper     else if (P.first->second->getIntrinsicTypes() != Def->getIntrinsicTypes())
575e2b7aabbSCraig Topper       PrintFatalError("Builtin with same name has different IntrinsicTypes");
576d6a0560bSZakk Chen   }
577f26c41e8SKito Cheng   emitCodeGenSwitchBody(Defs.back().get(), OS);
578d6a0560bSZakk Chen   OS << "\n";
579d6a0560bSZakk Chen }
580d6a0560bSZakk Chen 
581d6a0560bSZakk Chen void RVVEmitter::createRVVIntrinsics(
5827a5cb15eSKito Cheng     std::vector<std::unique_ptr<RVVIntrinsic>> &Out,
5837a5cb15eSKito Cheng     std::vector<SemaRecord> *SemaRecords) {
584974fa852SRahul Joshi   for (const Record *R : Records.getAllDerivedDefinitions("RVVBuiltin")) {
585d6a0560bSZakk Chen     StringRef Name = R->getValueAsString("Name");
58688c2d4c8SZakk Chen     StringRef SuffixProto = R->getValueAsString("Suffix");
58779e3d57fSZakk Chen     StringRef OverloadedName = R->getValueAsString("OverloadedName");
58879e3d57fSZakk Chen     StringRef OverloadedSuffixProto = R->getValueAsString("OverloadedSuffix");
589d6a0560bSZakk Chen     StringRef Prototypes = R->getValueAsString("Prototype");
590d6a0560bSZakk Chen     StringRef TypeRange = R->getValueAsString("TypeRange");
59123d60ce1SZakk Chen     bool HasMasked = R->getValueAsBit("HasMasked");
592d6a0560bSZakk Chen     bool HasMaskedOffOperand = R->getValueAsBit("HasMaskedOffOperand");
593d6a0560bSZakk Chen     bool HasVL = R->getValueAsBit("HasVL");
594974fa852SRahul Joshi     const Record *MPSRecord = R->getValueAsDef("MaskedPolicyScheme");
595bc4eef50SZakk Chen     auto MaskedPolicyScheme =
596bc4eef50SZakk Chen         static_cast<PolicyScheme>(MPSRecord->getValueAsInt("Value"));
597974fa852SRahul Joshi     const Record *UMPSRecord = R->getValueAsDef("UnMaskedPolicyScheme");
598bc4eef50SZakk Chen     auto UnMaskedPolicyScheme =
599bc4eef50SZakk Chen         static_cast<PolicyScheme>(UMPSRecord->getValueAsInt("Value"));
600d6a0560bSZakk Chen     std::vector<int64_t> Log2LMULList = R->getValueAsListOfInts("Log2LMUL");
60171fd6616SZakk Chen     bool HasTailPolicy = R->getValueAsBit("HasTailPolicy");
60271fd6616SZakk Chen     bool HasMaskPolicy = R->getValueAsBit("HasMaskPolicy");
60371fd6616SZakk Chen     bool SupportOverloading = R->getValueAsBit("SupportOverloading");
60423d60ce1SZakk Chen     bool HasBuiltinAlias = R->getValueAsBit("HasBuiltinAlias");
60595c0125fSZakk Chen     StringRef ManualCodegen = R->getValueAsString("ManualCodegen");
606d6a0560bSZakk Chen     std::vector<int64_t> IntrinsicTypes =
607d6a0560bSZakk Chen         R->getValueAsListOfInts("IntrinsicTypes");
6089ea3dfa5Sjacquesguan     std::vector<StringRef> RequiredFeatures =
6099ea3dfa5Sjacquesguan         R->getValueAsListOfStrings("RequiredFeatures");
610d6a0560bSZakk Chen     StringRef IRName = R->getValueAsString("IRName");
61123d60ce1SZakk Chen     StringRef MaskedIRName = R->getValueAsString("MaskedIRName");
612593bf9b4SHsiangkai Wang     unsigned NF = R->getValueAsInt("NF");
6130019226cSeopXD     bool IsTuple = R->getValueAsBit("IsTuple");
61476482078SeopXD     bool HasFRMRoundModeOp = R->getValueAsBit("HasFRMRoundModeOp");
615d6a0560bSZakk Chen 
616d94a315eSeopXD     const Policy DefaultPolicy;
61762449823SeopXD     SmallVector<Policy> SupportedUnMaskedPolicies =
618d94a315eSeopXD         RVVIntrinsic::getSupportedUnMaskedPolicies();
61971fd6616SZakk Chen     SmallVector<Policy> SupportedMaskedPolicies =
62071fd6616SZakk Chen         RVVIntrinsic::getSupportedMaskedPolicies(HasTailPolicy, HasMaskPolicy);
62171fd6616SZakk Chen 
622d6a0560bSZakk Chen     // Parse prototype and create a list of primitive type with transformers
6231467e01fSKito Cheng     // (operand) in Prototype. Prototype[0] is output operand.
624bc4eef50SZakk Chen     SmallVector<PrototypeDescriptor> BasicPrototype =
625bc4eef50SZakk Chen         parsePrototypes(Prototypes);
6267ff0bf57SKito Cheng 
6271467e01fSKito Cheng     SmallVector<PrototypeDescriptor> SuffixDesc = parsePrototypes(SuffixProto);
6281467e01fSKito Cheng     SmallVector<PrototypeDescriptor> OverloadedSuffixDesc =
6291467e01fSKito Cheng         parsePrototypes(OverloadedSuffixProto);
630d6a0560bSZakk Chen 
631d6a0560bSZakk Chen     // Compute Builtin types
6326f0d0be5SeopXD     auto Prototype = RVVIntrinsic::computeBuiltinTypes(
6336f0d0be5SeopXD         BasicPrototype, /*IsMasked=*/false,
6346f0d0be5SeopXD         /*HasMaskedOffOperand=*/false, HasVL, NF, UnMaskedPolicyScheme,
6350019226cSeopXD         DefaultPolicy, IsTuple);
6360e948bfdSRahul Joshi     SmallVector<PrototypeDescriptor> MaskedPrototype;
6371cb38271SeopXD     if (HasMasked)
6381cb38271SeopXD       MaskedPrototype = RVVIntrinsic::computeBuiltinTypes(
63971fd6616SZakk Chen           BasicPrototype, /*IsMasked=*/true, HasMaskedOffOperand, HasVL, NF,
6400019226cSeopXD           MaskedPolicyScheme, DefaultPolicy, IsTuple);
641d6a0560bSZakk Chen 
64295c0125fSZakk Chen     // Create Intrinsics for each type and LMUL.
643d6a0560bSZakk Chen     for (char I : TypeRange) {
644d6a0560bSZakk Chen       for (int Log2LMUL : Log2LMULList) {
6457ff0bf57SKito Cheng         BasicType BT = ParseBasicType(I);
6469cf4419eSKazu Hirata         std::optional<RVVTypes> Types =
6473fe89be8SKito Cheng             TypeCache.computeTypes(BT, Log2LMUL, NF, Prototype);
648d6a0560bSZakk Chen         // Ignored to create new intrinsic if there are any illegal types.
649452db157SKazu Hirata         if (!Types)
650d6a0560bSZakk Chen           continue;
651d6a0560bSZakk Chen 
6523fe89be8SKito Cheng         auto SuffixStr =
6533fe89be8SKito Cheng             RVVIntrinsic::getSuffixStr(TypeCache, BT, Log2LMUL, SuffixDesc);
6543fe89be8SKito Cheng         auto OverloadedSuffixStr = RVVIntrinsic::getSuffixStr(
6553fe89be8SKito Cheng             TypeCache, BT, Log2LMUL, OverloadedSuffixDesc);
65623d60ce1SZakk Chen         // Create a unmasked intrinsic
657d6a0560bSZakk Chen         Out.push_back(std::make_unique<RVVIntrinsic>(
6581467e01fSKito Cheng             Name, SuffixStr, OverloadedName, OverloadedSuffixStr, IRName,
65923d60ce1SZakk Chen             /*IsMasked=*/false, /*HasMaskedOffOperand=*/false, HasVL,
66071fd6616SZakk Chen             UnMaskedPolicyScheme, SupportOverloading, HasBuiltinAlias,
66184741940SCraig Topper             ManualCodegen, *Types, IntrinsicTypes, NF, DefaultPolicy,
66284741940SCraig Topper             HasFRMRoundModeOp));
66371fd6616SZakk Chen         if (UnMaskedPolicyScheme != PolicyScheme::SchemeNone)
66471fd6616SZakk Chen           for (auto P : SupportedUnMaskedPolicies) {
66571fd6616SZakk Chen             SmallVector<PrototypeDescriptor> PolicyPrototype =
66671fd6616SZakk Chen                 RVVIntrinsic::computeBuiltinTypes(
66771fd6616SZakk Chen                     BasicPrototype, /*IsMasked=*/false,
66871fd6616SZakk Chen                     /*HasMaskedOffOperand=*/false, HasVL, NF,
6690019226cSeopXD                     UnMaskedPolicyScheme, P, IsTuple);
6709cf4419eSKazu Hirata             std::optional<RVVTypes> PolicyTypes =
6713fe89be8SKito Cheng                 TypeCache.computeTypes(BT, Log2LMUL, NF, PolicyPrototype);
67271fd6616SZakk Chen             Out.push_back(std::make_unique<RVVIntrinsic>(
67371fd6616SZakk Chen                 Name, SuffixStr, OverloadedName, OverloadedSuffixStr, IRName,
67471fd6616SZakk Chen                 /*IsMask=*/false, /*HasMaskedOffOperand=*/false, HasVL,
67571fd6616SZakk Chen                 UnMaskedPolicyScheme, SupportOverloading, HasBuiltinAlias,
67684741940SCraig Topper                 ManualCodegen, *PolicyTypes, IntrinsicTypes, NF, P,
67784741940SCraig Topper                 HasFRMRoundModeOp));
67871fd6616SZakk Chen           }
67971fd6616SZakk Chen         if (!HasMasked)
68071fd6616SZakk Chen           continue;
68123d60ce1SZakk Chen         // Create a masked intrinsic
6829cf4419eSKazu Hirata         std::optional<RVVTypes> MaskTypes =
6831ab7e768SeopXD             TypeCache.computeTypes(BT, Log2LMUL, NF, MaskedPrototype);
68471fd6616SZakk Chen         Out.push_back(std::make_unique<RVVIntrinsic>(
68571fd6616SZakk Chen             Name, SuffixStr, OverloadedName, OverloadedSuffixStr, MaskedIRName,
68671fd6616SZakk Chen             /*IsMasked=*/true, HasMaskedOffOperand, HasVL, MaskedPolicyScheme,
6876b282294SeopXD             SupportOverloading, HasBuiltinAlias, ManualCodegen, *MaskTypes,
68884741940SCraig Topper             IntrinsicTypes, NF, DefaultPolicy, HasFRMRoundModeOp));
68971fd6616SZakk Chen         if (MaskedPolicyScheme == PolicyScheme::SchemeNone)
69071fd6616SZakk Chen           continue;
69171fd6616SZakk Chen         for (auto P : SupportedMaskedPolicies) {
69271fd6616SZakk Chen           SmallVector<PrototypeDescriptor> PolicyPrototype =
69371fd6616SZakk Chen               RVVIntrinsic::computeBuiltinTypes(
69471fd6616SZakk Chen                   BasicPrototype, /*IsMasked=*/true, HasMaskedOffOperand, HasVL,
6950019226cSeopXD                   NF, MaskedPolicyScheme, P, IsTuple);
6969cf4419eSKazu Hirata           std::optional<RVVTypes> PolicyTypes =
6973fe89be8SKito Cheng               TypeCache.computeTypes(BT, Log2LMUL, NF, PolicyPrototype);
698d6a0560bSZakk Chen           Out.push_back(std::make_unique<RVVIntrinsic>(
6991467e01fSKito Cheng               Name, SuffixStr, OverloadedName, OverloadedSuffixStr,
70071fd6616SZakk Chen               MaskedIRName, /*IsMasked=*/true, HasMaskedOffOperand, HasVL,
70171fd6616SZakk Chen               MaskedPolicyScheme, SupportOverloading, HasBuiltinAlias,
70284741940SCraig Topper               ManualCodegen, *PolicyTypes, IntrinsicTypes, NF, P,
70384741940SCraig Topper               HasFRMRoundModeOp));
704d6a0560bSZakk Chen         }
70571fd6616SZakk Chen       } // End for Log2LMULList
70671fd6616SZakk Chen     }   // End for TypeRange
7077a5cb15eSKito Cheng 
7087a5cb15eSKito Cheng     // We don't emit vsetvli and vsetvlimax for SemaRecord.
7097a5cb15eSKito Cheng     // They are written in riscv_vector.td and will emit those marco define in
7107a5cb15eSKito Cheng     // riscv_vector.h
7117a5cb15eSKito Cheng     if (Name == "vsetvli" || Name == "vsetvlimax")
7127a5cb15eSKito Cheng       continue;
7137a5cb15eSKito Cheng 
7147a5cb15eSKito Cheng     if (!SemaRecords)
7157a5cb15eSKito Cheng       continue;
7167a5cb15eSKito Cheng 
7177a5cb15eSKito Cheng     // Create SemaRecord
7187a5cb15eSKito Cheng     SemaRecord SR;
7197a5cb15eSKito Cheng     SR.Name = Name.str();
7207a5cb15eSKito Cheng     SR.OverloadedName = OverloadedName.str();
7217a5cb15eSKito Cheng     BasicType TypeRangeMask = BasicType::Unknown;
7227a5cb15eSKito Cheng     for (char I : TypeRange)
7237a5cb15eSKito Cheng       TypeRangeMask |= ParseBasicType(I);
7247a5cb15eSKito Cheng 
7257a5cb15eSKito Cheng     SR.TypeRangeMask = static_cast<unsigned>(TypeRangeMask);
7267a5cb15eSKito Cheng 
7277a5cb15eSKito Cheng     unsigned Log2LMULMask = 0;
7287a5cb15eSKito Cheng     for (int Log2LMUL : Log2LMULList)
7297a5cb15eSKito Cheng       Log2LMULMask |= 1 << (Log2LMUL + 3);
7307a5cb15eSKito Cheng 
7317a5cb15eSKito Cheng     SR.Log2LMULMask = Log2LMULMask;
7327a5cb15eSKito Cheng 
7337a5cb15eSKito Cheng     SR.RequiredExtensions = 0;
7347a5cb15eSKito Cheng     for (auto RequiredFeature : RequiredFeatures) {
73509058654SEric Biggers       RVVRequire RequireExt =
73609058654SEric Biggers           StringSwitch<RVVRequire>(RequiredFeature)
7377a5cb15eSKito Cheng               .Case("RV64", RVV_REQ_RV64)
7381e51b359SJim Lin               .Case("Zvfhmin", RVV_REQ_Zvfhmin)
739cd5c4cb7SKito Cheng               .Case("Xsfvcp", RVV_REQ_Xsfvcp)
74074f38df1SBrandon Wu               .Case("Xsfvfnrclipxfqf", RVV_REQ_Xsfvfnrclipxfqf)
741945d2e6eSBrandon Wu               .Case("Xsfvfwmaccqqq", RVV_REQ_Xsfvfwmaccqqq)
742d1985e3dSBrandon Wu               .Case("Xsfvqmaccdod", RVV_REQ_Xsfvqmaccdod)
743d1985e3dSBrandon Wu               .Case("Xsfvqmaccqoq", RVV_REQ_Xsfvqmaccqoq)
7448609819eS4vtomat               .Case("Zvbb", RVV_REQ_Zvbb)
7458609819eS4vtomat               .Case("Zvbc", RVV_REQ_Zvbc)
7468609819eS4vtomat               .Case("Zvkb", RVV_REQ_Zvkb)
7478609819eS4vtomat               .Case("Zvkg", RVV_REQ_Zvkg)
7488609819eS4vtomat               .Case("Zvkned", RVV_REQ_Zvkned)
7498609819eS4vtomat               .Case("Zvknha", RVV_REQ_Zvknha)
75065dc96c2SBrandon Wu               .Case("Zvknhb", RVV_REQ_Zvknhb)
7518609819eS4vtomat               .Case("Zvksed", RVV_REQ_Zvksed)
7528609819eS4vtomat               .Case("Zvksh", RVV_REQ_Zvksh)
753ae5ed2a5SBrandon Wu               .Case("Zvfbfwma", RVV_REQ_Zvfbfwma)
7543fa6b9c6SBrandon Wu               .Case("Zvfbfmin", RVV_REQ_Zvfbfmin)
75540c2aaf5SBrandon Wu               .Case("Zvfh", RVV_REQ_Zvfh)
75609058654SEric Biggers               .Case("Experimental", RVV_REQ_Experimental)
7577a5cb15eSKito Cheng               .Default(RVV_REQ_None);
7587a5cb15eSKito Cheng       assert(RequireExt != RVV_REQ_None && "Unrecognized required feature?");
7597a5cb15eSKito Cheng       SR.RequiredExtensions |= RequireExt;
7607a5cb15eSKito Cheng     }
7617a5cb15eSKito Cheng 
7627a5cb15eSKito Cheng     SR.NF = NF;
76393f8657cSZakk Chen     SR.HasMasked = HasMasked;
76493f8657cSZakk Chen     SR.HasVL = HasVL;
76593f8657cSZakk Chen     SR.HasMaskedOffOperand = HasMaskedOffOperand;
76671fd6616SZakk Chen     SR.HasTailPolicy = HasTailPolicy;
76771fd6616SZakk Chen     SR.HasMaskPolicy = HasMaskPolicy;
76871fd6616SZakk Chen     SR.UnMaskedPolicyScheme = static_cast<uint8_t>(UnMaskedPolicyScheme);
76971fd6616SZakk Chen     SR.MaskedPolicyScheme = static_cast<uint8_t>(MaskedPolicyScheme);
77093f8657cSZakk Chen     SR.Prototype = std::move(BasicPrototype);
7717a5cb15eSKito Cheng     SR.Suffix = parsePrototypes(SuffixProto);
7727a5cb15eSKito Cheng     SR.OverloadedSuffix = parsePrototypes(OverloadedSuffixProto);
7730019226cSeopXD     SR.IsTuple = IsTuple;
77476482078SeopXD     SR.HasFRMRoundModeOp = HasFRMRoundModeOp;
7757a5cb15eSKito Cheng 
7767a5cb15eSKito Cheng     SemaRecords->push_back(SR);
777d6a0560bSZakk Chen   }
778d6a0560bSZakk Chen }
779d6a0560bSZakk Chen 
78023d60ce1SZakk Chen void RVVEmitter::printHeaderCode(raw_ostream &OS) {
781974fa852SRahul Joshi   for (const Record *R : Records.getAllDerivedDefinitions("RVVHeader")) {
7825158cfefSHsiangkai Wang     StringRef HeaderCodeStr = R->getValueAsString("HeaderCode");
7835158cfefSHsiangkai Wang     OS << HeaderCodeStr.str();
7845158cfefSHsiangkai Wang   }
7855158cfefSHsiangkai Wang }
7865158cfefSHsiangkai Wang 
7877a5cb15eSKito Cheng void RVVEmitter::createRVVIntrinsicRecords(std::vector<RVVIntrinsicRecord> &Out,
7887a5cb15eSKito Cheng                                            SemaSignatureTable &SST,
7897a5cb15eSKito Cheng                                            ArrayRef<SemaRecord> SemaRecords) {
7907a5cb15eSKito Cheng   SST.init(SemaRecords);
7917a5cb15eSKito Cheng 
7927a5cb15eSKito Cheng   for (const auto &SR : SemaRecords) {
7937a5cb15eSKito Cheng     Out.emplace_back(RVVIntrinsicRecord());
7947a5cb15eSKito Cheng     RVVIntrinsicRecord &R = Out.back();
7957a5cb15eSKito Cheng     R.Name = SR.Name.c_str();
7967a5cb15eSKito Cheng     R.OverloadedName = SR.OverloadedName.c_str();
7977a5cb15eSKito Cheng     R.PrototypeIndex = SST.getIndex(SR.Prototype);
7987a5cb15eSKito Cheng     R.SuffixIndex = SST.getIndex(SR.Suffix);
7997a5cb15eSKito Cheng     R.OverloadedSuffixIndex = SST.getIndex(SR.OverloadedSuffix);
8007a5cb15eSKito Cheng     R.PrototypeLength = SR.Prototype.size();
8017a5cb15eSKito Cheng     R.SuffixLength = SR.Suffix.size();
8027a5cb15eSKito Cheng     R.OverloadedSuffixSize = SR.OverloadedSuffix.size();
8037a5cb15eSKito Cheng     R.RequiredExtensions = SR.RequiredExtensions;
8047a5cb15eSKito Cheng     R.TypeRangeMask = SR.TypeRangeMask;
8057a5cb15eSKito Cheng     R.Log2LMULMask = SR.Log2LMULMask;
8067a5cb15eSKito Cheng     R.NF = SR.NF;
80793f8657cSZakk Chen     R.HasMasked = SR.HasMasked;
80893f8657cSZakk Chen     R.HasVL = SR.HasVL;
80993f8657cSZakk Chen     R.HasMaskedOffOperand = SR.HasMaskedOffOperand;
81071fd6616SZakk Chen     R.HasTailPolicy = SR.HasTailPolicy;
81171fd6616SZakk Chen     R.HasMaskPolicy = SR.HasMaskPolicy;
81271fd6616SZakk Chen     R.UnMaskedPolicyScheme = SR.UnMaskedPolicyScheme;
81371fd6616SZakk Chen     R.MaskedPolicyScheme = SR.MaskedPolicyScheme;
8140019226cSeopXD     R.IsTuple = SR.IsTuple;
81576482078SeopXD     R.HasFRMRoundModeOp = SR.HasFRMRoundModeOp;
8167a5cb15eSKito Cheng 
8177a5cb15eSKito Cheng     assert(R.PrototypeIndex !=
8187a5cb15eSKito Cheng            static_cast<uint16_t>(SemaSignatureTable::INVALID_INDEX));
8197a5cb15eSKito Cheng     assert(R.SuffixIndex !=
8207a5cb15eSKito Cheng            static_cast<uint16_t>(SemaSignatureTable::INVALID_INDEX));
8217a5cb15eSKito Cheng     assert(R.OverloadedSuffixIndex !=
8227a5cb15eSKito Cheng            static_cast<uint16_t>(SemaSignatureTable::INVALID_INDEX));
823d6a0560bSZakk Chen   }
824d6a0560bSZakk Chen }
825d6a0560bSZakk Chen 
8267a5cb15eSKito Cheng void RVVEmitter::createSema(raw_ostream &OS) {
8277a5cb15eSKito Cheng   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
8287a5cb15eSKito Cheng   std::vector<RVVIntrinsicRecord> RVVIntrinsicRecords;
8297a5cb15eSKito Cheng   SemaSignatureTable SST;
8307a5cb15eSKito Cheng   std::vector<SemaRecord> SemaRecords;
8317a5cb15eSKito Cheng 
8327a5cb15eSKito Cheng   createRVVIntrinsics(Defs, &SemaRecords);
8337a5cb15eSKito Cheng 
8347a5cb15eSKito Cheng   createRVVIntrinsicRecords(RVVIntrinsicRecords, SST, SemaRecords);
8357a5cb15eSKito Cheng 
8367a5cb15eSKito Cheng   // Emit signature table for SemaRISCVVectorLookup.cpp.
8377a5cb15eSKito Cheng   OS << "#ifdef DECL_SIGNATURE_TABLE\n";
8387a5cb15eSKito Cheng   SST.print(OS);
8397a5cb15eSKito Cheng   OS << "#endif\n";
8407a5cb15eSKito Cheng 
8417a5cb15eSKito Cheng   // Emit RVVIntrinsicRecords for SemaRISCVVectorLookup.cpp.
8427a5cb15eSKito Cheng   OS << "#ifdef DECL_INTRINSIC_RECORDS\n";
8437a5cb15eSKito Cheng   for (const RVVIntrinsicRecord &Record : RVVIntrinsicRecords)
8447a5cb15eSKito Cheng     OS << Record;
8457a5cb15eSKito Cheng   OS << "#endif\n";
846d6a0560bSZakk Chen }
847d6a0560bSZakk Chen 
848d6a0560bSZakk Chen namespace clang {
849974fa852SRahul Joshi void EmitRVVHeader(const RecordKeeper &Records, raw_ostream &OS) {
850d6a0560bSZakk Chen   RVVEmitter(Records).createHeader(OS);
851d6a0560bSZakk Chen }
852d6a0560bSZakk Chen 
853974fa852SRahul Joshi void EmitRVVBuiltins(const RecordKeeper &Records, raw_ostream &OS) {
854d6a0560bSZakk Chen   RVVEmitter(Records).createBuiltins(OS);
855d6a0560bSZakk Chen }
856d6a0560bSZakk Chen 
857974fa852SRahul Joshi void EmitRVVBuiltinCG(const RecordKeeper &Records, raw_ostream &OS) {
858d6a0560bSZakk Chen   RVVEmitter(Records).createCodeGen(OS);
859d6a0560bSZakk Chen }
860d6a0560bSZakk Chen 
861974fa852SRahul Joshi void EmitRVVBuiltinSema(const RecordKeeper &Records, raw_ostream &OS) {
8627a5cb15eSKito Cheng   RVVEmitter(Records).createSema(OS);
8637a5cb15eSKito Cheng }
8647a5cb15eSKito Cheng 
865d6a0560bSZakk Chen } // End namespace clang
866