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 the bucket it should be inserted into.
39/// 2. Given a node that has already been created, remove it from the set.
40///
41/// This class is implemented as a single-link chained hash table, where the
42/// "buckets" are actually the nodes themselves (the next pointer is in the
43/// node). The last node points back to the bucket to simplify node removal.
44///
45/// Any node that is to be included in the folding set must be a subclass of
46/// FoldingSetNode. The node class must also define a Profile method used to
47/// establish the unique bits of data for the node. The Profile method is
48/// passed a FoldingSetNodeID object which is used to gather the bits. Just
49/// call one of the Add* functions defined in the FoldingSetNodeID class.
50/// NOTE: That the folding set does not own the nodes and it is the
51/// responsibility of the user to dispose of the nodes.
52///
53/// Eg.
54/// class MyNode : public FoldingSetNode {
55/// private:
56/// std::string Name;
57/// unsigned Value;
58/// public:
59/// MyNode(const char *N, unsigned V) : Name(N), Value(V) {}
60/// ...
61/// void Profile(FoldingSetNodeID &ID) const {
62/// ID.AddString(Name);
63/// ID.AddInteger(Value);
64/// }
65/// ...
66/// };
67///
68/// To define the folding set itself use the FoldingSet template;
69///
70/// Eg.
71/// FoldingSet<MyNode> MyFoldingSet;
72///
73/// Four public methods are available to manipulate the folding set;
74///
75/// 1) If you have an existing node that you want add to the set but unsure
76/// that the node might already exist then call;
77///
78/// MyNode *M = MyFoldingSet.GetOrInsertNode(N);
79///
80/// If The result is equal to the input then the node has been inserted.
81/// Otherwise, the result is the node existing in the folding set, and the
82/// input can be discarded (use the result instead.)
83///
84/// 2) If you are ready to construct a node but want to check if it already
85/// exists, then call FindNodeOrInsertPos with a FoldingSetNodeID of the bits to
86/// check;
87///
88/// FoldingSetNodeID ID;
89/// ID.AddString(Name);
90/// ID.AddInteger(Value);
91/// void *InsertPoint;
92///
93/// MyNode *M = MyFoldingSet.FindNodeOrInsertPos(ID, InsertPoint);
94///
95/// If found then M will be non-NULL, else InsertPoint will point to where it
96/// should be inserted using InsertNode.
97///
98/// 3) If you get a NULL result from FindNodeOrInsertPos then you can insert a
99/// new node with InsertNode;
100///
101/// MyNode *N = new MyNode(Name, Value);
102/// MyFoldingSet.InsertNode(N, InsertPoint);
103///
104/// 4) Finally, if you want to remove a node from the folding set call;
105///
106/// bool WasRemoved = MyFoldingSet.RemoveNode(M);
107///
108/// The result indicates whether the node existed in the folding set.
109
110class FoldingSetNodeID;
111class StringRef;
112
113//===----------------------------------------------------------------------===//
114
115/// This class provides default implementations for FoldingSetTrait
116/// implementations.
117template <typename T> struct DefaultFoldingSetTrait {
118 struct ContextStorage {};
119
120 static void Profile(const T &X, FoldingSetNodeID &ID) { X.Profile(ID); }
121 static void Profile(T &X, FoldingSetNodeID &ID) { X.Profile(ID); }
122
123 // Equals - Test if the profile for X would match ID, using TempID
124 // to compute a temporary ID if necessary. The default implementation
125 // just calls Profile and does a regular comparison. Implementations
126 // can override this to provide more efficient implementations.
127 static inline bool Equals(T &X, const FoldingSetNodeID &ID, unsigned IDHash,
128 FoldingSetNodeID &TempID);
129
130 // ComputeHash - Compute a hash value for X, using TempID to
131 // compute a temporary ID if necessary. The default implementation
132 // just calls Profile and does a regular hash computation.
133 // Implementations can override this to provide more efficient
134 // implementations.
135 static inline unsigned ComputeHash(T &X, FoldingSetNodeID &TempID);
136};
137
138/// This trait class is used to define behavior of how to "profile" (in the
139/// FoldingSet parlance) an object of a given type.
140/// The default behavior is to invoke a 'Profile' method on an object, but
141/// through template specialization the behavior can be tailored for specific
142/// types. Combined with the FoldingSetNodeWrapper class, one can add objects
143/// to FoldingSets that were not originally designed to have that behavior.
144template <typename T, typename Enable = void>
146
147/// Like DefaultFoldingSetTrait, but for ContextualFoldingSets.
148template <typename T, typename Ctx> struct DefaultContextualFoldingSetTrait {
152 Ctx getContext() const { return Context; }
153 };
154
155 static void Profile(T &X, FoldingSetNodeID &ID, Ctx Context) {
156 X.Profile(ID, Context);
157 }
158
159 static inline bool Equals(T &X, const FoldingSetNodeID &ID, unsigned IDHash,
160 FoldingSetNodeID &TempID, Ctx Context);
161 static inline unsigned ComputeHash(T &X, FoldingSetNodeID &TempID,
162 Ctx Context);
163};
164
165/// Like FoldingSetTrait, but for ContextualFoldingSets.
166template <typename T, typename Ctx>
168
169//===--------------------------------------------------------------------===//
170/// This class describes a reference to an interned FoldingSetNodeID, which can
171/// be a useful to store node id data rather than using plain FoldingSetNodeIDs,
172/// since the 32-element SmallVector is often much larger than necessary, and
173/// the possibility of heap allocation means it requires a non-trivial
174/// destructor call.
176 const unsigned *Data = nullptr;
177 size_t Size = 0;
178
179public:
181 FoldingSetNodeIDRef(const unsigned *D, size_t S) : Data(D), Size(S) {}
182
183 // Compute a strong hash value used to lookup the node in the FoldingSetBase.
184 // The hash value is not guaranteed to be deterministic across processes.
185 unsigned ComputeHash() const {
186 return static_cast<unsigned>(hash_combine_range(Data, Data + Size));
187 }
188
189 // Compute a deterministic hash value across processes that is suitable for
190 // on-disk serialization.
191 unsigned computeStableHash() const {
192 return static_cast<unsigned>(xxh3_64bits(
193 reinterpret_cast<const uint8_t *>(Data), sizeof(unsigned) * Size));
194 }
195
197
198 bool operator!=(FoldingSetNodeIDRef RHS) const { return !(*this == RHS); }
199
200 /// Used to compare the "ordering" of two nodes as defined by the
201 /// profiled bits and their ordering defined by memcmp().
203
204 const unsigned *getData() const { return Data; }
205 size_t getSize() const { return Size; }
206};
207
208//===--------------------------------------------------------------------===//
209/// This class is used to gather all the unique data bits of a node. When all
210/// the bits are gathered this class is used to produce a hash value for the
211/// node.
213 /// Vector of all the data bits that make the node unique.
214 /// Use a SmallVector to avoid a heap allocation in the common case.
216
217 template <typename T> void AddIntegerImpl(T I) {
218 static_assert(std::is_integral_v<T> && sizeof(T) <= sizeof(unsigned) * 2,
219 "T must be an integer type no wider than 64 bits");
220 Bits.push_back(static_cast<unsigned>(I));
221 if constexpr (sizeof(unsigned) < sizeof(T))
222 Bits.push_back(static_cast<unsigned long long>(I) >> 32);
223 }
224
225public:
226 FoldingSetNodeID() = default;
227
229 : Bits(Ref.getData(), Ref.getData() + Ref.getSize()) {}
230
231 /// Add* - Add various data types to Bit data.
232 void AddPointer(const void *Ptr) {
233 // Note: this adds pointers to the hash using sizes and endianness that
234 // depend on the host. It doesn't matter, however, because hashing on
235 // pointer values is inherently unstable. Nothing should depend on the
236 // ordering of nodes in the folding set.
237 static_assert(sizeof(uintptr_t) <= sizeof(unsigned long long),
238 "unexpected pointer size");
239 AddInteger(reinterpret_cast<uintptr_t>(Ptr));
240 }
241 void AddInteger(signed I) { AddIntegerImpl(I); }
242 void AddInteger(unsigned I) { AddIntegerImpl(I); }
243 void AddInteger(long I) { AddIntegerImpl(I); }
244 void AddInteger(unsigned long I) { AddIntegerImpl(I); }
245 void AddInteger(long long I) { AddIntegerImpl(I); }
246 void AddInteger(unsigned long long I) { AddIntegerImpl(I); }
247 void AddBoolean(bool B) { AddInteger(B ? 1U : 0U); }
249 LLVM_ABI void AddNodeID(const FoldingSetNodeID &ID);
250
251 template <typename T> inline void Add(const T &x) {
253 }
254
255 /// Clear the accumulated profile, allowing this FoldingSetNodeID
256 /// object to be used to compute a new profile.
257 inline void clear() { Bits.clear(); }
258
259 // Compute a strong hash value for this FoldingSetNodeID, used to lookup the
260 // node in the FoldingSetBase. The hash value is not guaranteed to be
261 // deterministic across processes.
262 unsigned ComputeHash() const {
263 return FoldingSetNodeIDRef(Bits.data(), Bits.size()).ComputeHash();
264 }
265
266 // Compute a deterministic hash value across processes that is suitable for
267 // on-disk serialization.
268 unsigned computeStableHash() const {
269 return FoldingSetNodeIDRef(Bits.data(), Bits.size()).computeStableHash();
270 }
271
272 /// operator== - Used to compare two nodes to each other.
273 LLVM_ABI bool operator==(const FoldingSetNodeID &RHS) const;
274 LLVM_ABI bool operator==(const FoldingSetNodeIDRef RHS) const;
275
276 bool operator!=(const FoldingSetNodeID &RHS) const { return !(*this == RHS); }
278 return !(*this == RHS);
279 }
280
281 /// Used to compare the "ordering" of two nodes as defined by the
282 /// profiled bits and their ordering defined by memcmp().
283 LLVM_ABI bool operator<(const FoldingSetNodeID &RHS) const;
284 LLVM_ABI bool operator<(const FoldingSetNodeIDRef RHS) const;
285
286 /// Copy this node's data to a memory region allocated from the
287 /// given allocator and return a FoldingSetNodeIDRef describing the
288 /// interned data.
290};
291
292//===----------------------------------------------------------------------===//
293/// Implements the folding set functionality. The main structure is an array of
294/// buckets. Each bucket is indexed by the hash of the nodes it contains. The
295/// bucket itself points to the nodes contained in the bucket via a singly
296/// linked list. The last node in the list points back to the bucket to
297/// facilitate node removal.
298///
300protected:
301 /// Array of bucket chains.
302 void **Buckets;
303
304 /// Length of the Buckets array. Always a power of 2.
305 unsigned NumBuckets;
306
307 /// Number of nodes in the folding set. Growth occurs when NumNodes
308 /// is greater than twice the number of buckets.
309 unsigned NumNodes;
310
311 LLVM_ABI explicit FoldingSetBase(unsigned Log2InitSize);
315
316public:
317 //===--------------------------------------------------------------------===//
318 /// This class is used to maintain the singly linked bucket list in
319 /// a folding set.
320 class Node {
321 private:
322 // NextInFoldingSetBucket - next link in the bucket list.
323 void *NextInFoldingSetBucket = nullptr;
324
325 public:
326 Node() = default;
327
328 // Accessors
329 void *getNextInBucket() const { return NextInFoldingSetBucket; }
330 void SetNextInBucket(void *N) { NextInFoldingSetBucket = N; }
331 };
332
333 /// Remove all nodes from the folding set.
334 LLVM_ABI void clear();
335
336 /// Returns the number of nodes in the folding set.
337 unsigned size() const { return NumNodes; }
338
339 /// Returns true if there are no nodes in the folding set.
340 [[nodiscard]] bool empty() const { return NumNodes == 0; }
341
342 /// Returns the number of nodes permitted in the folding set
343 /// before a rebucket operation is performed.
344 unsigned capacity() const {
345 // We allow a load factor of up to 2.0,
346 // so that means our capacity is NumBuckets * 2
347 return NumBuckets * 2;
348 }
349
350protected:
351 /// Functions provided by the derived class to compute folding properties.
352 /// This is effectively a vtable for FoldingSetBase, except that we don't
353 /// actually store a pointer to it in the object.
355 /// Instantiations of the FoldingSet template implement this function to
356 /// gather data bits for the given node.
357 void (*GetNodeProfile)(const FoldingSetBase *Self, Node *N,
358 FoldingSetNodeID &ID);
359
360 /// Instantiations of the FoldingSet template implement this function to
361 /// compare the given node with the given ID.
363 const FoldingSetNodeID &ID, unsigned IDHash,
364 FoldingSetNodeID &TempID);
365
366 /// Instantiations of the FoldingSet template implement this function to
367 /// compute a hash value for the given node.
369 FoldingSetNodeID &TempID);
370 };
371
372private:
373 /// Resize the hash table and rehash everything. \p NewBucketCount must be a
374 /// power of two, and must be greater than the old bucket count.
375 void GrowBucketCount(unsigned NewBucketCount, const FoldingSetInfo &Info);
376
377protected:
378 // The below methods are protected to encourage subclasses to provide a more
379 // type-safe API.
380
381 /// Grow the number of buckets so that we can hold at least \p EltCount
382 /// nodes before rebucketing. May allocate more space than requested.
383 LLVM_ABI void reserve(unsigned EltCount, const FoldingSetInfo &Info);
384
385 /// Remove a node from the folding set, returning true if one
386 /// was removed or false if the node was not in the folding set.
387 LLVM_ABI bool RemoveNode(Node *N);
388
389 /// If there is an existing node exactly equal to the node \p N,
390 /// return it. Otherwise, insert \p N and return it instead.
392
393 /// Look up the node specified by ID. If it exists, return it. If not,
394 /// return the insertion token that will make insertion faster.
396 void *&InsertPos,
397 const FoldingSetInfo &Info);
398
399 /// Insert the specified node into the folding set, knowing that
400 /// it is not already in the folding set. InsertPos must be obtained from
401 /// FindNodeOrInsertPos.
402 LLVM_ABI void InsertNode(Node *N, void *InsertPos,
403 const FoldingSetInfo &Info);
404};
405
406// Convenience type to hide the implementation of the folding set.
408template <class T> class FoldingSetIterator;
409
410// Definitions of FoldingSetTrait and ContextualFoldingSetTrait functions, which
411// require the definition of FoldingSetNodeID.
412template <typename T>
414 unsigned /*IDHash*/,
415 FoldingSetNodeID &TempID) {
417 return TempID == ID;
418}
419template <typename T>
420inline unsigned
425template <typename T, typename Ctx>
427 T &X, const FoldingSetNodeID &ID, unsigned /*IDHash*/,
428 FoldingSetNodeID &TempID, Ctx Context) {
430 return TempID == ID;
431}
432template <typename T, typename Ctx>
434 T &X, FoldingSetNodeID &TempID, Ctx Context) {
436 return TempID.ComputeHash();
437}
438
439//===----------------------------------------------------------------------===//
440/// An implementation detail that lets us share code between FoldingSet and
441/// ContextualFoldingSet.
442template <class T, class Trait = FoldingSetTrait<T>>
443class FoldingSetImpl : public FoldingSetBase, public Trait::ContextStorage {
444 // We define Info inside a static member function rather than as a static
445 // constexpr member variable to avoid eager instantiation on MSVC when T is an
446 // incomplete type.
447 static const FoldingSetBase::FoldingSetInfo &getFoldingSetInfo() {
448 static constexpr FoldingSetBase::FoldingSetInfo Info = {
449 // GetNodeProfile
451 FoldingSetNodeID &ID) {
452 if constexpr (std::is_empty_v<typename Trait::ContextStorage>)
453 Trait::Profile(*static_cast<T *>(N), ID);
454 else
455 Trait::Profile(
456 *static_cast<T *>(N), ID,
457 static_cast<const FoldingSetImpl *>(Base)->getContext());
458 },
459 // NodeEquals
461 const FoldingSetNodeID &ID, unsigned IDHash,
462 FoldingSetNodeID &TempID) {
463 if constexpr (std::is_empty_v<typename Trait::ContextStorage>)
464 return Trait::Equals(*static_cast<T *>(N), ID, IDHash, TempID);
465 else
466 return Trait::Equals(
467 *static_cast<T *>(N), ID, IDHash, TempID,
468 static_cast<const FoldingSetImpl *>(Base)->getContext());
469 },
470 // ComputeNodeHash
472 FoldingSetNodeID &TempID) {
473 if constexpr (std::is_empty_v<typename Trait::ContextStorage>)
474 return Trait::ComputeHash(*static_cast<T *>(N), TempID);
475 else
476 return Trait::ComputeHash(
477 *static_cast<T *>(N), TempID,
478 static_cast<const FoldingSetImpl *>(Base)->getContext());
479 }};
480 return Info;
481 }
482
483public:
484 explicit FoldingSetImpl(unsigned Log2InitSize = 6)
485 : FoldingSetBase(Log2InitSize) {}
486
487 template <typename C, typename = std::enable_if_t<std::is_constructible_v<
488 typename Trait::ContextStorage, C>>>
489 explicit FoldingSetImpl(C &&Context, unsigned Log2InitSize = 6)
490 : FoldingSetBase(Log2InitSize),
491 Trait::ContextStorage(std::forward<C>(Context)) {}
492
495 ~FoldingSetImpl() = default;
496
497public:
499
500 iterator begin() { return iterator(this, Buckets); }
501 iterator end() { return iterator(this, Buckets + NumBuckets); }
502
504
505 const_iterator begin() const { return const_iterator(this, Buckets); }
507 return const_iterator(this, Buckets + NumBuckets);
508 }
509
510 /// Grow the number of buckets so that we can hold at least \p EltCount
511 /// nodes before rebucketing. May allocate more space than requested.
512 void reserve(unsigned EltCount) {
513 FoldingSetBase::reserve(EltCount, getFoldingSetInfo());
514 }
515
516 /// Remove a node from the folding set, returning true if one
517 /// was removed or false if the node was not in the folding set.
519
520 /// If there is an existing node exactly equal to the specified node,
521 /// return it. Otherwise, insert 'N' and return it instead.
523 return static_cast<T *>(
524 FoldingSetBase::GetOrInsertNode(N, getFoldingSetInfo()));
525 }
526
527 /// Look up the node specified by ID. If it exists, return it. If not,
528 /// return the insertion token that will make insertion faster.
529 T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) {
530 return static_cast<T *>(FoldingSetBase::FindNodeOrInsertPos(
531 ID, InsertPos, getFoldingSetInfo()));
532 }
533
534 /// Insert the specified node into the folding set, knowing that
535 /// it is not already in the folding set. InsertPos must be obtained from
536 /// FindNodeOrInsertPos.
537 void InsertNode(T *N, void *InsertPos) {
538 FoldingSetBase::InsertNode(N, InsertPos, getFoldingSetInfo());
539 }
540
541 /// Insert the specified node into the folding set, knowing that it is not
542 /// already in the folding set.
543 void InsertNode(T *N) {
544 T *Inserted = GetOrInsertNode(N);
545 (void)Inserted;
546 assert(Inserted == N && "Node already inserted!");
547 }
548};
549
550//===----------------------------------------------------------------------===//
551/// This template class is used to instantiate a specialized
552/// implementation of the folding set to the node class T. T must be a
553/// subclass of FoldingSetNode and implement a Profile function.
554///
555/// Note that this set type is movable and move-assignable. However, its
556/// moved-from state is not a valid state for anything other than
557/// move-assigning and destroying. This is primarily to enable movable APIs
558/// that incorporate these objects.
559template <class T, class Trait = FoldingSetTrait<T>>
561
562//===----------------------------------------------------------------------===//
563/// This template class is a further refinement of FoldingSet which provides a
564/// context argument when calling Profile on its nodes. Currently, that
565/// argument is fixed at initialization time.
566///
567/// T must be a subclass of FoldingSetNode and implement a Profile
568/// function with signature
569/// void Profile(FoldingSetNodeID &, Ctx);
570template <class T, class Ctx>
573
574//===----------------------------------------------------------------------===//
575/// This template class combines a FoldingSet and a vector to provide the
576/// interface of FoldingSet but with deterministic iteration order based on the
577/// insertion order. T must be a subclass of FoldingSetNode and implement a
578/// Profile function.
579template <class T, class VectorT = SmallVector<T *, 8>> class FoldingSetVector {
580 FoldingSet<T> Set;
581 VectorT Vector;
582
583public:
584 explicit FoldingSetVector(unsigned Log2InitSize = 6) : Set(Log2InitSize) {}
585
587
588 iterator begin() { return Vector.begin(); }
589 iterator end() { return Vector.end(); }
590
592
593 const_iterator begin() const { return Vector.begin(); }
594 const_iterator end() const { return Vector.end(); }
595
596 /// Remove all nodes from the folding set.
597 void clear() {
598 Set.clear();
599 Vector.clear();
600 }
601
602 /// Look up the node specified by ID. If it exists, return it. If not,
603 /// return the insertion token that will make insertion faster.
604 T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) {
605 return Set.FindNodeOrInsertPos(ID, InsertPos);
606 }
607
608 /// If there is an existing node exactly equal to the specified node,
609 /// return it. Otherwise, insert 'N' and return it instead.
611 T *Result = Set.GetOrInsertNode(N);
612 if (Result == N)
613 Vector.push_back(N);
614 return Result;
615 }
616
617 /// Insert the specified node into the folding set, knowing that
618 /// it is not already in the folding set. InsertPos must be obtained from
619 /// FindNodeOrInsertPos.
620 void InsertNode(T *N, void *InsertPos) {
621 Set.InsertNode(N, InsertPos);
622 Vector.push_back(N);
623 }
624
625 /// Insert the specified node into the folding set, knowing that
626 /// it is not already in the folding set.
627 void InsertNode(T *N) {
628 Set.InsertNode(N);
629 Vector.push_back(N);
630 }
631
632 /// Returns the number of nodes in the folding set.
633 unsigned size() const { return Set.size(); }
634
635 /// Returns true if there are no nodes in the folding set.
636 [[nodiscard]] bool empty() const { return Set.empty(); }
637};
638
639//===----------------------------------------------------------------------===//
640/// This is the common iterator support shared by all folding sets, which knows
641/// how to walk the folding set hash table.
643protected:
645
646 LLVM_ABI FoldingSetIteratorImpl(const DebugEpochBase *Epoch, void **Bucket);
647
648 LLVM_ABI void advance();
649
651 assert(isHandleInSync() && "invalid iterator access!");
652 return NodePtr;
653 }
654
655public:
657 assert(isHandleInSync() && RHS.isHandleInSync() && "handle not in sync!");
658 return NodePtr == RHS.NodePtr;
659 }
661 return !(*this == RHS);
662 }
663};
664
665template <class T> class FoldingSetIterator : public FoldingSetIteratorImpl {
666public:
667 explicit FoldingSetIterator(const DebugEpochBase *Epoch, void **Bucket)
668 : FoldingSetIteratorImpl(Epoch, Bucket) {}
669
670 T &operator*() const { return *static_cast<T *>(getNode()); }
671
672 T *operator->() const { return static_cast<T *>(getNode()); }
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
685//===----------------------------------------------------------------------===//
686/// This template class is used to "wrap" arbitrary types in an enclosing object
687/// so that they can be inserted into FoldingSets.
688template <typename T> class FoldingSetNodeWrapper : public FoldingSetNode {
689 T data;
690
691public:
692 template <typename... Ts>
693 explicit FoldingSetNodeWrapper(Ts &&...Args)
694 : data(std::forward<Ts>(Args)...) {}
695
697
698 T &getValue() { return data; }
699 const T &getValue() const { return data; }
700
701 operator T &() { return data; }
702 operator const T &() const { return data; }
703};
704
705//===----------------------------------------------------------------------===//
706/// This is a subclass of FoldingSetNode which stores a FoldingSetNodeID value
707/// rather than requiring the node to recompute it each time it is needed. This
708/// trades space for speed (which can be significant if the ID is long), and it
709/// also permits nodes to drop information that would otherwise only be required
710/// for recomputing an ID.
712 FoldingSetNodeID FastID;
713
714protected:
715 explicit FastFoldingSetNode(const FoldingSetNodeID &ID) : FastID(ID) {}
716
717public:
718 void Profile(FoldingSetNodeID &ID) const { ID.AddNodeID(FastID); }
719};
720
721//===----------------------------------------------------------------------===//
722// Partial specializations of FoldingSetTrait.
723
724template <typename T> struct FoldingSetTrait<T *> {
725 static inline void Profile(T *X, FoldingSetNodeID &ID) { ID.AddPointer(X); }
726};
727template <typename T1, typename T2> struct FoldingSetTrait<std::pair<T1, T2>> {
728 static inline void Profile(const std::pair<T1, T2> &P, FoldingSetNodeID &ID) {
729 ID.Add(P.first);
730 ID.Add(P.second);
731 }
732};
733
734template <typename T>
735struct FoldingSetTrait<T, std::enable_if_t<std::is_enum<T>::value>> {
736 static void Profile(const T &X, FoldingSetNodeID &ID) {
737 ID.AddInteger(llvm::to_underlying(X));
738 }
739};
740
741} // namespace llvm
742
743#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:856
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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)
FastFoldingSetNode(const FoldingSetNodeID &ID)
Definition FoldingSet.h:715
void Profile(FoldingSetNodeID &ID) const
Definition FoldingSet.h:718
This class is used to maintain the singly linked bucket list in a folding set.
Definition FoldingSet.h:320
void * getNextInBucket() const
Definition FoldingSet.h:329
void SetNextInBucket(void *N)
Definition FoldingSet.h:330
Implements the folding set functionality.
Definition FoldingSet.h:299
void ** Buckets
Array of bucket chains.
Definition FoldingSet.h:302
unsigned size() const
Returns the number of nodes in the folding set.
Definition FoldingSet.h:337
LLVM_ABI void reserve(unsigned EltCount, const FoldingSetInfo &Info)
Grow the number of buckets so that we can hold at least EltCount nodes before rebucketing.
unsigned capacity() const
Returns the number of nodes permitted in the folding set before a rebucket operation is performed.
Definition FoldingSet.h:344
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 ~FoldingSetBase()
unsigned NumBuckets
Length of the Buckets array. Always a power of 2.
Definition FoldingSet.h:305
unsigned NumNodes
Number of nodes in the folding set.
Definition FoldingSet.h:309
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:340
LLVM_ABI void InsertNode(Node *N, void *InsertPos, const FoldingSetInfo &Info)
Insert the specified node into the folding set, knowing that it is not already in the folding set.
LLVM_ABI void clear()
Remove all nodes from the folding set.
LLVM_ABI Node * FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos, const FoldingSetInfo &Info)
Look up the node specified by ID.
LLVM_ABI FoldingSetBase(unsigned Log2InitSize)
An implementation detail that lets us share code between FoldingSet and ContextualFoldingSet.
Definition FoldingSet.h:443
FoldingSetImpl(FoldingSetImpl &&Arg)=default
FoldingSetImpl(C &&Context, unsigned Log2InitSize=6)
Definition FoldingSet.h:489
const_iterator begin() const
Definition FoldingSet.h:505
FoldingSetImpl & operator=(FoldingSetImpl &&RHS)=default
void reserve(unsigned EltCount)
Definition FoldingSet.h:512
FoldingSetIterator< const T > const_iterator
Definition FoldingSet.h:503
const_iterator end() const
Definition FoldingSet.h:506
FoldingSetIterator< T > iterator
Definition FoldingSet.h:498
FoldingSetImpl(unsigned Log2InitSize=6)
Definition FoldingSet.h:484
T * FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos)
Definition FoldingSet.h:529
void InsertNode(T *N, void *InsertPos)
Definition FoldingSet.h:537
FoldingSetNode * getNode() const
Definition FoldingSet.h:650
bool operator==(const FoldingSetIteratorImpl &RHS) const
Definition FoldingSet.h:656
LLVM_ABI FoldingSetIteratorImpl(const DebugEpochBase *Epoch, void **Bucket)
bool operator!=(const FoldingSetIteratorImpl &RHS) const
Definition FoldingSet.h:660
FoldingSetIterator(const DebugEpochBase *Epoch, void **Bucket)
Definition FoldingSet.h:667
FoldingSetIterator operator++(int)
Definition FoldingSet.h:678
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:175
unsigned computeStableHash() const
Definition FoldingSet.h:191
LLVM_ABI bool operator==(FoldingSetNodeIDRef) const
FoldingSetNodeIDRef(const unsigned *D, size_t S)
Definition FoldingSet.h:181
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:198
unsigned ComputeHash() const
Definition FoldingSet.h:185
const unsigned * getData() const
Definition FoldingSet.h:204
This class is used to gather all the unique data bits of a node.
Definition FoldingSet.h:212
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:241
void AddInteger(unsigned long I)
Definition FoldingSet.h:244
FoldingSetNodeID(FoldingSetNodeIDRef Ref)
Definition FoldingSet.h:228
unsigned computeStableHash() const
Definition FoldingSet.h:268
void AddPointer(const void *Ptr)
Add* - Add various data types to Bit data.
Definition FoldingSet.h:232
bool operator!=(const FoldingSetNodeIDRef RHS) const
Definition FoldingSet.h:277
void clear()
Clear the accumulated profile, allowing this FoldingSetNodeID object to be used to compute a new prof...
Definition FoldingSet.h:257
void AddInteger(unsigned I)
Definition FoldingSet.h:242
void AddInteger(long I)
Definition FoldingSet.h:243
void AddBoolean(bool B)
Definition FoldingSet.h:247
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:276
void AddInteger(unsigned long long I)
Definition FoldingSet.h:246
void AddInteger(long long I)
Definition FoldingSet.h:245
unsigned ComputeHash() const
Definition FoldingSet.h:262
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:251
LLVM_ABI void AddString(StringRef String)
const T & getValue() const
Definition FoldingSet.h:699
FoldingSetNodeWrapper(Ts &&...Args)
Definition FoldingSet.h:693
void Profile(FoldingSetNodeID &ID)
Definition FoldingSet.h:696
T * GetOrInsertNode(T *N)
If there is an existing node exactly equal to the specified node, return it.
Definition FoldingSet.h:610
const_iterator end() const
Definition FoldingSet.h:594
void InsertNode(T *N)
Insert the specified node into the folding set, knowing that it is not already in the folding set.
Definition FoldingSet.h:627
T * FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos)
Look up the node specified by ID.
Definition FoldingSet.h:604
unsigned size() const
Returns the number of nodes in the folding set.
Definition FoldingSet.h:633
pointee_iterator< typename VectorT::const_iterator > const_iterator
Definition FoldingSet.h:591
pointee_iterator< typename VectorT::iterator > iterator
Definition FoldingSet.h:586
void clear()
Remove all nodes from the folding set.
Definition FoldingSet.h:597
bool empty() const
Returns true if there are no nodes in the folding set.
Definition FoldingSet.h:636
FoldingSetVector(unsigned Log2InitSize=6)
Definition FoldingSet.h:584
void InsertNode(T *N, void *InsertPos)
Insert the specified node into the folding set, knowing that it is not already in the folding set.
Definition FoldingSet.h:620
const_iterator begin() const
Definition FoldingSet.h:593
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:407
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:571
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:560
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:167
Like DefaultFoldingSetTrait, but for ContextualFoldingSets.
Definition FoldingSet.h:148
static bool Equals(T &X, const FoldingSetNodeID &ID, unsigned IDHash, FoldingSetNodeID &TempID, Ctx Context)
Definition FoldingSet.h:426
static void Profile(T &X, FoldingSetNodeID &ID, Ctx Context)
Definition FoldingSet.h:155
static unsigned ComputeHash(T &X, FoldingSetNodeID &TempID, Ctx Context)
Definition FoldingSet.h:433
This class provides default implementations for FoldingSetTrait implementations.
Definition FoldingSet.h:117
static void Profile(const T &X, FoldingSetNodeID &ID)
Definition FoldingSet.h:120
static unsigned ComputeHash(T &X, FoldingSetNodeID &TempID)
Definition FoldingSet.h:421
static bool Equals(T &X, const FoldingSetNodeID &ID, unsigned IDHash, FoldingSetNodeID &TempID)
Definition FoldingSet.h:413
static void Profile(T &X, FoldingSetNodeID &ID)
Definition FoldingSet.h:121
Functions provided by the derived class to compute folding properties.
Definition FoldingSet.h:354
unsigned(* ComputeNodeHash)(const FoldingSetBase *Self, Node *N, FoldingSetNodeID &TempID)
Instantiations of the FoldingSet template implement this function to compute a hash value for the giv...
Definition FoldingSet.h:368
bool(* NodeEquals)(const FoldingSetBase *Self, Node *N, const FoldingSetNodeID &ID, unsigned IDHash, FoldingSetNodeID &TempID)
Instantiations of the FoldingSet template implement this function to compare the given node with the ...
Definition FoldingSet.h:362
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:357
static void Profile(T *X, FoldingSetNodeID &ID)
Definition FoldingSet.h:725
static void Profile(const std::pair< T1, T2 > &P, FoldingSetNodeID &ID)
Definition FoldingSet.h:728
This trait class is used to define behavior of how to "profile" (in the FoldingSet parlance) an objec...
Definition FoldingSet.h:145
An iterator type that allows iterating over the pointees via some other iterator.
Definition iterator.h:329