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
20#include "llvm/ADT/Hashing.h"
23#include "llvm/ADT/iterator.h"
26#include "llvm/Support/xxhash.h"
27#include <cassert>
28#include <cstddef>
29#include <cstdint>
30#include <type_traits>
31#include <utility>
32
33namespace llvm {
34
35/// This folding set is used for two purposes:
36/// 1. Given information about a node we want to create, look up the unique
37/// instance of the node in the set. If the node already exists, return
38/// it, otherwise return a token that makes the insertion cheap.
39/// 2. Given a node that has already been created, remove it from the set.
40///
41/// The hash table is linear-probing open addressing with tombstone-free
42/// deletion, power-of-two capacity, and a 0.75 maximum load factor.
43///
44/// Any node that is to be included in the folding set must be a subclass of
45/// FoldingSetNode. The node class must also define a Profile method used to
46/// establish the unique bits of data for the node. The Profile method is
47/// passed a FoldingSetNodeID object which is used to gather the bits. Just
48/// call one of the Add* functions defined in the FoldingSetNodeID class.
49/// NOTE: That the folding set does not own the nodes and it is the
50/// responsibility of the user to dispose of the nodes.
51///
52/// Eg.
53/// class MyNode : public FoldingSetNode {
54/// private:
55/// std::string Name;
56/// unsigned Value;
57/// public:
58/// MyNode(const char *N, unsigned V) : Name(N), Value(V) {}
59/// ...
60/// void Profile(FoldingSetNodeID &ID) const {
61/// ID.AddString(Name);
62/// ID.AddInteger(Value);
63/// }
64/// ...
65/// };
66///
67/// To define the folding set itself use the FoldingSet template;
68///
69/// Eg.
70/// FoldingSet<MyNode> MyFoldingSet;
71///
72/// Four public methods are available to manipulate the folding set;
73///
74/// 1) If you have an existing node that you want add to the set but unsure
75/// that the node might already exist then call;
76///
77/// MyNode *M = MyFoldingSet.getOrInsert(N);
78///
79/// If The result is equal to the input then the node has been inserted.
80/// Otherwise, the result is the node existing in the folding set, and the
81/// input can be discarded (use the result instead.)
82///
83/// 2) If you are ready to construct a node but want to check if it already
84/// exists, then call lookup with a FoldingSetNodeID of the bits to check;
85///
86/// FoldingSetNodeID ID;
87/// ID.AddString(Name);
88/// ID.AddInteger(Value);
89/// FoldingSetInsertToken Token;
90///
91/// MyNode *M = MyFoldingSet.lookup(ID, Token);
92///
93/// If found then M will be non-NULL, else Token holds what insert needs to
94/// place the node.
95///
96/// 3) If you get a NULL result from lookup then you can insert a new node with
97/// insert;
98///
99/// MyNode *N = new MyNode(Name, Value);
100/// MyFoldingSet.insert(N, Token);
101///
102/// Token survives intervening insertions, but N must profile identically to
103/// the ID that produced it, or N becomes unfindable.
104///
105/// 4) Finally, if you want to remove a node from the folding set call;
106///
107/// bool WasRemoved = MyFoldingSet.erase(M);
108///
109/// The result indicates whether the node existed in the folding set.
110
111class FoldingSetNodeID;
112class StringRef;
113
114//===----------------------------------------------------------------------===//
115
116/// This class provides default implementations for FoldingSetTrait
117/// implementations.
118template <typename T> struct DefaultFoldingSetTrait {
119 struct ContextStorage {};
120
121 static void Profile(const T &X, FoldingSetNodeID &ID) { X.Profile(ID); }
122 static void Profile(T &X, FoldingSetNodeID &ID) { X.Profile(ID); }
123
124 // Equals - Test if the profile for X would match ID, using TempID
125 // to compute a temporary ID if necessary. The default implementation
126 // just calls Profile and does a regular comparison. Implementations
127 // can override this to provide more efficient implementations.
128 static inline bool Equals(T &X, const FoldingSetNodeID &ID,
129 FoldingSetNodeID &TempID);
130};
131
132/// This trait class is used to define behavior of how to "profile" (in the
133/// FoldingSet parlance) an object of a given type.
134/// The default behavior is to invoke a 'Profile' method on an object, but
135/// through template specialization the behavior can be tailored for specific
136/// types. Combined with the FoldingSetNodeWrapper class, one can add objects
137/// to FoldingSets that were not originally designed to have that behavior.
138template <typename T, typename Enable = void>
140
141/// Like DefaultFoldingSetTrait, but for ContextualFoldingSets.
142template <typename T, typename Ctx> struct DefaultContextualFoldingSetTrait {
146 Ctx getContext() const { return Context; }
147 };
148
149 static void Profile(T &X, FoldingSetNodeID &ID, Ctx Context) {
150 X.Profile(ID, Context);
151 }
152
153 static inline bool Equals(T &X, const FoldingSetNodeID &ID,
154 FoldingSetNodeID &TempID, Ctx Context);
155};
156
157/// Like FoldingSetTrait, but for ContextualFoldingSets.
158template <typename T, typename Ctx>
160
161//===--------------------------------------------------------------------===//
162/// This class describes a reference to an interned FoldingSetNodeID, which can
163/// be a useful to store node id data rather than using plain FoldingSetNodeIDs,
164/// since the 32-element SmallVector is often much larger than necessary, and
165/// the possibility of heap allocation means it requires a non-trivial
166/// destructor call.
168 const unsigned *Data = nullptr;
169 size_t Size = 0;
170
171public:
173 FoldingSetNodeIDRef(const unsigned *D, size_t S) : Data(D), Size(S) {}
174
175 static constexpr unsigned NotAHash = 0;
176
177 // Compute a strong hash value used to lookup the node in the FoldingSetBase.
178 // The hash value is not guaranteed to be deterministic across processes.
179 // Never returns NotAHash: FoldingSetBase reserves it for the empty insert
180 // token and for a node belonging to no set.
181 unsigned ComputeHash() const {
182 unsigned Hash =
183 static_cast<unsigned>(hash_combine_range(Data, Data + Size));
184 return Hash == NotAHash ? 1 : Hash;
185 }
186
187 // Compute a deterministic hash value across processes that is suitable for
188 // on-disk serialization.
189 unsigned computeStableHash() const {
190 return static_cast<unsigned>(xxh3_64bits(
191 reinterpret_cast<const uint8_t *>(Data), sizeof(unsigned) * Size));
192 }
193
195
196 bool operator!=(FoldingSetNodeIDRef RHS) const { return !(*this == RHS); }
197
198 /// Used to compare the "ordering" of two nodes as defined by the
199 /// profiled bits and their ordering defined by memcmp().
201
202 const unsigned *getData() const { return Data; }
203 size_t getSize() const { return Size; }
204};
205
206//===--------------------------------------------------------------------===//
207/// This class is used to gather all the unique data bits of a node. When all
208/// the bits are gathered this class is used to produce a hash value for the
209/// node.
211 /// Vector of all the data bits that make the node unique.
212 /// Use a SmallVector to avoid a heap allocation in the common case.
214
215 template <typename T> void AddIntegerImpl(T I) {
216 static_assert(std::is_integral_v<T> && sizeof(T) <= sizeof(unsigned) * 2,
217 "T must be an integer type no wider than 64 bits");
218 Bits.push_back(static_cast<unsigned>(I));
219 if constexpr (sizeof(unsigned) < sizeof(T))
220 Bits.push_back(static_cast<unsigned long long>(I) >> 32);
221 }
222
223public:
224 FoldingSetNodeID() = default;
225
227 : Bits(Ref.getData(), Ref.getData() + Ref.getSize()) {}
228
229 /// Add* - Add various data types to Bit data.
230 void AddPointer(const void *Ptr) {
231 // Note: this adds pointers to the hash using sizes and endianness that
232 // depend on the host. It doesn't matter, however, because hashing on
233 // pointer values is inherently unstable. Nothing should depend on the
234 // ordering of nodes in the folding set.
235 static_assert(sizeof(uintptr_t) <= sizeof(unsigned long long),
236 "unexpected pointer size");
237 AddInteger(reinterpret_cast<uintptr_t>(Ptr));
238 }
239 void AddInteger(signed I) { AddIntegerImpl(I); }
240 void AddInteger(unsigned I) { AddIntegerImpl(I); }
241 void AddInteger(long I) { AddIntegerImpl(I); }
242 void AddInteger(unsigned long I) { AddIntegerImpl(I); }
243 void AddInteger(long long I) { AddIntegerImpl(I); }
244 void AddInteger(unsigned long long I) { AddIntegerImpl(I); }
245 void AddBoolean(bool B) { AddInteger(B ? 1U : 0U); }
247 LLVM_ABI void AddNodeID(const FoldingSetNodeID &ID);
248
249 template <typename T> inline void Add(const T &x) {
251 }
252
253 /// Clear the accumulated profile, allowing this FoldingSetNodeID
254 /// object to be used to compute a new profile.
255 inline void clear() { Bits.clear(); }
256
257 // Compute a strong hash value for this FoldingSetNodeID, used to lookup the
258 // node in the FoldingSetBase. The hash value is not guaranteed to be
259 // deterministic across processes.
260 unsigned ComputeHash() const {
261 return FoldingSetNodeIDRef(Bits.data(), Bits.size()).ComputeHash();
262 }
263
264 // Compute a deterministic hash value across processes that is suitable for
265 // on-disk serialization.
266 unsigned computeStableHash() const {
267 return FoldingSetNodeIDRef(Bits.data(), Bits.size()).computeStableHash();
268 }
269
270 /// operator== - Used to compare two nodes to each other.
271 LLVM_ABI bool operator==(const FoldingSetNodeID &RHS) const;
272 LLVM_ABI bool operator==(const FoldingSetNodeIDRef RHS) const;
273
274 bool operator!=(const FoldingSetNodeID &RHS) const { return !(*this == RHS); }
276 return !(*this == RHS);
277 }
278
279 /// Used to compare the "ordering" of two nodes as defined by the
280 /// profiled bits and their ordering defined by memcmp().
281 LLVM_ABI bool operator<(const FoldingSetNodeID &RHS) const;
282 LLVM_ABI bool operator<(const FoldingSetNodeIDRef RHS) const;
283
284 /// Copy this node's data to a memory region allocated from the
285 /// given allocator and return a FoldingSetNodeIDRef describing the
286 /// interned data.
288};
289
290/// Insertion token: a failed lookup fills it in, the matching insert consumes
291/// it.
292class FoldingSetInsertToken {
294
295 explicit FoldingSetInsertToken(uint32_t Hash) : Hash(Hash) {
296 assert(Hash != FoldingSetNodeIDRef::NotAHash && "Invalid insert token");
297 }
298
299 friend class FoldingSetBase;
300
301public:
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
315//===----------------------------------------------------------------------===//
316/// Non-templated base class for FoldingSet and ContextualFoldingSet, holding
317/// the memory management and probing that does not depend on the node type.
319protected:
320 /// Array of node pointers; a null entry marks an empty slot.
321 void **Buckets = nullptr;
322
323 /// Length of the Buckets array. Always a power of 2.
324 unsigned NumBuckets = 0;
325
326 /// Number of nodes in the folding set.
327 unsigned NumNodes = 0;
328
329 LLVM_ABI explicit FoldingSetBase(unsigned Log2InitSize);
333
334public:
335 //===--------------------------------------------------------------------===//
336 /// This class is used to maintain node state in a folding set.
337 class Node {
338 private:
339 // Hash of the node's profile, cached so that growth and removal never
340 // re-run Profile(). NotAHash while the node is in no folding set.
342
343 public:
344 Node() = default;
345
346 // Accessors
347 uint32_t getFoldingSetHash() const { return FoldingSetHash; }
348 void setFoldingSetHash(uint32_t Hash) { FoldingSetHash = Hash; }
349 };
350
351 /// Remove all nodes from the folding set.
352 LLVM_ABI void clear();
353
354 /// Returns the number of nodes in the folding set.
355 unsigned size() const { return NumNodes; }
356
357 /// Returns true if there are no nodes in the folding set.
358 [[nodiscard]] bool empty() const { return NumNodes == 0; }
359
360 /// Grow the number of buckets so that we can hold at least \p N nodes
361 /// before rebucketing. May allocate more space than requested.
362 LLVM_ABI void reserve(unsigned N);
363
364protected:
365 /// Functions provided by the derived class to compute folding properties.
366 /// This is effectively a vtable for FoldingSetBase, except that we don't
367 /// actually store a pointer to it in the object.
369 /// Instantiations of the FoldingSet template implement this function to
370 /// gather data bits for the given node.
371 void (*GetNodeProfile)(const FoldingSetBase *Self, Node *N,
372 FoldingSetNodeID &ID);
373
374 /// Instantiations of the FoldingSet template implement this function to
375 /// compare the given node with the given ID.
377 const FoldingSetNodeID &ID, FoldingSetNodeID &TempID);
378 };
379
380private:
381 /// Put \p N in the first empty slot following its home, without checking
382 /// capacity. Does not touch \p N, so a rehash need not dirty every node.
383 void placeNode(Node *N, uint32_t Hash);
384
385 /// Compare \p N against \p ID. Out of line to keep FoldingSetNodeID's inline
386 /// storage out of the probe loop's frame.
387 static bool nodeEquals(const FoldingSetInfo &Info, const FoldingSetBase *Self,
388 Node *N, const FoldingSetNodeID &ID);
389
390 /// Rehash into at least \p MinNumBuckets buckets, rounded up to a power of
391 /// two and floored at the constructor's minimum.
392 void grow(unsigned MinNumBuckets);
393
394protected:
395 // The below methods are protected to encourage subclasses to provide a more
396 // type-safe API.
397
398 /// Remove a node from the folding set, returning true if one
399 /// was removed or false if the node was not in the folding set.
400 LLVM_ABI bool RemoveNode(Node *N);
401
402 /// If there is an existing node exactly equal to the node \p N,
403 /// return it. Otherwise, insert \p N and return it instead.
405
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.
410 const FoldingSetInfo &Info);
412 void *&InsertPos,
413 const FoldingSetInfo &Info);
414
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.
419 LLVM_ABI void InsertNode(Node *N, void *InsertPos);
420};
421
422// Convenience type to hide the implementation of the folding set.
424template <class T> class FoldingSetIterator;
425
426// Definitions of FoldingSetTrait and ContextualFoldingSetTrait functions, which
427// require the definition of FoldingSetNodeID.
428template <typename T>
430 FoldingSetNodeID &TempID) {
432 return TempID == ID;
433}
434template <typename T, typename Ctx>
436 T &X, const FoldingSetNodeID &ID, FoldingSetNodeID &TempID, Ctx Context) {
438 return TempID == ID;
439}
440
441//===----------------------------------------------------------------------===//
442/// An implementation detail that lets us share code between FoldingSet and
443/// ContextualFoldingSet.
444template <class T, class Trait = FoldingSetTrait<T>>
445class FoldingSetImpl : public FoldingSetBase, public Trait::ContextStorage {
446 // We define Info inside a static member function rather than as a static
447 // constexpr member variable to avoid eager instantiation on MSVC when T is an
448 // incomplete type.
449 static const FoldingSetBase::FoldingSetInfo &getFoldingSetInfo() {
450 static constexpr FoldingSetBase::FoldingSetInfo Info = {
451 // GetNodeProfile
453 FoldingSetNodeID &ID) {
454 if constexpr (std::is_empty_v<typename Trait::ContextStorage>)
455 Trait::Profile(*static_cast<T *>(N), ID);
456 else
457 Trait::Profile(
458 *static_cast<T *>(N), ID,
459 static_cast<const FoldingSetImpl *>(Base)->getContext());
460 },
461 // NodeEquals
463 const FoldingSetNodeID &ID, FoldingSetNodeID &TempID) {
464 if constexpr (std::is_empty_v<typename Trait::ContextStorage>)
465 return Trait::Equals(*static_cast<T *>(N), ID, TempID);
466 else
467 return Trait::Equals(
468 *static_cast<T *>(N), ID, TempID,
469 static_cast<const FoldingSetImpl *>(Base)->getContext());
470 }};
471 return Info;
472 }
473
474public:
475 explicit FoldingSetImpl(unsigned Log2InitSize = 6)
476 : FoldingSetBase(Log2InitSize) {}
477
478 template <typename C, typename = std::enable_if_t<std::is_constructible_v<
479 typename Trait::ContextStorage, C>>>
480 explicit FoldingSetImpl(C &&Context, unsigned Log2InitSize = 6)
481 : FoldingSetBase(Log2InitSize),
482 Trait::ContextStorage(std::forward<C>(Context)) {}
483
486 ~FoldingSetImpl() = default;
487
488public:
490
493 return iterator(Buckets + NumBuckets, Buckets + NumBuckets, this);
494 }
495
497
499 return const_iterator(Buckets, Buckets + NumBuckets, this);
500 }
503 }
504
505 /// Remove a node from the folding set, returning true if one
506 /// was removed or false if the node was not in the folding set.
508 bool RemoveNode(T *N) { return erase(N); }
509
510 /// If there is an existing node exactly equal to the specified node,
511 /// return it. Otherwise, insert 'N' and return it instead.
513 return static_cast<T *>(
514 FoldingSetBase::GetOrInsertNode(N, getFoldingSetInfo()));
515 }
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 FoldingSetBase::lookup(ID, Token, getFoldingSetInfo()));
523 }
524 T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) {
525 return static_cast<T *>(FoldingSetBase::FindNodeOrInsertPos(
526 ID, InsertPos, getFoldingSetInfo()));
527 }
528
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.
534 }
535 void InsertNode(T *N, void *InsertPos) {
536 FoldingSetBase::InsertNode(N, InsertPos);
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 void InsertNode(T *N) { insert(N); }
547};
548
549//===----------------------------------------------------------------------===//
550/// This template class is used to instantiate a specialized
551/// implementation of the folding set to the node class T. T must be a
552/// subclass of FoldingSetNode and implement a Profile function.
553///
554/// Note that this set type is movable and move-assignable. However, its
555/// moved-from state is not a valid state for anything other than
556/// move-assigning and destroying. This is primarily to enable movable APIs
557/// that incorporate these objects.
558template <class T, class Trait = FoldingSetTrait<T>>
560
561//===----------------------------------------------------------------------===//
562/// This template class is a further refinement of FoldingSet which provides a
563/// context argument when calling Profile on its nodes. Currently, that
564/// argument is fixed at initialization time.
565///
566/// T must be a subclass of FoldingSetNode and implement a Profile
567/// function with signature
568/// void Profile(FoldingSetNodeID &, Ctx);
569template <class T, class Ctx>
572
573//===----------------------------------------------------------------------===//
574/// This template class combines a FoldingSet and a vector to provide the
575/// interface of FoldingSet but with deterministic iteration order based on the
576/// insertion order. T must be a subclass of FoldingSetNode and implement a
577/// Profile function.
578template <class T, class VectorT = SmallVector<T *, 8>> class FoldingSetVector {
579 FoldingSet<T> Set;
580 VectorT Vector;
581
582public:
583 explicit FoldingSetVector(unsigned Log2InitSize = 6) : Set(Log2InitSize) {}
584
586
587 iterator begin() { return Vector.begin(); }
588 iterator end() { return Vector.end(); }
589
591
592 const_iterator begin() const { return Vector.begin(); }
593 const_iterator end() const { return Vector.end(); }
594
595 /// Remove all nodes from the folding set.
596 void clear() {
597 Set.clear();
598 Vector.clear();
599 }
600
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.
604 return Set.lookup(ID, Token);
605 }
606 T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) {
607 return Set.FindNodeOrInsertPos(ID, InsertPos);
608 }
609
610 /// If there is an existing node exactly equal to the specified node,
611 /// return it. Otherwise, insert 'N' and return it instead.
613 T *Result = Set.getOrInsert(N);
614 if (Result == N)
615 Vector.push_back(N);
616 return Result;
617 }
619
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.
624 Set.insert(N, Token);
625 Vector.push_back(N);
626 }
627 void InsertNode(T *N, void *InsertPos) {
628 Set.InsertNode(N, InsertPos);
629 Vector.push_back(N);
630 }
631
632 /// Insert the specified node into the folding set, knowing that
633 /// it is not already in the folding set.
634 void insert(T *N) {
635 Set.insert(N);
636 Vector.push_back(N);
637 }
638 void InsertNode(T *N) { insert(N); }
639
640 /// Returns the number of nodes in the folding set.
641 unsigned size() const { return Set.size(); }
642
643 /// Returns true if there are no nodes in the folding set.
644 [[nodiscard]] bool empty() const { return Set.empty(); }
645};
646
647//===----------------------------------------------------------------------===//
648/// Forward iterator for FoldingSet and ContextualFoldingSet.
650 void **Bucket = nullptr;
651 void **End = nullptr;
652
653 void advance() {
654 assert(isHandleInSync() && "invalid iterator access!");
655 do
656 ++Bucket;
657 while (Bucket != End && *Bucket == nullptr);
658 }
659
660public:
661 FoldingSetIterator(void **Bucket, void **End, const DebugEpochBase *Epoch)
662 : DebugEpochBase::HandleBase(Epoch), Bucket(Bucket), End(End) {
663 while (this->Bucket != this->End && *this->Bucket == nullptr)
664 ++this->Bucket;
665 }
666
667 T &operator*() const {
668 assert(isHandleInSync() && "invalid iterator access!");
669 return *static_cast<T *>(static_cast<FoldingSetNode *>(*Bucket));
670 }
671
672 T *operator->() const { return &operator*(); }
673
674 inline FoldingSetIterator &operator++() { // Preincrement
675 advance();
676 return *this;
677 }
678 FoldingSetIterator operator++(int) { // Postincrement
679 FoldingSetIterator tmp = *this;
680 ++*this;
681 return tmp;
682 }
683
684 bool operator==(const FoldingSetIterator &RHS) const {
685 assert(isComparableWith(RHS) && "incomparable iterators!");
686 return Bucket == RHS.Bucket;
687 }
688 bool operator!=(const FoldingSetIterator &RHS) const {
689 return !(*this == RHS);
690 }
691};
692
693//===----------------------------------------------------------------------===//
694/// This template class is used to "wrap" arbitrary types in an enclosing object
695/// so that they can be inserted into FoldingSets.
696template <typename T> class FoldingSetNodeWrapper : public FoldingSetNode {
697 T data;
698
699public:
700 template <typename... Ts>
701 explicit FoldingSetNodeWrapper(Ts &&...Args)
702 : data(std::forward<Ts>(Args)...) {}
703
705
706 T &getValue() { return data; }
707 const T &getValue() const { return data; }
708
709 operator T &() { return data; }
710 operator const T &() const { return data; }
711};
712
713//===----------------------------------------------------------------------===//
714/// This is a subclass of FoldingSetNode which stores a FoldingSetNodeID value
715/// rather than requiring the node to recompute it each time it is needed. This
716/// trades space for speed (which can be significant if the ID is long), and it
717/// also permits nodes to drop information that would otherwise only be required
718/// for recomputing an ID.
720 FoldingSetNodeID FastID;
721
722protected:
723 explicit FastFoldingSetNode(const FoldingSetNodeID &ID) : FastID(ID) {}
724
725public:
726 void Profile(FoldingSetNodeID &ID) const { ID.AddNodeID(FastID); }
727};
728
729//===----------------------------------------------------------------------===//
730// Partial specializations of FoldingSetTrait.
731
732template <typename T> struct FoldingSetTrait<T *> {
733 static inline void Profile(T *X, FoldingSetNodeID &ID) { ID.AddPointer(X); }
734};
735template <typename T1, typename T2> struct FoldingSetTrait<std::pair<T1, T2>> {
736 static inline void Profile(const std::pair<T1, T2> &P, FoldingSetNodeID &ID) {
737 ID.Add(P.first);
738 ID.Add(P.second);
739 }
740};
741
742template <typename T>
743struct FoldingSetTrait<T, std::enable_if_t<std::is_enum<T>::value>> {
744 static void Profile(const T &X, FoldingSetNodeID &ID) {
745 ID.AddInteger(llvm::to_underlying(X));
746 }
747};
748
749} // namespace llvm
750
751#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< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_ABI
Definition Compiler.h:215
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
static unsigned getSize(unsigned Kind)
bool isComparableWith(const HandleBase &) const
FastFoldingSetNode(const FoldingSetNodeID &ID)
Definition FoldingSet.h:723
void Profile(FoldingSetNodeID &ID) const
Definition FoldingSet.h:726
This class is used to maintain node state in a folding set.
Definition FoldingSet.h:337
uint32_t getFoldingSetHash() const
Definition FoldingSet.h:347
void setFoldingSetHash(uint32_t Hash)
Definition FoldingSet.h:348
Non-templated base class for FoldingSet and ContextualFoldingSet, holding the memory management and p...
Definition FoldingSet.h:318
void ** Buckets
Array of node pointers; a null entry marks an empty slot.
Definition FoldingSet.h:321
unsigned size() const
Returns the number of nodes in the folding set.
Definition FoldingSet.h:355
LLVM_ABI bool RemoveNode(Node *N)
Remove a node from the folding set, returning true if one was removed or false if the node was not in...
LLVM_ABI FoldingSetBase & operator=(FoldingSetBase &&RHS)
LLVM_ABI Node * lookup(const FoldingSetNodeID &ID, FoldingSetInsertToken &Token, const FoldingSetInfo &Info)
Look up the node specified by ID.
LLVM_ABI ~FoldingSetBase()
unsigned NumBuckets
Length of the Buckets array. Always a power of 2.
Definition FoldingSet.h:324
unsigned NumNodes
Number of nodes in the folding set.
Definition FoldingSet.h:327
LLVM_ABI Node * GetOrInsertNode(Node *N, const FoldingSetInfo &Info)
If there is an existing node exactly equal to the node N, return it.
bool empty() const
Returns true if there are no nodes in the folding set.
Definition FoldingSet.h:358
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 insert(Node *N, FoldingSetInsertToken Token)
Insert the specified node into the folding set, knowing that it is not already in the folding set.
LLVM_ABI void InsertNode(Node *N, void *InsertPos)
LLVM_ABI void clear()
Remove all nodes from the folding set.
LLVM_ABI Node * FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos, const FoldingSetInfo &Info)
LLVM_ABI FoldingSetBase(unsigned Log2InitSize)
An implementation detail that lets us share code between FoldingSet and ContextualFoldingSet.
Definition FoldingSet.h:445
FoldingSetImpl(FoldingSetImpl &&Arg)=default
FoldingSetImpl(C &&Context, unsigned Log2InitSize=6)
Definition FoldingSet.h:480
const_iterator begin() const
Definition FoldingSet.h:498
FoldingSetImpl & operator=(FoldingSetImpl &&RHS)=default
FoldingSetIterator< const T > const_iterator
Definition FoldingSet.h:496
void insert(T *N, FoldingSetInsertToken Token)
Definition FoldingSet.h:532
const_iterator end() const
Definition FoldingSet.h:501
FoldingSetIterator< T > iterator
Definition FoldingSet.h:489
FoldingSetImpl(unsigned Log2InitSize=6)
Definition FoldingSet.h:475
T * FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos)
Definition FoldingSet.h:524
void InsertNode(T *N, void *InsertPos)
Definition FoldingSet.h:535
T * lookup(const FoldingSetNodeID &ID, FoldingSetInsertToken &Token)
Definition FoldingSet.h:520
Insertion token: a failed lookup fills it in, the matching insert consumes it.
Definition FoldingSet.h:292
friend bool operator!=(FoldingSetInsertToken A, FoldingSetInsertToken B)
Definition FoldingSet.h:310
friend bool operator==(FoldingSetInsertToken A, FoldingSetInsertToken B)
Definition FoldingSet.h:307
Forward iterator for FoldingSet and ContextualFoldingSet.
Definition FoldingSet.h:649
bool operator==(const FoldingSetIterator &RHS) const
Definition FoldingSet.h:684
FoldingSetIterator operator++(int)
Definition FoldingSet.h:678
bool operator!=(const FoldingSetIterator &RHS) const
Definition FoldingSet.h:688
FoldingSetIterator(void **Bucket, void **End, const DebugEpochBase *Epoch)
Definition FoldingSet.h:661
FoldingSetIterator & operator++()
Definition FoldingSet.h:674
This class describes a reference to an interned FoldingSetNodeID, which can be a useful to store node...
Definition FoldingSet.h:167
unsigned computeStableHash() const
Definition FoldingSet.h:189
LLVM_ABI bool operator==(FoldingSetNodeIDRef) const
FoldingSetNodeIDRef(const unsigned *D, size_t S)
Definition FoldingSet.h:173
LLVM_ABI bool operator<(FoldingSetNodeIDRef) const
Used to compare the "ordering" of two nodes as defined by the profiled bits and their ordering define...
bool operator!=(FoldingSetNodeIDRef RHS) const
Definition FoldingSet.h:196
unsigned ComputeHash() const
Definition FoldingSet.h:181
const unsigned * getData() const
Definition FoldingSet.h:202
static constexpr unsigned NotAHash
Definition FoldingSet.h:175
This class is used to gather all the unique data bits of a node.
Definition FoldingSet.h:210
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:239
void AddInteger(unsigned long I)
Definition FoldingSet.h:242
FoldingSetNodeID(FoldingSetNodeIDRef Ref)
Definition FoldingSet.h:226
unsigned computeStableHash() const
Definition FoldingSet.h:266
void AddPointer(const void *Ptr)
Add* - Add various data types to Bit data.
Definition FoldingSet.h:230
bool operator!=(const FoldingSetNodeIDRef RHS) const
Definition FoldingSet.h:275
void clear()
Clear the accumulated profile, allowing this FoldingSetNodeID object to be used to compute a new prof...
Definition FoldingSet.h:255
void AddInteger(unsigned I)
Definition FoldingSet.h:240
void AddInteger(long I)
Definition FoldingSet.h:241
void AddBoolean(bool B)
Definition FoldingSet.h:245
LLVM_ABI bool operator==(const FoldingSetNodeID &RHS) const
operator== - Used to compare two nodes to each other.
bool operator!=(const FoldingSetNodeID &RHS) const
Definition FoldingSet.h:274
void AddInteger(unsigned long long I)
Definition FoldingSet.h:244
void AddInteger(long long I)
Definition FoldingSet.h:243
unsigned ComputeHash() const
Definition FoldingSet.h:260
LLVM_ABI bool operator<(const FoldingSetNodeID &RHS) const
Used to compare the "ordering" of two nodes as defined by the profiled bits and their ordering define...
LLVM_ABI void AddNodeID(const FoldingSetNodeID &ID)
void Add(const T &x)
Definition FoldingSet.h:249
LLVM_ABI void AddString(StringRef String)
const T & getValue() const
Definition FoldingSet.h:707
FoldingSetNodeWrapper(Ts &&...Args)
Definition FoldingSet.h:701
void Profile(FoldingSetNodeID &ID)
Definition FoldingSet.h:704
const_iterator end() const
Definition FoldingSet.h:593
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:634
T * FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos)
Definition FoldingSet.h:606
unsigned size() const
Returns the number of nodes in the folding set.
Definition FoldingSet.h:641
pointee_iterator< typename VectorT::const_iterator > const_iterator
Definition FoldingSet.h:590
T * lookup(const FoldingSetNodeID &ID, FoldingSetInsertToken &Token)
Look up the node specified by ID.
Definition FoldingSet.h:603
pointee_iterator< typename VectorT::iterator > iterator
Definition FoldingSet.h:585
void clear()
Remove all nodes from the folding set.
Definition FoldingSet.h:596
bool empty() const
Returns true if there are no nodes in the folding set.
Definition FoldingSet.h:644
FoldingSetVector(unsigned Log2InitSize=6)
Definition FoldingSet.h:583
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:623
T * getOrInsert(T *N)
If there is an existing node exactly equal to the specified node, return it.
Definition FoldingSet.h:612
void InsertNode(T *N, void *InsertPos)
Definition FoldingSet.h:627
const_iterator begin() const
Definition FoldingSet.h:592
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
This is an optimization pass for GlobalISel generic memory operations.
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
FoldingSetBase::Node FoldingSetNode
Definition FoldingSet.h:423
constexpr std::underlying_type_t< Enum > to_underlying(Enum E)
Returns underlying integer value of an enum.
@ 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:570
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
Definition Allocator.h:390
hash_code hash_combine_range(InputIteratorT first, InputIteratorT last)
Compute a hash_code for a sequence of values.
Definition Hashing.h:285
FoldingSetImpl< T, Trait > FoldingSet
This template class is used to instantiate a specialized implementation of the folding set to the nod...
Definition FoldingSet.h:559
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:159
Like DefaultFoldingSetTrait, but for ContextualFoldingSets.
Definition FoldingSet.h:142
static bool Equals(T &X, const FoldingSetNodeID &ID, FoldingSetNodeID &TempID, Ctx Context)
Definition FoldingSet.h:435
static void Profile(T &X, FoldingSetNodeID &ID, Ctx Context)
Definition FoldingSet.h:149
This class provides default implementations for FoldingSetTrait implementations.
Definition FoldingSet.h:118
static bool Equals(T &X, const FoldingSetNodeID &ID, FoldingSetNodeID &TempID)
Definition FoldingSet.h:429
static void Profile(const T &X, FoldingSetNodeID &ID)
Definition FoldingSet.h:121
static void Profile(T &X, FoldingSetNodeID &ID)
Definition FoldingSet.h:122
Functions provided by the derived class to compute folding properties.
Definition FoldingSet.h:368
void(* GetNodeProfile)(const FoldingSetBase *Self, Node *N, FoldingSetNodeID &ID)
Instantiations of the FoldingSet template implement this function to gather data bits for the given n...
Definition FoldingSet.h:371
bool(* NodeEquals)(const FoldingSetBase *Self, Node *N, const FoldingSetNodeID &ID, FoldingSetNodeID &TempID)
Instantiations of the FoldingSet template implement this function to compare the given node with the ...
Definition FoldingSet.h:376
static void Profile(T *X, FoldingSetNodeID &ID)
Definition FoldingSet.h:733
static void Profile(const std::pair< T1, T2 > &P, FoldingSetNodeID &ID)
Definition FoldingSet.h:736
This trait class is used to define behavior of how to "profile" (in the FoldingSet parlance) an objec...
Definition FoldingSet.h:139
An iterator type that allows iterating over the pointees via some other iterator.
Definition iterator.h:329