[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