serge-sans-paille updated this revision to Diff 389187.
serge-sans-paille added a comment.

Remove static Dict and replace it by a dict attached to LLVMContext.

Some early benchmarks, on the SQLite amalgamation, through ` valgrind 
--tool=callgrind ./bin/clang -c -o/dev/null sqlite3.c`

Instruction count
Before: 6,072,172,562
After:    6,011,551,695


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D114394/new/

https://reviews.llvm.org/D114394

Files:
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGOpenMPRuntime.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  llvm/include/llvm/Analysis/TargetLibraryInfo.h
  llvm/include/llvm/Analysis/VectorUtils.h
  llvm/include/llvm/CodeGen/CommandFlags.h
  llvm/include/llvm/IR/Assumptions.h
  llvm/include/llvm/IR/Attributes.h
  llvm/include/llvm/IR/Function.h
  llvm/include/llvm/IR/GlobalVariable.h
  llvm/include/llvm/IR/InstrTypes.h
  llvm/include/llvm/ProfileData/SampleProf.h
  llvm/lib/Analysis/InlineCost.cpp
  llvm/lib/AsmParser/LLParser.cpp
  llvm/lib/Bitcode/Reader/BitcodeReader.cpp
  llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
  llvm/lib/CodeGen/CommandFlags.cpp
  llvm/lib/IR/AttributeImpl.h
  llvm/lib/IR/Attributes.cpp
  llvm/lib/IR/Core.cpp
  llvm/lib/IR/DiagnosticInfo.cpp
  llvm/lib/IR/Function.cpp
  llvm/lib/IR/Instructions.cpp
  llvm/lib/IR/LLVMContextImpl.h
  llvm/lib/IR/Verifier.cpp
  llvm/lib/Transforms/IPO/Attributor.cpp
  llvm/lib/Transforms/IPO/OpenMPOpt.cpp
  llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
  llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp
  llvm/lib/Transforms/Utils/CodeExtractor.cpp
  llvm/lib/Transforms/Utils/EntryExitInstrumenter.cpp

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();
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/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/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/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<Value *> SimplifiedValueBefore = SimplifiedValue;
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/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/IR/LLVMContextImpl.h
===================================================================
--- llvm/lib/IR/LLVMContextImpl.h
+++ llvm/lib/IR/LLVMContextImpl.h
@@ -1378,6 +1378,9 @@
   LLVMContext::YieldCallbackTy YieldCallback = nullptr;
   void *YieldOpaqueHandle = nullptr;
 
+  using AttributeKeyMapTy = DenseMap<StringRef, AttributeKey>;
+  AttributeKeyMapTy AttributeKeys;
+
   using IntMapTy =
       DenseMap<APInt, std::unique_ptr<ConstantInt>, DenseMapAPIntKeyInfo>;
   IntMapTy IntConstants;
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<ConstantExpr>(V))
     if (CE->getOpcode() == BitCast)
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/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/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<Function>(F)->getAttributeAtIndex(Idx, StringRef(K, KLen)));
+  Function *Func = unwrap<Function>(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<Function>(F)->removeAttributeAtIndex(Idx, StringRef(K, KLen));
+  Function *Func = unwrap<Function>(F);
+  Func->removeAttributeAtIndex(
+      Idx, AttributeKey::get(Func->getContext(), StringRef(K, KLen)));
 }
 
 void LLVMAddTargetDependentFunctionAttr(LLVMValueRef Fn, const char *A,
                                         const char *V) {
   Function *Func = unwrap<Function>(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<CallBase>(C)->getAttributeAtIndex(Idx, StringRef(K, KLen)));
+  CallBase *CB = unwrap<CallBase>(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<CallBase>(C)->removeAttributeAtIndex(Idx, StringRef(K, KLen));
+  CallBase *CB = unwrap<CallBase>(C);
+  CB->removeAttributeAtIndex(
+      Idx, AttributeKey::get(CB->getContext(), StringRef(K, KLen)));
 }
 
 LLVMValueRef LLVMGetCalledValue(LLVMValueRef Instr) {
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<const StringAttributeImpl *>(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<StringRef> Kinds) {
+                                 ArrayRef<AttributeKey> Kinds) {
   SmallVector<std::pair<unsigned, Attribute>, 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,19 @@
   // that aspect in the merged function.
   mergeFnAttrs(Base, ToMerge);
 }
+
+AttributeKey AttributeKey::get(LLVMContext &Context, StringRef s) {
+  assert(s.size() < std::numeric_limits<decltype(size_)>::max() &&
+         "large enough size storage");
+
+  LLVMContextImpl *pImpl = Context.pImpl;
+  auto &AttributeKeys = pImpl->AttributeKeys;
+  auto Where = AttributeKeys.find(s);
+  if (Where == AttributeKeys.end()) {
+    AttributeKey Key(s);
+    AttributeKeys.insert({Key.value(), Key});
+    return Key;
+  } else {
+    return Where->second;
+  }
+}
Index: llvm/lib/IR/AttributeImpl.h
===================================================================
--- llvm/lib/IR/AttributeImpl.h
+++ llvm/lib/IR/AttributeImpl.h
@@ -25,6 +25,7 @@
 #include <cstddef>
 #include <cstdint>
 #include <string>
+#include <unordered_map>
 #include <utility>
 
 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<StringAttributeImpl, char> {
   friend TrailingObjects;
 
-  unsigned KindSize;
+  AttributeKey Kind;
   unsigned ValSize;
-  size_t numTrailingObjects(OverloadToken<char>) const {
-    return KindSize + 1 + ValSize + 1;
-  }
+  size_t numTrailingObjects(OverloadToken<char>) 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<char>();
     // 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<char>(), KindSize);
-  }
+  AttributeKey getStringKind() const { return Kind; }
   StringRef getStringValue() const {
-    return StringRef(getTrailingObjects<char>() + KindSize + 1, ValSize);
+    return StringRef(getTrailingObjects<char>(), ValSize);
   }
 
-  static size_t totalSizeToAlloc(StringRef Kind, StringRef Val) {
-    return TrailingObjects::totalSizeToAlloc<char>(Kind.size() + 1 +
-                                                   Val.size() + 1);
+  static size_t totalSizeToAlloc(StringRef Val) {
+    return TrailingObjects::totalSizeToAlloc<char>(Val.size() + 1);
   }
 };
 
@@ -217,7 +211,7 @@
   unsigned NumAttrs; ///< Number of attributes in this node.
   AttributeBitSet AvailableAttrs; ///< Available enum attributes.
 
-  DenseMap<StringRef, Attribute> StringAttrs;
+  std::unordered_map<AttributeKey, Attribute> StringAttrs;
 
   AttributeSetNode(ArrayRef<Attribute> 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/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/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/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/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/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<int> getStringFnAttrAsInt(CallBase &CB, StringRef AttrKind) {
+Optional<int> getStringFnAttrAsInt(CallBase &CB, AttributeKey AttrKind) {
   Attribute Attr = getFnAttr(CB, AttrKind);
   int AttrValue;
   if (Attr.getValueAsString().getAsInteger(10, AttrValue))
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/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 <typename AttrKind> 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 <typename AttrKind> bool hasRetAttrImpl(AttrKind Kind) const {
     if (Attrs.hasRetAttr(Kind))
       return true;
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/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/Attributes.h
===================================================================
--- llvm/include/llvm/IR/Attributes.h
+++ llvm/include/llvm/IR/Attributes.h
@@ -17,6 +17,7 @@
 
 #include "llvm-c/Types.h"
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringRef.h"
@@ -33,6 +34,63 @@
 
 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_;
+
+  static constexpr uint32_t dj2(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;
+  }
+
+  AttributeKey(StringRef s)
+      : value_(strndup(s.data(), s.size())), hash_(dj2(s.data(), s.size())),
+        size_(s.size()) {}
+
+public:
+  static AttributeKey get(LLVMContext &Ctxt, StringRef s);
+
+  template <std::size_t N>
+  constexpr AttributeKey(const char (&s)[N])
+      : value_(s), hash_(dj2(s, N - 1)), size_(N - 1) {
+    static_assert(N - 1 < std::numeric_limits<decltype(size_)>::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;
+  }
+};
+} // namespace llvm
+
+template <> struct std::hash<llvm::AttributeKey> {
+  std::size_t operator()(llvm::AttributeKey const &s) const noexcept {
+    return s.hash();
+  }
+};
+
+namespace llvm {
+
 class AttrBuilder;
 class AttributeImpl;
 class AttributeListImpl;
@@ -109,7 +167,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 +229,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 +245,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 +355,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 +371,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 +388,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 +509,7 @@
                            ArrayRef<Attribute::AttrKind> Kinds,
                            ArrayRef<uint64_t> Values);
   static AttributeList get(LLVMContext &C, unsigned Index,
-                           ArrayRef<StringRef> Kind);
+                           ArrayRef<AttributeKey> Kind);
   static AttributeList get(LLVMContext &C, unsigned Index,
                            const AttrBuilder &B);
 
@@ -464,7 +522,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 +554,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 +596,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 +624,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 +650,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 +677,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 +699,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 +771,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 +782,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 +797,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 +808,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 +823,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 +831,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 +841,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 +988,7 @@
 /// equality, presence of attributes, etc.
 class AttrBuilder {
   std::bitset<Attribute::EndAttrKinds> Attrs;
-  std::map<SmallString<32>, SmallString<32>, std::less<>> TargetDepAttrs;
+  std::map<AttributeKey, SmallString<32>> TargetDepAttrs;
   std::array<uint64_t, Attribute::NumIntAttrKinds> IntAttrs = {};
   std::array<Type *, Attribute::NumTypeAttrKinds> TypeAttrs = {};
 
@@ -963,7 +1021,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 +1030,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 +1050,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/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/CodeGen/CommandFlags.h
===================================================================
--- llvm/include/llvm/CodeGen/CommandFlags.h
+++ llvm/include/llvm/CodeGen/CommandFlags.h
@@ -161,7 +161,7 @@
 
 std::vector<std::string> 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/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/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: 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: 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/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-<name>
   // * 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);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to