Index: clang/lib/CodeGen/CGCall.cpp =================================================================== --- clang/lib/CodeGen/CGCall.cpp +++ clang/lib/CodeGen/CGCall.cpp @@ -1893,7 +1893,8 @@ for (StringRef Attr : CodeGenOpts.DefaultFunctionAttrs) { StringRef Var, Value; std::tie(Var, Value) = Attr.split('='); - FuncAttrs.addAttribute(Var, Value); + FuncAttrs.addAttribute(llvm::AttributeKey::get(getLLVMContext(), Var), + Value); } } @@ -1912,14 +1913,15 @@ GetCPUAndFeaturesAttributes(GlobalDecl(), attrs); } -static void addNoBuiltinAttributes(llvm::AttrBuilder &FuncAttrs, +static void addNoBuiltinAttributes(llvm::LLVMContext &LLVMCtxt, + llvm::AttrBuilder &FuncAttrs, const LangOptions &LangOpts, const NoBuiltinAttr *NBA = nullptr) { - auto AddNoBuiltinAttr = [&FuncAttrs](StringRef BuiltinName) { + auto AddNoBuiltinAttr = [&FuncAttrs, &LLVMCtxt](StringRef BuiltinName) { SmallString<32> AttributeName; AttributeName += "no-builtin-"; AttributeName += BuiltinName; - FuncAttrs.addAttribute(AttributeName); + FuncAttrs.addAttribute(llvm::AttributeKey::get(LLVMCtxt, AttributeName)); }; // First, handle the language options passed through -fno-builtin. @@ -2148,7 +2150,7 @@ // The attributes can come from: // * LangOpts: -ffreestanding, -fno-builtin, -fno-builtin- // * FunctionDecl attributes: __attribute__((no_builtin(...))) - addNoBuiltinAttributes(FuncAttrs, getLangOpts(), NBA); + addNoBuiltinAttributes(getLLVMContext(), FuncAttrs, getLangOpts(), NBA); // Collect function IR attributes based on global settiings. getDefaultFunctionAttributes(Name, HasOptnone, AttrOnCallSite, FuncAttrs); Index: clang/lib/CodeGen/CGOpenMPRuntime.cpp =================================================================== --- clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -11614,7 +11614,7 @@ Out << 'a' << ParamAttr.Alignment; } Out << '_' << Fn->getName(); - Fn->addFnAttr(Out.str()); + Fn->addFnAttr(llvm::AttributeKey::get(Fn->getContext(), Out.str())); } } } @@ -11772,7 +11772,7 @@ if (OutputBecomesInput) Out << "v"; Out << ParSeq << "_" << MangledName; - Fn->addFnAttr(Out.str()); + Fn->addFnAttr(llvm::AttributeKey::get(Fn->getContext(), Out.str())); } // Helper function to generate the Advanced SIMD names depending on Index: clang/lib/CodeGen/CodeGenFunction.cpp =================================================================== --- clang/lib/CodeGen/CodeGenFunction.cpp +++ clang/lib/CodeGen/CodeGenFunction.cpp @@ -162,7 +162,7 @@ NewRoundingBehavior == llvm::RoundingMode::NearestTiesToEven)) && "FPConstrained should be enabled on entire function"); - auto mergeFnAttrValue = [&](StringRef Name, bool Value) { + auto mergeFnAttrValue = [&](llvm::AttributeKey Name, bool Value) { auto OldValue = CGF.CurFn->getFnAttribute(Name).getValueAsBool(); auto NewValue = OldValue & Value; Index: llvm/include/llvm/Analysis/TargetLibraryInfo.h =================================================================== --- llvm/include/llvm/Analysis/TargetLibraryInfo.h +++ llvm/include/llvm/Analysis/TargetLibraryInfo.h @@ -244,7 +244,7 @@ for (const Attribute &Attr : FnAttrs) { if (!Attr.isStringAttribute()) continue; - auto AttrStr = Attr.getKindAsString(); + auto AttrStr = Attr.getKindAsKey().value(); if (!AttrStr.consume_front("no-builtin-")) continue; if (getLibFunc(AttrStr, LF)) Index: llvm/include/llvm/Analysis/VectorUtils.h =================================================================== --- llvm/include/llvm/Analysis/VectorUtils.h +++ llvm/include/llvm/Analysis/VectorUtils.h @@ -190,7 +190,7 @@ VFParamKind getVFParamKindFromString(const StringRef Token); // Name of the attribute where the variant mappings are stored. -static constexpr char const *MappingsAttrName = "vector-function-abi-variant"; +constexpr AttributeKey MappingsAttrName("vector-function-abi-variant"); /// Populates a set of strings representing the Vector Function ABI variants /// associated to the CallInst CI. If the CI does not contain the Index: llvm/include/llvm/CodeGen/CommandFlags.h =================================================================== --- llvm/include/llvm/CodeGen/CommandFlags.h +++ llvm/include/llvm/CodeGen/CommandFlags.h @@ -161,7 +161,7 @@ std::vector getFeatureList(); -void renderBoolStringAttr(AttrBuilder &B, StringRef Name, bool Val); +void renderBoolStringAttr(AttrBuilder &B, AttributeKey Name, bool Val); /// Set function attributes of function \p F based on CPU, Features, and command /// line flags. Index: llvm/include/llvm/IR/Assumptions.h =================================================================== --- llvm/include/llvm/IR/Assumptions.h +++ llvm/include/llvm/IR/Assumptions.h @@ -25,7 +25,7 @@ class CallBase; /// The key we use for assumption attributes. -constexpr StringRef AssumptionAttrKey = "llvm.assume"; +constexpr char AssumptionAttrKey[] = "llvm.assume"; /// A set of known assumption strings that are accepted without warning and /// which can be recommended as typo correction. Index: llvm/include/llvm/IR/Attributes.h =================================================================== --- llvm/include/llvm/IR/Attributes.h +++ llvm/include/llvm/IR/Attributes.h @@ -17,6 +17,8 @@ #include "llvm-c/Types.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/CachedHashString.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" @@ -33,6 +35,65 @@ namespace llvm { +class LLVMContext; + +//===----------------------------------------------------------------------===// +/// \class +/// Lightweight representation of a free-form attribute key. Its hash value is +/// precomputed to speed-up lookups, and they are either pool-allocated or just +/// reference a global string literal. + +class AttributeKey { + const char *value_; + uint32_t hash_; + uint32_t size_; + + AttributeKey(CachedHashStringRef HashedS) + : value_(strndup(HashedS.data(), HashedS.size())), hash_(HashedS.hash()), + size_(HashedS.size()) { + assert(hash_ == hasher(s.data(), s.size()) && "consistent hashing"); + } + +public: + static AttributeKey get(LLVMContext &Ctxt, StringRef s); + + template + constexpr AttributeKey(const char (&s)[N]) + : value_(s), hash_(hasher(s, N - 1)), size_(N - 1) { + static_assert(N - 1 < std::numeric_limits::max(), + "large enough size storage"); + } + constexpr AttributeKey() : AttributeKey("") {} + StringRef value() const { return StringRef(value_, size_); } + uint32_t hash() const { return hash_; } + uint32_t size() const { return size_; } + bool operator==(AttributeKey const &other) const { + return size_ == other.size_ && strncmp(value_, other.value_, size_) == 0; + } + bool operator!=(AttributeKey const &other) const { + return !((*this) == other); + } + bool operator<(AttributeKey const &other) const { + return strcmp(value_, other.value_) < 0; + } + + static constexpr uint32_t hasher(const char *str, size_t n) { + uint32_t hash = 5381; + for (size_t i = 0; i < n; ++i) + hash = hash * 33 + str[i]; + return hash; + } +}; +} // namespace llvm + +template <> struct std::hash { + std::size_t operator()(llvm::AttributeKey const &s) const noexcept { + return s.hash(); + } +}; + +namespace llvm { + class AttrBuilder; class AttributeImpl; class AttributeListImpl; @@ -109,7 +170,7 @@ /// Return a uniquified Attribute object. static Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val = 0); - static Attribute get(LLVMContext &Context, StringRef Kind, + static Attribute get(LLVMContext &Context, AttributeKey Kind, StringRef Val = StringRef()); static Attribute get(LLVMContext &Context, AttrKind Kind, Type *Ty); @@ -171,7 +232,7 @@ bool hasAttribute(AttrKind Val) const; /// Return true if the target-dependent attribute is present. - bool hasAttribute(StringRef Val) const; + bool hasAttribute(AttributeKey Val) const; /// Return the attribute's kind as an enum (Attribute::AttrKind). This /// requires the attribute to be an enum, integer, or type attribute. @@ -187,7 +248,7 @@ /// Return the attribute's kind as a string. This requires the /// attribute to be a string attribute. - StringRef getKindAsString() const; + AttributeKey getKindAsKey() const; /// Return the attribute's value as a string. This requires the /// attribute to be a string attribute. @@ -297,7 +358,7 @@ /// Add a target-dependent attribute. Returns a new set because attribute sets /// are immutable. - LLVM_NODISCARD AttributeSet addAttribute(LLVMContext &C, StringRef Kind, + LLVM_NODISCARD AttributeSet addAttribute(LLVMContext &C, AttributeKey Kind, StringRef Value = StringRef()) const; /// Add attributes to the attribute set. Returns a new set because attribute @@ -313,7 +374,7 @@ /// Remove the specified attribute from this set. Returns a new set because /// attribute sets are immutable. LLVM_NODISCARD AttributeSet removeAttribute(LLVMContext &C, - StringRef Kind) const; + AttributeKey Kind) const; /// Remove the specified attributes from this set. Returns a new set because /// attribute sets are immutable. @@ -330,13 +391,13 @@ bool hasAttribute(Attribute::AttrKind Kind) const; /// Return true if the attribute exists in this set. - bool hasAttribute(StringRef Kind) const; + bool hasAttribute(AttributeKey Kind) const; /// Return the attribute object. Attribute getAttribute(Attribute::AttrKind Kind) const; /// Return the target-dependent attribute object. - Attribute getAttribute(StringRef Kind) const; + Attribute getAttribute(AttributeKey Kind) const; MaybeAlign getAlignment() const; MaybeAlign getStackAlignment() const; @@ -451,7 +512,7 @@ ArrayRef Kinds, ArrayRef Values); static AttributeList get(LLVMContext &C, unsigned Index, - ArrayRef Kind); + ArrayRef Kind); static AttributeList get(LLVMContext &C, unsigned Index, const AttrBuilder &B); @@ -464,7 +525,7 @@ /// Add an attribute to the attribute set at the given index. /// Returns a new list because attribute lists are immutable. LLVM_NODISCARD AttributeList - addAttributeAtIndex(LLVMContext &C, unsigned Index, StringRef Kind, + addAttributeAtIndex(LLVMContext &C, unsigned Index, AttributeKey Kind, StringRef Value = StringRef()) const; /// Add an attribute to the attribute set at the given index. @@ -496,7 +557,7 @@ /// Add a function attribute to the list. Returns a new list because /// attribute lists are immutable. LLVM_NODISCARD AttributeList addFnAttribute( - LLVMContext &C, StringRef Kind, StringRef Value = StringRef()) const { + LLVMContext &C, AttributeKey Kind, StringRef Value = StringRef()) const { return addAttributeAtIndex(C, FunctionIndex, Kind, Value); } @@ -538,7 +599,7 @@ /// Add an argument attribute to the list. Returns a new list because /// attribute lists are immutable. LLVM_NODISCARD AttributeList - addParamAttribute(LLVMContext &C, unsigned ArgNo, StringRef Kind, + addParamAttribute(LLVMContext &C, unsigned ArgNo, AttributeKey Kind, StringRef Value = StringRef()) const { return addAttributeAtIndex(C, ArgNo + FirstArgIndex, Kind, Value); } @@ -566,9 +627,9 @@ /// attribute list. Returns a new list because attribute lists are immutable. LLVM_NODISCARD AttributeList removeAttributeAtIndex(LLVMContext &C, unsigned Index, - StringRef Kind) const; + AttributeKey Kind) const; LLVM_NODISCARD AttributeList removeAttribute(LLVMContext &C, unsigned Index, - StringRef Kind) const { + AttributeKey Kind) const { return removeAttributeAtIndex(C, Index, Kind); } @@ -592,7 +653,7 @@ /// Remove the specified attribute at the function index from this /// attribute list. Returns a new list because attribute lists are immutable. LLVM_NODISCARD AttributeList removeFnAttribute(LLVMContext &C, - StringRef Kind) const { + AttributeKey Kind) const { return removeAttributeAtIndex(C, FunctionIndex, Kind); } @@ -619,7 +680,7 @@ /// Remove the specified attribute at the return value index from this /// attribute list. Returns a new list because attribute lists are immutable. LLVM_NODISCARD AttributeList removeRetAttribute(LLVMContext &C, - StringRef Kind) const { + AttributeKey Kind) const { return removeAttributeAtIndex(C, ReturnIndex, Kind); } @@ -641,7 +702,7 @@ /// attribute list. Returns a new list because attribute lists are immutable. LLVM_NODISCARD AttributeList removeParamAttribute(LLVMContext &C, unsigned ArgNo, - StringRef Kind) const { + AttributeKey Kind) const { return removeAttributeAtIndex(C, ArgNo + FirstArgIndex, Kind); } @@ -713,7 +774,7 @@ bool hasAttributeAtIndex(unsigned Index, Attribute::AttrKind Kind) const; /// Return true if the attribute exists at the given index. - bool hasAttributeAtIndex(unsigned Index, StringRef Kind) const; + bool hasAttributeAtIndex(unsigned Index, AttributeKey Kind) const; /// Return true if attribute exists at the given index. bool hasAttributesAtIndex(unsigned Index) const; @@ -724,7 +785,7 @@ } /// Return true if the attribute exists for the given argument - bool hasParamAttr(unsigned ArgNo, StringRef Kind) const { + bool hasParamAttr(unsigned ArgNo, AttributeKey Kind) const { return hasAttributeAtIndex(ArgNo + FirstArgIndex, Kind); } @@ -739,7 +800,7 @@ } /// Return true if the attribute exists for the return value. - bool hasRetAttr(StringRef Kind) const { + bool hasRetAttr(AttributeKey Kind) const { return hasAttributeAtIndex(ReturnIndex, Kind); } @@ -750,7 +811,7 @@ bool hasFnAttr(Attribute::AttrKind Kind) const; /// Return true if the attribute exists for the function. - bool hasFnAttr(StringRef Kind) const; + bool hasFnAttr(AttributeKey Kind) const; /// Return true the attributes exist for the function. bool hasFnAttrs() const { return hasAttributesAtIndex(FunctionIndex); } @@ -765,7 +826,7 @@ Attribute getAttributeAtIndex(unsigned Index, Attribute::AttrKind Kind) const; /// Return the attribute object that exists at the given index. - Attribute getAttributeAtIndex(unsigned Index, StringRef Kind) const; + Attribute getAttributeAtIndex(unsigned Index, AttributeKey Kind) const; /// Return the attribute object that exists at the arg index. Attribute getParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) const { @@ -773,7 +834,7 @@ } /// Return the attribute object that exists at the given index. - Attribute getParamAttr(unsigned ArgNo, StringRef Kind) const { + Attribute getParamAttr(unsigned ArgNo, AttributeKey Kind) const { return getAttributeAtIndex(ArgNo + FirstArgIndex, Kind); } @@ -783,7 +844,7 @@ } /// Return the attribute object that exists for the function. - Attribute getFnAttr(StringRef Kind) const { + Attribute getFnAttr(AttributeKey Kind) const { return getAttributeAtIndex(FunctionIndex, Kind); } @@ -930,7 +991,7 @@ /// equality, presence of attributes, etc. class AttrBuilder { std::bitset Attrs; - std::map, SmallString<32>, std::less<>> TargetDepAttrs; + std::map> TargetDepAttrs; std::array IntAttrs = {}; std::array TypeAttrs = {}; @@ -963,7 +1024,7 @@ AttrBuilder &addAttribute(Attribute A); /// Add the target-dependent attribute to the builder. - AttrBuilder &addAttribute(StringRef A, StringRef V = StringRef()); + AttrBuilder &addAttribute(AttributeKey A, StringRef V = StringRef()); /// Remove an attribute from the builder. AttrBuilder &removeAttribute(Attribute::AttrKind Val); @@ -972,7 +1033,7 @@ AttrBuilder &removeAttributes(AttributeList A, uint64_t WithoutIndex); /// Remove the target-dependent attribute to the builder. - AttrBuilder &removeAttribute(StringRef A); + AttrBuilder &removeAttribute(AttributeKey A); /// Add the attributes from the builder. AttrBuilder &merge(const AttrBuilder &B); @@ -992,7 +1053,7 @@ /// Return true if the builder has the specified target-dependent /// attribute. - bool contains(StringRef A) const; + bool contains(AttributeKey A) const; /// Return true if the builder has IR-level attributes. bool hasAttributes() const; Index: llvm/include/llvm/IR/Function.h =================================================================== --- llvm/include/llvm/IR/Function.h +++ llvm/include/llvm/IR/Function.h @@ -337,7 +337,7 @@ void addFnAttr(Attribute::AttrKind Kind); /// Add function attributes to this function. - void addFnAttr(StringRef Kind, StringRef Val = StringRef()); + void addFnAttr(AttributeKey Kind, StringRef Val = StringRef()); /// Add function attributes to this function. void addFnAttr(Attribute Attr); @@ -367,13 +367,13 @@ void removeAttributeAtIndex(unsigned i, Attribute::AttrKind Kind); /// removes the attribute from the list of attributes. - void removeAttributeAtIndex(unsigned i, StringRef Kind); + void removeAttributeAtIndex(unsigned i, AttributeKey Kind); /// Remove function attributes from this function. void removeFnAttr(Attribute::AttrKind Kind); /// Remove function attribute from this function. - void removeFnAttr(StringRef Kind); + void removeFnAttr(AttributeKey Kind); void removeFnAttrs(const AttrBuilder &Attrs); @@ -381,7 +381,7 @@ void removeRetAttr(Attribute::AttrKind Kind); /// removes the attribute from the return value list of attributes. - void removeRetAttr(StringRef Kind); + void removeRetAttr(AttributeKey Kind); /// removes the attributes from the return value list of attributes. void removeRetAttrs(const AttrBuilder &Attrs); @@ -390,7 +390,7 @@ void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind); /// removes the attribute from the list of attributes. - void removeParamAttr(unsigned ArgNo, StringRef Kind); + void removeParamAttr(unsigned ArgNo, AttributeKey Kind); /// removes the attribute from the list of attributes. void removeParamAttrs(unsigned ArgNo, const AttrBuilder &Attrs); @@ -399,7 +399,7 @@ bool hasFnAttribute(Attribute::AttrKind Kind) const; /// Return true if the function has the attribute. - bool hasFnAttribute(StringRef Kind) const; + bool hasFnAttribute(AttributeKey Kind) const; /// check if an attribute is in the list of attributes for the return value. bool hasRetAttribute(Attribute::AttrKind Kind) const; @@ -411,13 +411,13 @@ Attribute getAttributeAtIndex(unsigned i, Attribute::AttrKind Kind) const; /// gets the attribute from the list of attributes. - Attribute getAttributeAtIndex(unsigned i, StringRef Kind) const; + Attribute getAttributeAtIndex(unsigned i, AttributeKey Kind) const; /// Return the attribute for the given attribute kind. Attribute getFnAttribute(Attribute::AttrKind Kind) const; /// Return the attribute for the given attribute kind. - Attribute getFnAttribute(StringRef Kind) const; + Attribute getFnAttribute(AttributeKey Kind) const; /// gets the specified attribute from the list of attributes. Attribute getParamAttribute(unsigned ArgNo, Attribute::AttrKind Kind) const; Index: llvm/include/llvm/IR/GlobalVariable.h =================================================================== --- llvm/include/llvm/IR/GlobalVariable.h +++ llvm/include/llvm/IR/GlobalVariable.h @@ -190,7 +190,7 @@ } /// Add attribute to this global. - void addAttribute(StringRef Kind, StringRef Val = StringRef()) { + void addAttribute(AttributeKey Kind, StringRef Val = StringRef()) { Attrs = Attrs.addAttribute(getContext(), Kind, Val); } @@ -200,7 +200,7 @@ } /// Return true if the attribute exists. - bool hasAttribute(StringRef Kind) const { + bool hasAttribute(AttributeKey Kind) const { return Attrs.hasAttribute(Kind); } @@ -215,7 +215,7 @@ } /// Return the attribute object. - Attribute getAttribute(StringRef Kind) const { + Attribute getAttribute(AttributeKey Kind) const { return Attrs.getAttribute(Kind); } Index: llvm/include/llvm/IR/InstrTypes.h =================================================================== --- llvm/include/llvm/IR/InstrTypes.h +++ llvm/include/llvm/IR/InstrTypes.h @@ -1488,7 +1488,7 @@ /// Determine whether this call has the given attribute. If it does not /// then determine if the called function has the attribute, but only if /// the attribute is allowed for the call. - bool hasFnAttr(StringRef Kind) const { return hasFnAttrImpl(Kind); } + bool hasFnAttr(AttributeKey Kind) const { return hasFnAttrImpl(Kind); } // TODO: remove non-AtIndex versions of these methods. /// adds the attribute to the list of attributes. @@ -1539,7 +1539,7 @@ } /// removes the attribute from the list of attributes. - void removeAttributeAtIndex(unsigned i, StringRef Kind) { + void removeAttributeAtIndex(unsigned i, AttributeKey Kind) { Attrs = Attrs.removeAttributeAtIndex(getContext(), i, Kind); } @@ -1570,7 +1570,7 @@ } /// Removes the attribute from the given argument - void removeParamAttr(unsigned ArgNo, StringRef Kind) { + void removeParamAttr(unsigned ArgNo, AttributeKey Kind) { assert(ArgNo < arg_size() && "Out of bounds"); Attrs = Attrs.removeParamAttribute(getContext(), ArgNo, Kind); } @@ -1595,7 +1595,7 @@ return hasRetAttrImpl(Kind); } /// Determine whether the return value has the given attribute. - bool hasRetAttr(StringRef Kind) const { return hasRetAttrImpl(Kind); } + bool hasRetAttr(AttributeKey Kind) const { return hasRetAttrImpl(Kind); } /// Determine whether the argument or parameter has the given attribute. bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const; @@ -1606,12 +1606,12 @@ } /// Get the attribute of a given kind at a position. - Attribute getAttributeAtIndex(unsigned i, StringRef Kind) const { + Attribute getAttributeAtIndex(unsigned i, AttributeKey Kind) const { return getAttributes().getAttributeAtIndex(i, Kind); } /// Get the attribute of a given kind for the function. - Attribute getFnAttr(StringRef Kind) const { + Attribute getFnAttr(AttributeKey Kind) const { return getAttributes().getFnAttr(Kind); } @@ -1627,7 +1627,7 @@ } /// Get the attribute of a given kind from a given arg - Attribute getParamAttr(unsigned ArgNo, StringRef Kind) const { + Attribute getParamAttr(unsigned ArgNo, AttributeKey Kind) const { assert(ArgNo < arg_size() && "Out of bounds"); return getAttributes().getParamAttr(ArgNo, Kind); } @@ -2086,7 +2086,7 @@ /// Is the function attribute S disallowed by some operand bundle on /// this operand bundle user? - bool isFnAttrDisallowedByOpBundle(StringRef S) const { + bool isFnAttrDisallowedByOpBundle(AttributeKey S) const { // Operand bundles only possibly disallow readnone, readonly and argmemonly // attributes. All String attributes are fine. return false; @@ -2271,7 +2271,7 @@ private: bool hasFnAttrOnCalledFunction(Attribute::AttrKind Kind) const; - bool hasFnAttrOnCalledFunction(StringRef Kind) const; + bool hasFnAttrOnCalledFunction(AttributeKey Kind) const; template bool hasFnAttrImpl(AttrKind Kind) const { if (Attrs.hasFnAttr(Kind)) @@ -2286,7 +2286,7 @@ } /// Determine whether the return value has the given attribute. Supports - /// Attribute::AttrKind and StringRef as \p AttrKind types. + /// Attribute::AttrKind and AttributeKey as \p AttrKind types. template bool hasRetAttrImpl(AttrKind Kind) const { if (Attrs.hasRetAttr(Kind)) return true; Index: llvm/include/llvm/ProfileData/SampleProf.h =================================================================== --- llvm/include/llvm/ProfileData/SampleProf.h +++ llvm/include/llvm/ProfileData/SampleProf.h @@ -942,7 +942,7 @@ /// Return the canonical name for a function, taking into account /// suffix elision policy attributes. static StringRef getCanonicalFnName(const Function &F) { - auto AttrName = "sample-profile-suffix-elision-policy"; + AttributeKey AttrName = "sample-profile-suffix-elision-policy"; auto Attr = F.getFnAttribute(AttrName).getValueAsString(); return getCanonicalFnName(F.getName(), Attr); } Index: llvm/lib/Analysis/InlineCost.cpp =================================================================== --- llvm/lib/Analysis/InlineCost.cpp +++ llvm/lib/Analysis/InlineCost.cpp @@ -138,7 +138,7 @@ /// This function behaves more like CallBase::hasFnAttr: when it looks for the /// requested attribute, it check both the call instruction and the called /// function (if it's available and operand bundles don't prohibit that). -Attribute getFnAttr(CallBase &CB, StringRef AttrKind) { +Attribute getFnAttr(CallBase &CB, AttributeKey AttrKind) { Attribute CallAttr = CB.getFnAttr(AttrKind); if (CallAttr.isValid()) return CallAttr; @@ -152,7 +152,7 @@ return {}; } -Optional getStringFnAttrAsInt(CallBase &CB, StringRef AttrKind) { +Optional getStringFnAttrAsInt(CallBase &CB, AttributeKey AttrKind) { Attribute Attr = getFnAttr(CB, AttrKind); int AttrValue; if (Attr.getValueAsString().getAsInteger(10, AttrValue)) Index: llvm/lib/AsmParser/LLParser.cpp =================================================================== --- llvm/lib/AsmParser/LLParser.cpp +++ llvm/lib/AsmParser/LLParser.cpp @@ -1612,7 +1612,7 @@ std::string Val; if (EatIfPresent(lltok::equal) && parseStringConstant(Val)) return true; - B.addAttribute(Attr, Val); + B.addAttribute(AttributeKey::get(getContext(), Attr), Val); return false; } Index: llvm/lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1644,7 +1644,7 @@ assert(Record[i] == 0 && "Value string not null terminated"); } - B.addAttribute(KindStr.str(), ValStr.str()); + B.addAttribute(AttributeKey::get(Context, KindStr), ValStr.str()); } else { assert((Record[i] == 5 || Record[i] == 6) && "Invalid attribute group entry"); Index: llvm/lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -799,7 +799,7 @@ Record.push_back(getAttrKindEncoding(Attr.getKindAsEnum())); Record.push_back(Attr.getValueAsInt()); } else if (Attr.isStringAttribute()) { - StringRef Kind = Attr.getKindAsString(); + StringRef Kind = Attr.getKindAsKey().value(); StringRef Val = Attr.getValueAsString(); Record.push_back(Val.empty() ? 3 : 4); Index: llvm/lib/CodeGen/CommandFlags.cpp =================================================================== --- llvm/lib/CodeGen/CommandFlags.cpp +++ llvm/lib/CodeGen/CommandFlags.cpp @@ -599,7 +599,8 @@ return Features.getFeatures(); } -void codegen::renderBoolStringAttr(AttrBuilder &B, StringRef Name, bool Val) { +void codegen::renderBoolStringAttr(AttrBuilder &B, AttributeKey Name, + bool Val) { B.addAttribute(Name, Val ? "true" : "false"); } Index: llvm/lib/IR/AttributeImpl.h =================================================================== --- llvm/lib/IR/AttributeImpl.h +++ llvm/lib/IR/AttributeImpl.h @@ -25,6 +25,7 @@ #include #include #include +#include #include namespace llvm { @@ -60,13 +61,13 @@ bool isTypeAttribute() const { return KindID == TypeAttrEntry; } bool hasAttribute(Attribute::AttrKind A) const; - bool hasAttribute(StringRef Kind) const; + bool hasAttribute(AttributeKey Kind) const; Attribute::AttrKind getKindAsEnum() const; uint64_t getValueAsInt() const; bool getValueAsBool() const; - StringRef getKindAsString() const; + AttributeKey getKindAsKey() const; StringRef getValueAsString() const; Type *getValueAsType() const; @@ -80,7 +81,7 @@ else if (isIntAttribute()) Profile(ID, getKindAsEnum(), getValueAsInt()); else if (isStringAttribute()) - Profile(ID, getKindAsString(), getValueAsString()); + Profile(ID, getKindAsKey(), getValueAsString()); else Profile(ID, getKindAsEnum(), getValueAsType()); } @@ -91,8 +92,9 @@ if (Val) ID.AddInteger(Val); } - static void Profile(FoldingSetNodeID &ID, StringRef Kind, StringRef Values) { - ID.AddString(Kind); + static void Profile(FoldingSetNodeID &ID, AttributeKey Kind, + StringRef Values) { + ID.AddString(Kind.value()); if (!Values.empty()) ID.AddString(Values); } @@ -148,34 +150,26 @@ private TrailingObjects { friend TrailingObjects; - unsigned KindSize; + AttributeKey Kind; unsigned ValSize; - size_t numTrailingObjects(OverloadToken) const { - return KindSize + 1 + ValSize + 1; - } + size_t numTrailingObjects(OverloadToken) const { return ValSize + 1; } public: - StringAttributeImpl(StringRef Kind, StringRef Val = StringRef()) - : AttributeImpl(StringAttrEntry), KindSize(Kind.size()), - ValSize(Val.size()) { + StringAttributeImpl(AttributeKey Kind, StringRef Val = StringRef()) + : AttributeImpl(StringAttrEntry), Kind(Kind), ValSize(Val.size()) { char *TrailingString = getTrailingObjects(); // Some users rely on zero-termination. - llvm::copy(Kind, TrailingString); - TrailingString[KindSize] = '\0'; - llvm::copy(Val, &TrailingString[KindSize + 1]); - TrailingString[KindSize + 1 + ValSize] = '\0'; + llvm::copy(Val, TrailingString); + TrailingString[ValSize] = '\0'; } - StringRef getStringKind() const { - return StringRef(getTrailingObjects(), KindSize); - } + AttributeKey getStringKind() const { return Kind; } StringRef getStringValue() const { - return StringRef(getTrailingObjects() + KindSize + 1, ValSize); + return StringRef(getTrailingObjects(), ValSize); } - static size_t totalSizeToAlloc(StringRef Kind, StringRef Val) { - return TrailingObjects::totalSizeToAlloc(Kind.size() + 1 + - Val.size() + 1); + static size_t totalSizeToAlloc(StringRef Val) { + return TrailingObjects::totalSizeToAlloc(Val.size() + 1); } }; @@ -217,7 +211,7 @@ unsigned NumAttrs; ///< Number of attributes in this node. AttributeBitSet AvailableAttrs; ///< Available enum attributes. - DenseMap StringAttrs; + std::unordered_map StringAttrs; AttributeSetNode(ArrayRef Attrs); @@ -242,11 +236,11 @@ bool hasAttribute(Attribute::AttrKind Kind) const { return AvailableAttrs.hasAttribute(Kind); } - bool hasAttribute(StringRef Kind) const; + bool hasAttribute(AttributeKey Kind) const; bool hasAttributes() const { return NumAttrs != 0; } Attribute getAttribute(Attribute::AttrKind Kind) const; - Attribute getAttribute(StringRef Kind) const; + Attribute getAttribute(AttributeKey Kind) const; MaybeAlign getAlignment() const; MaybeAlign getStackAlignment() const; Index: llvm/lib/IR/Attributes.cpp =================================================================== --- llvm/lib/IR/Attributes.cpp +++ llvm/lib/IR/Attributes.cpp @@ -118,10 +118,11 @@ return Attribute(PA); } -Attribute Attribute::get(LLVMContext &Context, StringRef Kind, StringRef Val) { +Attribute Attribute::get(LLVMContext &Context, AttributeKey Kind, + StringRef Val) { LLVMContextImpl *pImpl = Context.pImpl; FoldingSetNodeID ID; - ID.AddString(Kind); + ID.AddString(Kind.value()); if (!Val.empty()) ID.AddString(Val); void *InsertPoint; @@ -131,7 +132,7 @@ // If we didn't find any existing attributes of the same shape then create a // new one and insert it. void *Mem = - pImpl->Alloc.Allocate(StringAttributeImpl::totalSizeToAlloc(Kind, Val), + pImpl->Alloc.Allocate(StringAttributeImpl::totalSizeToAlloc(Val), alignof(StringAttributeImpl)); PA = new (Mem) StringAttributeImpl(Kind, Val); pImpl->AttrsSet.InsertNode(PA, InsertPoint); @@ -291,11 +292,11 @@ return pImpl->getValueAsBool(); } -StringRef Attribute::getKindAsString() const { +AttributeKey Attribute::getKindAsKey() const { if (!pImpl) return {}; assert(isStringAttribute() && "Invalid attribute type to get the kind as a string!"); - return pImpl->getKindAsString(); + return pImpl->getKindAsKey(); } StringRef Attribute::getValueAsString() const { @@ -317,7 +318,7 @@ return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None); } -bool Attribute::hasAttribute(StringRef Kind) const { +bool Attribute::hasAttribute(AttributeKey Kind) const { if (!isStringAttribute()) return false; return pImpl && pImpl->hasAttribute(Kind); } @@ -448,7 +449,7 @@ std::string Result; { raw_string_ostream OS(Result); - OS << '"' << getKindAsString() << '"'; + OS << '"' << getKindAsKey().value() << '"'; // Since some attribute strings contain special characters that cannot be // printable, those have to be escaped to make the attribute value @@ -523,9 +524,9 @@ return getKindAsEnum() == A; } -bool AttributeImpl::hasAttribute(StringRef Kind) const { +bool AttributeImpl::hasAttribute(AttributeKey Kind) const { if (!isStringAttribute()) return false; - return getKindAsString() == Kind; + return getKindAsKey() == Kind; } Attribute::AttrKind AttributeImpl::getKindAsEnum() const { @@ -543,7 +544,7 @@ return getValueAsString() == "true"; } -StringRef AttributeImpl::getKindAsString() const { +AttributeKey AttributeImpl::getKindAsKey() const { assert(isStringAttribute()); return static_cast(this)->getStringKind(); } @@ -578,9 +579,9 @@ if (!AI.isStringAttribute()) return false; - if (getKindAsString() == AI.getKindAsString()) + if (getKindAsKey() == AI.getKindAsKey()) return getValueAsString() < AI.getValueAsString(); - return getKindAsString() < AI.getKindAsString(); + return getKindAsKey() < AI.getKindAsKey(); } //===----------------------------------------------------------------------===// @@ -603,7 +604,7 @@ return addAttributes(C, AttributeSet::get(C, B)); } -AttributeSet AttributeSet::addAttribute(LLVMContext &C, StringRef Kind, +AttributeSet AttributeSet::addAttribute(LLVMContext &C, AttributeKey Kind, StringRef Value) const { AttrBuilder B; B.addAttribute(Kind, Value); @@ -634,7 +635,7 @@ } AttributeSet AttributeSet::removeAttribute(LLVMContext &C, - StringRef Kind) const { + AttributeKey Kind) const { if (!hasAttribute(Kind)) return *this; AttrBuilder B(*this); B.removeAttribute(Kind); @@ -660,7 +661,7 @@ return SetNode ? SetNode->hasAttribute(Kind) : false; } -bool AttributeSet::hasAttribute(StringRef Kind) const { +bool AttributeSet::hasAttribute(AttributeKey Kind) const { return SetNode ? SetNode->hasAttribute(Kind) : false; } @@ -668,7 +669,7 @@ return SetNode ? SetNode->getAttribute(Kind) : Attribute(); } -Attribute AttributeSet::getAttribute(StringRef Kind) const { +Attribute AttributeSet::getAttribute(AttributeKey Kind) const { return SetNode ? SetNode->getAttribute(Kind) : Attribute(); } @@ -761,7 +762,7 @@ for (const auto &I : *this) { if (I.isStringAttribute()) - StringAttrs.insert({ I.getKindAsString(), I }); + StringAttrs.insert({I.getKindAsKey(), I}); else AvailableAttrs.addAttribute(I.getKindAsEnum()); } @@ -829,7 +830,7 @@ return getSorted(C, Attrs); } -bool AttributeSetNode::hasAttribute(StringRef Kind) const { +bool AttributeSetNode::hasAttribute(AttributeKey Kind) const { return StringAttrs.count(Kind); } @@ -856,8 +857,9 @@ return {}; } -Attribute AttributeSetNode::getAttribute(StringRef Kind) const { - return StringAttrs.lookup(Kind); +Attribute AttributeSetNode::getAttribute(AttributeKey Kind) const { + auto Where = StringAttrs.find(Kind); + return Where != StringAttrs.end() ? Where->second : Attribute(); } MaybeAlign AttributeSetNode::getAlignment() const { @@ -1147,7 +1149,7 @@ } AttributeList AttributeList::get(LLVMContext &C, unsigned Index, - ArrayRef Kinds) { + ArrayRef Kinds) { SmallVector, 8> Attrs; for (const auto &K : Kinds) Attrs.emplace_back(Index, Attribute::get(C, K)); @@ -1193,7 +1195,7 @@ } AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index, - StringRef Kind, + AttributeKey Kind, StringRef Value) const { AttrBuilder B; B.addAttribute(Kind, Value); @@ -1278,7 +1280,7 @@ AttributeList AttributeList::removeAttributeAtIndex(LLVMContext &C, unsigned Index, - StringRef Kind) const { + AttributeKey Kind) const { if (!hasAttributeAtIndex(Index, Kind)) return *this; @@ -1368,7 +1370,8 @@ return getAttributes(Index).hasAttribute(Kind); } -bool AttributeList::hasAttributeAtIndex(unsigned Index, StringRef Kind) const { +bool AttributeList::hasAttributeAtIndex(unsigned Index, + AttributeKey Kind) const { return getAttributes(Index).hasAttribute(Kind); } @@ -1380,7 +1383,7 @@ return pImpl && pImpl->hasFnAttribute(Kind); } -bool AttributeList::hasFnAttr(StringRef Kind) const { +bool AttributeList::hasFnAttr(AttributeKey Kind) const { return hasAttributeAtIndex(AttributeList::FunctionIndex, Kind); } @@ -1395,7 +1398,7 @@ } Attribute AttributeList::getAttributeAtIndex(unsigned Index, - StringRef Kind) const { + AttributeKey Kind) const { return getAttributes(Index).getAttribute(Kind); } @@ -1561,7 +1564,7 @@ AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) { if (Attr.isStringAttribute()) { - addAttribute(Attr.getKindAsString(), Attr.getValueAsString()); + addAttribute(Attr.getKindAsKey(), Attr.getValueAsString()); return *this; } @@ -1576,7 +1579,7 @@ return *this; } -AttrBuilder &AttrBuilder::addAttribute(StringRef A, StringRef V) { +AttrBuilder &AttrBuilder::addAttribute(AttributeKey A, StringRef V) { TargetDepAttrs[A] = V; return *this; } @@ -1598,7 +1601,7 @@ return *this; } -AttrBuilder &AttrBuilder::removeAttribute(StringRef A) { +AttrBuilder &AttrBuilder::removeAttribute(AttributeKey A) { TargetDepAttrs.erase(A); return *this; } @@ -1764,7 +1767,7 @@ return false; } -bool AttrBuilder::contains(StringRef A) const { +bool AttrBuilder::contains(AttributeKey A) const { return TargetDepAttrs.find(A) != TargetDepAttrs.end(); } @@ -1781,7 +1784,7 @@ return true; } else { assert(Attr.isStringAttribute() && "Invalid attribute kind!"); - return contains(Attr.getKindAsString()); + return contains(Attr.getKindAsKey()); } } @@ -1988,14 +1991,12 @@ }; struct StrBoolAttr { - static bool isSet(const Function &Fn, - StringRef Kind) { + static bool isSet(const Function &Fn, AttributeKey Kind) { auto A = Fn.getFnAttribute(Kind); return A.getValueAsString().equals("true"); } - static void set(Function &Fn, - StringRef Kind, bool Val) { + static void set(Function &Fn, AttributeKey Kind, bool Val) { Fn.addFnAttr(Kind, Val ? "true" : "false"); } }; @@ -2009,7 +2010,7 @@ }; #define ATTRIBUTE_STRBOOL(ENUM_NAME, DISPLAY_NAME) \ struct ENUM_NAME##Attr : StrBoolAttr { \ - static StringRef getKind() { return #DISPLAY_NAME; } \ + static AttributeKey getKind() { return #DISPLAY_NAME; } \ }; #include "llvm/IR/Attributes.inc" @@ -2043,3 +2044,20 @@ // that aspect in the merged function. mergeFnAttrs(Base, ToMerge); } + +AttributeKey AttributeKey::get(LLVMContext &Context, StringRef S) { + assert(S.size() < std::numeric_limits::max() && + "large enough size storage"); + + LLVMContextImpl *pImpl = Context.pImpl; + auto &AttributeKeys = pImpl->AttributeKeys; + CachedHashStringRef HashedS(S, AttributeKey::hasher(S.data(), S.size())); + auto Where = AttributeKeys.find(HashedS); + if (Where == AttributeKeys.end()) { + AttributeKey Key(HashedS); + AttributeKeys.insert({CachedHashStringRef(Key.value(), Key.hash()), Key}); + return Key; + } else { + return Where->second; + } +} Index: llvm/lib/IR/Core.cpp =================================================================== --- llvm/lib/IR/Core.cpp +++ llvm/lib/IR/Core.cpp @@ -179,13 +179,14 @@ LLVMAttributeRef LLVMCreateStringAttribute(LLVMContextRef C, const char *K, unsigned KLength, const char *V, unsigned VLength) { - return wrap(Attribute::get(*unwrap(C), StringRef(K, KLength), + auto &Ctx = *unwrap(C); + return wrap(Attribute::get(Ctx, AttributeKey::get(Ctx, StringRef(K, KLength)), StringRef(V, VLength))); } const char *LLVMGetStringAttributeKind(LLVMAttributeRef A, unsigned *Length) { - auto S = unwrap(A).getKindAsString(); + StringRef S = unwrap(A).getKindAsKey().value(); *Length = S.size(); return S.data(); } @@ -2485,8 +2486,9 @@ LLVMAttributeRef LLVMGetStringAttributeAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx, const char *K, unsigned KLen) { - return wrap( - unwrap(F)->getAttributeAtIndex(Idx, StringRef(K, KLen))); + Function *Func = unwrap(F); + return wrap(Func->getAttributeAtIndex( + Idx, AttributeKey::get(Func->getContext(), StringRef(K, KLen)))); } void LLVMRemoveEnumAttributeAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx, @@ -2496,13 +2498,16 @@ void LLVMRemoveStringAttributeAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx, const char *K, unsigned KLen) { - unwrap(F)->removeAttributeAtIndex(Idx, StringRef(K, KLen)); + Function *Func = unwrap(F); + Func->removeAttributeAtIndex( + Idx, AttributeKey::get(Func->getContext(), StringRef(K, KLen))); } void LLVMAddTargetDependentFunctionAttr(LLVMValueRef Fn, const char *A, const char *V) { Function *Func = unwrap(Fn); - Attribute Attr = Attribute::get(Func->getContext(), A, V); + Attribute Attr = Attribute::get(Func->getContext(), + AttributeKey::get(Func->getContext(), A), V); Func->addFnAttr(Attr); } @@ -2896,8 +2901,9 @@ LLVMAttributeRef LLVMGetCallSiteStringAttribute(LLVMValueRef C, LLVMAttributeIndex Idx, const char *K, unsigned KLen) { - return wrap( - unwrap(C)->getAttributeAtIndex(Idx, StringRef(K, KLen))); + CallBase *CB = unwrap(C); + return wrap(CB->getAttributeAtIndex( + Idx, AttributeKey::get(CB->getContext(), StringRef(K, KLen)))); } void LLVMRemoveCallSiteEnumAttribute(LLVMValueRef C, LLVMAttributeIndex Idx, @@ -2907,7 +2913,9 @@ void LLVMRemoveCallSiteStringAttribute(LLVMValueRef C, LLVMAttributeIndex Idx, const char *K, unsigned KLen) { - unwrap(C)->removeAttributeAtIndex(Idx, StringRef(K, KLen)); + CallBase *CB = unwrap(C); + CB->removeAttributeAtIndex( + Idx, AttributeKey::get(CB->getContext(), StringRef(K, KLen))); } LLVMValueRef LLVMGetCalledValue(LLVMValueRef Instr) { Index: llvm/lib/IR/DiagnosticInfo.cpp =================================================================== --- llvm/lib/IR/DiagnosticInfo.cpp +++ llvm/lib/IR/DiagnosticInfo.cpp @@ -406,7 +406,8 @@ return; for (int i = 0; i != 2; ++i) { - auto AttrName = i == 0 ? "dontcall-error" : "dontcall-warn"; + auto AttrName = + i == 0 ? AttributeKey("dontcall-error") : AttributeKey("dontcall-warn"); auto Sev = i == 0 ? DS_Error : DS_Warning; if (F->hasFnAttribute(AttrName)) { Index: llvm/lib/IR/Function.cpp =================================================================== --- llvm/lib/IR/Function.cpp +++ llvm/lib/IR/Function.cpp @@ -537,7 +537,7 @@ AttributeSets = AttributeSets.addFnAttribute(getContext(), Kind); } -void Function::addFnAttr(StringRef Kind, StringRef Val) { +void Function::addFnAttr(AttributeKey Kind, StringRef Val) { AttributeSets = AttributeSets.addFnAttribute(getContext(), Kind, Val); } @@ -577,7 +577,7 @@ AttributeSets = AttributeSets.removeAttributeAtIndex(getContext(), i, Kind); } -void Function::removeAttributeAtIndex(unsigned i, StringRef Kind) { +void Function::removeAttributeAtIndex(unsigned i, AttributeKey Kind) { AttributeSets = AttributeSets.removeAttributeAtIndex(getContext(), i, Kind); } @@ -585,7 +585,7 @@ AttributeSets = AttributeSets.removeFnAttribute(getContext(), Kind); } -void Function::removeFnAttr(StringRef Kind) { +void Function::removeFnAttr(AttributeKey Kind) { AttributeSets = AttributeSets.removeFnAttribute(getContext(), Kind); } @@ -597,7 +597,7 @@ AttributeSets = AttributeSets.removeRetAttribute(getContext(), Kind); } -void Function::removeRetAttr(StringRef Kind) { +void Function::removeRetAttr(AttributeKey Kind) { AttributeSets = AttributeSets.removeRetAttribute(getContext(), Kind); } @@ -609,7 +609,7 @@ AttributeSets = AttributeSets.removeParamAttribute(getContext(), ArgNo, Kind); } -void Function::removeParamAttr(unsigned ArgNo, StringRef Kind) { +void Function::removeParamAttr(unsigned ArgNo, AttributeKey Kind) { AttributeSets = AttributeSets.removeParamAttribute(getContext(), ArgNo, Kind); } @@ -627,7 +627,7 @@ return AttributeSets.hasFnAttr(Kind); } -bool Function::hasFnAttribute(StringRef Kind) const { +bool Function::hasFnAttribute(AttributeKey Kind) const { return AttributeSets.hasFnAttr(Kind); } @@ -645,7 +645,7 @@ return AttributeSets.getAttributeAtIndex(i, Kind); } -Attribute Function::getAttributeAtIndex(unsigned i, StringRef Kind) const { +Attribute Function::getAttributeAtIndex(unsigned i, AttributeKey Kind) const { return AttributeSets.getAttributeAtIndex(i, Kind); } @@ -653,7 +653,7 @@ return AttributeSets.getFnAttr(Kind); } -Attribute Function::getFnAttribute(StringRef Kind) const { +Attribute Function::getFnAttribute(AttributeKey Kind) const { return AttributeSets.getFnAttr(Kind); } Index: llvm/lib/IR/Instructions.cpp =================================================================== --- llvm/lib/IR/Instructions.cpp +++ llvm/lib/IR/Instructions.cpp @@ -360,7 +360,7 @@ return false; } -bool CallBase::hasFnAttrOnCalledFunction(StringRef Kind) const { +bool CallBase::hasFnAttrOnCalledFunction(AttributeKey Kind) const { Value *V = getCalledOperand(); if (auto *CE = dyn_cast(V)) if (CE->getOpcode() == BitCast) Index: llvm/lib/IR/LLVMContextImpl.h =================================================================== --- llvm/lib/IR/LLVMContextImpl.h +++ llvm/lib/IR/LLVMContextImpl.h @@ -19,6 +19,7 @@ #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/CachedHashString.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/DenseSet.h" @@ -1378,6 +1379,9 @@ LLVMContext::YieldCallbackTy YieldCallback = nullptr; void *YieldOpaqueHandle = nullptr; + using AttributeKeyMapTy = DenseMap; + AttributeKeyMapTy AttributeKeys; + using IntMapTy = DenseMap, DenseMapAPIntKeyInfo>; IntMapTy IntConstants; Index: llvm/lib/IR/Verifier.cpp =================================================================== --- llvm/lib/IR/Verifier.cpp +++ llvm/lib/IR/Verifier.cpp @@ -548,7 +548,7 @@ bool verifyAttributeCount(AttributeList Attrs, unsigned Params); void verifyAttributeTypes(AttributeSet Attrs, const Value *V); void verifyParameterAttrs(AttributeSet Attrs, Type *Ty, const Value *V); - void checkUnsignedBaseTenFuncAttr(AttributeList Attrs, StringRef Attr, + void checkUnsignedBaseTenFuncAttr(AttributeList Attrs, AttributeKey Attr, const Value *V); void verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs, const Value *V, bool IsIntrinsic); @@ -1706,7 +1706,7 @@ #define GET_ATTR_NAMES #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) #define ATTRIBUTE_STRBOOL(ENUM_NAME, DISPLAY_NAME) \ - if (A.getKindAsString() == #DISPLAY_NAME) { \ + if (A.getKindAsKey().value() == #DISPLAY_NAME) { \ auto V = A.getValueAsString(); \ if (!(V.empty() || V == "true" || V == "false")) \ CheckFailed("invalid value for '" #DISPLAY_NAME "' attribute: " + V + \ @@ -1868,13 +1868,14 @@ } } -void Verifier::checkUnsignedBaseTenFuncAttr(AttributeList Attrs, StringRef Attr, - const Value *V) { +void Verifier::checkUnsignedBaseTenFuncAttr(AttributeList Attrs, + AttributeKey Attr, const Value *V) { if (Attrs.hasFnAttr(Attr)) { StringRef S = Attrs.getFnAttr(Attr).getValueAsString(); unsigned N; if (S.getAsInteger(10, N)) - CheckFailed("\"" + Attr + "\" takes an unsigned integer: " + S, V); + CheckFailed("\"" + Attr.value() + "\" takes an unsigned integer: " + S, + V); } } Index: llvm/lib/Transforms/IPO/Attributor.cpp =================================================================== --- llvm/lib/Transforms/IPO/Attributor.cpp +++ llvm/lib/Transforms/IPO/Attributor.cpp @@ -390,7 +390,7 @@ return true; } if (Attr.isStringAttribute()) { - StringRef Kind = Attr.getKindAsString(); + AttributeKey Kind = Attr.getKindAsKey(); if (Attrs.hasAttributeAtIndex(AttrIdx, Kind)) if (!ForceReplace && isEqualOrWorse(Attr, Attrs.getAttributeAtIndex(AttrIdx, Kind))) Index: llvm/lib/Transforms/IPO/OpenMPOpt.cpp =================================================================== --- llvm/lib/Transforms/IPO/OpenMPOpt.cpp +++ llvm/lib/Transforms/IPO/OpenMPOpt.cpp @@ -4319,7 +4319,7 @@ : ChangeStatus::CHANGED; } - ChangeStatus foldKernelFnAttribute(Attributor &A, llvm::StringRef Attr) { + ChangeStatus foldKernelFnAttribute(Attributor &A, AttributeKey Attr) { // Specialize only if all the calls agree with the attribute constant value int32_t CurrentAttrValue = -1; Optional SimplifiedValueBefore = SimplifiedValue; Index: llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp =================================================================== --- llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -4194,14 +4194,9 @@ MemorySanitizerVisitor &MSV) : F(F), MS(MS), MSV(MSV) { AMD64FpEndOffset = AMD64FpEndOffsetSSE; - for (const auto &Attr : F.getAttributes().getFnAttrs()) { - if (Attr.isStringAttribute() && - (Attr.getKindAsString() == "target-features")) { - if (Attr.getValueAsString().contains("-sse")) - AMD64FpEndOffset = AMD64FpEndOffsetNoSSE; - break; - } - } + if (F.hasFnAttribute("target-features") && + F.getFnAttribute("target-features").getValueAsString().contains("-sse")) + AMD64FpEndOffset = AMD64FpEndOffsetNoSSE; } ArgKind classifyArgument(Value* arg) { Index: llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp =================================================================== --- llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp +++ llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp @@ -1528,7 +1528,7 @@ } // end anonymous namespace static StringRef getDeoptLowering(CallBase *Call) { - const char *DeoptLowering = "deopt-lowering"; + const char DeoptLowering[] = "deopt-lowering"; if (Call->hasFnAttr(DeoptLowering)) { // FIXME: Calls have a *really* confusing interface around attributes // with values. Index: llvm/lib/Transforms/Utils/CodeExtractor.cpp =================================================================== --- llvm/lib/Transforms/Utils/CodeExtractor.cpp +++ llvm/lib/Transforms/Utils/CodeExtractor.cpp @@ -888,7 +888,7 @@ // attribute can not be inherited. for (const auto &Attr : oldFunction->getAttributes().getFnAttrs()) { if (Attr.isStringAttribute()) { - if (Attr.getKindAsString() == "thunk") + if (Attr.getKindAsKey() == "thunk") continue; } else switch (Attr.getKindAsEnum()) { Index: llvm/lib/Transforms/Utils/EntryExitInstrumenter.cpp =================================================================== --- llvm/lib/Transforms/Utils/EntryExitInstrumenter.cpp +++ llvm/lib/Transforms/Utils/EntryExitInstrumenter.cpp @@ -67,11 +67,13 @@ } static bool runOnFunction(Function &F, bool PostInlining) { - StringRef EntryAttr = PostInlining ? "instrument-function-entry-inlined" - : "instrument-function-entry"; + AttributeKey EntryAttr = + PostInlining ? AttributeKey("instrument-function-entry-inlined") + : AttributeKey("instrument-function-entry"); - StringRef ExitAttr = PostInlining ? "instrument-function-exit-inlined" - : "instrument-function-exit"; + AttributeKey ExitAttr = PostInlining + ? AttributeKey("instrument-function-exit-inlined") + : AttributeKey("instrument-function-exit"); StringRef EntryFunc = F.getFnAttribute(EntryAttr).getValueAsString(); StringRef ExitFunc = F.getFnAttribute(ExitAttr).getValueAsString();