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