//
//===----------------------------------------------------------------------===//
+#define DEBUG_TYPE "foldingset"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/Debug.h"
+#include <cassert>
using namespace llvm;
//===----------------------------------------------------------------------===//
}
void FoldingSetImpl::NodeID::AddInteger(uint64_t I) {
Bits.push_back(unsigned(I));
- Bits.push_back(unsigned(I >> 32));
+
+ // If the integer is small, encode it just as 32-bits.
+ if ((uint64_t)(int)I != I)
+ Bits.push_back(unsigned(I >> 32));
}
void FoldingSetImpl::NodeID::AddFloat(float F) {
Bits.push_back(FloatToBits(F));
}
void FoldingSetImpl::NodeID::AddString(const std::string &String) {
unsigned Size = String.size();
+ Bits.push_back(Size);
+ if (!Size) return;
+
unsigned Units = Size / 4;
unsigned Pos = 0;
const unsigned *Base = (const unsigned *)String.data();
// If the string is aligned do a bulk transfer.
-#if 0 // FIXME - Add insert to SmallVector (tested with vector)
if (!((intptr_t)Base & 3)) {
- Bits.insert(Bits.end(), Base, Base + Units);
- Pos = Units * sizeof(unsigned);
+ Bits.append(Base, Base + Units);
+ Pos = (Units + 1) * 4;
} else {
-#else
- }
-#endif
// Otherwise do it the hard way.
- for ( Pos += 4; Pos < Size; Pos += 4) {
+ 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) |
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.
+ default: return; // Nothing left.
}
Bits.push_back(V);
/// 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.
+/// 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)
//===----------------------------------------------------------------------===//
// FoldingSetImpl Implementation
-FoldingSetImpl::FoldingSetImpl() : NumNodes(0) {
- NumBuckets = 64;
+FoldingSetImpl::FoldingSetImpl(unsigned Log2InitSize) : NumNodes(0) {
+ assert(5 < Log2InitSize && Log2InitSize < 32 &&
+ "Initial hash table size out of range");
+ NumBuckets = 1 << Log2InitSize;
Buckets = new void*[NumBuckets];
memset(Buckets, 0, NumBuckets*sizeof(void*));
}
for (unsigned i = 0; i != OldNumBuckets; ++i) {
void *Probe = OldBuckets[i];
if (!Probe) continue;
- while (Node *NodeInBucket = GetNextPtr(Probe, OldBuckets, OldNumBuckets)){
+ while (Node *NodeInBucket = GetNextPtr(Probe, OldBuckets, OldNumBuckets)) {
// Figure out the next link, remove NodeInBucket from the old link.
Probe = NodeInBucket->getNextInBucket();
NodeInBucket->SetNextInBucket(0);
/// is not already in the map. InsertPos must be obtained from
/// FindNodeOrInsertPos.
void FoldingSetImpl::InsertNode(Node *N, void *InsertPos) {
- ++NumNodes;
+ assert(N->getNextInBucket() == 0);
// Do we need to grow the hashtable?
- if (NumNodes > NumBuckets*2) {
+ DEBUG(DOUT << "INSERT: " << N << '\n');
+ if (NumNodes+1 > NumBuckets*2) {
GrowHashTable();
NodeID ID;
GetNodeProfile(ID, N);
InsertPos = GetBucketFor(ID, Buckets, NumBuckets);
}
+
+ ++NumNodes;
/// The insert position is actually a bucket pointer.
void **Bucket = static_cast<void**>(InsertPos);
if (Next == 0)
Next = Bucket;
- // Set the nodes next pointer, and make the bucket point to the node.
+ // Set the node's next pointer, and make the bucket point to the node.
N->SetNextInBucket(Next);
*Bucket = N;
}
/// removed or false if the node was not in the folding set.
bool FoldingSetImpl::RemoveNode(Node *N) {
// Because each bucket is a circular list, we don't need to compute N's hash
- // to remove it. Chase around the list until we find the node (or bucket)
- // which points to N.
+ // to remove it.
+ DEBUG(DOUT << "REMOVE: " << N << '\n');
void *Ptr = N->getNextInBucket();
if (Ptr == 0) return false; // Not in folding set.
--NumNodes;
+ N->SetNextInBucket(0);
+ // Remember what N originally pointed to, either a bucket or another node.
void *NodeNextPtr = Ptr;
- N->SetNextInBucket(0);
+
+ // Chase around the list until we find the node (or bucket) which points to N.
while (true) {
if (Node *NodeInBucket = GetNextPtr(Ptr, Buckets, NumBuckets)) {
// Advance pointer.