LCOV - code coverage report
Current view: top level - llvm/ADT - FoldingSet.h (source / functions) Hit Total Coverage
Test: clang.info Lines: 0 2 0.0 %
Date: 2016-01-31 12:01:00 Functions: 0 6 0.0 %

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

Generated by: LCOV version 1.11