LLVM 22.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/Hashing.h"
22#include "llvm/ADT/iterator.h"
25#include "llvm/Support/xxhash.h"
26#include <cassert>
27#include <cstddef>
28#include <cstdint>
29#include <type_traits>
30#include <utility>
31
32namespace llvm {
33
34/// This folding set used for two purposes:
35/// 1. Given information about a node we want to create, look up the unique
36/// instance of the node in the set. If the node already exists, return
37/// it, otherwise return the bucket it should be inserted into.
38/// 2. Given a node that has already been created, remove it from the set.
39///
40/// This class is implemented as a single-link chained hash table, where the
41/// "buckets" are actually the nodes themselves (the next pointer is in the
42/// node). The last node points back to the bucket to simplify node removal.
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 FoldingSetBase::NodeID 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.GetOrInsertNode(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 FindNodeOrInsertPos with a FoldingSetNodeID of the bits to
85/// check;
86///
87/// FoldingSetNodeID ID;
88/// ID.AddString(Name);
89/// ID.AddInteger(Value);
90/// void *InsertPoint;
91///
92/// MyNode *M = MyFoldingSet.FindNodeOrInsertPos(ID, InsertPoint);
93///
94/// If found then M will be non-NULL, else InsertPoint will point to where it
95/// should be inserted using InsertNode.
96///
97/// 3) If you get a NULL result from FindNodeOrInsertPos then you can insert a
98/// new node with InsertNode;
99///
100/// MyFoldingSet.InsertNode(M, InsertPoint);
101///
102/// 4) Finally, if you want to remove a node from the folding set call;
103///
104/// bool WasRemoved = MyFoldingSet.RemoveNode(M);
105///
106/// The result indicates whether the node existed in the folding set.
107
108class FoldingSetNodeID;
109class StringRef;
110
111//===----------------------------------------------------------------------===//
112/// FoldingSetBase - Implements the folding set functionality. The main
113/// structure is an array of buckets. Each bucket is indexed by the hash of
114/// the nodes it contains. The bucket itself points to the nodes contained
115/// in the bucket via a singly linked list. The last node in the list points
116/// back to the bucket to facilitate node removal.
117///
119protected:
120 /// Buckets - Array of bucket chains.
121 void **Buckets;
122
123 /// NumBuckets - Length of the Buckets array. Always a power of 2.
124 unsigned NumBuckets;
125
126 /// NumNodes - Number of nodes in the folding set. Growth occurs when NumNodes
127 /// is greater than twice the number of buckets.
128 unsigned NumNodes;
129
130 LLVM_ABI explicit FoldingSetBase(unsigned Log2InitSize = 6);
134
135public:
136 //===--------------------------------------------------------------------===//
137 /// Node - This class is used to maintain the singly linked bucket list in
138 /// a folding set.
139 class Node {
140 private:
141 // NextInFoldingSetBucket - next link in the bucket list.
142 void *NextInFoldingSetBucket = nullptr;
143
144 public:
145 Node() = default;
146
147 // Accessors
148 void *getNextInBucket() const { return NextInFoldingSetBucket; }
149 void SetNextInBucket(void *N) { NextInFoldingSetBucket = N; }
150 };
151
152 /// clear - Remove all nodes from the folding set.
153 LLVM_ABI void clear();
154
155 /// size - Returns the number of nodes in the folding set.
156 unsigned size() const { return NumNodes; }
157
158 /// empty - Returns true if there are no nodes in the folding set.
159 bool empty() const { return NumNodes == 0; }
160
161 /// capacity - Returns the number of nodes permitted in the folding set
162 /// before a rebucket operation is performed.
163 unsigned capacity() {
164 // We allow a load factor of up to 2.0,
165 // so that means our capacity is NumBuckets * 2
166 return NumBuckets * 2;
167 }
168
169protected:
170 /// Functions provided by the derived class to compute folding properties.
171 /// This is effectively a vtable for FoldingSetBase, except that we don't
172 /// actually store a pointer to it in the object.
174 /// GetNodeProfile - Instantiations of the FoldingSet template implement
175 /// this function to gather data bits for the given node.
176 void (*GetNodeProfile)(const FoldingSetBase *Self, Node *N,
178
179 /// NodeEquals - Instantiations of the FoldingSet template implement
180 /// this function to compare the given node with the given ID.
182 const FoldingSetNodeID &ID, unsigned IDHash,
183 FoldingSetNodeID &TempID);
184
185 /// ComputeNodeHash - Instantiations of the FoldingSet template implement
186 /// this function to compute a hash value for the given node.
188 FoldingSetNodeID &TempID);
189 };
190
191private:
192 /// GrowHashTable - Double the size of the hash table and rehash everything.
193 void GrowHashTable(const FoldingSetInfo &Info);
194
195 /// GrowBucketCount - resize the hash table and rehash everything.
196 /// NewBucketCount must be a power of two, and must be greater than the old
197 /// bucket count.
198 void GrowBucketCount(unsigned NewBucketCount, const FoldingSetInfo &Info);
199
200protected:
201 // The below methods are protected to encourage subclasses to provide a more
202 // type-safe API.
203
204 /// reserve - Increase the number of buckets such that adding the
205 /// EltCount-th node won't cause a rebucket operation. reserve is permitted
206 /// to allocate more space than requested by EltCount.
207 LLVM_ABI void reserve(unsigned EltCount, const FoldingSetInfo &Info);
208
209 /// RemoveNode - Remove a node from the folding set, returning true if one
210 /// was removed or false if the node was not in the folding set.
211 LLVM_ABI bool RemoveNode(Node *N);
212
213 /// GetOrInsertNode - If there is an existing simple Node exactly
214 /// equal to the specified node, return it. Otherwise, insert 'N' and return
215 /// it instead.
217
218 /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists,
219 /// return it. If not, return the insertion token that will make insertion
220 /// faster.
222 void *&InsertPos,
223 const FoldingSetInfo &Info);
224
225 /// InsertNode - Insert the specified node into the folding set, knowing that
226 /// it is not already in the folding set. InsertPos must be obtained from
227 /// FindNodeOrInsertPos.
228 LLVM_ABI void InsertNode(Node *N, void *InsertPos,
229 const FoldingSetInfo &Info);
230};
231
232//===----------------------------------------------------------------------===//
233
234/// DefaultFoldingSetTrait - This class provides default implementations
235/// for FoldingSetTrait implementations.
236template<typename T> struct DefaultFoldingSetTrait {
237 static void Profile(const T &X, FoldingSetNodeID &ID) {
238 X.Profile(ID);
239 }
240 static void Profile(T &X, FoldingSetNodeID &ID) {
241 X.Profile(ID);
242 }
243
244 // Equals - Test if the profile for X would match ID, using TempID
245 // to compute a temporary ID if necessary. The default implementation
246 // just calls Profile and does a regular comparison. Implementations
247 // can override this to provide more efficient implementations.
248 static inline bool Equals(T &X, const FoldingSetNodeID &ID, unsigned IDHash,
249 FoldingSetNodeID &TempID);
250
251 // ComputeHash - Compute a hash value for X, using TempID to
252 // compute a temporary ID if necessary. The default implementation
253 // just calls Profile and does a regular hash computation.
254 // Implementations can override this to provide more efficient
255 // implementations.
256 static inline unsigned ComputeHash(T &X, FoldingSetNodeID &TempID);
257};
258
259/// FoldingSetTrait - This trait class is used to define behavior of how
260/// to "profile" (in the FoldingSet parlance) an object of a given type.
261/// The default behavior is to invoke a 'Profile' method on an object, but
262/// through template specialization the behavior can be tailored for specific
263/// types. Combined with the FoldingSetNodeWrapper class, one can add objects
264/// to FoldingSets that were not originally designed to have that behavior.
265template <typename T, typename Enable = void>
267
268/// DefaultContextualFoldingSetTrait - Like DefaultFoldingSetTrait, but
269/// for ContextualFoldingSets.
270template<typename T, typename Ctx>
272 static void Profile(T &X, FoldingSetNodeID &ID, Ctx Context) {
273 X.Profile(ID, Context);
274 }
275
276 static inline bool Equals(T &X, const FoldingSetNodeID &ID, unsigned IDHash,
277 FoldingSetNodeID &TempID, Ctx Context);
278 static inline unsigned ComputeHash(T &X, FoldingSetNodeID &TempID,
279 Ctx Context);
280};
281
282/// ContextualFoldingSetTrait - Like FoldingSetTrait, but for
283/// ContextualFoldingSets.
284template<typename T, typename Ctx> struct ContextualFoldingSetTrait
285 : public DefaultContextualFoldingSetTrait<T, Ctx> {};
286
287//===--------------------------------------------------------------------===//
288/// FoldingSetNodeIDRef - This class describes a reference to an interned
289/// FoldingSetNodeID, which can be a useful to store node id data rather
290/// than using plain FoldingSetNodeIDs, since the 32-element SmallVector
291/// is often much larger than necessary, and the possibility of heap
292/// allocation means it requires a non-trivial destructor call.
294 const unsigned *Data = nullptr;
295 size_t Size = 0;
296
297public:
299 FoldingSetNodeIDRef(const unsigned *D, size_t S) : Data(D), Size(S) {}
300
301 // Compute a strong hash value used to lookup the node in the FoldingSetBase.
302 // The hash value is not guaranteed to be deterministic across processes.
303 unsigned ComputeHash() const {
304 return static_cast<unsigned>(hash_combine_range(Data, Data + Size));
305 }
306
307 // Compute a deterministic hash value across processes that is suitable for
308 // on-disk serialization.
309 unsigned computeStableHash() const {
310 return static_cast<unsigned>(xxh3_64bits(ArrayRef(
311 reinterpret_cast<const uint8_t *>(Data), sizeof(unsigned) * Size)));
312 }
313
315
316 bool operator!=(FoldingSetNodeIDRef RHS) const { return !(*this == RHS); }
317
318 /// Used to compare the "ordering" of two nodes as defined by the
319 /// profiled bits and their ordering defined by memcmp().
321
322 const unsigned *getData() const { return Data; }
323 size_t getSize() const { return Size; }
324};
325
326//===--------------------------------------------------------------------===//
327/// FoldingSetNodeID - This class is used to gather all the unique data bits of
328/// a node. When all the bits are gathered this class is used to produce a
329/// hash value for the node.
331 /// Bits - Vector of all the data bits that make the node unique.
332 /// Use a SmallVector to avoid a heap allocation in the common case.
334
335 template <typename T> void AddIntegerImpl(T I) {
336 static_assert(std::is_integral_v<T> && sizeof(T) <= sizeof(unsigned) * 2,
337 "T must be an integer type no wider than 64 bits");
338 Bits.push_back(static_cast<unsigned>(I));
339 if constexpr (sizeof(unsigned) < sizeof(T))
340 Bits.push_back(static_cast<unsigned long long>(I) >> 32);
341 }
342
343public:
344 FoldingSetNodeID() = default;
345
347 : Bits(Ref.getData(), Ref.getData() + Ref.getSize()) {}
348
349 /// Add* - Add various data types to Bit data.
350 void AddPointer(const void *Ptr) {
351 // Note: this adds pointers to the hash using sizes and endianness that
352 // depend on the host. It doesn't matter, however, because hashing on
353 // pointer values is inherently unstable. Nothing should depend on the
354 // ordering of nodes in the folding set.
355 static_assert(sizeof(uintptr_t) <= sizeof(unsigned long long),
356 "unexpected pointer size");
357 AddInteger(reinterpret_cast<uintptr_t>(Ptr));
358 }
359 void AddInteger(signed I) { AddIntegerImpl(I); }
360 void AddInteger(unsigned I) { AddIntegerImpl(I); }
361 void AddInteger(long I) { AddIntegerImpl(I); }
362 void AddInteger(unsigned long I) { AddIntegerImpl(I); }
363 void AddInteger(long long I) { AddIntegerImpl(I); }
364 void AddInteger(unsigned long long I) { AddIntegerImpl(I); }
365 void AddBoolean(bool B) { AddInteger(B ? 1U : 0U); }
368
369 template <typename T>
370 inline void Add(const T &x) { FoldingSetTrait<T>::Profile(x, *this); }
371
372 /// clear - Clear the accumulated profile, allowing this FoldingSetNodeID
373 /// object to be used to compute a new profile.
374 inline void clear() { Bits.clear(); }
375
376 // Compute a strong hash value for this FoldingSetNodeID, used to lookup the
377 // node in the FoldingSetBase. The hash value is not guaranteed to be
378 // deterministic across processes.
379 unsigned ComputeHash() const {
380 return FoldingSetNodeIDRef(Bits.data(), Bits.size()).ComputeHash();
381 }
382
383 // Compute a deterministic hash value across processes that is suitable for
384 // on-disk serialization.
385 unsigned computeStableHash() const {
386 return FoldingSetNodeIDRef(Bits.data(), Bits.size()).computeStableHash();
387 }
388
389 /// operator== - Used to compare two nodes to each other.
390 LLVM_ABI bool operator==(const FoldingSetNodeID &RHS) const;
391 LLVM_ABI bool operator==(const FoldingSetNodeIDRef RHS) const;
392
393 bool operator!=(const FoldingSetNodeID &RHS) const { return !(*this == RHS); }
394 bool operator!=(const FoldingSetNodeIDRef RHS) const { return !(*this ==RHS);}
395
396 /// Used to compare the "ordering" of two nodes as defined by the
397 /// profiled bits and their ordering defined by memcmp().
398 LLVM_ABI bool operator<(const FoldingSetNodeID &RHS) const;
399 LLVM_ABI bool operator<(const FoldingSetNodeIDRef RHS) const;
400
401 /// Intern - Copy this node's data to a memory region allocated from the
402 /// given allocator and return a FoldingSetNodeIDRef describing the
403 /// interned data.
405};
406
407// Convenience type to hide the implementation of the folding set.
409template<class T> class FoldingSetIterator;
410template<class T> class FoldingSetBucketIterator;
411
412// Definitions of FoldingSetTrait and ContextualFoldingSetTrait functions, which
413// require the definition of FoldingSetNodeID.
414template<typename T>
415inline bool
417 unsigned /*IDHash*/,
418 FoldingSetNodeID &TempID) {
420 return TempID == ID;
421}
422template<typename T>
423inline unsigned
428template<typename T, typename Ctx>
429inline bool
431 const FoldingSetNodeID &ID,
432 unsigned /*IDHash*/,
433 FoldingSetNodeID &TempID,
434 Ctx Context) {
436 return TempID == ID;
437}
438template<typename T, typename Ctx>
439inline unsigned
441 FoldingSetNodeID &TempID,
442 Ctx Context) {
444 return TempID.ComputeHash();
445}
446
447//===----------------------------------------------------------------------===//
448/// FoldingSetImpl - An implementation detail that lets us share code between
449/// FoldingSet and ContextualFoldingSet.
450template <class Derived, class T> class FoldingSetImpl : public FoldingSetBase {
451protected:
452 explicit FoldingSetImpl(unsigned Log2InitSize)
453 : FoldingSetBase(Log2InitSize) {}
454
457 ~FoldingSetImpl() = default;
458
459public:
461
464
466
469
471
473 return bucket_iterator(Buckets + (hash & (NumBuckets-1)));
474 }
475
477 return bucket_iterator(Buckets + (hash & (NumBuckets-1)), true);
478 }
479
480 /// reserve - Increase the number of buckets such that adding the
481 /// EltCount-th node won't cause a rebucket operation. reserve is permitted
482 /// to allocate more space than requested by EltCount.
483 void reserve(unsigned EltCount) {
484 return FoldingSetBase::reserve(EltCount, Derived::getFoldingSetInfo());
485 }
486
487 /// RemoveNode - Remove a node from the folding set, returning true if one
488 /// was removed or false if the node was not in the folding set.
489 bool RemoveNode(T *N) {
491 }
492
493 /// GetOrInsertNode - If there is an existing simple Node exactly
494 /// equal to the specified node, return it. Otherwise, insert 'N' and
495 /// return it instead.
497 return static_cast<T *>(
498 FoldingSetBase::GetOrInsertNode(N, Derived::getFoldingSetInfo()));
499 }
500
501 /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists,
502 /// return it. If not, return the insertion token that will make insertion
503 /// faster.
504 T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) {
505 return static_cast<T *>(FoldingSetBase::FindNodeOrInsertPos(
506 ID, InsertPos, Derived::getFoldingSetInfo()));
507 }
508
509 /// InsertNode - Insert the specified node into the folding set, knowing that
510 /// it is not already in the folding set. InsertPos must be obtained from
511 /// FindNodeOrInsertPos.
512 void InsertNode(T *N, void *InsertPos) {
513 FoldingSetBase::InsertNode(N, InsertPos, Derived::getFoldingSetInfo());
514 }
515
516 /// InsertNode - Insert the specified node into the folding set, knowing that
517 /// it is not already in the folding set.
518 void InsertNode(T *N) {
519 T *Inserted = GetOrInsertNode(N);
520 (void)Inserted;
521 assert(Inserted == N && "Node already inserted!");
522 }
523};
524
525//===----------------------------------------------------------------------===//
526/// FoldingSet - This template class is used to instantiate a specialized
527/// implementation of the folding set to the node class T. T must be a
528/// subclass of FoldingSetNode and implement a Profile function.
529///
530/// Note that this set type is movable and move-assignable. However, its
531/// moved-from state is not a valid state for anything other than
532/// move-assigning and destroying. This is primarily to enable movable APIs
533/// that incorporate these objects.
534template <class T>
535class FoldingSet : public FoldingSetImpl<FoldingSet<T>, T> {
536 using Super = FoldingSetImpl<FoldingSet, T>;
537 using Node = typename Super::Node;
538
539 /// GetNodeProfile - Each instantiation of the FoldingSet needs to provide a
540 /// way to convert nodes into a unique specifier.
541 static void GetNodeProfile(const FoldingSetBase *, Node *N,
543 T *TN = static_cast<T *>(N);
545 }
546
547 /// NodeEquals - Instantiations may optionally provide a way to compare a
548 /// node with a specified ID.
549 static bool NodeEquals(const FoldingSetBase *, Node *N,
550 const FoldingSetNodeID &ID, unsigned IDHash,
551 FoldingSetNodeID &TempID) {
552 T *TN = static_cast<T *>(N);
553 return FoldingSetTrait<T>::Equals(*TN, ID, IDHash, TempID);
554 }
555
556 /// ComputeNodeHash - Instantiations may optionally provide a way to compute a
557 /// hash value directly from a node.
558 static unsigned ComputeNodeHash(const FoldingSetBase *, Node *N,
559 FoldingSetNodeID &TempID) {
560 T *TN = static_cast<T *>(N);
561 return FoldingSetTrait<T>::ComputeHash(*TN, TempID);
562 }
563
564 static const FoldingSetBase::FoldingSetInfo &getFoldingSetInfo() {
565 static constexpr FoldingSetBase::FoldingSetInfo Info = {
566 GetNodeProfile, NodeEquals, ComputeNodeHash};
567 return Info;
568 }
569 friend Super;
570
571public:
572 explicit FoldingSet(unsigned Log2InitSize = 6) : Super(Log2InitSize) {}
573 FoldingSet(FoldingSet &&Arg) = default;
575};
576
577//===----------------------------------------------------------------------===//
578/// ContextualFoldingSet - This template class is a further refinement
579/// of FoldingSet which provides a context argument when calling
580/// Profile on its nodes. Currently, that argument is fixed at
581/// initialization time.
582///
583/// T must be a subclass of FoldingSetNode and implement a Profile
584/// function with signature
585/// void Profile(FoldingSetNodeID &, Ctx);
586template <class T, class Ctx>
588 : public FoldingSetImpl<ContextualFoldingSet<T, Ctx>, T> {
589 // Unfortunately, this can't derive from FoldingSet<T> because the
590 // construction of the vtable for FoldingSet<T> requires
591 // FoldingSet<T>::GetNodeProfile to be instantiated, which in turn
592 // requires a single-argument T::Profile().
593
595 using Node = typename Super::Node;
596
597 Ctx Context;
598
599 static const Ctx &getContext(const FoldingSetBase *Base) {
600 return static_cast<const ContextualFoldingSet*>(Base)->Context;
601 }
602
603 /// GetNodeProfile - Each instantiatation of the FoldingSet needs to provide a
604 /// way to convert nodes into a unique specifier.
605 static void GetNodeProfile(const FoldingSetBase *Base, Node *N,
607 T *TN = static_cast<T *>(N);
609 }
610
611 static bool NodeEquals(const FoldingSetBase *Base, Node *N,
612 const FoldingSetNodeID &ID, unsigned IDHash,
613 FoldingSetNodeID &TempID) {
614 T *TN = static_cast<T *>(N);
615 return ContextualFoldingSetTrait<T, Ctx>::Equals(*TN, ID, IDHash, TempID,
617 }
618
619 static unsigned ComputeNodeHash(const FoldingSetBase *Base, Node *N,
620 FoldingSetNodeID &TempID) {
621 T *TN = static_cast<T *>(N);
624 }
625
626 static const FoldingSetBase::FoldingSetInfo &getFoldingSetInfo() {
627 static constexpr FoldingSetBase::FoldingSetInfo Info = {
628 GetNodeProfile, NodeEquals, ComputeNodeHash};
629 return Info;
630 }
631 friend Super;
632
633public:
634 explicit ContextualFoldingSet(Ctx Context, unsigned Log2InitSize = 6)
635 : Super(Log2InitSize), Context(Context) {}
636
637 Ctx getContext() const { return Context; }
638};
639
640//===----------------------------------------------------------------------===//
641/// FoldingSetVector - This template class combines a FoldingSet and a vector
642/// to provide the interface of FoldingSet but with deterministic iteration
643/// order based on the insertion order. T must be a subclass of FoldingSetNode
644/// and implement a Profile function.
645template <class T, class VectorT = SmallVector<T*, 8>>
647 FoldingSet<T> Set;
648 VectorT Vector;
649
650public:
651 explicit FoldingSetVector(unsigned Log2InitSize = 6) : Set(Log2InitSize) {}
652
654
655 iterator begin() { return Vector.begin(); }
656 iterator end() { return Vector.end(); }
657
659
660 const_iterator begin() const { return Vector.begin(); }
661 const_iterator end() const { return Vector.end(); }
662
663 /// clear - Remove all nodes from the folding set.
664 void clear() { Set.clear(); Vector.clear(); }
665
666 /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists,
667 /// return it. If not, return the insertion token that will make insertion
668 /// faster.
669 T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) {
670 return Set.FindNodeOrInsertPos(ID, InsertPos);
671 }
672
673 /// GetOrInsertNode - If there is an existing simple Node exactly
674 /// equal to the specified node, return it. Otherwise, insert 'N' and
675 /// return it instead.
677 T *Result = Set.GetOrInsertNode(N);
678 if (Result == N) Vector.push_back(N);
679 return Result;
680 }
681
682 /// InsertNode - Insert the specified node into the folding set, knowing that
683 /// it is not already in the folding set. InsertPos must be obtained from
684 /// FindNodeOrInsertPos.
685 void InsertNode(T *N, void *InsertPos) {
686 Set.InsertNode(N, InsertPos);
687 Vector.push_back(N);
688 }
689
690 /// InsertNode - Insert the specified node into the folding set, knowing that
691 /// it is not already in the folding set.
692 void InsertNode(T *N) {
693 Set.InsertNode(N);
694 Vector.push_back(N);
695 }
696
697 /// size - Returns the number of nodes in the folding set.
698 unsigned size() const { return Set.size(); }
699
700 /// empty - Returns true if there are no nodes in the folding set.
701 bool empty() const { return Set.empty(); }
702};
703
704//===----------------------------------------------------------------------===//
705/// FoldingSetIteratorImpl - This is the common iterator support shared by all
706/// folding sets, which knows how to walk the folding set hash table.
708protected:
710
711 LLVM_ABI FoldingSetIteratorImpl(void **Bucket);
712
713 LLVM_ABI void advance();
714
715public:
717 return NodePtr == RHS.NodePtr;
718 }
720 return NodePtr != RHS.NodePtr;
721 }
722};
723
724template <class T> class FoldingSetIterator : public FoldingSetIteratorImpl {
725public:
726 explicit FoldingSetIterator(void **Bucket) : FoldingSetIteratorImpl(Bucket) {}
727
728 T &operator*() const {
729 return *static_cast<T*>(NodePtr);
730 }
731
732 T *operator->() const {
733 return static_cast<T*>(NodePtr);
734 }
735
736 inline FoldingSetIterator &operator++() { // Preincrement
737 advance();
738 return *this;
739 }
740 FoldingSetIterator operator++(int) { // Postincrement
741 FoldingSetIterator tmp = *this; ++*this; return tmp;
742 }
743};
744
745//===----------------------------------------------------------------------===//
746/// FoldingSetBucketIteratorImpl - This is the common bucket iterator support
747/// shared by all folding sets, which knows how to walk a particular bucket
748/// of a folding set hash table.
750protected:
751 void *Ptr;
752
753 LLVM_ABI explicit FoldingSetBucketIteratorImpl(void **Bucket);
754
755 FoldingSetBucketIteratorImpl(void **Bucket, bool) : Ptr(Bucket) {}
756
757 void advance() {
758 void *Probe = static_cast<FoldingSetNode*>(Ptr)->getNextInBucket();
759 uintptr_t x = reinterpret_cast<uintptr_t>(Probe) & ~0x1;
760 Ptr = reinterpret_cast<void*>(x);
761 }
762
763public:
765 return Ptr == RHS.Ptr;
766 }
768 return Ptr != RHS.Ptr;
769 }
770};
771
772template <class T>
774public:
775 explicit FoldingSetBucketIterator(void **Bucket) :
777
778 FoldingSetBucketIterator(void **Bucket, bool) :
780
781 T &operator*() const { return *static_cast<T*>(Ptr); }
782 T *operator->() const { return static_cast<T*>(Ptr); }
783
784 inline FoldingSetBucketIterator &operator++() { // Preincrement
785 advance();
786 return *this;
787 }
788 FoldingSetBucketIterator operator++(int) { // Postincrement
789 FoldingSetBucketIterator tmp = *this; ++*this; return tmp;
790 }
791};
792
793//===----------------------------------------------------------------------===//
794/// FoldingSetNodeWrapper - This template class is used to "wrap" arbitrary
795/// types in an enclosing object so that they can be inserted into FoldingSets.
796template <typename T>
798 T data;
799
800public:
801 template <typename... Ts>
802 explicit FoldingSetNodeWrapper(Ts &&... Args)
803 : data(std::forward<Ts>(Args)...) {}
804
806
807 T &getValue() { return data; }
808 const T &getValue() const { return data; }
809
810 operator T&() { return data; }
811 operator const T&() const { return data; }
812};
813
814//===----------------------------------------------------------------------===//
815/// FastFoldingSetNode - This is a subclass of FoldingSetNode which stores
816/// a FoldingSetNodeID value rather than requiring the node to recompute it
817/// each time it is needed. This trades space for speed (which can be
818/// significant if the ID is long), and it also permits nodes to drop
819/// information that would otherwise only be required for recomputing an ID.
821 FoldingSetNodeID FastID;
822
823protected:
824 explicit FastFoldingSetNode(const FoldingSetNodeID &ID) : FastID(ID) {}
825
826public:
827 void Profile(FoldingSetNodeID &ID) const { ID.AddNodeID(FastID); }
828};
829
830//===----------------------------------------------------------------------===//
831// Partial specializations of FoldingSetTrait.
832
833template<typename T> struct FoldingSetTrait<T*> {
834 static inline void Profile(T *X, FoldingSetNodeID &ID) {
835 ID.AddPointer(X);
836 }
837};
838template <typename T1, typename T2>
839struct FoldingSetTrait<std::pair<T1, T2>> {
840 static inline void Profile(const std::pair<T1, T2> &P,
842 ID.Add(P.first);
843 ID.Add(P.second);
844 }
845};
846
847template <typename T>
848struct FoldingSetTrait<T, std::enable_if_t<std::is_enum<T>::value>> {
849 static void Profile(const T &X, FoldingSetNodeID &ID) {
850 ID.AddInteger(llvm::to_underlying(X));
851 }
852};
853
854} // end namespace llvm
855
856#endif // LLVM_ADT_FOLDINGSET_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the BumpPtrAllocator interface.
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
Definition CSEInfo.cpp:27
#define LLVM_ABI
Definition Compiler.h:213
#define I(x, y, z)
Definition MD5.cpp:58
#define T
#define P(N)
Basic Register Allocator
This file contains library features backported from future STL versions.
This file defines the SmallVector class.
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
Value * RHS
static unsigned getSize(unsigned Kind)
ContextualFoldingSet(Ctx Context, unsigned Log2InitSize=6)
Definition FoldingSet.h:634
FastFoldingSetNode(const FoldingSetNodeID &ID)
Definition FoldingSet.h:824
void Profile(FoldingSetNodeID &ID) const
Definition FoldingSet.h:827
Node - This class is used to maintain the singly linked bucket list in a folding set.
Definition FoldingSet.h:139
void * getNextInBucket() const
Definition FoldingSet.h:148
void SetNextInBucket(void *N)
Definition FoldingSet.h:149
FoldingSetBase - Implements the folding set functionality.
Definition FoldingSet.h:118
LLVM_ABI FoldingSetBase(unsigned Log2InitSize=6)
void ** Buckets
Buckets - Array of bucket chains.
Definition FoldingSet.h:121
unsigned size() const
size - Returns the number of nodes in the folding set.
Definition FoldingSet.h:156
LLVM_ABI void reserve(unsigned EltCount, const FoldingSetInfo &Info)
reserve - Increase the number of buckets such that adding the EltCount-th node won't cause a rebucket...
LLVM_ABI bool RemoveNode(Node *N)
RemoveNode - Remove a node from the folding set, returning true if one was removed or false if the no...
LLVM_ABI FoldingSetBase & operator=(FoldingSetBase &&RHS)
LLVM_ABI ~FoldingSetBase()
unsigned NumBuckets
NumBuckets - Length of the Buckets array. Always a power of 2.
Definition FoldingSet.h:124
unsigned NumNodes
NumNodes - Number of nodes in the folding set.
Definition FoldingSet.h:128
unsigned capacity()
capacity - Returns the number of nodes permitted in the folding set before a rebucket operation is pe...
Definition FoldingSet.h:163
LLVM_ABI Node * GetOrInsertNode(Node *N, const FoldingSetInfo &Info)
GetOrInsertNode - If there is an existing simple Node exactly equal to the specified node,...
bool empty() const
empty - Returns true if there are no nodes in the folding set.
Definition FoldingSet.h:159
LLVM_ABI void InsertNode(Node *N, void *InsertPos, const FoldingSetInfo &Info)
InsertNode - Insert the specified node into the folding set, knowing that it is not already in the fo...
LLVM_ABI void clear()
clear - Remove all nodes from the folding set.
LLVM_ABI Node * FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos, const FoldingSetInfo &Info)
FindNodeOrInsertPos - Look up the node specified by ID.
LLVM_ABI FoldingSetBucketIteratorImpl(void **Bucket)
FoldingSetBucketIteratorImpl(void **Bucket, bool)
Definition FoldingSet.h:755
bool operator!=(const FoldingSetBucketIteratorImpl &RHS) const
Definition FoldingSet.h:767
bool operator==(const FoldingSetBucketIteratorImpl &RHS) const
Definition FoldingSet.h:764
FoldingSetBucketIterator(void **Bucket, bool)
Definition FoldingSet.h:778
FoldingSetBucketIterator(void **Bucket)
Definition FoldingSet.h:775
FoldingSetBucketIterator operator++(int)
Definition FoldingSet.h:788
FoldingSetBucketIterator & operator++()
Definition FoldingSet.h:784
void reserve(unsigned EltCount)
reserve - Increase the number of buckets such that adding the EltCount-th node won't cause a rebucket...
Definition FoldingSet.h:483
FoldingSetIterator< T > iterator
Definition FoldingSet.h:460
const_iterator end() const
Definition FoldingSet.h:468
bucket_iterator bucket_begin(unsigned hash)
Definition FoldingSet.h:472
bool RemoveNode(T *N)
RemoveNode - Remove a node from the folding set, returning true if one was removed or false if the no...
Definition FoldingSet.h:489
~FoldingSetImpl()=default
FoldingSetImpl(FoldingSetImpl &&Arg)=default
FoldingSetBucketIterator< T > bucket_iterator
Definition FoldingSet.h:470
void InsertNode(T *N)
InsertNode - Insert the specified node into the folding set, knowing that it is not already in the fo...
Definition FoldingSet.h:518
void InsertNode(T *N, void *InsertPos)
InsertNode - Insert the specified node into the folding set, knowing that it is not already in the fo...
Definition FoldingSet.h:512
T * FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos)
FindNodeOrInsertPos - Look up the node specified by ID.
Definition FoldingSet.h:504
const_iterator begin() const
Definition FoldingSet.h:467
FoldingSetIterator< const T > const_iterator
Definition FoldingSet.h:465
FoldingSetImpl & operator=(FoldingSetImpl &&RHS)=default
T * GetOrInsertNode(T *N)
GetOrInsertNode - If there is an existing simple Node exactly equal to the specified node,...
Definition FoldingSet.h:496
FoldingSetImpl(unsigned Log2InitSize)
Definition FoldingSet.h:452
bucket_iterator bucket_end(unsigned hash)
Definition FoldingSet.h:476
LLVM_ABI FoldingSetIteratorImpl(void **Bucket)
bool operator==(const FoldingSetIteratorImpl &RHS) const
Definition FoldingSet.h:716
bool operator!=(const FoldingSetIteratorImpl &RHS) const
Definition FoldingSet.h:719
FoldingSetIterator(void **Bucket)
Definition FoldingSet.h:726
FoldingSetIterator operator++(int)
Definition FoldingSet.h:740
FoldingSetIterator & operator++()
Definition FoldingSet.h:736
FoldingSetNodeIDRef - This class describes a reference to an interned FoldingSetNodeID,...
Definition FoldingSet.h:293
unsigned computeStableHash() const
Definition FoldingSet.h:309
LLVM_ABI bool operator==(FoldingSetNodeIDRef) const
FoldingSetNodeIDRef(const unsigned *D, size_t S)
Definition FoldingSet.h:299
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:316
unsigned ComputeHash() const
Definition FoldingSet.h:303
const unsigned * getData() const
Definition FoldingSet.h:322
FoldingSetNodeID - This class is used to gather all the unique data bits of a node.
Definition FoldingSet.h:330
LLVM_ABI FoldingSetNodeIDRef Intern(BumpPtrAllocator &Allocator) const
Intern - Copy this node's data to a memory region allocated from the given allocator and return a Fol...
void AddInteger(signed I)
Definition FoldingSet.h:359
void AddInteger(unsigned long I)
Definition FoldingSet.h:362
FoldingSetNodeID(FoldingSetNodeIDRef Ref)
Definition FoldingSet.h:346
unsigned computeStableHash() const
Definition FoldingSet.h:385
void AddPointer(const void *Ptr)
Add* - Add various data types to Bit data.
Definition FoldingSet.h:350
bool operator!=(const FoldingSetNodeIDRef RHS) const
Definition FoldingSet.h:394
void clear()
clear - Clear the accumulated profile, allowing this FoldingSetNodeID object to be used to compute a ...
Definition FoldingSet.h:374
void AddInteger(unsigned I)
Definition FoldingSet.h:360
void AddInteger(long I)
Definition FoldingSet.h:361
void AddBoolean(bool B)
Definition FoldingSet.h:365
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:393
void AddInteger(unsigned long long I)
Definition FoldingSet.h:364
void AddInteger(long long I)
Definition FoldingSet.h:363
unsigned ComputeHash() const
Definition FoldingSet.h:379
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:370
LLVM_ABI void AddString(StringRef String)
Add* - Add various data types to Bit data.
FoldingSetNodeWrapper(Ts &&... Args)
Definition FoldingSet.h:802
const T & getValue() const
Definition FoldingSet.h:808
void Profile(FoldingSetNodeID &ID)
Definition FoldingSet.h:805
T * GetOrInsertNode(T *N)
GetOrInsertNode - If there is an existing simple Node exactly equal to the specified node,...
Definition FoldingSet.h:676
const_iterator end() const
Definition FoldingSet.h:661
void InsertNode(T *N)
InsertNode - Insert the specified node into the folding set, knowing that it is not already in the fo...
Definition FoldingSet.h:692
T * FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos)
FindNodeOrInsertPos - Look up the node specified by ID.
Definition FoldingSet.h:669
unsigned size() const
size - Returns the number of nodes in the folding set.
Definition FoldingSet.h:698
pointee_iterator< typename VectorT::const_iterator > const_iterator
Definition FoldingSet.h:658
pointee_iterator< typename VectorT::iterator > iterator
Definition FoldingSet.h:653
void clear()
clear - Remove all nodes from the folding set.
Definition FoldingSet.h:664
bool empty() const
empty - Returns true if there are no nodes in the folding set.
Definition FoldingSet.h:701
FoldingSetVector(unsigned Log2InitSize=6)
Definition FoldingSet.h:651
void InsertNode(T *N, void *InsertPos)
InsertNode - Insert the specified node into the folding set, knowing that it is not already in the fo...
Definition FoldingSet.h:685
const_iterator begin() const
Definition FoldingSet.h:660
FoldingSet - This template class is used to instantiate a specialized implementation of the folding s...
Definition FoldingSet.h:535
FoldingSet(FoldingSet &&Arg)=default
FoldingSet(unsigned Log2InitSize=6)
Definition FoldingSet.h:572
FoldingSet & operator=(FoldingSet &&RHS)=default
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI uint64_t xxh3_64bits(ArrayRef< uint8_t > data)
Definition xxhash.cpp:553
FoldingSetBase::Node FoldingSetNode
Definition FoldingSet.h:408
constexpr std::underlying_type_t< Enum > to_underlying(Enum E)
Returns underlying integer value of an enum.
BumpPtrAllocatorImpl BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
Definition Allocator.h:383
@ Ref
The access may reference the value stored in memory.
Definition ModRef.h:32
ArrayRef(const T &OneElt) -> ArrayRef< T >
hash_code hash_combine_range(InputIteratorT first, InputIteratorT last)
Compute a hash_code for a sequence of values.
Definition Hashing.h:466
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:867
#define N
ContextualFoldingSetTrait - Like FoldingSetTrait, but for ContextualFoldingSets.
Definition FoldingSet.h:285
DefaultContextualFoldingSetTrait - Like DefaultFoldingSetTrait, but for ContextualFoldingSets.
Definition FoldingSet.h:271
static bool Equals(T &X, const FoldingSetNodeID &ID, unsigned IDHash, FoldingSetNodeID &TempID, Ctx Context)
Definition FoldingSet.h:430
static void Profile(T &X, FoldingSetNodeID &ID, Ctx Context)
Definition FoldingSet.h:272
static unsigned ComputeHash(T &X, FoldingSetNodeID &TempID, Ctx Context)
Definition FoldingSet.h:440
DefaultFoldingSetTrait - This class provides default implementations for FoldingSetTrait implementati...
Definition FoldingSet.h:236
static void Profile(const T &X, FoldingSetNodeID &ID)
Definition FoldingSet.h:237
static unsigned ComputeHash(T &X, FoldingSetNodeID &TempID)
Definition FoldingSet.h:424
static bool Equals(T &X, const FoldingSetNodeID &ID, unsigned IDHash, FoldingSetNodeID &TempID)
Definition FoldingSet.h:416
static void Profile(T &X, FoldingSetNodeID &ID)
Definition FoldingSet.h:240
Functions provided by the derived class to compute folding properties.
Definition FoldingSet.h:173
unsigned(* ComputeNodeHash)(const FoldingSetBase *Self, Node *N, FoldingSetNodeID &TempID)
ComputeNodeHash - Instantiations of the FoldingSet template implement this function to compute a hash...
Definition FoldingSet.h:187
bool(* NodeEquals)(const FoldingSetBase *Self, Node *N, const FoldingSetNodeID &ID, unsigned IDHash, FoldingSetNodeID &TempID)
NodeEquals - Instantiations of the FoldingSet template implement this function to compare the given n...
Definition FoldingSet.h:181
void(* GetNodeProfile)(const FoldingSetBase *Self, Node *N, FoldingSetNodeID &ID)
GetNodeProfile - Instantiations of the FoldingSet template implement this function to gather data bit...
Definition FoldingSet.h:176
static void Profile(T *X, FoldingSetNodeID &ID)
Definition FoldingSet.h:834
static void Profile(const std::pair< T1, T2 > &P, FoldingSetNodeID &ID)
Definition FoldingSet.h:840
FoldingSetTrait - This trait class is used to define behavior of how to "profile" (in the FoldingSet ...
Definition FoldingSet.h:266
An iterator type that allows iterating over the pointees via some other iterator.
Definition iterator.h:324