[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