diff --git a/clang/include/clang/Support/RISCVVIntrinsicUtils.h b/clang/include/clang/Support/RISCVVIntrinsicUtils.h --- a/clang/include/clang/Support/RISCVVIntrinsicUtils.h +++ b/clang/include/clang/Support/RISCVVIntrinsicUtils.h @@ -15,7 +15,9 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include +#include #include +#include #include namespace llvm { @@ -182,9 +184,12 @@ class RVVType; using RVVTypePtr = RVVType *; using RVVTypes = std::vector; +class RVVTypeCache; // This class is compact representation of a valid and invalid RVVType. class RVVType { + friend class RVVTypeCache; + BasicType BT; ScalarTypeKind ScalarType = Invalid; LMULType LMUL; @@ -204,10 +209,9 @@ enum class FixedLMULType { LargerThan, SmallerThan }; -public: - RVVType() : BT(BasicType::Unknown), LMUL(0), Valid(false) {} RVVType(BasicType BT, int Log2LMUL, const PrototypeDescriptor &Profile); +public: // Return the string representation of a type, which is an encoded string for // passing to the BUILTIN() macro in Builtins.def. const std::string &getBuiltinStr() const { return BuiltinStr; } @@ -275,17 +279,25 @@ void initTypeStr(); // Compute and record a short name of a type for C/C++ name suffix. void initShortStr(); +}; + +// This class is used to manage RVVType, RVVType should only created by this +// class, also provided thread-safe cache capability. +class RVVTypeCache { +private: + std::unordered_map LegalTypes; + std::set IllegalTypes; public: /// Compute output and input types by applying different config (basic type /// and LMUL with type transformers). It also record result of type in legal /// or illegal set to avoid compute the same config again. The result maybe /// have illegal RVVType. - static llvm::Optional + llvm::Optional computeTypes(BasicType BT, int Log2LMUL, unsigned NF, llvm::ArrayRef Prototype); - static llvm::Optional computeType(BasicType BT, int Log2LMUL, - PrototypeDescriptor Proto); + llvm::Optional computeType(BasicType BT, int Log2LMUL, + PrototypeDescriptor Proto); }; enum PolicyScheme : uint8_t { @@ -373,7 +385,7 @@ std::string getBuiltinTypeStr() const; static std::string - getSuffixStr(BasicType Type, int Log2LMUL, + getSuffixStr(RVVTypeCache &TypeCache, BasicType Type, int Log2LMUL, llvm::ArrayRef PrototypeDescriptors); static llvm::SmallVector diff --git a/clang/lib/Sema/SemaRISCVVectorLookup.cpp b/clang/lib/Sema/SemaRISCVVectorLookup.cpp --- a/clang/lib/Sema/SemaRISCVVectorLookup.cpp +++ b/clang/lib/Sema/SemaRISCVVectorLookup.cpp @@ -132,6 +132,7 @@ private: Sema &S; ASTContext &Context; + RVVTypeCache TypeCache; // List of all RVV intrinsic. std::vector IntrinsicList; @@ -247,16 +248,16 @@ continue; Optional Types = - RVVType::computeTypes(BaseType, Log2LMUL, Record.NF, ProtoSeq); + TypeCache.computeTypes(BaseType, Log2LMUL, Record.NF, ProtoSeq); // Ignored to create new intrinsic if there are any illegal types. if (!Types.has_value()) continue; - std::string SuffixStr = - RVVIntrinsic::getSuffixStr(BaseType, Log2LMUL, SuffixProto); + std::string SuffixStr = RVVIntrinsic::getSuffixStr( + TypeCache, BaseType, Log2LMUL, SuffixProto); std::string OverloadedSuffixStr = RVVIntrinsic::getSuffixStr( - BaseType, Log2LMUL, OverloadedSuffixProto); + TypeCache, BaseType, Log2LMUL, OverloadedSuffixProto); // Create non-masked intrinsic. InitRVVIntrinsic(Record, SuffixStr, OverloadedSuffixStr, false, *Types, @@ -271,7 +272,7 @@ BasicProtoSeq, /*IsMasked=*/false, /*HasMaskedOffOperand=*/false, Record.HasVL, Record.NF, Record.IsPrototypeDefaultTU, UnMaskedPolicyScheme, P); - Optional PolicyTypes = RVVType::computeTypes( + Optional PolicyTypes = TypeCache.computeTypes( BaseType, Log2LMUL, Record.NF, PolicyPrototype); InitRVVIntrinsic(Record, SuffixStr, OverloadedSuffixStr, /*IsMask=*/false, *PolicyTypes, UnMaskedHasPolicy, @@ -282,7 +283,7 @@ continue; // Create masked intrinsic. Optional MaskTypes = - RVVType::computeTypes(BaseType, Log2LMUL, Record.NF, ProtoMaskSeq); + TypeCache.computeTypes(BaseType, Log2LMUL, Record.NF, ProtoMaskSeq); InitRVVIntrinsic(Record, SuffixStr, OverloadedSuffixStr, true, *MaskTypes, MaskedHasPolicy, Policy::PolicyNone, Record.IsPrototypeDefaultTU); @@ -295,7 +296,7 @@ BasicProtoSeq, /*IsMasked=*/true, Record.HasMaskedOffOperand, Record.HasVL, Record.NF, Record.IsPrototypeDefaultTU, MaskedPolicyScheme, P); - Optional PolicyTypes = RVVType::computeTypes( + Optional PolicyTypes = TypeCache.computeTypes( BaseType, Log2LMUL, Record.NF, PolicyPrototype); InitRVVIntrinsic(Record, SuffixStr, OverloadedSuffixStr, /*IsMask=*/true, *PolicyTypes, MaskedHasPolicy, P, diff --git a/clang/lib/Support/RISCVVIntrinsicUtils.cpp b/clang/lib/Support/RISCVVIntrinsicUtils.cpp --- a/clang/lib/Support/RISCVVIntrinsicUtils.cpp +++ b/clang/lib/Support/RISCVVIntrinsicUtils.cpp @@ -16,8 +16,6 @@ #include "llvm/ADT/Twine.h" #include "llvm/Support/raw_ostream.h" #include -#include -#include using namespace llvm; @@ -786,8 +784,8 @@ } Optional -RVVType::computeTypes(BasicType BT, int Log2LMUL, unsigned NF, - ArrayRef Prototype) { +RVVTypeCache::computeTypes(BasicType BT, int Log2LMUL, unsigned NF, + ArrayRef Prototype) { // LMUL x NF must be less than or equal to 8. if ((Log2LMUL >= 1) && (1 << Log2LMUL) * NF > 8) return llvm::None; @@ -816,11 +814,8 @@ ((uint64_t)(Proto.VTM & 0xff) << 32); } -Optional RVVType::computeType(BasicType BT, int Log2LMUL, - PrototypeDescriptor Proto) { - // Concat BasicType, LMUL and Proto as key - static std::unordered_map LegalTypes; - static std::set IllegalTypes; +Optional RVVTypeCache::computeType(BasicType BT, int Log2LMUL, + PrototypeDescriptor Proto) { uint64_t Idx = computeRVVTypeHashValue(BT, Log2LMUL, Proto); // Search first auto It = LegalTypes.find(Idx); @@ -834,8 +829,9 @@ RVVType T(BT, Log2LMUL, Proto); if (T.isValid()) { // Record legal type index and value. - LegalTypes.insert({Idx, T}); - return &(LegalTypes[Idx]); + std::pair::iterator, bool> + InsertResult = LegalTypes.insert({Idx, T}); + return &(InsertResult.first->second); } // Record illegal type index. IllegalTypes.insert(Idx); @@ -900,11 +896,11 @@ } std::string RVVIntrinsic::getSuffixStr( - BasicType Type, int Log2LMUL, + RVVTypeCache &TypeCache, BasicType Type, int Log2LMUL, llvm::ArrayRef PrototypeDescriptors) { SmallVector SuffixStrs; for (auto PD : PrototypeDescriptors) { - auto T = RVVType::computeType(Type, Log2LMUL, PD); + auto T = TypeCache.computeType(Type, Log2LMUL, PD); SuffixStrs.push_back((*T)->getShortStr()); } return join(SuffixStrs, "_"); diff --git a/clang/utils/TableGen/RISCVVEmitter.cpp b/clang/utils/TableGen/RISCVVEmitter.cpp --- a/clang/utils/TableGen/RISCVVEmitter.cpp +++ b/clang/utils/TableGen/RISCVVEmitter.cpp @@ -95,6 +95,7 @@ class RVVEmitter { private: RecordKeeper &Records; + RVVTypeCache TypeCache; public: RVVEmitter(RecordKeeper &R) : Records(R) {} @@ -349,8 +350,8 @@ constexpr int Log2LMULs[] = {-3, -2, -1, 0, 1, 2, 3}; // Print RVV boolean types. for (int Log2LMUL : Log2LMULs) { - auto T = RVVType::computeType(BasicType::Int8, Log2LMUL, - PrototypeDescriptor::Mask); + auto T = TypeCache.computeType(BasicType::Int8, Log2LMUL, + PrototypeDescriptor::Mask); if (T) printType(T.value()); } @@ -358,10 +359,10 @@ for (char I : StringRef("csil")) { BasicType BT = ParseBasicType(I); for (int Log2LMUL : Log2LMULs) { - auto T = RVVType::computeType(BT, Log2LMUL, PrototypeDescriptor::Vector); + auto T = TypeCache.computeType(BT, Log2LMUL, PrototypeDescriptor::Vector); if (T) { printType(T.value()); - auto UT = RVVType::computeType( + auto UT = TypeCache.computeType( BT, Log2LMUL, PrototypeDescriptor(BaseTypeModifier::Vector, VectorTypeModifier::NoModifier, @@ -372,8 +373,8 @@ } OS << "#if defined(__riscv_zvfh)\n"; for (int Log2LMUL : Log2LMULs) { - auto T = RVVType::computeType(BasicType::Float16, Log2LMUL, - PrototypeDescriptor::Vector); + auto T = TypeCache.computeType(BasicType::Float16, Log2LMUL, + PrototypeDescriptor::Vector); if (T) printType(T.value()); } @@ -381,8 +382,8 @@ OS << "#if (__riscv_v_elen_fp >= 32)\n"; for (int Log2LMUL : Log2LMULs) { - auto T = RVVType::computeType(BasicType::Float32, Log2LMUL, - PrototypeDescriptor::Vector); + auto T = TypeCache.computeType(BasicType::Float32, Log2LMUL, + PrototypeDescriptor::Vector); if (T) printType(T.value()); } @@ -390,8 +391,8 @@ OS << "#if (__riscv_v_elen_fp >= 64)\n"; for (int Log2LMUL : Log2LMULs) { - auto T = RVVType::computeType(BasicType::Float64, Log2LMUL, - PrototypeDescriptor::Vector); + auto T = TypeCache.computeType(BasicType::Float64, Log2LMUL, + PrototypeDescriptor::Vector); if (T) printType(T.value()); } @@ -553,14 +554,15 @@ for (int Log2LMUL : Log2LMULList) { BasicType BT = ParseBasicType(I); Optional Types = - RVVType::computeTypes(BT, Log2LMUL, NF, Prototype); + TypeCache.computeTypes(BT, Log2LMUL, NF, Prototype); // Ignored to create new intrinsic if there are any illegal types. if (!Types) continue; - auto SuffixStr = RVVIntrinsic::getSuffixStr(BT, Log2LMUL, SuffixDesc); - auto OverloadedSuffixStr = - RVVIntrinsic::getSuffixStr(BT, Log2LMUL, OverloadedSuffixDesc); + auto SuffixStr = + RVVIntrinsic::getSuffixStr(TypeCache, BT, Log2LMUL, SuffixDesc); + auto OverloadedSuffixStr = RVVIntrinsic::getSuffixStr( + TypeCache, BT, Log2LMUL, OverloadedSuffixDesc); // Create a unmasked intrinsic Out.push_back(std::make_unique( Name, SuffixStr, OverloadedName, OverloadedSuffixStr, IRName, @@ -576,7 +578,7 @@ /*HasMaskedOffOperand=*/false, HasVL, NF, IsPrototypeDefaultTU, UnMaskedPolicyScheme, P); Optional PolicyTypes = - RVVType::computeTypes(BT, Log2LMUL, NF, PolicyPrototype); + TypeCache.computeTypes(BT, Log2LMUL, NF, PolicyPrototype); Out.push_back(std::make_unique( Name, SuffixStr, OverloadedName, OverloadedSuffixStr, IRName, /*IsMask=*/false, /*HasMaskedOffOperand=*/false, HasVL, @@ -588,7 +590,7 @@ continue; // Create a masked intrinsic Optional MaskTypes = - RVVType::computeTypes(BT, Log2LMUL, NF, Prototype); + TypeCache.computeTypes(BT, Log2LMUL, NF, Prototype); Out.push_back(std::make_unique( Name, SuffixStr, OverloadedName, OverloadedSuffixStr, MaskedIRName, /*IsMasked=*/true, HasMaskedOffOperand, HasVL, MaskedPolicyScheme, @@ -603,7 +605,7 @@ BasicPrototype, /*IsMasked=*/true, HasMaskedOffOperand, HasVL, NF, IsPrototypeDefaultTU, MaskedPolicyScheme, P); Optional PolicyTypes = - RVVType::computeTypes(BT, Log2LMUL, NF, PolicyPrototype); + TypeCache.computeTypes(BT, Log2LMUL, NF, PolicyPrototype); Out.push_back(std::make_unique( Name, SuffixStr, OverloadedName, OverloadedSuffixStr, MaskedIRName, /*IsMasked=*/true, HasMaskedOffOperand, HasVL,