From 18529f35151f18345519e38496ac72350ee15f38 Mon Sep 17 00:00:00 2001 From: Jim Laskey Date: Fri, 27 Oct 2006 18:05:12 +0000 Subject: [PATCH] Apply editorials. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@31218 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ADT/FoldingSet.h | 147 ++++++++++++++-------------------- lib/Support/FoldingSet.cpp | 118 +++++++++++++++------------ 2 files changed, 124 insertions(+), 141 deletions(-) diff --git a/include/llvm/ADT/FoldingSet.h b/include/llvm/ADT/FoldingSet.h index c808d3bebb5..eb361e9ed24 100644 --- a/include/llvm/ADT/FoldingSet.h +++ b/include/llvm/ADT/FoldingSet.h @@ -35,6 +35,8 @@ namespace llvm { /// establish the unique bits of data for the node. The Profile method is /// passed a FoldingSetNodeID object which is used to gather the bits. Just /// call one of the Add* functions defined in the FoldingSetImpl::NodeID class. +/// NOTE: That the folding set does not own the nodes and it is the +/// responsibility of the user to dispose of the nodes. /// /// Eg. /// class MyNode : public FoldingSetNode { @@ -81,7 +83,7 @@ namespace llvm { /// If found then M with be non-NULL, else InsertPoint will point to where it /// should be inserted using InsertNode. /// -/// 3) If you get a NULL result from FindNodeOrInsertPos then you can ass a new +/// 3) If you get a NULL result from FindNodeOrInsertPos then you can as a new /// node with FindNodeOrInsertPos; /// /// InsertNode(N, InsertPoint); @@ -90,7 +92,7 @@ namespace llvm { /// /// bool WasRemoved = RemoveNode(N); /// -/// The result indicates whether the node did exist in the folding set. +/// The result indicates whether the node existed in the folding set. //===----------------------------------------------------------------------===// @@ -102,14 +104,16 @@ namespace llvm { /// class FoldingSetImpl { private: - // Buckets - Array of bucket chains. + /// Buckets - Array of bucket chains. + /// void **Buckets; - // NumBuckets - Length of the Buckets array. Always a power of 2. + /// NumBuckets - Length of the Buckets array. Always a power of 2. + /// unsigned NumBuckets; - // NumNodes - Number of nodes in the folding set. Growth occurs when NumNodes - // is greater than twice teh number of buckets. + /// NumNodes - Number of nodes in the folding set. Growth occurs when NumNodes + /// is greater than twice the number of buckets. unsigned NumNodes; public: @@ -163,16 +167,16 @@ public: /// class Node { private: - // nextInBucket - next linek in the bucket list. - void *nextInBucket; + // NextInFoldingSetBucket - next link in the bucket list. + void *NextInFoldingSetBucket; public: - Node() : nextInBucket(0) {} + Node() : NextInFoldingSetBucket(0) {} // Accessors - void *getNextInBucket() const { return nextInBucket; } - void SetNextInBucket(void *N) { nextInBucket = N; } + void *getNextInBucket() const { return NextInFoldingSetBucket; } + void SetNextInBucket(void *N) { NextInFoldingSetBucket = N; } }; /// RemoveNode - Remove a node from the folding set, returning true if one @@ -194,85 +198,52 @@ public: /// FindNodeOrInsertPos. void InsertNode(Node *N, void *InsertPos); - private: - /// GetNextPtr - In order to save space, each bucket is a - /// singly-linked-list. In order to make deletion more efficient, we make - /// the list circular, so we can delete a node without computing its hash. - /// The problem with this is that the start of the hash buckets are not - /// Nodes. If NextInBucketPtr is a bucket pointer, this method returns null - /// : use GetBucketPtr when this happens. - Node *GetNextPtr(void *NextInBucketPtr); - - /// GetNextPtr - This is just like the previous GetNextPtr implementation, - /// but allows a bucket array to be specified. - Node *GetNextPtr(void *NextInBucketPtr, void **Buckets, unsigned NumBuck); - - /// GetBucketPtr - Provides a casting of a bucket pointer for isNode - /// testing. - void **GetBucketPtr(void *NextInBucketPtr); - - /// GetBucketFor - Hash the specified node ID and return the hash bucket for - /// the specified ID. - void **GetBucketFor(const NodeID &ID) const; - - /// GrowHashTable - Double the size of the hash table and rehash everything. - /// - void GrowHashTable(); - - protected: - - /// GetNodeProfile - Instantiations of the FoldingSet template implement - /// this function to gather data bits for teh given node. - virtual void GetNodeProfile(NodeID &ID, Node *N) = 0; - }; +private: - // Convenence types to hide the implementation of the folding set. - typedef FoldingSetImpl::Node FoldingSetNode; - typedef FoldingSetImpl::NodeID FoldingSetNodeID; - - //===--------------------------------------------------------------------===// - /// FoldingSet - This template class is used to instantiate a specialized - /// implementation of the folding set to the node class T. T must be a - /// subclass of FoldingSetNode and implement a Profile function. + /// GrowHashTable - Double the size of the hash table and rehash everything. /// - template class FoldingSet : public FoldingSetImpl { - private: - /// GetNodeProfile - Each instantiatation of the FoldingSet - virtual void GetNodeProfile(NodeID &ID, Node *N) { - T *TN = static_cast(N); - TN->Profile(ID); - } - - public: - /// RemoveNode - Remove a node from the folding set, returning true if one - /// was removed or false if the node was not in the folding set. - bool RemoveNode(T *N) { - return FoldingSetImpl::RemoveNode(static_cast(N)); - } - - /// GetOrInsertNode - If there is an existing simple Node exactly - /// equal to the specified node, return it. Otherwise, insert 'N' and - /// return it instead. - T *GetOrInsertNode(Node *N) { - return static_cast(FoldingSetImpl::GetOrInsertNode( - static_cast(N))); - } - - /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists, - /// return it. If not, return the insertion token that will make insertion - /// faster. - T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) { - return static_cast(FoldingSetImpl::FindNodeOrInsertPos(ID, - InsertPos)); - } - - /// InsertNode - Insert the specified node into the folding set, knowing - /// that it is not already in the folding set. InsertPos must be obtained - /// from FindNodeOrInsertPos. - void InsertNode(T *N, void *InsertPos) { - FoldingSetImpl::InsertNode(static_cast(N), InsertPos); - } - }; + void GrowHashTable(); + +protected: + + /// GetNodeProfile - Instantiations of the FoldingSet template implement + /// this function to gather data bits for the given node. + virtual void GetNodeProfile(NodeID &ID, Node *N) const = 0; +}; + +// Convenience types to hide the implementation of the folding set. +typedef FoldingSetImpl::Node FoldingSetNode; +typedef FoldingSetImpl::NodeID FoldingSetNodeID; + +//===--------------------------------------------------------------------===// +/// FoldingSet - This template class is used to instantiate a specialized +/// implementation of the folding set to the node class T. T must be a +/// subclass of FoldingSetNode and implement a Profile function. +/// +template class FoldingSet : public FoldingSetImpl { +private: + /// GetNodeProfile - Each instantiatation of the FoldingSet + virtual void GetNodeProfile(NodeID &ID, Node *N) const { + T *TN = static_cast(N); + TN->Profile(ID); + } + +public: + /// GetOrInsertNode - If there is an existing simple Node exactly + /// equal to the specified node, return it. Otherwise, insert 'N' and + /// return it instead. + T *GetOrInsertNode(Node *N) { + return static_cast(FoldingSetImpl::GetOrInsertNode(N)); + } + + /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists, + /// return it. If not, return the insertion token that will make insertion + /// faster. + T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) { + return static_cast(FoldingSetImpl::FindNodeOrInsertPos(ID, + InsertPos)); + } +}; }; // End of namespace llvm. diff --git a/lib/Support/FoldingSet.cpp b/lib/Support/FoldingSet.cpp index 6c1b13f3b29..d8eff37df67 100644 --- a/lib/Support/FoldingSet.cpp +++ b/lib/Support/FoldingSet.cpp @@ -15,9 +15,7 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/FoldingSet.h" - #include "llvm/ADT/MathExtras.h" - using namespace llvm; //===----------------------------------------------------------------------===// @@ -49,21 +47,40 @@ void FoldingSetImpl::NodeID::AddFloat(float F) { Bits.push_back(FloatToBits(F)); } void FoldingSetImpl::NodeID::AddDouble(double D) { - Bits.push_back(DoubleToBits(D)); + AddInteger(DoubleToBits(D)); } void FoldingSetImpl::NodeID::AddString(const std::string &String) { - // Note: An assumption is made here that strings are composed of one byte - // chars. unsigned Size = String.size(); - unsigned Units = Size / sizeof(unsigned); + unsigned Units = Size / 4; + unsigned Pos = 0; const unsigned *Base = (const unsigned *)String.data(); - Bits.insert(Bits.end(), Base, Base + Units); - if (Size & 3) { - unsigned V = 0; - for (unsigned i = Units * sizeof(unsigned); i < Size; ++i) - V = (V << 8) | String[i]; - Bits.push_back(V); + + // If the string is aligned do a bulk transfer. + if (!((intptr_t)Base & 3)) { + Bits.insert(Bits.end(), Base, Base + Units); + Pos = Units * sizeof(unsigned); + } else { + // Otherwise do it the hard way. + for ( Pos += 4; Pos < Size; Pos += 4) { + unsigned V = ((unsigned char)String[Pos - 4] << 24) | + ((unsigned char)String[Pos - 3] << 16) | + ((unsigned char)String[Pos - 2] << 8) | + (unsigned char)String[Pos - 1]; + Bits.push_back(V); + } } + + // With the leftover bits. + unsigned V = 0; + // Pos will have overshot size by 4 - #bytes left over. + switch (Pos - Size) { + case 1: V = (V << 8) | (unsigned char)String[Size - 3]; // Fall thru. + case 2: V = (V << 8) | (unsigned char)String[Size - 2]; // Fall thru. + case 3: V = (V << 8) | (unsigned char)String[Size - 1]; break; + case 0: return; // Nothing left. + } + + Bits.push_back(V); } /// ComputeHash - Compute a strong hash value for this NodeID, used to @@ -97,6 +114,37 @@ bool FoldingSetImpl::NodeID::operator==(const FoldingSetImpl::NodeID &RHS)const{ } +//===----------------------------------------------------------------------===// +/// Helper functions for FoldingSetImpl. + +/// GetNextPtr - In order to save space, each bucket is a +/// singly-linked-list. In order to make deletion more efficient, we make +/// the list circular, so we can delete a node without computing its hash. +/// The problem with this is that the start of the hash buckets are not +/// Nodes. If NextInBucketPtr is a bucket pointer, this method returns null +/// : use GetBucketPtr when this happens. +static FoldingSetImpl::Node *GetNextPtr(void *NextInBucketPtr, + void **Buckets, unsigned NumBuckets) { + if (NextInBucketPtr >= Buckets && NextInBucketPtr < Buckets + NumBuckets) + return 0; + return static_cast(NextInBucketPtr); +} + +/// GetBucketPtr - Provides a casting of a bucket pointer for isNode +/// testing. +static void **GetBucketPtr(void *NextInBucketPtr) { + return static_cast(NextInBucketPtr); +} + +/// GetBucketFor - Hash the specified node ID and return the hash bucket for +/// the specified ID. +static void **GetBucketFor(const FoldingSetImpl::NodeID &ID, + void **Buckets, unsigned NumBuckets) { + // NumBuckets is always a power of 2. + unsigned BucketNum = ID.ComputeHash() & (NumBuckets-1); + return Buckets + BucketNum; +} + //===----------------------------------------------------------------------===// // FoldingSetImpl Implementation @@ -109,42 +157,6 @@ FoldingSetImpl::~FoldingSetImpl() { delete [] Buckets; } -/// GetNextPtr - In order to save space, each bucket is a -/// singly-linked-list. In order to make deletion more efficient, we make -/// the list circular, so we can delete a node without computing its hash. -/// The problem with this is that the start of the hash buckets are not -/// Nodes. If NextInBucketPtr is a bucket pointer, this method returns null -/// : use GetBucketPtr when this happens. -FoldingSetImpl::Node *FoldingSetImpl::GetNextPtr(void *NextInBucketPtr) { - if (NextInBucketPtr >= Buckets && NextInBucketPtr < Buckets+NumBuckets) - return 0; - return static_cast(NextInBucketPtr); -} - -/// GetNextPtr - This is just like the previous GetNextPtr implementation, -/// but allows a bucket array to be specified. -FoldingSetImpl::Node *FoldingSetImpl::GetNextPtr(void *NextInBucketPtr, - void **Bucks, - unsigned NumBuck) { - if (NextInBucketPtr >= Bucks && NextInBucketPtr < Bucks+NumBuck) - return 0; - return static_cast(NextInBucketPtr); -} - -/// GetBucketPtr - Provides a casting of a bucket pointer for isNode -/// testing. -void **FoldingSetImpl::GetBucketPtr(void *NextInBucketPtr) { - return static_cast(NextInBucketPtr); -} - -/// GetBucketFor - Hash the specified node ID and return the hash bucket for -/// the specified ID. -void **FoldingSetImpl::GetBucketFor(const NodeID &ID) const { - // NumBuckets is always a power of 2. - unsigned BucketNum = ID.ComputeHash() & (NumBuckets-1); - return Buckets+BucketNum; -} - /// GrowHashTable - Double the size of the hash table and rehash everything. /// void FoldingSetImpl::GrowHashTable() { @@ -171,7 +183,7 @@ void FoldingSetImpl::GrowHashTable() { // Insert the node into the new bucket, after recomputing the hash. NodeID ID; GetNodeProfile(ID, NodeInBucket); - InsertNode(NodeInBucket, GetBucketFor(ID)); + InsertNode(NodeInBucket, GetBucketFor(ID, Buckets, NumBuckets)); } } @@ -183,12 +195,12 @@ void FoldingSetImpl::GrowHashTable() { /// faster. FoldingSetImpl::Node *FoldingSetImpl::FindNodeOrInsertPos(const NodeID &ID, void *&InsertPos) { - void **Bucket = GetBucketFor(ID); + void **Bucket = GetBucketFor(ID, Buckets, NumBuckets); void *Probe = *Bucket; InsertPos = 0; - while (Node *NodeInBucket = GetNextPtr(Probe)) { + while (Node *NodeInBucket = GetNextPtr(Probe, Buckets, NumBuckets)) { NodeID OtherID; GetNodeProfile(OtherID, NodeInBucket); if (OtherID == ID) @@ -212,7 +224,7 @@ void FoldingSetImpl::InsertNode(Node *N, void *InsertPos) { GrowHashTable(); NodeID ID; GetNodeProfile(ID, N); - InsertPos = GetBucketFor(ID); + InsertPos = GetBucketFor(ID, Buckets, NumBuckets); } /// The insert position is actually a bucket pointer. @@ -244,7 +256,7 @@ bool FoldingSetImpl::RemoveNode(Node *N) { void *NodeNextPtr = Ptr; N->SetNextInBucket(0); while (true) { - if (Node *NodeInBucket = GetNextPtr(Ptr)) { + if (Node *NodeInBucket = GetNextPtr(Ptr, Buckets, NumBuckets)) { // Advance pointer. Ptr = NodeInBucket->getNextInBucket();