[lld] [llvm] [FoldingSet] Add typed lookup/insert/erase/getOrInsert (PR #219644)
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Sat Aug 29 00:39:49 PDT 2026
https://github.com/MaskRay updated https://github.com/llvm/llvm-project/pull/219644
>From 8beeabb3d5959454c53b6343444841eb87e48359 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Fri, 28 Aug 2026 23:16:51 -0700
Subject: [PATCH 1/2] [FoldingSet] Add typed lookup/insert/erase/getOrInsert
FindNodeOrInsertPos hands the insertion state to `InsertNode` as a `void *`:
any pointer converts to it, since the switch to linear probing it's the
hash, not a position at all.
Carry it in `FoldingSetInsertToken` instead: a 64-bit value (even on
32-bit platforms) holding the hash plus one, so every hash including
NotAHash yields a non-zero token.
Add lookup/insert as the typed replacements for FindNodeOrInsertPos/
InsertNode, plus erase/getOrInsert, on FoldingSetImpl, FoldingSetVector
and ContextualFoldingSet. The old `void *`-based names will be phased
out.
Migrate RecordKeeper's dozen Init/RecTy FoldingSet pools, the first
caller, to the new API.
LLM-aided
---
lld/ELF/SyntheticSections.cpp | 6 +--
llvm/include/llvm/ADT/FoldingSet.h | 43 +++++++++++++--
llvm/lib/Support/FoldingSet.cpp | 34 ++++++++----
llvm/lib/TableGen/Record.cpp | 87 +++++++++++++++---------------
4 files changed, 109 insertions(+), 61 deletions(-)
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index e2b9bb7590e26..aa7a859a9da9a 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -2875,14 +2875,14 @@ void DebugNamesBaseSection::computeHdrAndAbbrevTable(
FoldingSetNodeID id;
abbrev.Profile(id);
uint32_t newCode;
- void *insertPos;
- if (Abbrev *existing = abbrevSet.FindNodeOrInsertPos(id, insertPos)) {
+ FoldingSetInsertToken token;
+ if (Abbrev *existing = abbrevSet.lookup(id, token)) {
// Found it; we've already seen an identical abbreviation.
newCode = existing->code;
} else {
Abbrev *abbrev2 =
new (abbrevAlloc.Allocate()) Abbrev(std::move(abbrev));
- abbrevSet.InsertNode(abbrev2, insertPos);
+ abbrevSet.insert(abbrev2, token);
abbrevTable.push_back(abbrev2);
newCode = abbrevTable.size();
abbrev2->code = newCode;
diff --git a/llvm/include/llvm/ADT/FoldingSet.h b/llvm/include/llvm/ADT/FoldingSet.h
index c984c00b86fd1..070b23440c7fa 100644
--- a/llvm/include/llvm/ADT/FoldingSet.h
+++ b/llvm/include/llvm/ADT/FoldingSet.h
@@ -288,6 +288,21 @@ class FoldingSetNodeID {
LLVM_ABI FoldingSetNodeIDRef Intern(BumpPtrAllocator &Allocator) const;
};
+/// Insertion token: a failed lookup fills it in, the matching insert consumes
+/// it.
+class FoldingSetInsertToken {
+ uint64_t Value = 0; // hash + 1 while holding a token, 0 otherwise.
+
+ explicit FoldingSetInsertToken(uint32_t Hash) : Value(uint64_t(Hash) + 1) {}
+ uint32_t hash() const { return uint32_t(Value - 1); }
+
+ friend class FoldingSetBase;
+
+public:
+ FoldingSetInsertToken() = default;
+ explicit operator bool() const { return Value != 0; }
+};
+
//===----------------------------------------------------------------------===//
/// Non-templated base class for FoldingSet and ContextualFoldingSet, holding
/// the memory management and probing that does not depend on the node type.
@@ -384,11 +399,16 @@ class FoldingSetBase : public DebugEpochBase {
LLVM_ABI Node *FindNodeOrInsertPos(const FoldingSetNodeID &ID,
void *&InsertPos,
const FoldingSetInfo &Info);
+ LLVM_ABI Node *lookup(const FoldingSetNodeID &ID,
+ FoldingSetInsertToken &Token,
+ const FoldingSetInfo &Info);
/// Insert the specified node into the folding set, knowing that
/// it is not already in the folding set. InsertPos must be obtained from
- /// FindNodeOrInsertPos for an ID that \p N profiles identically to.
+ /// FindNodeOrInsertPos (or lookup) for an ID that \p N profiles identically
+ /// to.
LLVM_ABI void InsertNode(Node *N, void *InsertPos);
+ LLVM_ABI void insert(Node *N, FoldingSetInsertToken Token);
};
// Convenience type to hide the implementation of the folding set.
@@ -477,6 +497,7 @@ class FoldingSetImpl : public FoldingSetBase, public Trait::ContextStorage {
/// Remove a node from the folding set, returning true if one
/// was removed or false if the node was not in the folding set.
bool RemoveNode(T *N) { return FoldingSetBase::RemoveNode(N); }
+ bool erase(T *N) { return RemoveNode(N); }
/// If there is an existing node exactly equal to the specified node,
/// return it. Otherwise, insert 'N' and return it instead.
@@ -484,6 +505,7 @@ class FoldingSetImpl : public FoldingSetBase, public Trait::ContextStorage {
return static_cast<T *>(
FoldingSetBase::GetOrInsertNode(N, getFoldingSetInfo()));
}
+ T *getOrInsert(T *N) { return GetOrInsertNode(N); }
/// Look up the node specified by ID. If it exists, return it. If not,
/// return the insertion token that will make insertion faster.
@@ -491,13 +513,20 @@ class FoldingSetImpl : public FoldingSetBase, public Trait::ContextStorage {
return static_cast<T *>(FoldingSetBase::FindNodeOrInsertPos(
ID, InsertPos, getFoldingSetInfo()));
}
+ T *lookup(const FoldingSetNodeID &ID, FoldingSetInsertToken &Token) {
+ return static_cast<T *>(
+ FoldingSetBase::lookup(ID, Token, getFoldingSetInfo()));
+ }
/// Insert the specified node into the folding set, knowing that
/// it is not already in the folding set. InsertPos must be obtained from
- /// FindNodeOrInsertPos.
+ /// FindNodeOrInsertPos (or lookup).
void InsertNode(T *N, void *InsertPos) {
FoldingSetBase::InsertNode(N, InsertPos);
}
+ void insert(T *N, FoldingSetInsertToken Token) {
+ FoldingSetBase::insert(N, Token);
+ }
/// Insert the specified node into the folding set, knowing that it is not
/// already in the folding set.
@@ -565,6 +594,9 @@ template <class T, class VectorT = SmallVector<T *, 8>> class FoldingSetVector {
T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) {
return Set.FindNodeOrInsertPos(ID, InsertPos);
}
+ T *lookup(const FoldingSetNodeID &ID, FoldingSetInsertToken &Token) {
+ return Set.lookup(ID, Token);
+ }
/// If there is an existing node exactly equal to the specified node,
/// return it. Otherwise, insert 'N' and return it instead.
@@ -574,14 +606,19 @@ template <class T, class VectorT = SmallVector<T *, 8>> class FoldingSetVector {
Vector.push_back(N);
return Result;
}
+ T *getOrInsert(T *N) { return GetOrInsertNode(N); }
/// Insert the specified node into the folding set, knowing that
/// it is not already in the folding set. InsertPos must be obtained from
- /// FindNodeOrInsertPos.
+ /// FindNodeOrInsertPos (or lookup).
void InsertNode(T *N, void *InsertPos) {
Set.InsertNode(N, InsertPos);
Vector.push_back(N);
}
+ void insert(T *N, FoldingSetInsertToken Token) {
+ Set.insert(N, Token);
+ Vector.push_back(N);
+ }
/// Insert the specified node into the folding set, knowing that
/// it is not already in the folding set.
diff --git a/llvm/lib/Support/FoldingSet.cpp b/llvm/lib/Support/FoldingSet.cpp
index 0083e77ad95e4..784b33ae81ef2 100644
--- a/llvm/lib/Support/FoldingSet.cpp
+++ b/llvm/lib/Support/FoldingSet.cpp
@@ -219,33 +219,47 @@ FoldingSetBase::nodeEquals(const FoldingSetInfo &Info,
return Info.NodeEquals(Self, N, ID, TempID);
}
-FoldingSetBase::Node *FoldingSetBase::FindNodeOrInsertPos(
- const FoldingSetNodeID &ID, void *&InsertPos, const FoldingSetInfo &Info) {
+FoldingSetBase::Node *FoldingSetBase::lookup(const FoldingSetNodeID &ID,
+ FoldingSetInsertToken &Token,
+ const FoldingSetInfo &Info) {
unsigned IDHash = ID.ComputeHash();
unsigned Mask = NumBuckets - 1;
for (unsigned I = IDHash & Mask; Buckets[I]; I = (I + 1) & Mask) {
Node *N = static_cast<Node *>(Buckets[I]);
if (N->getFoldingSetHash() == IDHash && nodeEquals(Info, this, N, ID)) {
- InsertPos = nullptr;
+ Token = FoldingSetInsertToken();
return N;
}
}
- InsertPos = encodeHash(IDHash);
+ Token = FoldingSetInsertToken(IDHash);
return nullptr;
}
-void FoldingSetBase::InsertNode(Node *N, void *InsertPos) {
+FoldingSetBase::Node *FoldingSetBase::FindNodeOrInsertPos(
+ const FoldingSetNodeID &ID, void *&InsertPos, const FoldingSetInfo &Info) {
+ FoldingSetInsertToken Token;
+ Node *N = lookup(ID, Token, Info);
+ InsertPos = Token ? encodeHash(Token.hash()) : nullptr;
+ return N;
+}
+
+void FoldingSetBase::insert(Node *N, FoldingSetInsertToken Token) {
assert(N && "Cannot insert a null node");
- assert(InsertPos && "Invalid InsertPos!");
+ assert(Token && "Invalid token!");
incrementEpoch();
if (LLVM_UNLIKELY((NumNodes + 1) * 4 > NumBuckets * 3))
grow(NumBuckets * 2);
- uint32_t Hash = decodeHash(InsertPos);
+ uint32_t Hash = Token.hash();
placeNode(N, Hash);
N->setFoldingSetHash(Hash);
}
+void FoldingSetBase::InsertNode(Node *N, void *InsertPos) {
+ assert(InsertPos && "Invalid InsertPos!");
+ insert(N, FoldingSetInsertToken(decodeHash(InsertPos)));
+}
+
bool FoldingSetBase::RemoveNode(Node *N) {
uint32_t Hash = N->getFoldingSetHash();
if (Hash == FoldingSetNodeIDRef::NotAHash)
@@ -280,9 +294,9 @@ FoldingSetBase::Node *
FoldingSetBase::GetOrInsertNode(Node *N, const FoldingSetInfo &Info) {
FoldingSetNodeID ID;
Info.GetNodeProfile(this, N, ID);
- void *IP;
- if (Node *E = FindNodeOrInsertPos(ID, IP, Info))
+ FoldingSetInsertToken Token;
+ if (Node *E = lookup(ID, Token, Info))
return E;
- InsertNode(N, IP);
+ insert(N, Token);
return N;
}
diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp
index ac62e2f5785ae..3aa2e5ce2b94a 100644
--- a/llvm/lib/TableGen/Record.cpp
+++ b/llvm/lib/TableGen/Record.cpp
@@ -254,8 +254,8 @@ const RecordRecTy *RecordRecTy::get(RecordKeeper &RK,
FoldingSetNodeID ID;
ProfileRecordRecTy(ID, Classes);
- void *IP = nullptr;
- if (RecordRecTy *Ty = ThePool.FindNodeOrInsertPos(ID, IP))
+ FoldingSetInsertToken Token;
+ if (RecordRecTy *Ty = ThePool.lookup(ID, Token))
return Ty;
#ifndef NDEBUG
@@ -271,7 +271,7 @@ const RecordRecTy *RecordRecTy::get(RecordKeeper &RK,
void *Mem = RKImpl.Allocator.Allocate(
totalSizeToAlloc<const Record *>(Classes.size()), alignof(RecordRecTy));
RecordRecTy *Ty = new (Mem) RecordRecTy(RK, Classes);
- ThePool.InsertNode(Ty, IP);
+ ThePool.insert(Ty, Token);
return Ty;
}
@@ -416,13 +416,12 @@ const ArgumentInit *ArgumentInit::get(const Init *Value, ArgAuxType Aux) {
RecordKeeper &RK = Value->getRecordKeeper();
detail::RecordKeeperImpl &RKImpl = RK.getImpl();
- void *IP = nullptr;
- if (const ArgumentInit *I =
- RKImpl.TheArgumentInitPool.FindNodeOrInsertPos(ID, IP))
+ FoldingSetInsertToken Token;
+ if (const ArgumentInit *I = RKImpl.TheArgumentInitPool.lookup(ID, Token))
return I;
ArgumentInit *I = new (RKImpl.Allocator) ArgumentInit(Value, Aux);
- RKImpl.TheArgumentInitPool.InsertNode(I, IP);
+ RKImpl.TheArgumentInitPool.insert(I, Token);
return I;
}
@@ -473,14 +472,14 @@ BitsInit *BitsInit::get(RecordKeeper &RK, ArrayRef<const Init *> Bits) {
ProfileBitsInit(ID, Bits);
detail::RecordKeeperImpl &RKImpl = RK.getImpl();
- void *IP = nullptr;
- if (BitsInit *I = RKImpl.TheBitsInitPool.FindNodeOrInsertPos(ID, IP))
+ FoldingSetInsertToken Token;
+ if (BitsInit *I = RKImpl.TheBitsInitPool.lookup(ID, Token))
return I;
void *Mem = RKImpl.Allocator.Allocate(
totalSizeToAlloc<const Init *>(Bits.size()), alignof(BitsInit));
BitsInit *I = new (Mem) BitsInit(RK, Bits);
- RKImpl.TheBitsInitPool.InsertNode(I, IP);
+ RKImpl.TheBitsInitPool.insert(I, Token);
return I;
}
@@ -716,8 +715,8 @@ const ListInit *ListInit::get(ArrayRef<const Init *> Elements,
ProfileListInit(ID, Elements, EltTy);
detail::RecordKeeperImpl &RK = EltTy->getRecordKeeper().getImpl();
- void *IP = nullptr;
- if (const ListInit *I = RK.TheListInitPool.FindNodeOrInsertPos(ID, IP))
+ FoldingSetInsertToken Token;
+ if (const ListInit *I = RK.TheListInitPool.lookup(ID, Token))
return I;
assert(Elements.empty() || !isa<TypedInit>(Elements[0]) ||
@@ -726,7 +725,7 @@ const ListInit *ListInit::get(ArrayRef<const Init *> Elements,
void *Mem = RK.Allocator.Allocate(
totalSizeToAlloc<const Init *>(Elements.size()), alignof(ListInit));
ListInit *I = new (Mem) ListInit(Elements, EltTy);
- RK.TheListInitPool.InsertNode(I, IP);
+ RK.TheListInitPool.insert(I, Token);
return I;
}
@@ -826,12 +825,12 @@ const UnOpInit *UnOpInit::get(UnaryOp Opc, const Init *LHS, const RecTy *Type) {
ProfileUnOpInit(ID, Opc, LHS, Type);
detail::RecordKeeperImpl &RK = Type->getRecordKeeper().getImpl();
- void *IP = nullptr;
- if (const UnOpInit *I = RK.TheUnOpInitPool.FindNodeOrInsertPos(ID, IP))
+ FoldingSetInsertToken Token;
+ if (const UnOpInit *I = RK.TheUnOpInitPool.lookup(ID, Token))
return I;
UnOpInit *I = new (RK.Allocator) UnOpInit(Opc, LHS, Type);
- RK.TheUnOpInitPool.InsertNode(I, IP);
+ RK.TheUnOpInitPool.insert(I, Token);
return I;
}
@@ -1098,12 +1097,12 @@ const BinOpInit *BinOpInit::get(BinaryOp Opc, const Init *LHS, const Init *RHS,
ProfileBinOpInit(ID, Opc, LHS, RHS, Type);
detail::RecordKeeperImpl &RK = LHS->getRecordKeeper().getImpl();
- void *IP = nullptr;
- if (const BinOpInit *I = RK.TheBinOpInitPool.FindNodeOrInsertPos(ID, IP))
+ FoldingSetInsertToken Token;
+ if (const BinOpInit *I = RK.TheBinOpInitPool.lookup(ID, Token))
return I;
BinOpInit *I = new (RK.Allocator) BinOpInit(Opc, LHS, RHS, Type);
- RK.TheBinOpInitPool.InsertNode(I, IP);
+ RK.TheBinOpInitPool.insert(I, Token);
return I;
}
@@ -1693,12 +1692,12 @@ const TernOpInit *TernOpInit::get(TernaryOp Opc, const Init *LHS,
ProfileTernOpInit(ID, Opc, LHS, MHS, RHS, Type);
detail::RecordKeeperImpl &RK = LHS->getRecordKeeper().getImpl();
- void *IP = nullptr;
- if (TernOpInit *I = RK.TheTernOpInitPool.FindNodeOrInsertPos(ID, IP))
+ FoldingSetInsertToken Token;
+ if (TernOpInit *I = RK.TheTernOpInitPool.lookup(ID, Token))
return I;
TernOpInit *I = new (RK.Allocator) TernOpInit(Opc, LHS, MHS, RHS, Type);
- RK.TheTernOpInitPool.InsertNode(I, IP);
+ RK.TheTernOpInitPool.insert(I, Token);
return I;
}
@@ -2122,12 +2121,12 @@ const FoldOpInit *FoldOpInit::get(const Init *Start, const Init *List,
ProfileFoldOpInit(ID, Start, List, A, B, Expr, Type);
detail::RecordKeeperImpl &RK = Start->getRecordKeeper().getImpl();
- void *IP = nullptr;
- if (const FoldOpInit *I = RK.TheFoldOpInitPool.FindNodeOrInsertPos(ID, IP))
+ FoldingSetInsertToken Token;
+ if (const FoldOpInit *I = RK.TheFoldOpInitPool.lookup(ID, Token))
return I;
FoldOpInit *I = new (RK.Allocator) FoldOpInit(Start, List, A, B, Expr, Type);
- RK.TheFoldOpInitPool.InsertNode(I, IP);
+ RK.TheFoldOpInitPool.insert(I, Token);
return I;
}
@@ -2189,12 +2188,12 @@ const IsAOpInit *IsAOpInit::get(const RecTy *CheckType, const Init *Expr) {
ProfileIsAOpInit(ID, CheckType, Expr);
detail::RecordKeeperImpl &RK = Expr->getRecordKeeper().getImpl();
- void *IP = nullptr;
- if (const IsAOpInit *I = RK.TheIsAOpInitPool.FindNodeOrInsertPos(ID, IP))
+ FoldingSetInsertToken Token;
+ if (const IsAOpInit *I = RK.TheIsAOpInitPool.lookup(ID, Token))
return I;
IsAOpInit *I = new (RK.Allocator) IsAOpInit(CheckType, Expr);
- RK.TheIsAOpInitPool.InsertNode(I, IP);
+ RK.TheIsAOpInitPool.insert(I, Token);
return I;
}
@@ -2253,13 +2252,12 @@ const ExistsOpInit *ExistsOpInit::get(const RecTy *CheckType,
ProfileExistsOpInit(ID, CheckType, Expr);
detail::RecordKeeperImpl &RK = Expr->getRecordKeeper().getImpl();
- void *IP = nullptr;
- if (const ExistsOpInit *I =
- RK.TheExistsOpInitPool.FindNodeOrInsertPos(ID, IP))
+ FoldingSetInsertToken Token;
+ if (const ExistsOpInit *I = RK.TheExistsOpInitPool.lookup(ID, Token))
return I;
ExistsOpInit *I = new (RK.Allocator) ExistsOpInit(CheckType, Expr);
- RK.TheExistsOpInitPool.InsertNode(I, IP);
+ RK.TheExistsOpInitPool.insert(I, Token);
return I;
}
@@ -2328,13 +2326,12 @@ const InstancesOpInit *InstancesOpInit::get(const RecTy *Type,
ProfileInstancesOpInit(ID, Type, Regex);
detail::RecordKeeperImpl &RK = Regex->getRecordKeeper().getImpl();
- void *IP = nullptr;
- if (const InstancesOpInit *I =
- RK.TheInstancesOpInitPool.FindNodeOrInsertPos(ID, IP))
+ FoldingSetInsertToken Token;
+ if (const InstancesOpInit *I = RK.TheInstancesOpInitPool.lookup(ID, Token))
return I;
InstancesOpInit *I = new (RK.Allocator) InstancesOpInit(Type, Regex);
- RK.TheInstancesOpInitPool.InsertNode(I, IP);
+ RK.TheInstancesOpInitPool.insert(I, Token);
return I;
}
@@ -2521,14 +2518,14 @@ const VarDefInit *VarDefInit::get(SMLoc Loc, const Record *Class,
ProfileVarDefInit(ID, Class, Args);
detail::RecordKeeperImpl &RK = Class->getRecords().getImpl();
- void *IP = nullptr;
- if (const VarDefInit *I = RK.TheVarDefInitPool.FindNodeOrInsertPos(ID, IP))
+ FoldingSetInsertToken Token;
+ if (const VarDefInit *I = RK.TheVarDefInitPool.lookup(ID, Token))
return I;
void *Mem = RK.Allocator.Allocate(
totalSizeToAlloc<const ArgumentInit *>(Args.size()), alignof(VarDefInit));
VarDefInit *I = new (Mem) VarDefInit(Loc, Class, Args);
- RK.TheVarDefInitPool.InsertNode(I, IP);
+ RK.TheVarDefInitPool.insert(I, Token);
return I;
}
@@ -2714,14 +2711,14 @@ const CondOpInit *CondOpInit::get(ArrayRef<const Init *> Conds,
ProfileCondOpInit(ID, Conds, Values, Ty);
detail::RecordKeeperImpl &RK = Ty->getRecordKeeper().getImpl();
- void *IP = nullptr;
- if (const CondOpInit *I = RK.TheCondOpInitPool.FindNodeOrInsertPos(ID, IP))
+ FoldingSetInsertToken Token;
+ if (const CondOpInit *I = RK.TheCondOpInitPool.lookup(ID, Token))
return I;
void *Mem = RK.Allocator.Allocate(
totalSizeToAlloc<const Init *>(2 * Conds.size()), alignof(CondOpInit));
CondOpInit *I = new (Mem) CondOpInit(Conds, Values, Ty);
- RK.TheCondOpInitPool.InsertNode(I, IP);
+ RK.TheCondOpInitPool.insert(I, Token);
return I;
}
@@ -2836,8 +2833,8 @@ const DagInit *DagInit::get(const Init *V, const StringInit *VN,
ProfileDagInit(ID, V, VN, Args, ArgNames);
detail::RecordKeeperImpl &RK = V->getRecordKeeper().getImpl();
- void *IP = nullptr;
- if (const DagInit *I = RK.TheDagInitPool.FindNodeOrInsertPos(ID, IP))
+ FoldingSetInsertToken Token;
+ if (const DagInit *I = RK.TheDagInitPool.lookup(ID, Token))
return I;
void *Mem =
@@ -2845,7 +2842,7 @@ const DagInit *DagInit::get(const Init *V, const StringInit *VN,
Args.size(), ArgNames.size()),
alignof(DagInit));
DagInit *I = new (Mem) DagInit(V, VN, Args, ArgNames);
- RK.TheDagInitPool.InsertNode(I, IP);
+ RK.TheDagInitPool.insert(I, Token);
return I;
}
>From 33942eb5794a6584f63fa19ede8799034114e6cb Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Sat, 29 Aug 2026 00:39:38 -0700
Subject: [PATCH 2/2] forward Legacy Functions to new ones
---
llvm/include/llvm/ADT/FoldingSet.h | 111 +++++++++++++++--------------
llvm/lib/Support/FoldingSet.cpp | 2 +-
llvm/unittests/ADT/FoldingSet.cpp | 65 ++++++++++-------
3 files changed, 100 insertions(+), 78 deletions(-)
diff --git a/llvm/include/llvm/ADT/FoldingSet.h b/llvm/include/llvm/ADT/FoldingSet.h
index 070b23440c7fa..27e4eec24f947 100644
--- a/llvm/include/llvm/ADT/FoldingSet.h
+++ b/llvm/include/llvm/ADT/FoldingSet.h
@@ -74,38 +74,37 @@ namespace llvm {
/// 1) If you have an existing node that you want add to the set but unsure
/// that the node might already exist then call;
///
-/// MyNode *M = MyFoldingSet.GetOrInsertNode(N);
+/// MyNode *M = MyFoldingSet.getOrInsert(N);
///
/// If The result is equal to the input then the node has been inserted.
/// Otherwise, the result is the node existing in the folding set, and the
/// input can be discarded (use the result instead.)
///
/// 2) If you are ready to construct a node but want to check if it already
-/// exists, then call FindNodeOrInsertPos with a FoldingSetNodeID of the bits to
-/// check;
+/// exists, then call lookup with a FoldingSetNodeID of the bits to check;
///
/// FoldingSetNodeID ID;
/// ID.AddString(Name);
/// ID.AddInteger(Value);
-/// void *InsertPoint;
+/// FoldingSetInsertToken Token;
///
-/// MyNode *M = MyFoldingSet.FindNodeOrInsertPos(ID, InsertPoint);
+/// MyNode *M = MyFoldingSet.lookup(ID, Token);
///
-/// If found then M will be non-NULL, else InsertPoint will point to where it
-/// should be inserted using InsertNode.
+/// If found then M will be non-NULL, else Token holds what insert needs to
+/// place the node.
///
-/// 3) If you get a NULL result from FindNodeOrInsertPos then you can insert a
-/// new node with InsertNode;
+/// 3) If you get a NULL result from lookup then you can insert a new node with
+/// insert;
///
/// MyNode *N = new MyNode(Name, Value);
-/// MyFoldingSet.InsertNode(N, InsertPoint);
+/// MyFoldingSet.insert(N, Token);
///
-/// InsertPoint survives intervening insertions, but N must profile identically
-/// to the ID that produced it, or N becomes unfindable.
+/// Token survives intervening insertions, but N must profile identically to
+/// the ID that produced it, or N becomes unfindable.
///
/// 4) Finally, if you want to remove a node from the folding set call;
///
-/// bool WasRemoved = MyFoldingSet.RemoveNode(M);
+/// bool WasRemoved = MyFoldingSet.erase(M);
///
/// The result indicates whether the node existed in the folding set.
@@ -291,16 +290,23 @@ class FoldingSetNodeID {
/// Insertion token: a failed lookup fills it in, the matching insert consumes
/// it.
class FoldingSetInsertToken {
- uint64_t Value = 0; // hash + 1 while holding a token, 0 otherwise.
+ uint32_t Hash = FoldingSetNodeIDRef::NotAHash;
- explicit FoldingSetInsertToken(uint32_t Hash) : Value(uint64_t(Hash) + 1) {}
- uint32_t hash() const { return uint32_t(Value - 1); }
+ explicit FoldingSetInsertToken(uint32_t Hash) : Hash(Hash) {
+ assert(Hash != FoldingSetNodeIDRef::NotAHash);
+ }
+ uint32_t hash() const {
+ assert(*this && "no token held");
+ return Hash;
+ }
friend class FoldingSetBase;
public:
FoldingSetInsertToken() = default;
- explicit operator bool() const { return Value != 0; }
+ explicit operator bool() const {
+ return Hash != FoldingSetNodeIDRef::NotAHash;
+ }
};
//===----------------------------------------------------------------------===//
@@ -396,19 +402,18 @@ class FoldingSetBase : public DebugEpochBase {
/// Look up the node specified by ID. If it exists, return it. If not,
/// return the insertion token that will make insertion faster.
- LLVM_ABI Node *FindNodeOrInsertPos(const FoldingSetNodeID &ID,
- void *&InsertPos,
- const FoldingSetInfo &Info);
LLVM_ABI Node *lookup(const FoldingSetNodeID &ID,
FoldingSetInsertToken &Token,
const FoldingSetInfo &Info);
+ LLVM_ABI Node *FindNodeOrInsertPos(const FoldingSetNodeID &ID,
+ void *&InsertPos,
+ const FoldingSetInfo &Info);
- /// Insert the specified node into the folding set, knowing that
- /// it is not already in the folding set. InsertPos must be obtained from
- /// FindNodeOrInsertPos (or lookup) for an ID that \p N profiles identically
- /// to.
- LLVM_ABI void InsertNode(Node *N, void *InsertPos);
+ /// Insert the specified node into the folding set, knowing that it is not
+ /// already in the folding set. \p Token must come from lookup for an ID that
+ /// \p N profiles identically to.
LLVM_ABI void insert(Node *N, FoldingSetInsertToken Token);
+ LLVM_ABI void InsertNode(Node *N, void *InsertPos);
};
// Convenience type to hide the implementation of the folding set.
@@ -496,42 +501,42 @@ class FoldingSetImpl : public FoldingSetBase, public Trait::ContextStorage {
/// Remove a node from the folding set, returning true if one
/// was removed or false if the node was not in the folding set.
- bool RemoveNode(T *N) { return FoldingSetBase::RemoveNode(N); }
- bool erase(T *N) { return RemoveNode(N); }
+ bool erase(T *N) { return FoldingSetBase::RemoveNode(N); }
+ bool RemoveNode(T *N) { return erase(N); }
/// If there is an existing node exactly equal to the specified node,
/// return it. Otherwise, insert 'N' and return it instead.
- T *GetOrInsertNode(T *N) {
+ T *getOrInsert(T *N) {
return static_cast<T *>(
FoldingSetBase::GetOrInsertNode(N, getFoldingSetInfo()));
}
- T *getOrInsert(T *N) { return GetOrInsertNode(N); }
+ T *GetOrInsertNode(T *N) { return getOrInsert(N); }
/// Look up the node specified by ID. If it exists, return it. If not,
/// return the insertion token that will make insertion faster.
- T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) {
- return static_cast<T *>(FoldingSetBase::FindNodeOrInsertPos(
- ID, InsertPos, getFoldingSetInfo()));
- }
T *lookup(const FoldingSetNodeID &ID, FoldingSetInsertToken &Token) {
return static_cast<T *>(
FoldingSetBase::lookup(ID, Token, getFoldingSetInfo()));
}
-
- /// Insert the specified node into the folding set, knowing that
- /// it is not already in the folding set. InsertPos must be obtained from
- /// FindNodeOrInsertPos (or lookup).
- void InsertNode(T *N, void *InsertPos) {
- FoldingSetBase::InsertNode(N, InsertPos);
+ T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) {
+ return static_cast<T *>(FoldingSetBase::FindNodeOrInsertPos(
+ ID, InsertPos, getFoldingSetInfo()));
}
+
+ /// Insert the specified node into the folding set, knowing that it is not
+ /// already in the folding set. \p Token must come from lookup for an ID that
+ /// \p N profiles identically to.
void insert(T *N, FoldingSetInsertToken Token) {
FoldingSetBase::insert(N, Token);
}
+ void InsertNode(T *N, void *InsertPos) {
+ FoldingSetBase::InsertNode(N, InsertPos);
+ }
/// Insert the specified node into the folding set, knowing that it is not
/// already in the folding set.
void InsertNode(T *N) {
- T *Inserted = GetOrInsertNode(N);
+ T *Inserted = getOrInsert(N);
(void)Inserted;
assert(Inserted == N && "Node already inserted!");
}
@@ -591,34 +596,34 @@ template <class T, class VectorT = SmallVector<T *, 8>> class FoldingSetVector {
/// Look up the node specified by ID. If it exists, return it. If not,
/// return the insertion token that will make insertion faster.
- T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) {
- return Set.FindNodeOrInsertPos(ID, InsertPos);
- }
T *lookup(const FoldingSetNodeID &ID, FoldingSetInsertToken &Token) {
return Set.lookup(ID, Token);
}
+ T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) {
+ return Set.FindNodeOrInsertPos(ID, InsertPos);
+ }
/// If there is an existing node exactly equal to the specified node,
/// return it. Otherwise, insert 'N' and return it instead.
- T *GetOrInsertNode(T *N) {
- T *Result = Set.GetOrInsertNode(N);
+ T *getOrInsert(T *N) {
+ T *Result = Set.getOrInsert(N);
if (Result == N)
Vector.push_back(N);
return Result;
}
- T *getOrInsert(T *N) { return GetOrInsertNode(N); }
+ T *GetOrInsertNode(T *N) { return getOrInsert(N); }
- /// Insert the specified node into the folding set, knowing that
- /// it is not already in the folding set. InsertPos must be obtained from
- /// FindNodeOrInsertPos (or lookup).
- void InsertNode(T *N, void *InsertPos) {
- Set.InsertNode(N, InsertPos);
- Vector.push_back(N);
- }
+ /// Insert the specified node into the folding set, knowing that it is not
+ /// already in the folding set. \p Token must come from lookup for an ID that
+ /// \p N profiles identically to.
void insert(T *N, FoldingSetInsertToken Token) {
Set.insert(N, Token);
Vector.push_back(N);
}
+ void InsertNode(T *N, void *InsertPos) {
+ Set.InsertNode(N, InsertPos);
+ Vector.push_back(N);
+ }
/// Insert the specified node into the folding set, knowing that
/// it is not already in the folding set.
diff --git a/llvm/lib/Support/FoldingSet.cpp b/llvm/lib/Support/FoldingSet.cpp
index 784b33ae81ef2..d34c507b4bafa 100644
--- a/llvm/lib/Support/FoldingSet.cpp
+++ b/llvm/lib/Support/FoldingSet.cpp
@@ -227,7 +227,7 @@ FoldingSetBase::Node *FoldingSetBase::lookup(const FoldingSetNodeID &ID,
for (unsigned I = IDHash & Mask; Buckets[I]; I = (I + 1) & Mask) {
Node *N = static_cast<Node *>(Buckets[I]);
if (N->getFoldingSetHash() == IDHash && nodeEquals(Info, this, N, ID)) {
- Token = FoldingSetInsertToken();
+ Token = {};
return N;
}
}
diff --git a/llvm/unittests/ADT/FoldingSet.cpp b/llvm/unittests/ADT/FoldingSet.cpp
index 2556d64bae7a3..42dd6ddfa1f1f 100644
--- a/llvm/unittests/ADT/FoldingSet.cpp
+++ b/llvm/unittests/ADT/FoldingSet.cpp
@@ -130,6 +130,23 @@ TEST(FoldingSetTest, RemoveNodeThatIsAbsent) {
EXPECT_EQ(0U, Trivial.size());
}
+TEST(FoldingSetTest, TypedApi) {
+ FoldingSet<TrivialPair> Set;
+ TrivialPair T(99, 42), TCopy(99, 42);
+ FoldingSetNodeID ID;
+ T.Profile(ID);
+
+ FoldingSetInsertToken Token;
+ EXPECT_EQ(nullptr, Set.lookup(ID, Token));
+ ASSERT_TRUE(static_cast<bool>(Token));
+ Set.insert(&T, Token);
+ EXPECT_EQ(&T, Set.lookup(ID, Token));
+ EXPECT_FALSE(static_cast<bool>(Token));
+ EXPECT_EQ(&T, Set.getOrInsert(&TCopy));
+ EXPECT_TRUE(Set.erase(&T));
+ EXPECT_FALSE(Set.erase(&T));
+}
+
TEST(FoldingSetTest, GetOrInsertInserting) {
FoldingSet<TrivialPair> Trivial;
@@ -299,20 +316,20 @@ TEST(FoldingSetTest, FoldingSetVectorBasic) {
TrivialPair T2(20, 200);
TrivialPair T3(30, 300);
- EXPECT_EQ(&T1, Vec.GetOrInsertNode(&T1));
- EXPECT_EQ(&T1, Vec.GetOrInsertNode(&T1Copy));
+ EXPECT_EQ(&T1, Vec.getOrInsert(&T1));
+ EXPECT_EQ(&T1, Vec.getOrInsert(&T1Copy));
EXPECT_THAT(Vec, SizeIs(1));
// Insert a new node using an insertion token.
FoldingSetNodeID ID2;
T2.Profile(ID2);
- void *InsertPos = nullptr;
- EXPECT_EQ(nullptr, Vec.FindNodeOrInsertPos(ID2, InsertPos));
- ASSERT_NE(nullptr, InsertPos);
- Vec.InsertNode(&T2, InsertPos);
+ FoldingSetInsertToken Token;
+ EXPECT_EQ(nullptr, Vec.lookup(ID2, Token));
+ ASSERT_TRUE(static_cast<bool>(Token));
+ Vec.insert(&T2, Token);
EXPECT_THAT(Vec, SizeIs(2));
- Vec.InsertNode(&T3);
+ EXPECT_EQ(&T3, Vec.getOrInsert(&T3));
EXPECT_THAT(Vec, SizeIs(3));
EXPECT_THAT(Vec, testing::Not(IsEmpty()));
@@ -354,26 +371,26 @@ TEST(FoldingSetTest, ContextualFoldingSetBasic) {
ContextualPair T1Copy(10, 100);
ContextualPair T2(20, 200);
- EXPECT_EQ(&T1, Set.GetOrInsertNode(&T1));
- EXPECT_EQ(&T1, Set.GetOrInsertNode(&T1Copy));
+ EXPECT_EQ(&T1, Set.getOrInsert(&T1));
+ EXPECT_EQ(&T1, Set.getOrInsert(&T1Copy));
EXPECT_THAT(Set, SizeIs(1));
// Insert a new node using an insertion token.
- void *InsertPos = nullptr;
+ FoldingSetInsertToken Token;
FoldingSetNodeID ID2;
T2.Profile(ID2, ContextVal);
- EXPECT_EQ(nullptr, Set.FindNodeOrInsertPos(ID2, InsertPos));
- ASSERT_NE(nullptr, InsertPos);
- Set.InsertNode(&T2, InsertPos);
+ EXPECT_EQ(nullptr, Set.lookup(ID2, Token));
+ ASSERT_TRUE(static_cast<bool>(Token));
+ Set.insert(&T2, Token);
EXPECT_THAT(Set, SizeIs(2));
- EXPECT_EQ(&T2, Set.FindNodeOrInsertPos(ID2, InsertPos));
+ EXPECT_EQ(&T2, Set.lookup(ID2, Token));
EXPECT_THAT(Set, UnorderedElementsAre(T1, T2));
- EXPECT_TRUE(Set.RemoveNode(&T1));
+ EXPECT_TRUE(Set.erase(&T1));
EXPECT_THAT(Set, SizeIs(1));
- EXPECT_FALSE(Set.RemoveNode(&T1));
+ EXPECT_FALSE(Set.erase(&T1));
EXPECT_THAT(Set, UnorderedElementsAre(T2));
@@ -492,26 +509,26 @@ TEST(FoldingSetTest, MoveInvalidatesIterators) {
#endif
// The InsertPos token is a hash, not a position, so a rehash cannot stale it.
-TEST(FoldingSetTest, InsertPosSurvivesGrowth) {
+TEST(FoldingSetTest, TokenSurvivesGrowth) {
FoldingSet<TrivialPair> Set;
TrivialPair Late(9999, 9999);
FoldingSetNodeID ID;
Late.Profile(ID);
- void *InsertPos = nullptr;
- ASSERT_EQ(nullptr, Set.FindNodeOrInsertPos(ID, InsertPos));
- ASSERT_NE(nullptr, InsertPos);
+ FoldingSetInsertToken Token;
+ ASSERT_EQ(nullptr, Set.lookup(ID, Token));
+ ASSERT_TRUE(static_cast<bool>(Token));
// Force several rehashes while the token is held.
std::vector<std::unique_ptr<TrivialPair>> Nodes;
for (unsigned I = 0; I != 200; ++I) {
Nodes.push_back(std::make_unique<TrivialPair>(I, I));
- Set.InsertNode(Nodes.back().get());
+ Set.getOrInsert(Nodes.back().get());
}
- Set.InsertNode(&Late, InsertPos);
- void *Unused = nullptr;
- EXPECT_EQ(&Late, Set.FindNodeOrInsertPos(ID, Unused));
+ Set.insert(&Late, Token);
+ EXPECT_EQ(&Late, Set.lookup(ID, Token));
+ EXPECT_FALSE(static_cast<bool>(Token));
EXPECT_EQ(201u, Set.size());
}
More information about the llvm-commits
mailing list