Skip to content

Commit 11e915f

Browse files
authored
[FoldingSet] Add typed lookup/insert/erase/getOrInsert (#219644)
FindNodeOrInsertPos hands the insertion state to InsertNode as a `void *`: any pointer converts to it, only a comment says where it may come from, and since the switch to linear probing the value is the node's hash, not a position at all. Carry it in FoldingSetInsertToken instead, the hash wrapped in a type whose constructor and accessor are private to FoldingSetBase, with NotAHash as the no-token state. The `void *` overloads remain, forwarding to the typed ones, until their callers are migrated. LLM-aided
1 parent 0f3ffcd commit 11e915f

5 files changed

Lines changed: 196 additions & 122 deletions

File tree

lld/ELF/SyntheticSections.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2875,14 +2875,14 @@ void DebugNamesBaseSection::computeHdrAndAbbrevTable(
28752875
FoldingSetNodeID id;
28762876
abbrev.Profile(id);
28772877
uint32_t newCode;
2878-
void *insertPos;
2879-
if (Abbrev *existing = abbrevSet.FindNodeOrInsertPos(id, insertPos)) {
2878+
FoldingSetInsertToken token;
2879+
if (Abbrev *existing = abbrevSet.lookup(id, token)) {
28802880
// Found it; we've already seen an identical abbreviation.
28812881
newCode = existing->code;
28822882
} else {
28832883
Abbrev *abbrev2 =
28842884
new (abbrevAlloc.Allocate()) Abbrev(std::move(abbrev));
2885-
abbrevSet.InsertNode(abbrev2, insertPos);
2885+
abbrevSet.insert(abbrev2, token);
28862886
abbrevTable.push_back(abbrev2);
28872887
newCode = abbrevTable.size();
28882888
abbrev2->code = newCode;

llvm/include/llvm/ADT/FoldingSet.h

Lines changed: 85 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -74,38 +74,37 @@ namespace llvm {
7474
/// 1) If you have an existing node that you want add to the set but unsure
7575
/// that the node might already exist then call;
7676
///
77-
/// MyNode *M = MyFoldingSet.GetOrInsertNode(N);
77+
/// MyNode *M = MyFoldingSet.getOrInsert(N);
7878
///
7979
/// If The result is equal to the input then the node has been inserted.
8080
/// Otherwise, the result is the node existing in the folding set, and the
8181
/// input can be discarded (use the result instead.)
8282
///
8383
/// 2) If you are ready to construct a node but want to check if it already
84-
/// exists, then call FindNodeOrInsertPos with a FoldingSetNodeID of the bits to
85-
/// check;
84+
/// exists, then call lookup with a FoldingSetNodeID of the bits to check;
8685
///
8786
/// FoldingSetNodeID ID;
8887
/// ID.AddString(Name);
8988
/// ID.AddInteger(Value);
90-
/// void *InsertPoint;
89+
/// FoldingSetInsertToken Token;
9190
///
92-
/// MyNode *M = MyFoldingSet.FindNodeOrInsertPos(ID, InsertPoint);
91+
/// MyNode *M = MyFoldingSet.lookup(ID, Token);
9392
///
94-
/// If found then M will be non-NULL, else InsertPoint will point to where it
95-
/// should be inserted using InsertNode.
93+
/// If found then M will be non-NULL, else Token holds what insert needs to
94+
/// place the node.
9695
///
97-
/// 3) If you get a NULL result from FindNodeOrInsertPos then you can insert a
98-
/// new node with InsertNode;
96+
/// 3) If you get a NULL result from lookup then you can insert a new node with
97+
/// insert;
9998
///
10099
/// MyNode *N = new MyNode(Name, Value);
101-
/// MyFoldingSet.InsertNode(N, InsertPoint);
100+
/// MyFoldingSet.insert(N, Token);
102101
///
103-
/// InsertPoint survives intervening insertions, but N must profile identically
104-
/// to the ID that produced it, or N becomes unfindable.
102+
/// Token survives intervening insertions, but N must profile identically to
103+
/// the ID that produced it, or N becomes unfindable.
105104
///
106105
/// 4) Finally, if you want to remove a node from the folding set call;
107106
///
108-
/// bool WasRemoved = MyFoldingSet.RemoveNode(M);
107+
/// bool WasRemoved = MyFoldingSet.erase(M);
109108
///
110109
/// The result indicates whether the node existed in the folding set.
111110

@@ -177,8 +176,8 @@ class FoldingSetNodeIDRef {
177176

178177
// Compute a strong hash value used to lookup the node in the FoldingSetBase.
179178
// The hash value is not guaranteed to be deterministic across processes.
180-
// Never returns NotAHash: FoldingSetBase uses it to keep the InsertPos token
181-
// non-null and to mark a node belonging to no set.
179+
// Never returns NotAHash: FoldingSetBase reserves it for the empty insert
180+
// token and for a node belonging to no set.
182181
unsigned ComputeHash() const {
183182
unsigned Hash =
184183
static_cast<unsigned>(hash_combine_range(Data, Data + Size));
@@ -288,6 +287,31 @@ class FoldingSetNodeID {
288287
LLVM_ABI FoldingSetNodeIDRef Intern(BumpPtrAllocator &Allocator) const;
289288
};
290289

290+
/// Insertion token: a failed lookup fills it in, the matching insert consumes
291+
/// it.
292+
class FoldingSetInsertToken {
293+
uint32_t Hash = FoldingSetNodeIDRef::NotAHash;
294+
295+
explicit FoldingSetInsertToken(uint32_t Hash) : Hash(Hash) {
296+
assert(Hash != FoldingSetNodeIDRef::NotAHash && "Invalid insert token");
297+
}
298+
299+
friend class FoldingSetBase;
300+
301+
public:
302+
FoldingSetInsertToken() = default;
303+
explicit operator bool() const {
304+
return Hash != FoldingSetNodeIDRef::NotAHash;
305+
}
306+
307+
friend bool operator==(FoldingSetInsertToken A, FoldingSetInsertToken B) {
308+
return A.Hash == B.Hash;
309+
}
310+
friend bool operator!=(FoldingSetInsertToken A, FoldingSetInsertToken B) {
311+
return !(A == B);
312+
}
313+
};
314+
291315
//===----------------------------------------------------------------------===//
292316
/// Non-templated base class for FoldingSet and ContextualFoldingSet, holding
293317
/// the memory management and probing that does not depend on the node type.
@@ -379,15 +403,19 @@ class FoldingSetBase : public DebugEpochBase {
379403
/// return it. Otherwise, insert \p N and return it instead.
380404
LLVM_ABI Node *GetOrInsertNode(Node *N, const FoldingSetInfo &Info);
381405

382-
/// Look up the node specified by ID. If it exists, return it. If not,
383-
/// return the insertion token that will make insertion faster.
406+
/// Look up the node specified by ID. If it exists, return it and clear
407+
/// \p Token; otherwise return null and set \p Token for a subsequent insert.
408+
LLVM_ABI Node *lookup(const FoldingSetNodeID &ID,
409+
FoldingSetInsertToken &Token,
410+
const FoldingSetInfo &Info);
384411
LLVM_ABI Node *FindNodeOrInsertPos(const FoldingSetNodeID &ID,
385412
void *&InsertPos,
386413
const FoldingSetInfo &Info);
387414

388-
/// Insert the specified node into the folding set, knowing that
389-
/// it is not already in the folding set. InsertPos must be obtained from
390-
/// FindNodeOrInsertPos for an ID that \p N profiles identically to.
415+
/// Insert the specified node into the folding set, knowing that it is not
416+
/// already in the folding set. \p Token must come from lookup for an ID that
417+
/// \p N profiles identically to.
418+
LLVM_ABI void insert(Node *N, FoldingSetInsertToken Token);
391419
LLVM_ABI void InsertNode(Node *N, void *InsertPos);
392420
};
393421

@@ -476,36 +504,46 @@ class FoldingSetImpl : public FoldingSetBase, public Trait::ContextStorage {
476504

477505
/// Remove a node from the folding set, returning true if one
478506
/// was removed or false if the node was not in the folding set.
479-
bool RemoveNode(T *N) { return FoldingSetBase::RemoveNode(N); }
507+
bool erase(T *N) { return FoldingSetBase::RemoveNode(N); }
508+
bool RemoveNode(T *N) { return erase(N); }
480509

481510
/// If there is an existing node exactly equal to the specified node,
482511
/// return it. Otherwise, insert 'N' and return it instead.
483-
T *GetOrInsertNode(T *N) {
512+
T *getOrInsert(T *N) {
484513
return static_cast<T *>(
485514
FoldingSetBase::GetOrInsertNode(N, getFoldingSetInfo()));
486515
}
516+
T *GetOrInsertNode(T *N) { return getOrInsert(N); }
487517

488-
/// Look up the node specified by ID. If it exists, return it. If not,
489-
/// return the insertion token that will make insertion faster.
518+
/// Look up the node specified by ID. If it exists, return it and clear
519+
/// \p Token; otherwise return null and set \p Token for a subsequent insert.
520+
T *lookup(const FoldingSetNodeID &ID, FoldingSetInsertToken &Token) {
521+
return static_cast<T *>(
522+
FoldingSetBase::lookup(ID, Token, getFoldingSetInfo()));
523+
}
490524
T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) {
491525
return static_cast<T *>(FoldingSetBase::FindNodeOrInsertPos(
492526
ID, InsertPos, getFoldingSetInfo()));
493527
}
494528

495-
/// Insert the specified node into the folding set, knowing that
496-
/// it is not already in the folding set. InsertPos must be obtained from
497-
/// FindNodeOrInsertPos.
529+
/// Insert the specified node into the folding set, knowing that it is not
530+
/// already in the folding set. \p Token must come from lookup for an ID that
531+
/// \p N profiles identically to.
532+
void insert(T *N, FoldingSetInsertToken Token) {
533+
FoldingSetBase::insert(N, Token);
534+
}
498535
void InsertNode(T *N, void *InsertPos) {
499536
FoldingSetBase::InsertNode(N, InsertPos);
500537
}
501538

502539
/// Insert the specified node into the folding set, knowing that it is not
503540
/// already in the folding set.
504-
void InsertNode(T *N) {
505-
T *Inserted = GetOrInsertNode(N);
541+
void insert(T *N) {
542+
T *Inserted = getOrInsert(N);
506543
(void)Inserted;
507544
assert(Inserted == N && "Node already inserted!");
508545
}
546+
void InsertNode(T *N) { insert(N); }
509547
};
510548

511549
//===----------------------------------------------------------------------===//
@@ -560,35 +598,44 @@ template <class T, class VectorT = SmallVector<T *, 8>> class FoldingSetVector {
560598
Vector.clear();
561599
}
562600

563-
/// Look up the node specified by ID. If it exists, return it. If not,
564-
/// return the insertion token that will make insertion faster.
601+
/// Look up the node specified by ID. If it exists, return it and clear
602+
/// \p Token; otherwise return null and set \p Token for a subsequent insert.
603+
T *lookup(const FoldingSetNodeID &ID, FoldingSetInsertToken &Token) {
604+
return Set.lookup(ID, Token);
605+
}
565606
T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) {
566607
return Set.FindNodeOrInsertPos(ID, InsertPos);
567608
}
568609

569610
/// If there is an existing node exactly equal to the specified node,
570611
/// return it. Otherwise, insert 'N' and return it instead.
571-
T *GetOrInsertNode(T *N) {
572-
T *Result = Set.GetOrInsertNode(N);
612+
T *getOrInsert(T *N) {
613+
T *Result = Set.getOrInsert(N);
573614
if (Result == N)
574615
Vector.push_back(N);
575616
return Result;
576617
}
618+
T *GetOrInsertNode(T *N) { return getOrInsert(N); }
577619

578-
/// Insert the specified node into the folding set, knowing that
579-
/// it is not already in the folding set. InsertPos must be obtained from
580-
/// FindNodeOrInsertPos.
620+
/// Insert the specified node into the folding set, knowing that it is not
621+
/// already in the folding set. \p Token must come from lookup for an ID that
622+
/// \p N profiles identically to.
623+
void insert(T *N, FoldingSetInsertToken Token) {
624+
Set.insert(N, Token);
625+
Vector.push_back(N);
626+
}
581627
void InsertNode(T *N, void *InsertPos) {
582628
Set.InsertNode(N, InsertPos);
583629
Vector.push_back(N);
584630
}
585631

586632
/// Insert the specified node into the folding set, knowing that
587633
/// it is not already in the folding set.
588-
void InsertNode(T *N) {
589-
Set.InsertNode(N);
634+
void insert(T *N) {
635+
Set.insert(N);
590636
Vector.push_back(N);
591637
}
638+
void InsertNode(T *N) { insert(N); }
592639

593640
/// Returns the number of nodes in the folding set.
594641
unsigned size() const { return Set.size(); }

llvm/lib/Support/FoldingSet.cpp

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -219,33 +219,46 @@ FoldingSetBase::nodeEquals(const FoldingSetInfo &Info,
219219
return Info.NodeEquals(Self, N, ID, TempID);
220220
}
221221

222-
FoldingSetBase::Node *FoldingSetBase::FindNodeOrInsertPos(
223-
const FoldingSetNodeID &ID, void *&InsertPos, const FoldingSetInfo &Info) {
222+
FoldingSetBase::Node *FoldingSetBase::lookup(const FoldingSetNodeID &ID,
223+
FoldingSetInsertToken &Token,
224+
const FoldingSetInfo &Info) {
224225
unsigned IDHash = ID.ComputeHash();
225226
unsigned Mask = NumBuckets - 1;
226227
for (unsigned I = IDHash & Mask; Buckets[I]; I = (I + 1) & Mask) {
227228
Node *N = static_cast<Node *>(Buckets[I]);
228229
if (N->getFoldingSetHash() == IDHash && nodeEquals(Info, this, N, ID)) {
229-
InsertPos = nullptr;
230+
Token = {};
230231
return N;
231232
}
232233
}
233234

234-
InsertPos = encodeHash(IDHash);
235+
Token = FoldingSetInsertToken(IDHash);
235236
return nullptr;
236237
}
237238

238-
void FoldingSetBase::InsertNode(Node *N, void *InsertPos) {
239+
FoldingSetBase::Node *FoldingSetBase::FindNodeOrInsertPos(
240+
const FoldingSetNodeID &ID, void *&InsertPos, const FoldingSetInfo &Info) {
241+
FoldingSetInsertToken Token;
242+
Node *N = lookup(ID, Token, Info);
243+
InsertPos = Token ? encodeHash(Token.Hash) : nullptr;
244+
return N;
245+
}
246+
247+
void FoldingSetBase::insert(Node *N, FoldingSetInsertToken Token) {
239248
assert(N && "Cannot insert a null node");
240-
assert(InsertPos && "Invalid InsertPos!");
249+
assert(Token && "Invalid token!");
241250
incrementEpoch();
242251
if (LLVM_UNLIKELY((NumNodes + 1) * 4 > NumBuckets * 3))
243252
grow(NumBuckets * 2);
244-
uint32_t Hash = decodeHash(InsertPos);
253+
uint32_t Hash = Token.Hash;
245254
placeNode(N, Hash);
246255
N->setFoldingSetHash(Hash);
247256
}
248257

258+
void FoldingSetBase::InsertNode(Node *N, void *InsertPos) {
259+
insert(N, FoldingSetInsertToken(decodeHash(InsertPos)));
260+
}
261+
249262
bool FoldingSetBase::RemoveNode(Node *N) {
250263
uint32_t Hash = N->getFoldingSetHash();
251264
if (Hash == FoldingSetNodeIDRef::NotAHash)
@@ -280,9 +293,9 @@ FoldingSetBase::Node *
280293
FoldingSetBase::GetOrInsertNode(Node *N, const FoldingSetInfo &Info) {
281294
FoldingSetNodeID ID;
282295
Info.GetNodeProfile(this, N, ID);
283-
void *IP;
284-
if (Node *E = FindNodeOrInsertPos(ID, IP, Info))
296+
FoldingSetInsertToken Token;
297+
if (Node *E = lookup(ID, Token, Info))
285298
return E;
286-
InsertNode(N, IP);
299+
insert(N, Token);
287300
return N;
288301
}

0 commit comments

Comments
 (0)