diff options
-rw-r--r-- | include/llvm/ADT/FoldingSet.h | 139 | ||||
-rw-r--r-- | lib/Support/FoldingSet.cpp | 87 |
2 files changed, 176 insertions, 50 deletions
diff --git a/include/llvm/ADT/FoldingSet.h b/include/llvm/ADT/FoldingSet.h index 41a34d85ab..662b5e2735 100644 --- a/include/llvm/ADT/FoldingSet.h +++ b/include/llvm/ADT/FoldingSet.h @@ -191,25 +191,75 @@ protected: /// GetNodeProfile - Instantiations of the FoldingSet template implement /// this function to gather data bits for the given node. virtual void GetNodeProfile(Node *N, FoldingSetNodeID &ID) const = 0; + /// NodeEquals - Instantiations of the FoldingSet template implement + /// this function to compare the given node with the given ID. + virtual bool NodeEquals(Node *N, const FoldingSetNodeID &ID, + FoldingSetNodeID &TempID) const=0; + /// NodeEquals - Instantiations of the FoldingSet template implement + /// this function to compute a hash value for the given node. + virtual unsigned ComputeNodeHash(Node *N, + FoldingSetNodeID &TempID) const = 0; }; //===----------------------------------------------------------------------===// + +template<typename T> struct FoldingSetTrait; + +/// DefaultFoldingSetTrait - This class provides default implementations +/// for FoldingSetTrait implementations. +/// +template<typename T> struct DefaultFoldingSetTrait { + static void Profile(const T& X, FoldingSetNodeID& ID) { + X.Profile(ID); + } + static void Profile(T& X, FoldingSetNodeID& ID) { + X.Profile(ID); + } + + // Equals - Test if the profile for X would match ID, using TempID + // to compute a temporary ID if necessary. The default implementation + // just calls Profile and does a regular comparison. Implementations + // can override this to provide more efficient implementations. + static inline bool Equals(T &X, const FoldingSetNodeID &ID, + FoldingSetNodeID &TempID); + + // ComputeHash - Compute a hash value for X, using TempID to + // compute a temporary ID if necessary. The default implementation + // just calls Profile and does a regular hash computation. + // Implementations can override this to provide more efficient + // implementations. + static inline unsigned ComputeHash(T &X, FoldingSetNodeID &TempID); +}; + /// FoldingSetTrait - This trait class is used to define behavior of how /// to "profile" (in the FoldingSet parlance) an object of a given type. /// The default behavior is to invoke a 'Profile' method on an object, but /// through template specialization the behavior can be tailored for specific /// types. Combined with the FoldingSetNodeWrapper class, one can add objects /// to FoldingSets that were not originally designed to have that behavior. -/// -template<typename T> struct FoldingSetTrait { - static inline void Profile(const T& X, FoldingSetNodeID& ID) { X.Profile(ID);} - static inline void Profile(T& X, FoldingSetNodeID& ID) { X.Profile(ID); } - template <typename Ctx> - static inline void Profile(T &X, FoldingSetNodeID &ID, Ctx Context) { +template<typename T> struct FoldingSetTrait + : public DefaultFoldingSetTrait<T> {}; + +template<typename T, typename Ctx> struct ContextualFoldingSetTrait; + +/// DefaultContextualFoldingSetTrait - Like DefaultFoldingSetTrait, but +/// for ContextualFoldingSets. +template<typename T, typename Ctx> +struct DefaultContextualFoldingSetTrait { + static void Profile(T &X, FoldingSetNodeID &ID, Ctx Context) { X.Profile(ID, Context); } + static inline bool Equals(T &X, const FoldingSetNodeID &ID, + FoldingSetNodeID &TempID, Ctx Context); + static inline unsigned ComputeHash(T &X, FoldingSetNodeID &TempID, + Ctx Context); }; +/// ContextualFoldingSetTrait - Like FoldingSetTrait, but for +/// ContextualFoldingSets. +template<typename T, typename Ctx> struct ContextualFoldingSetTrait + : public DefaultContextualFoldingSetTrait<T, Ctx> {}; + //===--------------------------------------------------------------------===// /// FoldingSetNodeIDRef - This class describes a reference to an interned /// FoldingSetNodeID, which can be a useful to store node id data rather @@ -223,6 +273,12 @@ public: FoldingSetNodeIDRef() : Data(0), Size(0) {} FoldingSetNodeIDRef(const unsigned *D, size_t S) : Data(D), Size(S) {} + /// ComputeHash - Compute a strong hash value for this FoldingSetNodeIDRef, + /// used to lookup the node in the FoldingSetImpl. + unsigned ComputeHash() const; + + bool operator==(FoldingSetNodeIDRef) const; + const unsigned *getData() const { return Data; } size_t getSize() const { return Size; } }; @@ -269,6 +325,7 @@ public: /// operator== - Used to compare two nodes to each other. /// bool operator==(const FoldingSetNodeID &RHS) const; + bool operator==(const FoldingSetNodeIDRef RHS) const; /// Intern - Copy this node's data to a memory region allocated from the /// given allocator and return a FoldingSetNodeIDRef describing the @@ -281,6 +338,39 @@ typedef FoldingSetImpl::Node FoldingSetNode; template<class T> class FoldingSetIterator; template<class T> class FoldingSetBucketIterator; +// Definitions of FoldingSetTrait and ContextualFoldingSetTrait functions, which +// require the definition of FoldingSetNodeID. +template<typename T> +inline bool +DefaultFoldingSetTrait<T>::Equals(T &X, const FoldingSetNodeID &ID, + FoldingSetNodeID &TempID) { + FoldingSetTrait<T>::Profile(X, TempID); + return TempID == ID; +} +template<typename T> +inline unsigned +DefaultFoldingSetTrait<T>::ComputeHash(T &X, FoldingSetNodeID &TempID) { + FoldingSetTrait<T>::Profile(X, TempID); + return TempID.ComputeHash(); +} +template<typename T, typename Ctx> +inline bool +DefaultContextualFoldingSetTrait<T, Ctx>::Equals(T &X, + const FoldingSetNodeID &ID, + FoldingSetNodeID &TempID, + Ctx Context) { + ContextualFoldingSetTrait<T, Ctx>::Profile(X, TempID, Context); + return TempID == ID; +} +template<typename T, typename Ctx> +inline unsigned +DefaultContextualFoldingSetTrait<T, Ctx>::ComputeHash(T &X, + FoldingSetNodeID &TempID, + Ctx Context) { + ContextualFoldingSetTrait<T, Ctx>::Profile(X, TempID, Context); + return TempID.ComputeHash(); +} + //===----------------------------------------------------------------------===// /// FoldingSet - This template class is used to instantiate a specialized /// implementation of the folding set to the node class T. T must be a @@ -292,7 +382,21 @@ private: /// way to convert nodes into a unique specifier. virtual void GetNodeProfile(Node *N, FoldingSetNodeID &ID) const { T *TN = static_cast<T *>(N); - FoldingSetTrait<T>::Profile(*TN,ID); + FoldingSetTrait<T>::Profile(*TN, ID); + } + /// NodeEquals - Instantiations may optionally provide a way to compare a + /// node with a specified ID. + virtual bool NodeEquals(Node *N, const FoldingSetNodeID &ID, + FoldingSetNodeID &TempID) const { + T *TN = static_cast<T *>(N); + return FoldingSetTrait<T>::Equals(*TN, ID, TempID); + } + /// NodeEquals - Instantiations may optionally provide a way to compute a + /// hash value directly from a node. + virtual unsigned ComputeNodeHash(Node *N, + FoldingSetNodeID &TempID) const { + T *TN = static_cast<T *>(N); + return FoldingSetTrait<T>::ComputeHash(*TN, TempID); } public: @@ -357,10 +461,18 @@ private: virtual void GetNodeProfile(FoldingSetImpl::Node *N, FoldingSetNodeID &ID) const { T *TN = static_cast<T *>(N); - - // We must use explicit template arguments in case Ctx is a - // reference type. - FoldingSetTrait<T>::template Profile<Ctx>(*TN, ID, Context); + ContextualFoldingSetTrait<T, Ctx>::Profile(*TN, ID, Context); + } + virtual bool NodeEquals(FoldingSetImpl::Node *N, + const FoldingSetNodeID &ID, + FoldingSetNodeID &TempID) const { + T *TN = static_cast<T *>(N); + return ContextualFoldingSetTrait<T, Ctx>::Equals(*TN, ID, TempID, Context); + } + virtual unsigned ComputeNodeHash(FoldingSetImpl::Node *N, + FoldingSetNodeID &TempID) const { + T *TN = static_cast<T *>(N); + return ContextualFoldingSetTrait<T, Ctx>::ComputeHash(*TN, TempID, Context); } public: @@ -549,7 +661,7 @@ class FastFoldingSetNode : public FoldingSetNode { protected: explicit FastFoldingSetNode(const FoldingSetNodeID &ID) : FastID(ID) {} public: - void Profile(FoldingSetNodeID& ID) { ID = FastID; } + void Profile(FoldingSetNodeID& ID) const { ID = FastID; } }; //===----------------------------------------------------------------------===// @@ -559,9 +671,6 @@ template<typename T> struct FoldingSetTrait<T*> { static inline void Profile(const T* X, FoldingSetNodeID& ID) { ID.AddPointer(X); } - static inline void Profile(T* X, FoldingSetNodeID& ID) { - ID.AddPointer(X); - } }; template<typename T> struct FoldingSetTrait<const T*> { diff --git a/lib/Support/FoldingSet.cpp b/lib/Support/FoldingSet.cpp index c1b6511a93..4da220382d 100644 --- a/lib/Support/FoldingSet.cpp +++ b/lib/Support/FoldingSet.cpp @@ -23,6 +23,37 @@ using namespace llvm; //===----------------------------------------------------------------------===// +// FoldingSetNodeIDRef Implementation + +/// ComputeHash - Compute a strong hash value for this FoldingSetNodeIDRef, +/// used to lookup the node in the FoldingSetImpl. +unsigned FoldingSetNodeIDRef::ComputeHash() const { + // This is adapted from SuperFastHash by Paul Hsieh. + unsigned Hash = static_cast<unsigned>(Size); + for (const unsigned *BP = Data, *E = BP+Size; BP != E; ++BP) { + unsigned Data = *BP; + Hash += Data & 0xFFFF; + unsigned Tmp = ((Data >> 16) << 11) ^ Hash; + Hash = (Hash << 16) ^ Tmp; + Hash += Hash >> 11; + } + + // Force "avalanching" of final 127 bits. + Hash ^= Hash << 3; + Hash += Hash >> 5; + Hash ^= Hash << 4; + Hash += Hash >> 17; + Hash ^= Hash << 25; + Hash += Hash >> 6; + return Hash; +} + +bool FoldingSetNodeIDRef::operator==(FoldingSetNodeIDRef RHS) const { + if (Size != RHS.Size) return false; + return memcmp(Data, RHS.Data, Size*sizeof(*Data)) == 0; +} + +//===----------------------------------------------------------------------===// // FoldingSetNodeID Implementation /// Add* - Add various data types to Bit data. @@ -104,31 +135,19 @@ void FoldingSetNodeID::AddString(StringRef String) { /// ComputeHash - Compute a strong hash value for this FoldingSetNodeID, used to /// lookup the node in the FoldingSetImpl. unsigned FoldingSetNodeID::ComputeHash() const { - // This is adapted from SuperFastHash by Paul Hsieh. - unsigned Hash = static_cast<unsigned>(Bits.size()); - for (const unsigned *BP = &Bits[0], *E = BP+Bits.size(); BP != E; ++BP) { - unsigned Data = *BP; - Hash += Data & 0xFFFF; - unsigned Tmp = ((Data >> 16) << 11) ^ Hash; - Hash = (Hash << 16) ^ Tmp; - Hash += Hash >> 11; - } - - // Force "avalanching" of final 127 bits. - Hash ^= Hash << 3; - Hash += Hash >> 5; - Hash ^= Hash << 4; - Hash += Hash >> 17; - Hash ^= Hash << 25; - Hash += Hash >> 6; - return Hash; + return FoldingSetNodeIDRef(&Bits[0], Bits.size()).ComputeHash(); } /// operator== - Used to compare two nodes to each other. /// bool FoldingSetNodeID::operator==(const FoldingSetNodeID &RHS)const{ - if (Bits.size() != RHS.Bits.size()) return false; - return memcmp(&Bits[0], &RHS.Bits[0], Bits.size()*sizeof(Bits[0])) == 0; + return *this == FoldingSetNodeIDRef(&RHS.Bits[0], RHS.Bits.size()); +} + +/// operator== - Used to compare two nodes to each other. +/// +bool FoldingSetNodeID::operator==(FoldingSetNodeIDRef RHS) const { + return FoldingSetNodeIDRef(&Bits[0], Bits.size()) == RHS; } /// Intern - Copy this node's data to a memory region allocated from the @@ -168,10 +187,9 @@ static void **GetBucketPtr(void *NextInBucketPtr) { /// GetBucketFor - Hash the specified node ID and return the hash bucket for /// the specified ID. -static void **GetBucketFor(const FoldingSetNodeID &ID, - void **Buckets, unsigned NumBuckets) { +static void **GetBucketFor(unsigned Hash, void **Buckets, unsigned NumBuckets) { // NumBuckets is always a power of 2. - unsigned BucketNum = ID.ComputeHash() & (NumBuckets-1); + unsigned BucketNum = Hash & (NumBuckets-1); return Buckets + BucketNum; } @@ -219,7 +237,7 @@ void FoldingSetImpl::GrowHashTable() { NumNodes = 0; // Walk the old buckets, rehashing nodes into their new place. - FoldingSetNodeID ID; + FoldingSetNodeID TempID; for (unsigned i = 0; i != OldNumBuckets; ++i) { void *Probe = OldBuckets[i]; if (!Probe) continue; @@ -229,9 +247,10 @@ void FoldingSetImpl::GrowHashTable() { NodeInBucket->SetNextInBucket(0); // Insert the node into the new bucket, after recomputing the hash. - GetNodeProfile(NodeInBucket, ID); - InsertNode(NodeInBucket, GetBucketFor(ID, Buckets, NumBuckets)); - ID.clear(); + InsertNode(NodeInBucket, + GetBucketFor(ComputeNodeHash(NodeInBucket, TempID), + Buckets, NumBuckets)); + TempID.clear(); } } @@ -245,19 +264,18 @@ FoldingSetImpl::Node *FoldingSetImpl::FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) { - void **Bucket = GetBucketFor(ID, Buckets, NumBuckets); + void **Bucket = GetBucketFor(ID.ComputeHash(), Buckets, NumBuckets); void *Probe = *Bucket; InsertPos = 0; - FoldingSetNodeID OtherID; + FoldingSetNodeID TempID; while (Node *NodeInBucket = GetNextPtr(Probe)) { - GetNodeProfile(NodeInBucket, OtherID); - if (OtherID == ID) + if (NodeEquals(NodeInBucket, ID, TempID)) return NodeInBucket; + TempID.clear(); Probe = NodeInBucket->getNextInBucket(); - OtherID.clear(); } // Didn't find the node, return null with the bucket as the InsertPos. @@ -273,9 +291,8 @@ void FoldingSetImpl::InsertNode(Node *N, void *InsertPos) { // Do we need to grow the hashtable? if (NumNodes+1 > NumBuckets*2) { GrowHashTable(); - FoldingSetNodeID ID; - GetNodeProfile(N, ID); - InsertPos = GetBucketFor(ID, Buckets, NumBuckets); + FoldingSetNodeID TempID; + InsertPos = GetBucketFor(ComputeNodeHash(N, TempID), Buckets, NumBuckets); } ++NumNodes; |