LLVM 24.0.0git
FoldingSet.h
Go to the documentation of this file.
1//===- llvm/ADT/FoldingSet.h - Uniquing Hash Set ----------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file defines a hash set that can be used to remove duplication of nodes
11/// in a graph. This code was originally created by Chris Lattner for use with
12/// SelectionDAGCSEMap, but was isolated to provide use across the llvm code
13/// set.
14//===----------------------------------------------------------------------===//
15
16#ifndef LLVM_ADT_FOLDINGSET_H
17#define LLVM_ADT_FOLDINGSET_H
18
19#include "llvm/ADT/ArrayRef.h"
22#include "llvm/ADT/Hashing.h"
25#include "llvm/ADT/iterator.h"
28#include "llvm/Support/xxhash.h"
29#include <cassert>
30#include <cstddef>
31#include <cstdint>
32#include <cstring>
33#include <type_traits>
34#include <utility>
35
36namespace llvm {
37
38/// This folding set is used for two purposes:
39/// 1. Given information about a node we want to create, look up the unique
40/// instance of the node in the set. If the node already exists, return
41/// it, otherwise return a token that makes the insertion cheap.
42/// 2. Given a node that has already been created, remove it from the set.
43///
44/// The hash table is linear-probing open addressing with tombstone-free
45/// deletion, power-of-two capacity, and a 0.75 maximum load factor.
46///
47/// Any node that is to be included in the folding set must be a subclass of
48/// FoldingSetNode. The node class must also define a Profile method used to
49/// establish the unique bits of data for the node. The Profile method is
50/// passed a FoldingSetNodeID object which is used to gather the bits. Just
51/// call one of the Add* functions defined in the FoldingSetNodeID class.
52/// NOTE: That the folding set does not own the nodes and it is the
53/// responsibility of the user to dispose of the nodes.
54///
55/// Eg.
56/// class MyNode : public FoldingSetNode {
57/// private:
58/// std::string Name;
59/// unsigned Value;
60/// public:
61/// MyNode(const char *N, unsigned V) : Name(N), Value(V) {}
62/// ...
63/// void Profile(FoldingSetNodeID &ID) const {
64/// ID.AddString(Name);
65/// ID.AddInteger(Value);
66/// }
67/// ...
68/// };
69///
70/// To define the folding set itself use the FoldingSet template;
71///
72/// Eg.
73/// FoldingSet<MyNode> MyFoldingSet;
74///
75/// Four public methods are available to manipulate the folding set;
76///
77/// 1) If you have an existing node that you want add to the set but unsure
78/// that the node might already exist then call;
79///
80/// MyNode *M = MyFoldingSet.getOrInsert(N);
81///
82/// If The result is equal to the input then the node has been inserted.
83/// Otherwise, the result is the node existing in the folding set, and the
84/// input can be discarded (use the result instead.)
85///
86/// 2) If you are ready to construct a node but want to check if it already
87/// exists, then call lookup with a FoldingSetNodeID of the bits to check;
88///
89/// FoldingSetNodeID ID;
90/// ID.AddString(Name);
91/// ID.AddInteger(Value);
92/// FoldingSetInsertToken Token;
93///
94/// MyNode *M = MyFoldingSet.lookup(ID, Token);
95///
96/// If found then M will be non-NULL, else Token holds what insert needs to
97/// place the node.
98///
99/// 3) If you get a NULL result from lookup then you can insert a new node with
100/// insert;
101///
102/// MyNode *N = new MyNode(Name, Value);
103/// MyFoldingSet.insert(N, Token);
104///
105/// Token survives intervening insertions, but N must profile identically to
106/// the ID that produced it, or N becomes unfindable.
107///
108/// 4) Finally, if you want to remove a node from the folding set call;
109///
110/// bool WasRemoved = MyFoldingSet.erase(M);
111///
112/// The result indicates whether the node existed in the folding set.
113
114class StringRef;
115template <typename T, typename Enable = void> struct FoldingSetTrait;
116
117//===----------------------------------------------------------------------===//
118/// This class describes a reference to an interned FoldingSetNodeID, which can
119/// be a useful to store node id data rather than using plain FoldingSetNodeIDs,
120/// since the 32-element SmallVector is often much larger than necessary, and
121/// the possibility of heap allocation means it requires a non-trivial
122/// destructor call.
123class FoldingSetNodeIDRef : public ArrayRef<unsigned> {
124public:
125 using ArrayRef<unsigned>::ArrayRef;
126
127 static constexpr unsigned NotAHash = 0;
128
129 // Compute a strong hash value used to lookup the node in the FoldingSetBase.
130 // The hash value is not guaranteed to be deterministic across processes.
131 // Never returns NotAHash: FoldingSetBase reserves it for the empty insert
132 // token and for a node belonging to no set.
133 unsigned computeHash() const {
134 unsigned Hash = static_cast<unsigned>(hash_value(*this));
135 return Hash == NotAHash ? 1 : Hash;
136 }
137
138 // Compute a deterministic hash value across processes that is suitable for
139 // on-disk serialization.
140 unsigned computeStableHash() const {
141 return static_cast<unsigned>(xxh3_64bits(
142 reinterpret_cast<const uint8_t *>(data()), sizeof(unsigned) * size()));
143 }
144};
145
147 return LHS.equals(RHS);
148}
149
151 return !(LHS == RHS);
152}
153
154/// Used to compare the "ordering" of two nodes as defined by the
155/// profiled bits and their ordering defined by memcmp().
156LLVM_ABI bool operator<(FoldingSetNodeIDRef LHS, FoldingSetNodeIDRef RHS);
157
158//===--------------------------------------------------------------------===//
159/// This class is used to gather all the unique data bits of a node. When all
160/// the bits are gathered this class is used to produce a hash value for the
161/// node.
163 /// Vector of all the data bits that make the node unique.
164 /// Use a SmallVector to avoid a heap allocation in the common case.
166
167 template <typename T> void AddIntegerImpl(T I) {
168 static_assert(std::is_integral_v<T> && sizeof(T) <= sizeof(unsigned) * 2,
169 "T must be an integer type no wider than 64 bits");
170 Bits.push_back(static_cast<unsigned>(I));
171 if constexpr (sizeof(unsigned) < sizeof(T))
172 Bits.push_back(static_cast<unsigned long long>(I) >> 32);
173 }
174
175public:
176 FoldingSetNodeID() = default;
177
179
180 /// Add* - Add various data types to Bit data.
181 void AddPointer(const void *Ptr) {
182 // Note: this adds pointers to the hash using sizes and endianness that
183 // depend on the host. It doesn't matter, however, because hashing on
184 // pointer values is inherently unstable. Nothing should depend on the
185 // ordering of nodes in the folding set.
186 static_assert(sizeof(uintptr_t) <= sizeof(unsigned long long),
187 "unexpected pointer size");
188 AddInteger(reinterpret_cast<uintptr_t>(Ptr));
189 }
190 void AddInteger(signed I) { AddIntegerImpl(I); }
191 void AddInteger(unsigned I) { AddIntegerImpl(I); }
192 void AddInteger(long I) { AddIntegerImpl(I); }
193 void AddInteger(unsigned long I) { AddIntegerImpl(I); }
194 void AddInteger(long long I) { AddIntegerImpl(I); }
195 void AddInteger(unsigned long long I) { AddIntegerImpl(I); }
196 void AddBoolean(bool B) { AddInteger(B ? 1U : 0U); }
198 LLVM_ABI void AddNodeID(const FoldingSetNodeID &ID);
199
200 template <typename T> inline void Add(const T &x) {
202 }
203
204 /// Clear the accumulated profile, allowing this FoldingSetNodeID
205 /// object to be used to compute a new profile.
206 inline void clear() { Bits.clear(); }
207
208 /// The accumulated profile, valid until this object is next modified.
209 FoldingSetNodeIDRef getRef() const { return Bits; }
210
211 // Compute a strong hash value for this FoldingSetNodeID, used to lookup the
212 // node in the FoldingSetBase. The hash value is not guaranteed to be
213 // deterministic across processes.
214 unsigned computeHash() const { return getRef().computeHash(); }
215
216 // Compute a deterministic hash value across processes that is suitable for
217 // on-disk serialization.
218 unsigned computeStableHash() const { return getRef().computeStableHash(); }
219
220 operator FoldingSetNodeIDRef() const { return Bits; }
221
222 /// Copy this node's data to a memory region allocated from the
223 /// given allocator and return a FoldingSetNodeIDRef describing the
224 /// interned data.
226};
227
228//===----------------------------------------------------------------------===//
229
230/// This class provides default implementations for FoldingSetTrait
231/// implementations.
232template <typename T> struct DefaultFoldingSetTrait {
233 struct ContextStorage {};
234
235 static void Profile(const T &X, FoldingSetNodeID &ID) { X.Profile(ID); }
236 static void Profile(T &X, FoldingSetNodeID &ID) { X.Profile(ID); }
237
238 // Test if the profile for X would match ID. Implementations can override this
239 // to compare against X's fields, which avoids building a profile for every
240 // candidate.
241 static bool Equals(T &X, const FoldingSetNodeID &ID) {
242 FoldingSetNodeID TempID;
244 return TempID == ID;
245 }
246};
247
248/// This trait class is used to define behavior of how to "profile" (in the
249/// FoldingSet parlance) an object of a given type.
250/// The default behavior is to invoke a 'Profile' method on an object, but
251/// through template specialization the behavior can be tailored for specific
252/// types. Combined with the FoldingSetNodeWrapper class, one can add objects
253/// to FoldingSets that were not originally designed to have that behavior.
254template <typename T, typename Enable>
256
257template <typename T, typename Ctx> struct ContextualFoldingSetTrait;
258
259/// Like DefaultFoldingSetTrait, but for ContextualFoldingSets.
260template <typename T, typename Ctx> struct DefaultContextualFoldingSetTrait {
264 Ctx getContext() const { return Context; }
265 };
266
267 static void Profile(T &X, FoldingSetNodeID &ID, Ctx Context) {
268 X.Profile(ID, Context);
269 }
270
271 static bool Equals(T &X, const FoldingSetNodeID &ID, Ctx Context) {
272 FoldingSetNodeID TempID;
274 return TempID == ID;
275 }
276};
277
278/// Like FoldingSetTrait, but for ContextualFoldingSets.
279template <typename T, typename Ctx>
281
282/// Insertion token: a failed lookup fills it in, the matching insert consumes
283/// it.
284class FoldingSetInsertToken {
286
287 explicit FoldingSetInsertToken(uint32_t Hash) : Hash(Hash) {
288 assert(Hash != FoldingSetNodeIDRef::NotAHash && "Invalid insert token");
289 }
290
291 friend class FoldingSetBase;
292
293public:
295 explicit operator bool() const {
296 return Hash != FoldingSetNodeIDRef::NotAHash;
297 }
298
299 friend bool operator==(FoldingSetInsertToken A, FoldingSetInsertToken B) {
300 return A.Hash == B.Hash;
301 }
302 friend bool operator!=(FoldingSetInsertToken A, FoldingSetInsertToken B) {
303 return !(A == B);
304 }
305};
306
307//===----------------------------------------------------------------------===//
308/// This class is used to maintain node state in a folding set.
310 // Hash of the node's profile, cached so that growth and removal never
311 // re-run Profile(). NotAHash while the node is in no folding set.
313
314public:
315 FoldingSetNode() = default;
316
317 uint32_t getFoldingSetHash() const { return FoldingSetHash; }
318 void setFoldingSetHash(uint32_t Hash) { FoldingSetHash = Hash; }
319};
320
321//===----------------------------------------------------------------------===//
322/// Forward iterator for FoldingSet and ContextualFoldingSet.
324 FoldingSetNode **Bucket = nullptr;
325 FoldingSetNode **End = nullptr;
326
327 void advance() {
328 assert(isHandleInSync() && "invalid iterator access!");
329 do
330 ++Bucket;
331 while (Bucket != End && *Bucket == nullptr);
332 }
333
334public:
336 const DebugEpochBase *Epoch)
337 : DebugEpochBase::HandleBase(Epoch), Bucket(Bucket), End(End) {
338 while (this->Bucket != this->End && *this->Bucket == nullptr)
339 ++this->Bucket;
340 }
341
342 T &operator*() const {
343 assert(isHandleInSync() && "invalid iterator access!");
344 return *static_cast<T *>(*Bucket);
345 }
346
347 T *operator->() const { return &operator*(); }
348
350 advance();
351 return *this;
352 }
354 FoldingSetIterator tmp = *this;
355 ++*this;
356 return tmp;
357 }
358
359 bool operator==(const FoldingSetIterator &RHS) const {
360 assert(isComparableWith(RHS) && "incomparable iterators!");
361 return Bucket == RHS.Bucket;
362 }
363 bool operator!=(const FoldingSetIterator &RHS) const {
364 return !(*this == RHS);
365 }
366};
367
368//===----------------------------------------------------------------------===//
369/// Non-templated base class for FoldingSet and ContextualFoldingSet, holding
370/// the memory management and probing that does not depend on the node type.
372protected:
373 /// Array of node pointers; a null entry marks an empty slot.
375
376 /// Length of the Buckets array. Always a power of 2.
377 unsigned NumBuckets = 0;
378
379 /// Number of nodes in the folding set.
380 unsigned NumNodes = 0;
381
382 LLVM_ABI explicit FoldingSetBase(unsigned Log2InitSize);
386
387public:
388 /// Remove all nodes from the folding set.
389 LLVM_ABI void clear();
390
391 /// Returns the number of nodes in the folding set.
392 unsigned size() const { return NumNodes; }
393
394 /// Returns true if there are no nodes in the folding set.
395 [[nodiscard]] bool empty() const { return NumNodes == 0; }
396
397 /// Grow the number of buckets so that we can hold at least \p N nodes
398 /// before rebucketing. May allocate more space than requested.
399 LLVM_ABI void reserve(unsigned N);
400
401private:
402 /// Put \p N in the first empty slot following its home, without checking
403 /// capacity. Does not touch \p N, so a rehash need not dirty every node.
404 void placeNode(FoldingSetNode *N, uint32_t Hash);
405
406 /// Rehash into at least \p MinNumBuckets buckets, rounded up to a power of
407 /// two and floored at the constructor's minimum.
408 void grow(unsigned MinNumBuckets);
409
410protected:
411 // The below methods are protected to encourage subclasses to provide a more
412 // type-safe API.
413
414 /// Remove a node from the folding set, returning true if one
415 /// was removed or false if the node was not in the folding set.
417
418 /// Walk the probe chain for \p Hash, offering each node whose cached hash
419 /// matches to \p IsMatch. \p IsMatch is a template parameter so that it, and
420 /// the profile it may build, inline into the loop.
421 template <typename MatchFn>
423 MatchFn IsMatch) {
424 assert(Hash != FoldingSetNodeIDRef::NotAHash && "Hash must be normalized");
425 unsigned Mask = NumBuckets - 1;
426 for (unsigned I = Hash & Mask; Buckets[I]; I = (I + 1) & Mask) {
428 if (N->getFoldingSetHash() == Hash && IsMatch(N)) {
429 Token = {};
430 return N;
431 }
432 }
433
434 Token = FoldingSetInsertToken(Hash);
435 return nullptr;
436 }
437
438 /// Insert the specified node into the folding set, knowing that it is not
439 /// already in the folding set. \p Token must come from lookup for an ID that
440 /// \p N profiles identically to.
442
443 /// Wrap \p Hash, which must not be NotAHash, as the token insert takes.
447};
448
449//===----------------------------------------------------------------------===//
450/// An implementation detail that lets us share code between FoldingSet and
451/// ContextualFoldingSet.
452template <class T, class Trait = FoldingSetTrait<T>>
453class FoldingSetImpl : public FoldingSetBase, public Trait::ContextStorage {
454 void nodeProfile(FoldingSetNode *N, FoldingSetNodeID &ID) const {
455 if constexpr (std::is_empty_v<typename Trait::ContextStorage>)
456 Trait::Profile(*static_cast<T *>(N), ID);
457 else
458 Trait::Profile(*static_cast<T *>(N), ID, this->getContext());
459 }
460
461 bool nodeEquals(FoldingSetNode *N, const FoldingSetNodeID &ID) const {
462 if constexpr (std::is_empty_v<typename Trait::ContextStorage>)
463 return Trait::Equals(*static_cast<T *>(N), ID);
464 else
465 return Trait::Equals(*static_cast<T *>(N), ID, this->getContext());
466 }
467
468public:
469 explicit FoldingSetImpl(unsigned Log2InitSize = 6)
470 : FoldingSetBase(Log2InitSize) {}
471
472 template <typename C, typename = std::enable_if_t<std::is_constructible_v<
473 typename Trait::ContextStorage, C>>>
474 explicit FoldingSetImpl(C &&Context, unsigned Log2InitSize = 6)
475 : FoldingSetBase(Log2InitSize),
476 Trait::ContextStorage(std::forward<C>(Context)) {}
477
480 ~FoldingSetImpl() = default;
481
482public:
484
487 return iterator(Buckets + NumBuckets, Buckets + NumBuckets, this);
488 }
489
491
493 return const_iterator(Buckets, Buckets + NumBuckets, this);
494 }
497 }
498
499 /// Remove a node from the folding set, returning true if one
500 /// was removed or false if the node was not in the folding set.
501 bool erase(T *N) { return FoldingSetBase::erase(N); }
502
503 /// If there is an existing node exactly equal to the specified node,
504 /// return it. Otherwise, insert 'N' and return it instead.
505 ///
506 /// Out of line so that callers do not inherit the ID's inline storage; some
507 /// of them recurse.
510 nodeProfile(N, ID);
512 if (T *E = lookup(ID, Token))
513 return E;
515 return N;
516 }
517
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.
521 return static_cast<T *>(
522 probe(ID.computeHash(), Token,
523 [&](FoldingSetNode *N) { return nodeEquals(N, ID); }));
524 }
525
526 /// Insert the specified node into the folding set, knowing that it is not
527 /// already in the folding set. \p Token must come from lookup for an ID that
528 /// \p N profiles identically to.
530#ifndef NDEBUG
531 FoldingSetNodeID ProfileID;
532 nodeProfile(N, ProfileID);
533 assert(makeInsertToken(ProfileID.computeHash()) == Token &&
534 "node profile must match the insert token");
535#endif
537 }
538
539 /// Insert the specified node into the folding set, knowing that it is not
540 /// already in the folding set.
541 void insert(T *N) {
542 T *Inserted = getOrInsert(N);
543 (void)Inserted;
544 assert(Inserted == N && "Node already inserted!");
545 }
546};
547
548//===----------------------------------------------------------------------===//
549/// This template class is used to instantiate a specialized
550/// implementation of the folding set to the node class T. T must be a
551/// subclass of FoldingSetNode and implement a Profile function.
552///
553/// Note that this set type is movable and move-assignable. However, its
554/// moved-from state is not a valid state for anything other than
555/// move-assigning and destroying. This is primarily to enable movable APIs
556/// that incorporate these objects.
557template <class T, class Trait = FoldingSetTrait<T>>
559
560//===----------------------------------------------------------------------===//
561/// This template class is a further refinement of FoldingSet which provides a
562/// context argument when calling Profile on its nodes. Currently, that
563/// argument is fixed at initialization time.
564///
565/// T must be a subclass of FoldingSetNode and implement a Profile
566/// function with signature
567/// void Profile(FoldingSetNodeID &, Ctx);
568template <class T, class Ctx>
571
572//===----------------------------------------------------------------------===//
573/// This template class combines a FoldingSet and a vector to provide the
574/// interface of FoldingSet but with deterministic iteration order based on the
575/// insertion order. T must be a subclass of FoldingSetNode and implement a
576/// Profile function.
577template <class T, class VectorT = SmallVector<T *, 8>> class FoldingSetVector {
578 FoldingSet<T> Set;
579 VectorT Vector;
580
581public:
582 explicit FoldingSetVector(unsigned Log2InitSize = 6) : Set(Log2InitSize) {}
583
585
586 iterator begin() { return Vector.begin(); }
587 iterator end() { return Vector.end(); }
588
590
591 const_iterator begin() const { return Vector.begin(); }
592 const_iterator end() const { return Vector.end(); }
593
594 /// Remove all nodes from the folding set.
595 void clear() {
596 Set.clear();
597 Vector.clear();
598 }
599
600 /// Look up the node specified by ID. If it exists, return it and clear
601 /// \p Token; otherwise return null and set \p Token for a subsequent insert.
603 return Set.lookup(ID, Token);
604 }
605
606 /// If there is an existing node exactly equal to the specified node,
607 /// return it. Otherwise, insert 'N' and return it instead.
609 T *Result = Set.getOrInsert(N);
610 if (Result == N)
611 Vector.push_back(N);
612 return Result;
613 }
614
615 /// Insert the specified node into the folding set, knowing that it is not
616 /// already in the folding set. \p Token must come from lookup for an ID that
617 /// \p N profiles identically to.
619 Set.insert(N, Token);
620 Vector.push_back(N);
621 }
622
623 /// Insert the specified node into the folding set, knowing that
624 /// it is not already in the folding set.
625 void insert(T *N) {
626 Set.insert(N);
627 Vector.push_back(N);
628 }
629
630 /// Returns the number of nodes in the folding set.
631 unsigned size() const { return Set.size(); }
632
633 /// Returns true if there are no nodes in the folding set.
634 [[nodiscard]] bool empty() const { return Set.empty(); }
635};
636
637//===----------------------------------------------------------------------===//
638/// This template class is used to "wrap" arbitrary types in an enclosing object
639/// so that they can be inserted into FoldingSets.
640template <typename T> class FoldingSetNodeWrapper : public FoldingSetNode {
641 T data;
642
643public:
644 template <typename... Ts>
645 explicit FoldingSetNodeWrapper(Ts &&...Args)
646 : data(std::forward<Ts>(Args)...) {}
647
649
650 T &getValue() { return data; }
651 const T &getValue() const { return data; }
652
653 operator T &() { return data; }
654 operator const T &() const { return data; }
655};
656
657//===----------------------------------------------------------------------===//
658/// The default UniquingSet Info: \p T supplies its own key.
659template <typename T> struct UniquingSetInfo {
661 static KeyTy getKey(const T &N) { return N.getKey(); }
662 static unsigned getHashValue(const KeyTy &Key) {
664 }
665 static bool isEqual(const KeyTy &Key, const T &N) {
666 return Key == N.getKey();
667 }
668};
669
670/// A uniquing set that compares nodes against a typed key rather than a
671/// serialized FoldingSetNodeID.
672///
673/// \p T must derive from FoldingSetNode and provide a getKey() whose result is
674/// comparable with == and for which DenseMapInfo<KeyTy>::getHashValue exists.
675/// \p Info overrides that:
676///
677/// \code
678/// using KeyTy = ...;
679/// static KeyTy getKey(const T &N);
680/// static unsigned getHashValue(const KeyTy &K);
681/// static bool isEqual(const KeyTy &K, const T &N);
682/// \endcode
683///
684/// Override isEqual when comparing a key against a node's fields is cheaper
685/// than building a key from the node, which is what the default does.
686///
687/// Derive \p Info from UniquingSetInfo<T> to override only the hash. The
688/// default Info needs \p T complete wherever UniquingSet<T> is instantiated;
689/// FoldingSet does not. A key may alias storage owned by the node; it is only
690/// used within a single lookup().
691///
692/// Prefer FoldingSet when a key cannot be read cheaply out of a node: a
693/// FoldingSetNodeID cannot disagree with itself, whereas getKey and the code
694/// that builds a key to look up must be kept in step by hand.
695template <typename T, typename Info = UniquingSetInfo<T>>
697public:
698 using KeyTy = typename Info::KeyTy;
699
700 explicit UniquingSet(unsigned Log2InitSize = 6)
701 : FoldingSetBase(Log2InitSize) {}
702
706 return iterator(Buckets + NumBuckets, Buckets + NumBuckets, this);
707 }
708
711 return const_iterator(Buckets, Buckets + NumBuckets, this);
712 }
715 }
716
717 /// Look up \p Key. On a hit \p Token is cleared; on a miss it receives a
718 /// token for insert().
720 return static_cast<T *>(probe(hashKey(Key), Token, [&](FoldingSetNode *N) {
721 return Info::isEqual(Key, *static_cast<T *>(N));
722 }));
723 }
724
725 /// Insert \p N, which must key identically to the lookup that produced
726 /// \p Token.
728 assert(Token && "Invalid token!");
729 assert(makeInsertToken(hashKey(Info::getKey(*N))) == Token &&
730 "N does not key as the lookup that produced Token did");
732 }
733
734 /// Look \p N up by its own key, inserting it if absent, and return the node
735 /// in the set. Out of line so that callers do not inherit the key's inline
736 /// storage; some of them recurse.
739 if (T *E = lookup(Info::getKey(*N), Token))
740 return E;
742 return N;
743 }
744
745 /// Remove \p N, returning whether it was present.
746 bool erase(T *N) { return FoldingSetBase::erase(N); }
747
748private:
749 // Never NotAHash, for the reason FoldingSetNodeIDRef::computeHash gives.
750 static uint32_t hashKey(const KeyTy &Key) {
751 uint32_t Hash = Info::getHashValue(Key);
752 return Hash == FoldingSetNodeIDRef::NotAHash ? 1 : Hash;
753 }
754};
755
756//===----------------------------------------------------------------------===//
757/// This is a subclass of FoldingSetNode which stores a FoldingSetNodeID value
758/// rather than requiring the node to recompute it each time it is needed. This
759/// trades space for speed (which can be significant if the ID is long), and it
760/// also permits nodes to drop information that would otherwise only be required
761/// for recomputing an ID.
763 FoldingSetNodeID FastID;
764
765protected:
766 explicit FastFoldingSetNode(const FoldingSetNodeID &ID) : FastID(ID) {}
767
768public:
769 void Profile(FoldingSetNodeID &ID) const { ID.AddNodeID(FastID); }
770};
771
772//===----------------------------------------------------------------------===//
773// Partial specializations of FoldingSetTrait.
774
775template <typename T> struct FoldingSetTrait<T *> {
776 static inline void Profile(T *X, FoldingSetNodeID &ID) { ID.AddPointer(X); }
777};
778template <typename T1, typename T2> struct FoldingSetTrait<std::pair<T1, T2>> {
779 static inline void Profile(const std::pair<T1, T2> &P, FoldingSetNodeID &ID) {
780 ID.Add(P.first);
781 ID.Add(P.second);
782 }
783};
784
785template <typename T>
786struct FoldingSetTrait<T, std::enable_if_t<std::is_enum<T>::value>> {
787 static void Profile(const T &X, FoldingSetNodeID &ID) {
788 ID.AddInteger(llvm::to_underlying(X));
789 }
790};
791
792} // namespace llvm
793
794#endif // LLVM_ADT_FOLDINGSET_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the BumpPtrAllocator interface.
#define X(NUM, ENUM, NAME)
Definition ELF.h:857
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_ABI
Definition Compiler.h:215
#define LLVM_ATTRIBUTE_NOINLINE
LLVM_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so, mark a method "not for inl...
Definition Compiler.h:354
This file defines DenseMapInfo traits for DenseMap.
This file defines the DebugEpochBase and DebugEpochBase::HandleBase classes.
#define I(x, y, z)
Definition MD5.cpp:57
#define T
#define P(N)
Basic Register Allocator
Func getContext().diagnose(DiagnosticInfoUnsupported(Func
This file contains library features backported from future STL versions.
This file defines the SmallVector class.
Value * RHS
Value * LHS
const unsigned * data() const
Definition ArrayRef.h:138
bool isComparableWith(const HandleBase &) const
FastFoldingSetNode(const FoldingSetNodeID &ID)
Definition FoldingSet.h:766
void Profile(FoldingSetNodeID &ID) const
Definition FoldingSet.h:769
Non-templated base class for FoldingSet and ContextualFoldingSet, holding the memory management and p...
Definition FoldingSet.h:371
static FoldingSetInsertToken makeInsertToken(uint32_t Hash)
Wrap Hash, which must not be NotAHash, as the token insert takes.
Definition FoldingSet.h:444
LLVM_ABI bool erase(FoldingSetNode *N)
Remove a node from the folding set, returning true if one was removed or false if the node was not in...
unsigned size() const
Returns the number of nodes in the folding set.
Definition FoldingSet.h:392
FoldingSetNode ** Buckets
Array of node pointers; a null entry marks an empty slot.
Definition FoldingSet.h:374
LLVM_ABI FoldingSetBase & operator=(FoldingSetBase &&RHS)
LLVM_ABI ~FoldingSetBase()
FoldingSetNode * probe(uint32_t Hash, FoldingSetInsertToken &Token, MatchFn IsMatch)
Walk the probe chain for Hash, offering each node whose cached hash matches to IsMatch.
Definition FoldingSet.h:422
unsigned NumBuckets
Length of the Buckets array. Always a power of 2.
Definition FoldingSet.h:377
unsigned NumNodes
Number of nodes in the folding set.
Definition FoldingSet.h:380
bool empty() const
Returns true if there are no nodes in the folding set.
Definition FoldingSet.h:395
LLVM_ABI void insert(FoldingSetNode *N, FoldingSetInsertToken Token)
Insert the specified node into the folding set, knowing that it is not already in the folding set.
LLVM_ABI void reserve(unsigned N)
Grow the number of buckets so that we can hold at least N nodes before rebucketing.
LLVM_ABI void clear()
Remove all nodes from the folding set.
LLVM_ABI FoldingSetBase(unsigned Log2InitSize)
An implementation detail that lets us share code between FoldingSet and ContextualFoldingSet.
Definition FoldingSet.h:453
FoldingSetImpl(FoldingSetImpl &&Arg)=default
FoldingSetImpl(C &&Context, unsigned Log2InitSize=6)
Definition FoldingSet.h:474
const_iterator begin() const
Definition FoldingSet.h:492
LLVM_ATTRIBUTE_NOINLINE T * getOrInsert(T *N)
Definition FoldingSet.h:508
FoldingSetImpl & operator=(FoldingSetImpl &&RHS)=default
FoldingSetIterator< const T > const_iterator
Definition FoldingSet.h:490
void insert(T *N, FoldingSetInsertToken Token)
Definition FoldingSet.h:529
const_iterator end() const
Definition FoldingSet.h:495
FoldingSetIterator< T > iterator
Definition FoldingSet.h:483
FoldingSetImpl(unsigned Log2InitSize=6)
Definition FoldingSet.h:469
T * lookup(const FoldingSetNodeID &ID, FoldingSetInsertToken &Token)
Look up the node specified by ID.
Definition FoldingSet.h:520
Insertion token: a failed lookup fills it in, the matching insert consumes it.
Definition FoldingSet.h:284
friend bool operator!=(FoldingSetInsertToken A, FoldingSetInsertToken B)
Definition FoldingSet.h:302
friend bool operator==(FoldingSetInsertToken A, FoldingSetInsertToken B)
Definition FoldingSet.h:299
Forward iterator for FoldingSet and ContextualFoldingSet.
Definition FoldingSet.h:323
bool operator==(const FoldingSetIterator &RHS) const
Definition FoldingSet.h:359
FoldingSetIterator(FoldingSetNode **Bucket, FoldingSetNode **End, const DebugEpochBase *Epoch)
Definition FoldingSet.h:335
FoldingSetIterator operator++(int)
Definition FoldingSet.h:353
bool operator!=(const FoldingSetIterator &RHS) const
Definition FoldingSet.h:363
FoldingSetIterator & operator++()
Definition FoldingSet.h:349
This class describes a reference to an interned FoldingSetNodeID, which can be a useful to store node...
Definition FoldingSet.h:123
unsigned computeStableHash() const
Definition FoldingSet.h:140
unsigned computeHash() const
Definition FoldingSet.h:133
static constexpr unsigned NotAHash
Definition FoldingSet.h:127
This class is used to gather all the unique data bits of a node.
Definition FoldingSet.h:162
LLVM_ABI FoldingSetNodeIDRef Intern(BumpPtrAllocator &Allocator) const
Copy this node's data to a memory region allocated from the given allocator and return a FoldingSetNo...
void AddInteger(signed I)
Definition FoldingSet.h:190
void AddInteger(unsigned long I)
Definition FoldingSet.h:193
FoldingSetNodeID(FoldingSetNodeIDRef Ref)
Definition FoldingSet.h:178
unsigned computeStableHash() const
Definition FoldingSet.h:218
void AddPointer(const void *Ptr)
Add* - Add various data types to Bit data.
Definition FoldingSet.h:181
void clear()
Clear the accumulated profile, allowing this FoldingSetNodeID object to be used to compute a new prof...
Definition FoldingSet.h:206
FoldingSetNodeIDRef getRef() const
The accumulated profile, valid until this object is next modified.
Definition FoldingSet.h:209
void AddInteger(unsigned I)
Definition FoldingSet.h:191
void AddInteger(long I)
Definition FoldingSet.h:192
void AddBoolean(bool B)
Definition FoldingSet.h:196
void AddInteger(unsigned long long I)
Definition FoldingSet.h:195
void AddInteger(long long I)
Definition FoldingSet.h:194
LLVM_ABI void AddNodeID(const FoldingSetNodeID &ID)
void Add(const T &x)
Definition FoldingSet.h:200
unsigned computeHash() const
Definition FoldingSet.h:214
LLVM_ABI void AddString(StringRef String)
const T & getValue() const
Definition FoldingSet.h:651
FoldingSetNodeWrapper(Ts &&...Args)
Definition FoldingSet.h:645
void Profile(FoldingSetNodeID &ID)
Definition FoldingSet.h:648
This class is used to maintain node state in a folding set.
Definition FoldingSet.h:309
uint32_t getFoldingSetHash() const
Definition FoldingSet.h:317
void setFoldingSetHash(uint32_t Hash)
Definition FoldingSet.h:318
FoldingSetNode()=default
const_iterator end() const
Definition FoldingSet.h:592
void insert(T *N)
Insert the specified node into the folding set, knowing that it is not already in the folding set.
Definition FoldingSet.h:625
unsigned size() const
Returns the number of nodes in the folding set.
Definition FoldingSet.h:631
pointee_iterator< typename VectorT::const_iterator > const_iterator
Definition FoldingSet.h:589
T * lookup(const FoldingSetNodeID &ID, FoldingSetInsertToken &Token)
Look up the node specified by ID.
Definition FoldingSet.h:602
pointee_iterator< typename VectorT::iterator > iterator
Definition FoldingSet.h:584
void clear()
Remove all nodes from the folding set.
Definition FoldingSet.h:595
bool empty() const
Returns true if there are no nodes in the folding set.
Definition FoldingSet.h:634
FoldingSetVector(unsigned Log2InitSize=6)
Definition FoldingSet.h:582
void insert(T *N, FoldingSetInsertToken Token)
Insert the specified node into the folding set, knowing that it is not already in the folding set.
Definition FoldingSet.h:618
T * getOrInsert(T *N)
If there is an existing node exactly equal to the specified node, return it.
Definition FoldingSet.h:608
const_iterator begin() const
Definition FoldingSet.h:591
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
FoldingSetIterator< T > iterator
Definition FoldingSet.h:703
bool erase(T *N)
Remove N, returning whether it was present.
Definition FoldingSet.h:746
const_iterator begin() const
Definition FoldingSet.h:710
UniquingSet(unsigned Log2InitSize=6)
Definition FoldingSet.h:700
T * lookup(const KeyTy &Key, FoldingSetInsertToken &Token)
Look up Key.
Definition FoldingSet.h:719
void insert(T *N, FoldingSetInsertToken Token)
Insert N, which must key identically to the lookup that produced Token.
Definition FoldingSet.h:727
FoldingSetIterator< const T > const_iterator
Definition FoldingSet.h:709
iterator begin()
Definition FoldingSet.h:704
const_iterator end() const
Definition FoldingSet.h:713
typename Info::KeyTy KeyTy
Definition FoldingSet.h:698
LLVM_ATTRIBUTE_NOINLINE T * getOrInsert(T *N)
Look N up by its own key, inserting it if absent, and return the node in the set.
Definition FoldingSet.h:737
This is an optimization pass for GlobalISel generic memory operations.
bool operator<(int64_t V1, const APSInt &V2)
Definition APSInt.h:360
hash_code hash_value(const FixedPointSemantics &Val)
uint64_t xxh3_64bits(ArrayRef< uint8_t > data)
Inline ArrayRef overloads of the xxhash entry points declared out-of-line in llvm/Support/xxhash....
Definition ArrayRef.h:558
bool operator!=(uint64_t V1, const APInt &V2)
Definition APInt.h:2140
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
constexpr std::underlying_type_t< Enum > to_underlying(Enum E)
Returns underlying integer value of an enum.
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
@ Ref
The access may reference the value stored in memory.
Definition ModRef.h:32
FoldingSetImpl< T, ContextualFoldingSetTrait< T, Ctx > > ContextualFoldingSet
This template class is a further refinement of FoldingSet which provides a context argument when call...
Definition FoldingSet.h:569
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
Definition Allocator.h:390
FoldingSetImpl< T, Trait > FoldingSet
This template class is used to instantiate a specialized implementation of the folding set to the nod...
Definition FoldingSet.h:558
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
#define N
Like FoldingSetTrait, but for ContextualFoldingSets.
Definition FoldingSet.h:280
Like DefaultFoldingSetTrait, but for ContextualFoldingSets.
Definition FoldingSet.h:260
static void Profile(T &X, FoldingSetNodeID &ID, Ctx Context)
Definition FoldingSet.h:267
static bool Equals(T &X, const FoldingSetNodeID &ID, Ctx Context)
Definition FoldingSet.h:271
This class provides default implementations for FoldingSetTrait implementations.
Definition FoldingSet.h:232
static bool Equals(T &X, const FoldingSetNodeID &ID)
Definition FoldingSet.h:241
static void Profile(const T &X, FoldingSetNodeID &ID)
Definition FoldingSet.h:235
static void Profile(T &X, FoldingSetNodeID &ID)
Definition FoldingSet.h:236
An information struct used to provide DenseMap with the various necessary components for a given valu...
static void Profile(T *X, FoldingSetNodeID &ID)
Definition FoldingSet.h:776
static void Profile(const std::pair< T1, T2 > &P, FoldingSetNodeID &ID)
Definition FoldingSet.h:779
This trait class is used to define behavior of how to "profile" (in the FoldingSet parlance) an objec...
Definition FoldingSet.h:255
The default UniquingSet Info: T supplies its own key.
Definition FoldingSet.h:659
static bool isEqual(const KeyTy &Key, const T &N)
Definition FoldingSet.h:665
static unsigned getHashValue(const KeyTy &Key)
Definition FoldingSet.h:662
remove_cvref_t< decltype(std::declval< const T & >().getKey())> KeyTy
Definition FoldingSet.h:660
static KeyTy getKey(const T &N)
Definition FoldingSet.h:661
An iterator type that allows iterating over the pointees via some other iterator.
Definition iterator.h:329