Path: blob/main/contrib/llvm-project/clang/utils/TableGen/RISCVVEmitter.cpp
35231 views
//===- RISCVVEmitter.cpp - Generate riscv_vector.h for use with clang -----===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This tablegen backend is responsible for emitting riscv_vector.h which9// includes a declaration and definition of each intrinsic functions specified10// in https://github.com/riscv/rvv-intrinsic-doc.11//12// See also the documentation in include/clang/Basic/riscv_vector.td.13//14//===----------------------------------------------------------------------===//1516#include "clang/Support/RISCVVIntrinsicUtils.h"17#include "llvm/ADT/ArrayRef.h"18#include "llvm/ADT/SmallSet.h"19#include "llvm/ADT/StringExtras.h"20#include "llvm/ADT/StringMap.h"21#include "llvm/ADT/StringSet.h"22#include "llvm/ADT/StringSwitch.h"23#include "llvm/ADT/Twine.h"24#include "llvm/TableGen/Error.h"25#include "llvm/TableGen/Record.h"26#include <numeric>27#include <optional>2829using namespace llvm;30using namespace clang::RISCV;3132namespace {33struct SemaRecord {34// Intrinsic name, e.g. vadd_vv35std::string Name;3637// Overloaded intrinsic name, could be empty if can be computed from Name38// e.g. vadd39std::string OverloadedName;4041// Supported type, mask of BasicType.42unsigned TypeRangeMask;4344// Supported LMUL.45unsigned Log2LMULMask;4647// Required extensions for this intrinsic.48uint32_t RequiredExtensions;4950// Prototype for this intrinsic.51SmallVector<PrototypeDescriptor> Prototype;5253// Suffix of intrinsic name.54SmallVector<PrototypeDescriptor> Suffix;5556// Suffix of overloaded intrinsic name.57SmallVector<PrototypeDescriptor> OverloadedSuffix;5859// Number of field, large than 1 if it's segment load/store.60unsigned NF;6162bool HasMasked :1;63bool HasVL :1;64bool HasMaskedOffOperand :1;65bool HasTailPolicy : 1;66bool HasMaskPolicy : 1;67bool HasFRMRoundModeOp : 1;68bool IsTuple : 1;69LLVM_PREFERRED_TYPE(PolicyScheme)70uint8_t UnMaskedPolicyScheme : 2;71LLVM_PREFERRED_TYPE(PolicyScheme)72uint8_t MaskedPolicyScheme : 2;73};7475// Compressed function signature table.76class SemaSignatureTable {77private:78std::vector<PrototypeDescriptor> SignatureTable;7980void insert(ArrayRef<PrototypeDescriptor> Signature);8182public:83static constexpr unsigned INVALID_INDEX = ~0U;8485// Create compressed signature table from SemaRecords.86void init(ArrayRef<SemaRecord> SemaRecords);8788// Query the Signature, return INVALID_INDEX if not found.89unsigned getIndex(ArrayRef<PrototypeDescriptor> Signature);9091/// Print signature table in RVVHeader Record to \p OS92void print(raw_ostream &OS);93};9495class RVVEmitter {96private:97RecordKeeper &Records;98RVVTypeCache TypeCache;99100public:101RVVEmitter(RecordKeeper &R) : Records(R) {}102103/// Emit riscv_vector.h104void createHeader(raw_ostream &o);105106/// Emit all the __builtin prototypes and code needed by Sema.107void createBuiltins(raw_ostream &o);108109/// Emit all the information needed to map builtin -> LLVM IR intrinsic.110void createCodeGen(raw_ostream &o);111112/// Emit all the information needed by SemaRISCVVectorLookup.cpp.113/// We've large number of intrinsic function for RVV, creating a customized114/// could speed up the compilation time.115void createSema(raw_ostream &o);116117private:118/// Create all intrinsics and add them to \p Out and SemaRecords.119void createRVVIntrinsics(std::vector<std::unique_ptr<RVVIntrinsic>> &Out,120std::vector<SemaRecord> *SemaRecords = nullptr);121/// Create all intrinsic records and SemaSignatureTable from SemaRecords.122void createRVVIntrinsicRecords(std::vector<RVVIntrinsicRecord> &Out,123SemaSignatureTable &SST,124ArrayRef<SemaRecord> SemaRecords);125126/// Print HeaderCode in RVVHeader Record to \p Out127void printHeaderCode(raw_ostream &OS);128};129130} // namespace131132static BasicType ParseBasicType(char c) {133switch (c) {134case 'c':135return BasicType::Int8;136break;137case 's':138return BasicType::Int16;139break;140case 'i':141return BasicType::Int32;142break;143case 'l':144return BasicType::Int64;145break;146case 'x':147return BasicType::Float16;148break;149case 'f':150return BasicType::Float32;151break;152case 'd':153return BasicType::Float64;154break;155case 'y':156return BasicType::BFloat16;157break;158default:159return BasicType::Unknown;160}161}162163static VectorTypeModifier getTupleVTM(unsigned NF) {164assert(2 <= NF && NF <= 8 && "2 <= NF <= 8");165return static_cast<VectorTypeModifier>(166static_cast<uint8_t>(VectorTypeModifier::Tuple2) + (NF - 2));167}168169void emitCodeGenSwitchBody(const RVVIntrinsic *RVVI, raw_ostream &OS) {170if (!RVVI->getIRName().empty())171OS << " ID = Intrinsic::riscv_" + RVVI->getIRName() + ";\n";172if (RVVI->getNF() >= 2)173OS << " NF = " + utostr(RVVI->getNF()) + ";\n";174175OS << " PolicyAttrs = " << RVVI->getPolicyAttrsBits() << ";\n";176177if (RVVI->hasManualCodegen()) {178OS << "IsMasked = " << (RVVI->isMasked() ? "true" : "false") << ";\n";179OS << RVVI->getManualCodegen();180OS << "break;\n";181return;182}183184for (const auto &I : enumerate(RVVI->getInputTypes())) {185if (I.value()->isPointer()) {186assert(RVVI->getIntrinsicTypes().front() == -1 &&187"RVVI should be vector load intrinsic.");188}189}190191if (RVVI->isMasked()) {192if (RVVI->hasVL()) {193OS << " std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);\n";194if (RVVI->hasPolicyOperand())195OS << " Ops.push_back(ConstantInt::get(Ops.back()->getType(),"196" PolicyAttrs));\n";197if (RVVI->hasMaskedOffOperand() && RVVI->getPolicyAttrs().isTAMAPolicy())198OS << " Ops.insert(Ops.begin(), "199"llvm::PoisonValue::get(ResultType));\n";200// Masked reduction cases.201if (!RVVI->hasMaskedOffOperand() && RVVI->hasPassthruOperand() &&202RVVI->getPolicyAttrs().isTAMAPolicy())203OS << " Ops.insert(Ops.begin(), "204"llvm::PoisonValue::get(ResultType));\n";205} else {206OS << " std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end());\n";207}208} else {209if (RVVI->hasPolicyOperand())210OS << " Ops.push_back(ConstantInt::get(Ops.back()->getType(), "211"PolicyAttrs));\n";212else if (RVVI->hasPassthruOperand() && RVVI->getPolicyAttrs().isTAPolicy())213OS << " Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));\n";214}215216OS << " IntrinsicTypes = {";217ListSeparator LS;218for (const auto &Idx : RVVI->getIntrinsicTypes()) {219if (Idx == -1)220OS << LS << "ResultType";221else222OS << LS << "Ops[" << Idx << "]->getType()";223}224225// VL could be i64 or i32, need to encode it in IntrinsicTypes. VL is226// always last operand.227if (RVVI->hasVL())228OS << ", Ops.back()->getType()";229OS << "};\n";230OS << " break;\n";231}232233//===----------------------------------------------------------------------===//234// SemaSignatureTable implementation235//===----------------------------------------------------------------------===//236void SemaSignatureTable::init(ArrayRef<SemaRecord> SemaRecords) {237// Sort signature entries by length, let longer signature insert first, to238// make it more possible to reuse table entries, that can reduce ~10% table239// size.240struct Compare {241bool operator()(const SmallVector<PrototypeDescriptor> &A,242const SmallVector<PrototypeDescriptor> &B) const {243if (A.size() != B.size())244return A.size() > B.size();245246size_t Len = A.size();247for (size_t i = 0; i < Len; ++i) {248if (A[i] != B[i])249return A[i] < B[i];250}251252return false;253}254};255256std::set<SmallVector<PrototypeDescriptor>, Compare> Signatures;257auto InsertToSignatureSet =258[&](const SmallVector<PrototypeDescriptor> &Signature) {259if (Signature.empty())260return;261262Signatures.insert(Signature);263};264265assert(!SemaRecords.empty());266267for (const SemaRecord &SR : SemaRecords) {268InsertToSignatureSet(SR.Prototype);269InsertToSignatureSet(SR.Suffix);270InsertToSignatureSet(SR.OverloadedSuffix);271}272273for (auto &Sig : Signatures)274insert(Sig);275}276277void SemaSignatureTable::insert(ArrayRef<PrototypeDescriptor> Signature) {278if (getIndex(Signature) != INVALID_INDEX)279return;280281// Insert Signature into SignatureTable if not found in the table.282SignatureTable.insert(SignatureTable.begin(), Signature.begin(),283Signature.end());284}285286unsigned SemaSignatureTable::getIndex(ArrayRef<PrototypeDescriptor> Signature) {287// Empty signature could be point into any index since there is length288// field when we use, so just always point it to 0.289if (Signature.empty())290return 0;291292// Checking Signature already in table or not.293if (Signature.size() <= SignatureTable.size()) {294size_t Bound = SignatureTable.size() - Signature.size() + 1;295for (size_t Index = 0; Index < Bound; ++Index) {296if (equal(Signature.begin(), Signature.end(),297SignatureTable.begin() + Index))298return Index;299}300}301302return INVALID_INDEX;303}304305void SemaSignatureTable::print(raw_ostream &OS) {306for (const auto &Sig : SignatureTable)307OS << "PrototypeDescriptor(" << static_cast<int>(Sig.PT) << ", "308<< static_cast<int>(Sig.VTM) << ", " << static_cast<int>(Sig.TM)309<< "),\n";310}311312//===----------------------------------------------------------------------===//313// RVVEmitter implementation314//===----------------------------------------------------------------------===//315void RVVEmitter::createHeader(raw_ostream &OS) {316317OS << "/*===---- riscv_vector.h - RISC-V V-extension RVVIntrinsics "318"-------------------===\n"319" *\n"320" *\n"321" * Part of the LLVM Project, under the Apache License v2.0 with LLVM "322"Exceptions.\n"323" * See https://llvm.org/LICENSE.txt for license information.\n"324" * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n"325" *\n"326" *===-----------------------------------------------------------------"327"------===\n"328" */\n\n";329330OS << "#ifndef __RISCV_VECTOR_H\n";331OS << "#define __RISCV_VECTOR_H\n\n";332333OS << "#include <stdint.h>\n";334OS << "#include <stddef.h>\n\n";335336OS << "#ifdef __cplusplus\n";337OS << "extern \"C\" {\n";338OS << "#endif\n\n";339340OS << "#pragma clang riscv intrinsic vector\n\n";341342printHeaderCode(OS);343344auto printType = [&](auto T) {345OS << "typedef " << T->getClangBuiltinStr() << " " << T->getTypeStr()346<< ";\n";347};348349constexpr int Log2LMULs[] = {-3, -2, -1, 0, 1, 2, 3};350// Print RVV boolean types.351for (int Log2LMUL : Log2LMULs) {352auto T = TypeCache.computeType(BasicType::Int8, Log2LMUL,353PrototypeDescriptor::Mask);354if (T)355printType(*T);356}357// Print RVV int/float types.358for (char I : StringRef("csil")) {359BasicType BT = ParseBasicType(I);360for (int Log2LMUL : Log2LMULs) {361auto T = TypeCache.computeType(BT, Log2LMUL, PrototypeDescriptor::Vector);362if (T) {363printType(*T);364auto UT = TypeCache.computeType(365BT, Log2LMUL,366PrototypeDescriptor(BaseTypeModifier::Vector,367VectorTypeModifier::NoModifier,368TypeModifier::UnsignedInteger));369printType(*UT);370}371for (int NF = 2; NF <= 8; ++NF) {372auto TupleT = TypeCache.computeType(373BT, Log2LMUL,374PrototypeDescriptor(BaseTypeModifier::Vector, getTupleVTM(NF),375TypeModifier::SignedInteger));376auto TupleUT = TypeCache.computeType(377BT, Log2LMUL,378PrototypeDescriptor(BaseTypeModifier::Vector, getTupleVTM(NF),379TypeModifier::UnsignedInteger));380if (TupleT)381printType(*TupleT);382if (TupleUT)383printType(*TupleUT);384}385}386}387388for (BasicType BT : {BasicType::Float16, BasicType::Float32,389BasicType::Float64, BasicType::BFloat16}) {390for (int Log2LMUL : Log2LMULs) {391auto T = TypeCache.computeType(BT, Log2LMUL, PrototypeDescriptor::Vector);392if (T)393printType(*T);394for (int NF = 2; NF <= 8; ++NF) {395auto TupleT = TypeCache.computeType(396BT, Log2LMUL,397PrototypeDescriptor(BaseTypeModifier::Vector, getTupleVTM(NF),398(BT == BasicType::BFloat16399? TypeModifier::BFloat400: TypeModifier::Float)));401if (TupleT)402printType(*TupleT);403}404}405}406407OS << "#define __riscv_v_intrinsic_overloading 1\n";408409OS << "\n#ifdef __cplusplus\n";410OS << "}\n";411OS << "#endif // __cplusplus\n";412OS << "#endif // __RISCV_VECTOR_H\n";413}414415void RVVEmitter::createBuiltins(raw_ostream &OS) {416std::vector<std::unique_ptr<RVVIntrinsic>> Defs;417createRVVIntrinsics(Defs);418419// Map to keep track of which builtin names have already been emitted.420StringMap<RVVIntrinsic *> BuiltinMap;421422OS << "#if defined(TARGET_BUILTIN) && !defined(RISCVV_BUILTIN)\n";423OS << "#define RISCVV_BUILTIN(ID, TYPE, ATTRS) TARGET_BUILTIN(ID, TYPE, "424"ATTRS, \"zve32x\")\n";425OS << "#endif\n";426for (auto &Def : Defs) {427auto P =428BuiltinMap.insert(std::make_pair(Def->getBuiltinName(), Def.get()));429if (!P.second) {430// Verf that this would have produced the same builtin definition.431if (P.first->second->hasBuiltinAlias() != Def->hasBuiltinAlias())432PrintFatalError("Builtin with same name has different hasAutoDef");433else if (!Def->hasBuiltinAlias() &&434P.first->second->getBuiltinTypeStr() != Def->getBuiltinTypeStr())435PrintFatalError("Builtin with same name has different type string");436continue;437}438OS << "RISCVV_BUILTIN(__builtin_rvv_" << Def->getBuiltinName() << ",\"";439if (!Def->hasBuiltinAlias())440OS << Def->getBuiltinTypeStr();441OS << "\", \"n\")\n";442}443OS << "#undef RISCVV_BUILTIN\n";444}445446void RVVEmitter::createCodeGen(raw_ostream &OS) {447std::vector<std::unique_ptr<RVVIntrinsic>> Defs;448createRVVIntrinsics(Defs);449// IR name could be empty, use the stable sort preserves the relative order.450llvm::stable_sort(Defs, [](const std::unique_ptr<RVVIntrinsic> &A,451const std::unique_ptr<RVVIntrinsic> &B) {452if (A->getIRName() == B->getIRName())453return (A->getPolicyAttrs() < B->getPolicyAttrs());454return (A->getIRName() < B->getIRName());455});456457// Map to keep track of which builtin names have already been emitted.458StringMap<RVVIntrinsic *> BuiltinMap;459460// Print switch body when the ir name, ManualCodegen or policy changes from461// previous iteration.462RVVIntrinsic *PrevDef = Defs.begin()->get();463for (auto &Def : Defs) {464StringRef CurIRName = Def->getIRName();465if (CurIRName != PrevDef->getIRName() ||466(Def->getManualCodegen() != PrevDef->getManualCodegen()) ||467(Def->getPolicyAttrs() != PrevDef->getPolicyAttrs())) {468emitCodeGenSwitchBody(PrevDef, OS);469}470PrevDef = Def.get();471472auto P =473BuiltinMap.insert(std::make_pair(Def->getBuiltinName(), Def.get()));474if (P.second) {475OS << "case RISCVVector::BI__builtin_rvv_" << Def->getBuiltinName()476<< ":\n";477continue;478}479480if (P.first->second->getIRName() != Def->getIRName())481PrintFatalError("Builtin with same name has different IRName");482else if (P.first->second->getManualCodegen() != Def->getManualCodegen())483PrintFatalError("Builtin with same name has different ManualCodegen");484else if (P.first->second->isMasked() != Def->isMasked())485PrintFatalError("Builtin with same name has different isMasked");486else if (P.first->second->hasVL() != Def->hasVL())487PrintFatalError("Builtin with same name has different hasVL");488else if (P.first->second->getPolicyScheme() != Def->getPolicyScheme())489PrintFatalError("Builtin with same name has different getPolicyScheme");490else if (P.first->second->getIntrinsicTypes() != Def->getIntrinsicTypes())491PrintFatalError("Builtin with same name has different IntrinsicTypes");492}493emitCodeGenSwitchBody(Defs.back().get(), OS);494OS << "\n";495}496497void RVVEmitter::createRVVIntrinsics(498std::vector<std::unique_ptr<RVVIntrinsic>> &Out,499std::vector<SemaRecord> *SemaRecords) {500std::vector<Record *> RV = Records.getAllDerivedDefinitions("RVVBuiltin");501for (auto *R : RV) {502StringRef Name = R->getValueAsString("Name");503StringRef SuffixProto = R->getValueAsString("Suffix");504StringRef OverloadedName = R->getValueAsString("OverloadedName");505StringRef OverloadedSuffixProto = R->getValueAsString("OverloadedSuffix");506StringRef Prototypes = R->getValueAsString("Prototype");507StringRef TypeRange = R->getValueAsString("TypeRange");508bool HasMasked = R->getValueAsBit("HasMasked");509bool HasMaskedOffOperand = R->getValueAsBit("HasMaskedOffOperand");510bool HasVL = R->getValueAsBit("HasVL");511Record *MPSRecord = R->getValueAsDef("MaskedPolicyScheme");512auto MaskedPolicyScheme =513static_cast<PolicyScheme>(MPSRecord->getValueAsInt("Value"));514Record *UMPSRecord = R->getValueAsDef("UnMaskedPolicyScheme");515auto UnMaskedPolicyScheme =516static_cast<PolicyScheme>(UMPSRecord->getValueAsInt("Value"));517std::vector<int64_t> Log2LMULList = R->getValueAsListOfInts("Log2LMUL");518bool HasTailPolicy = R->getValueAsBit("HasTailPolicy");519bool HasMaskPolicy = R->getValueAsBit("HasMaskPolicy");520bool SupportOverloading = R->getValueAsBit("SupportOverloading");521bool HasBuiltinAlias = R->getValueAsBit("HasBuiltinAlias");522StringRef ManualCodegen = R->getValueAsString("ManualCodegen");523std::vector<int64_t> IntrinsicTypes =524R->getValueAsListOfInts("IntrinsicTypes");525std::vector<StringRef> RequiredFeatures =526R->getValueAsListOfStrings("RequiredFeatures");527StringRef IRName = R->getValueAsString("IRName");528StringRef MaskedIRName = R->getValueAsString("MaskedIRName");529unsigned NF = R->getValueAsInt("NF");530bool IsTuple = R->getValueAsBit("IsTuple");531bool HasFRMRoundModeOp = R->getValueAsBit("HasFRMRoundModeOp");532533const Policy DefaultPolicy;534SmallVector<Policy> SupportedUnMaskedPolicies =535RVVIntrinsic::getSupportedUnMaskedPolicies();536SmallVector<Policy> SupportedMaskedPolicies =537RVVIntrinsic::getSupportedMaskedPolicies(HasTailPolicy, HasMaskPolicy);538539// Parse prototype and create a list of primitive type with transformers540// (operand) in Prototype. Prototype[0] is output operand.541SmallVector<PrototypeDescriptor> BasicPrototype =542parsePrototypes(Prototypes);543544SmallVector<PrototypeDescriptor> SuffixDesc = parsePrototypes(SuffixProto);545SmallVector<PrototypeDescriptor> OverloadedSuffixDesc =546parsePrototypes(OverloadedSuffixProto);547548// Compute Builtin types549auto Prototype = RVVIntrinsic::computeBuiltinTypes(550BasicPrototype, /*IsMasked=*/false,551/*HasMaskedOffOperand=*/false, HasVL, NF, UnMaskedPolicyScheme,552DefaultPolicy, IsTuple);553llvm::SmallVector<PrototypeDescriptor> MaskedPrototype;554if (HasMasked)555MaskedPrototype = RVVIntrinsic::computeBuiltinTypes(556BasicPrototype, /*IsMasked=*/true, HasMaskedOffOperand, HasVL, NF,557MaskedPolicyScheme, DefaultPolicy, IsTuple);558559// Create Intrinsics for each type and LMUL.560for (char I : TypeRange) {561for (int Log2LMUL : Log2LMULList) {562BasicType BT = ParseBasicType(I);563std::optional<RVVTypes> Types =564TypeCache.computeTypes(BT, Log2LMUL, NF, Prototype);565// Ignored to create new intrinsic if there are any illegal types.566if (!Types)567continue;568569auto SuffixStr =570RVVIntrinsic::getSuffixStr(TypeCache, BT, Log2LMUL, SuffixDesc);571auto OverloadedSuffixStr = RVVIntrinsic::getSuffixStr(572TypeCache, BT, Log2LMUL, OverloadedSuffixDesc);573// Create a unmasked intrinsic574Out.push_back(std::make_unique<RVVIntrinsic>(575Name, SuffixStr, OverloadedName, OverloadedSuffixStr, IRName,576/*IsMasked=*/false, /*HasMaskedOffOperand=*/false, HasVL,577UnMaskedPolicyScheme, SupportOverloading, HasBuiltinAlias,578ManualCodegen, *Types, IntrinsicTypes, NF, DefaultPolicy,579HasFRMRoundModeOp));580if (UnMaskedPolicyScheme != PolicyScheme::SchemeNone)581for (auto P : SupportedUnMaskedPolicies) {582SmallVector<PrototypeDescriptor> PolicyPrototype =583RVVIntrinsic::computeBuiltinTypes(584BasicPrototype, /*IsMasked=*/false,585/*HasMaskedOffOperand=*/false, HasVL, NF,586UnMaskedPolicyScheme, P, IsTuple);587std::optional<RVVTypes> PolicyTypes =588TypeCache.computeTypes(BT, Log2LMUL, NF, PolicyPrototype);589Out.push_back(std::make_unique<RVVIntrinsic>(590Name, SuffixStr, OverloadedName, OverloadedSuffixStr, IRName,591/*IsMask=*/false, /*HasMaskedOffOperand=*/false, HasVL,592UnMaskedPolicyScheme, SupportOverloading, HasBuiltinAlias,593ManualCodegen, *PolicyTypes, IntrinsicTypes, NF, P,594HasFRMRoundModeOp));595}596if (!HasMasked)597continue;598// Create a masked intrinsic599std::optional<RVVTypes> MaskTypes =600TypeCache.computeTypes(BT, Log2LMUL, NF, MaskedPrototype);601Out.push_back(std::make_unique<RVVIntrinsic>(602Name, SuffixStr, OverloadedName, OverloadedSuffixStr, MaskedIRName,603/*IsMasked=*/true, HasMaskedOffOperand, HasVL, MaskedPolicyScheme,604SupportOverloading, HasBuiltinAlias, ManualCodegen, *MaskTypes,605IntrinsicTypes, NF, DefaultPolicy, HasFRMRoundModeOp));606if (MaskedPolicyScheme == PolicyScheme::SchemeNone)607continue;608for (auto P : SupportedMaskedPolicies) {609SmallVector<PrototypeDescriptor> PolicyPrototype =610RVVIntrinsic::computeBuiltinTypes(611BasicPrototype, /*IsMasked=*/true, HasMaskedOffOperand, HasVL,612NF, MaskedPolicyScheme, P, IsTuple);613std::optional<RVVTypes> PolicyTypes =614TypeCache.computeTypes(BT, Log2LMUL, NF, PolicyPrototype);615Out.push_back(std::make_unique<RVVIntrinsic>(616Name, SuffixStr, OverloadedName, OverloadedSuffixStr,617MaskedIRName, /*IsMasked=*/true, HasMaskedOffOperand, HasVL,618MaskedPolicyScheme, SupportOverloading, HasBuiltinAlias,619ManualCodegen, *PolicyTypes, IntrinsicTypes, NF, P,620HasFRMRoundModeOp));621}622} // End for Log2LMULList623} // End for TypeRange624625// We don't emit vsetvli and vsetvlimax for SemaRecord.626// They are written in riscv_vector.td and will emit those marco define in627// riscv_vector.h628if (Name == "vsetvli" || Name == "vsetvlimax")629continue;630631if (!SemaRecords)632continue;633634// Create SemaRecord635SemaRecord SR;636SR.Name = Name.str();637SR.OverloadedName = OverloadedName.str();638BasicType TypeRangeMask = BasicType::Unknown;639for (char I : TypeRange)640TypeRangeMask |= ParseBasicType(I);641642SR.TypeRangeMask = static_cast<unsigned>(TypeRangeMask);643644unsigned Log2LMULMask = 0;645for (int Log2LMUL : Log2LMULList)646Log2LMULMask |= 1 << (Log2LMUL + 3);647648SR.Log2LMULMask = Log2LMULMask;649650SR.RequiredExtensions = 0;651for (auto RequiredFeature : RequiredFeatures) {652RVVRequire RequireExt =653StringSwitch<RVVRequire>(RequiredFeature)654.Case("RV64", RVV_REQ_RV64)655.Case("Zvfhmin", RVV_REQ_Zvfhmin)656.Case("Xsfvcp", RVV_REQ_Xsfvcp)657.Case("Xsfvfnrclipxfqf", RVV_REQ_Xsfvfnrclipxfqf)658.Case("Xsfvfwmaccqqq", RVV_REQ_Xsfvfwmaccqqq)659.Case("Xsfvqmaccdod", RVV_REQ_Xsfvqmaccdod)660.Case("Xsfvqmaccqoq", RVV_REQ_Xsfvqmaccqoq)661.Case("Zvbb", RVV_REQ_Zvbb)662.Case("Zvbc", RVV_REQ_Zvbc)663.Case("Zvkb", RVV_REQ_Zvkb)664.Case("Zvkg", RVV_REQ_Zvkg)665.Case("Zvkned", RVV_REQ_Zvkned)666.Case("Zvknha", RVV_REQ_Zvknha)667.Case("Zvknhb", RVV_REQ_Zvknhb)668.Case("Zvksed", RVV_REQ_Zvksed)669.Case("Zvksh", RVV_REQ_Zvksh)670.Case("Zvfbfwma", RVV_REQ_Zvfbfwma)671.Case("Zvfbfmin", RVV_REQ_Zvfbfmin)672.Case("Experimental", RVV_REQ_Experimental)673.Default(RVV_REQ_None);674assert(RequireExt != RVV_REQ_None && "Unrecognized required feature?");675SR.RequiredExtensions |= RequireExt;676}677678SR.NF = NF;679SR.HasMasked = HasMasked;680SR.HasVL = HasVL;681SR.HasMaskedOffOperand = HasMaskedOffOperand;682SR.HasTailPolicy = HasTailPolicy;683SR.HasMaskPolicy = HasMaskPolicy;684SR.UnMaskedPolicyScheme = static_cast<uint8_t>(UnMaskedPolicyScheme);685SR.MaskedPolicyScheme = static_cast<uint8_t>(MaskedPolicyScheme);686SR.Prototype = std::move(BasicPrototype);687SR.Suffix = parsePrototypes(SuffixProto);688SR.OverloadedSuffix = parsePrototypes(OverloadedSuffixProto);689SR.IsTuple = IsTuple;690SR.HasFRMRoundModeOp = HasFRMRoundModeOp;691692SemaRecords->push_back(SR);693}694}695696void RVVEmitter::printHeaderCode(raw_ostream &OS) {697std::vector<Record *> RVVHeaders =698Records.getAllDerivedDefinitions("RVVHeader");699for (auto *R : RVVHeaders) {700StringRef HeaderCodeStr = R->getValueAsString("HeaderCode");701OS << HeaderCodeStr.str();702}703}704705void RVVEmitter::createRVVIntrinsicRecords(std::vector<RVVIntrinsicRecord> &Out,706SemaSignatureTable &SST,707ArrayRef<SemaRecord> SemaRecords) {708SST.init(SemaRecords);709710for (const auto &SR : SemaRecords) {711Out.emplace_back(RVVIntrinsicRecord());712RVVIntrinsicRecord &R = Out.back();713R.Name = SR.Name.c_str();714R.OverloadedName = SR.OverloadedName.c_str();715R.PrototypeIndex = SST.getIndex(SR.Prototype);716R.SuffixIndex = SST.getIndex(SR.Suffix);717R.OverloadedSuffixIndex = SST.getIndex(SR.OverloadedSuffix);718R.PrototypeLength = SR.Prototype.size();719R.SuffixLength = SR.Suffix.size();720R.OverloadedSuffixSize = SR.OverloadedSuffix.size();721R.RequiredExtensions = SR.RequiredExtensions;722R.TypeRangeMask = SR.TypeRangeMask;723R.Log2LMULMask = SR.Log2LMULMask;724R.NF = SR.NF;725R.HasMasked = SR.HasMasked;726R.HasVL = SR.HasVL;727R.HasMaskedOffOperand = SR.HasMaskedOffOperand;728R.HasTailPolicy = SR.HasTailPolicy;729R.HasMaskPolicy = SR.HasMaskPolicy;730R.UnMaskedPolicyScheme = SR.UnMaskedPolicyScheme;731R.MaskedPolicyScheme = SR.MaskedPolicyScheme;732R.IsTuple = SR.IsTuple;733R.HasFRMRoundModeOp = SR.HasFRMRoundModeOp;734735assert(R.PrototypeIndex !=736static_cast<uint16_t>(SemaSignatureTable::INVALID_INDEX));737assert(R.SuffixIndex !=738static_cast<uint16_t>(SemaSignatureTable::INVALID_INDEX));739assert(R.OverloadedSuffixIndex !=740static_cast<uint16_t>(SemaSignatureTable::INVALID_INDEX));741}742}743744void RVVEmitter::createSema(raw_ostream &OS) {745std::vector<std::unique_ptr<RVVIntrinsic>> Defs;746std::vector<RVVIntrinsicRecord> RVVIntrinsicRecords;747SemaSignatureTable SST;748std::vector<SemaRecord> SemaRecords;749750createRVVIntrinsics(Defs, &SemaRecords);751752createRVVIntrinsicRecords(RVVIntrinsicRecords, SST, SemaRecords);753754// Emit signature table for SemaRISCVVectorLookup.cpp.755OS << "#ifdef DECL_SIGNATURE_TABLE\n";756SST.print(OS);757OS << "#endif\n";758759// Emit RVVIntrinsicRecords for SemaRISCVVectorLookup.cpp.760OS << "#ifdef DECL_INTRINSIC_RECORDS\n";761for (const RVVIntrinsicRecord &Record : RVVIntrinsicRecords)762OS << Record;763OS << "#endif\n";764}765766namespace clang {767void EmitRVVHeader(RecordKeeper &Records, raw_ostream &OS) {768RVVEmitter(Records).createHeader(OS);769}770771void EmitRVVBuiltins(RecordKeeper &Records, raw_ostream &OS) {772RVVEmitter(Records).createBuiltins(OS);773}774775void EmitRVVBuiltinCG(RecordKeeper &Records, raw_ostream &OS) {776RVVEmitter(Records).createCodeGen(OS);777}778779void EmitRVVBuiltinSema(RecordKeeper &Records, raw_ostream &OS) {780RVVEmitter(Records).createSema(OS);781}782783} // End namespace clang784785786