[llvm] ccfc54a - [IR] Split the attribute pool by kind. NFC (#221620)

via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 7 01:41:03 PDT 2026


Author: Fangrui Song
Date: 2026-09-07T01:40:56-07:00
New Revision: ccfc54aa053e1e0614660cc5f3ff0122eff02ab9

URL: https://github.com/llvm/llvm-project/commit/ccfc54aa053e1e0614660cc5f3ff0122eff02ab9
DIFF: https://github.com/llvm/llvm-project/commit/ccfc54aa053e1e0614660cc5f3ff0122eff02ab9.diff

LOG: [IR] Split the attribute pool by kind. NFC (#221620)

Change Attribute::get overloads to use fine-grained hash-consing pools
(Enum/Int/String/Type), avoiding FoldingSetNodeID serialization
overhead. Use a flat array for Enum attributes, which carry no value.

The two ConstantRange kinds keep using FoldingSet: they are not used
often, and UniquingSet cannot be used with custom UniquingSetInfo
(`APInt::operator==` asserts identical BitWidth).

Aided by Opus 5

Added: 
    

Modified: 
    llvm/include/llvm/IR/Attributes.h
    llvm/lib/IR/AttributeImpl.h
    llvm/lib/IR/Attributes.cpp
    llvm/lib/IR/LLVMContextImpl.h

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/IR/Attributes.h b/llvm/include/llvm/IR/Attributes.h
index 03efc5d677f93..f8185c76dfb5c 100644
--- a/llvm/include/llvm/IR/Attributes.h
+++ b/llvm/include/llvm/IR/Attributes.h
@@ -132,6 +132,7 @@ class Attribute {
     TombstoneKey,          ///< Use as Tombstone key for DenseMap of AttrKind
   };
 
+  static const unsigned NumEnumAttrKinds = LastEnumAttr - FirstEnumAttr + 1;
   static const unsigned NumIntAttrKinds = LastIntAttr - FirstIntAttr + 1;
   static const unsigned NumTypeAttrKinds = LastTypeAttr - FirstTypeAttr + 1;
 

diff  --git a/llvm/lib/IR/AttributeImpl.h b/llvm/lib/IR/AttributeImpl.h
index 7e1815d83b4e4..e8a814d8476a1 100644
--- a/llvm/lib/IR/AttributeImpl.h
+++ b/llvm/lib/IR/AttributeImpl.h
@@ -92,44 +92,15 @@ class AttributeImpl : public FoldingSetNode {
   /// Used when sorting the attributes.
   bool operator<(const AttributeImpl &AI) const;
 
+  /// Only the ConstantRange kinds are uniqued by profile; every other kind
+  /// has a pool with a typed key.
   void Profile(FoldingSetNodeID &ID) const {
-    if (isEnumAttribute())
-      Profile(ID, getKindAsEnum());
-    else if (isIntAttribute())
-      Profile(ID, getKindAsEnum(), getValueAsInt());
-    else if (isStringAttribute())
-      Profile(ID, getKindAsString(), getValueAsString());
-    else if (isTypeAttribute())
-      Profile(ID, getKindAsEnum(), getValueAsType());
-    else if (isConstantRangeAttribute())
+    if (isConstantRangeAttribute())
       Profile(ID, getKindAsEnum(), getValueAsConstantRange());
     else
       Profile(ID, getKindAsEnum(), getValueAsConstantRangeList());
   }
 
-  static void Profile(FoldingSetNodeID &ID, Attribute::AttrKind Kind) {
-    assert(Attribute::isEnumAttrKind(Kind) && "Expected enum attribute");
-    ID.AddInteger(Kind);
-  }
-
-  static void Profile(FoldingSetNodeID &ID, Attribute::AttrKind Kind,
-                      uint64_t Val) {
-    assert(Attribute::isIntAttrKind(Kind) && "Expected int attribute");
-    ID.AddInteger(Kind);
-    ID.AddInteger(Val);
-  }
-
-  static void Profile(FoldingSetNodeID &ID, StringRef Kind, StringRef Values) {
-    ID.AddString(Kind);
-    if (!Values.empty()) ID.AddString(Values);
-  }
-
-  static void Profile(FoldingSetNodeID &ID, Attribute::AttrKind Kind,
-                      Type *Ty) {
-    ID.AddInteger(Kind);
-    ID.AddPointer(Ty);
-  }
-
   static void Profile(FoldingSetNodeID &ID, Attribute::AttrKind Kind,
                       const ConstantRange &CR) {
     ID.AddInteger(Kind);
@@ -186,6 +157,8 @@ class IntAttributeImpl : public EnumAttributeImpl {
   }
 
   uint64_t getValue() const { return Val; }
+
+  std::pair<unsigned, uint64_t> getKey() const { return {getEnumKind(), Val}; }
 };
 
 class StringAttributeImpl final
@@ -215,6 +188,10 @@ class StringAttributeImpl final
     return StringRef(getTrailingObjects() + KindSize + 1, ValSize);
   }
 
+  std::pair<StringRef, StringRef> getKey() const {
+    return {getStringKind(), getStringValue()};
+  }
+
   static size_t totalSizeToAlloc(StringRef Kind, StringRef Val) {
     return TrailingObjects::totalSizeToAlloc<char>(Kind.size() + 1 +
                                                    Val.size() + 1);
@@ -229,6 +206,8 @@ class TypeAttributeImpl : public EnumAttributeImpl {
       : EnumAttributeImpl(TypeAttrEntry, Kind), Ty(Ty) {}
 
   Type *getTypeValue() const { return Ty; }
+
+  std::pair<unsigned, Type *> getKey() const { return {getEnumKind(), Ty}; }
 };
 
 class ConstantRangeAttributeImpl : public EnumAttributeImpl {

diff  --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp
index c75f0536f172d..727a7bcb6a144 100644
--- a/llvm/lib/IR/Attributes.cpp
+++ b/llvm/lib/IR/Attributes.cpp
@@ -99,24 +99,21 @@ Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
          "Not an enum or int attribute");
 
   LLVMContextImpl *pImpl = Context.pImpl;
-  FoldingSetNodeID ID;
-  ID.AddInteger(Kind);
-  if (IsIntAttr)
-    ID.AddInteger(Val);
-  else
+  if (!IsIntAttr) {
     assert(Val == 0 && "Value must be zero for enum attributes");
+    EnumAttributeImpl *&PA = pImpl->EnumAttrs[Kind - Attribute::FirstEnumAttr];
+    if (!PA)
+      PA = new (pImpl->Alloc) EnumAttributeImpl(Kind);
+    return Attribute(PA);
+  }
 
   FoldingSetInsertToken Token;
-  AttributeImpl *PA = pImpl->AttrsSet.lookup(ID, Token);
-
+  IntAttributeImpl *PA = pImpl->IntAttrs.lookup({Kind, Val}, Token);
   if (!PA) {
     // If we didn't find any existing attributes of the same shape then create a
     // new one and insert it.
-    if (!IsIntAttr)
-      PA = new (pImpl->Alloc) EnumAttributeImpl(Kind);
-    else
-      PA = new (pImpl->Alloc) IntAttributeImpl(Kind, Val);
-    pImpl->AttrsSet.insert(PA, Token);
+    PA = new (pImpl->Alloc) IntAttributeImpl(Kind, Val);
+    pImpl->IntAttrs.insert(PA, Token);
   }
 
   // Return the Attribute that we found or created.
@@ -125,13 +122,8 @@ Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
 
 Attribute Attribute::get(LLVMContext &Context, StringRef Kind, StringRef Val) {
   LLVMContextImpl *pImpl = Context.pImpl;
-  FoldingSetNodeID ID;
-  ID.AddString(Kind);
-  if (!Val.empty()) ID.AddString(Val);
-
   FoldingSetInsertToken Token;
-  AttributeImpl *PA = pImpl->AttrsSet.lookup(ID, Token);
-
+  StringAttributeImpl *PA = pImpl->StringAttrs.lookup({Kind, Val}, Token);
   if (!PA) {
     // If we didn't find any existing attributes of the same shape then create a
     // new one and insert it.
@@ -139,7 +131,7 @@ Attribute Attribute::get(LLVMContext &Context, StringRef Kind, StringRef Val) {
         pImpl->Alloc.Allocate(StringAttributeImpl::totalSizeToAlloc(Kind, Val),
                               alignof(StringAttributeImpl));
     PA = new (Mem) StringAttributeImpl(Kind, Val);
-    pImpl->AttrsSet.insert(PA, Token);
+    pImpl->StringAttrs.insert(PA, Token);
   }
 
   // Return the Attribute that we found or created.
@@ -150,18 +142,13 @@ Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
                          Type *Ty) {
   assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
   LLVMContextImpl *pImpl = Context.pImpl;
-  FoldingSetNodeID ID;
-  ID.AddInteger(Kind);
-  ID.AddPointer(Ty);
-
   FoldingSetInsertToken Token;
-  AttributeImpl *PA = pImpl->AttrsSet.lookup(ID, Token);
-
+  TypeAttributeImpl *PA = pImpl->TypeAttrs.lookup({Kind, Ty}, Token);
   if (!PA) {
     // If we didn't find any existing attributes of the same shape then create a
     // new one and insert it.
     PA = new (pImpl->Alloc) TypeAttributeImpl(Kind, Ty);
-    pImpl->AttrsSet.insert(PA, Token);
+    pImpl->TypeAttrs.insert(PA, Token);
   }
 
   // Return the Attribute that we found or created.
@@ -778,10 +765,24 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
 
 bool Attribute::hasParentContext(LLVMContext &C) const {
   assert(isValid() && "invalid Attribute doesn't refer to any context");
+  LLVMContextImpl *pI = C.pImpl;
+  FoldingSetInsertToken Token;
+  if (pImpl->isEnumAttribute())
+    return pI->EnumAttrs[pImpl->getKindAsEnum() - FirstEnumAttr] == pImpl;
+  if (pImpl->isIntAttribute())
+    return pI->IntAttrs.lookup({pImpl->getKindAsEnum(), pImpl->getValueAsInt()},
+                               Token) == pImpl;
+  if (pImpl->isStringAttribute())
+    return pI->StringAttrs.lookup(
+               {pImpl->getKindAsString(), pImpl->getValueAsString()}, Token) ==
+           pImpl;
+  if (pImpl->isTypeAttribute())
+    return pI->TypeAttrs.lookup(
+               {pImpl->getKindAsEnum(), pImpl->getValueAsType()}, Token) ==
+           pImpl;
   FoldingSetNodeID ID;
   pImpl->Profile(ID);
-  FoldingSetInsertToken Token;
-  return C.pImpl->AttrsSet.lookup(ID, Token) == pImpl;
+  return pI->AttrsSet.lookup(ID, Token) == pImpl;
 }
 
 int Attribute::cmpKind(Attribute A) const {

diff  --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h
index 1b8169f845824..49a8a803732a5 100644
--- a/llvm/lib/IR/LLVMContextImpl.h
+++ b/llvm/lib/IR/LLVMContextImpl.h
@@ -1624,6 +1624,10 @@ class LLVMContextImpl {
   DenseMap<std::pair<ElementCount, APFloat>, std::unique_ptr<ConstantFP>>
       FPSplatConstants;
 
+  EnumAttributeImpl *EnumAttrs[Attribute::NumEnumAttrKinds] = {};
+  UniquingSet<IntAttributeImpl> IntAttrs;
+  UniquingSet<StringAttributeImpl> StringAttrs;
+  UniquingSet<TypeAttributeImpl> TypeAttrs;
   FoldingSet<AttributeImpl> AttrsSet;
   UniquingSet<AttributeListImpl> AttrsLists;
   UniquingSet<AttributeSetNode> AttrsSetNodes;


        


More information about the llvm-commits mailing list