FoldingSet.cpp revision ae9f3a3b7c915f725aef5a7250e88eaeddda03c6
158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)//===-- Support/FoldingSet.cpp - Uniquing Hash Set --------------*- C++ -*-===//
258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)//
358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)//                     The LLVM Compiler Infrastructure
458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)//
558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// This file is distributed under the University of Illinois Open Source
658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// License. See LICENSE.TXT for details.
758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)//
858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)//===----------------------------------------------------------------------===//
958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)//
1058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// This file implements a hash set that can be used to remove duplication of
1158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// nodes in a graph.  This code was originally created by Chris Lattner for use
124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// with SelectionDAGCSEMap, but was isolated to provide use across the llvm code
131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// set.
14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)//
15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)//===----------------------------------------------------------------------===//
164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
17d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "llvm/ADT/FoldingSet.h"
184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "llvm/Support/MathExtras.h"
1958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include <cassert>
201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <cstring>
2158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using namespace llvm;
224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)//===----------------------------------------------------------------------===//
244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// FoldingSetNodeID Implementation
256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)/// Add* - Add various data types to Bit data.
274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)///
284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void FoldingSetNodeID::AddPointer(const void *Ptr) {
2958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Note: this adds pointers to the hash using sizes and endianness that
3058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // depend on the host.  It doesn't matter however, because hashing on
314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // pointer values in inherently unstable.  Nothing  should depend on the
324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // ordering of nodes in the folding set.
336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  intptr_t PtrI = (intptr_t)Ptr;
344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Bits.push_back(unsigned(PtrI));
3558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (sizeof(intptr_t) > sizeof(unsigned))
36d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    Bits.push_back(unsigned(uint64_t(PtrI) >> 32));
37d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
38d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void FoldingSetNodeID::AddInteger(signed I) {
39d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  Bits.push_back(I);
4058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void FoldingSetNodeID::AddInteger(unsigned I) {
424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Bits.push_back(I);
434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void FoldingSetNodeID::AddInteger(int64_t I) {
45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  AddInteger((uint64_t)I);
46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void FoldingSetNodeID::AddInteger(uint64_t I) {
484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Bits.push_back(unsigned(I));
494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // If the integer is small, encode it just as 32-bits.
5158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if ((uint64_t)(int)I != I)
5258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    Bits.push_back(unsigned(I >> 32));
5358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
5458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void FoldingSetNodeID::AddFloat(float F) {
5558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  Bits.push_back(FloatToBits(F));
5658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
5758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void FoldingSetNodeID::AddDouble(double D) {
58d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) AddInteger(DoubleToBits(D));
59d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
6058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void FoldingSetNodeID::AddString(const std::string &String) {
61d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  unsigned Size = String.size();
62d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  Bits.push_back(Size);
63d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (!Size) return;
64d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
6558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  unsigned Units = Size / 4;
6658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  unsigned Pos = 0;
6758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const unsigned *Base = (const unsigned *)String.data();
6858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
69d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // If the string is aligned do a bulk transfer.
7058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!((intptr_t)Base & 3)) {
710f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    Bits.append(Base, Base + Units);
720f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    Pos = (Units + 1) * 4;
7358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  } else {
7458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // Otherwise do it the hard way.
7558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    for ( Pos += 4; Pos <= Size; Pos += 4) {
7658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      unsigned V = ((unsigned char)String[Pos - 4] << 24) |
7758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                   ((unsigned char)String[Pos - 3] << 16) |
7858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                   ((unsigned char)String[Pos - 2] << 8) |
7958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                    (unsigned char)String[Pos - 1];
800f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      Bits.push_back(V);
8158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
8258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
8358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
8458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // With the leftover bits.
85d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  unsigned V = 0;
86d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Pos will have overshot size by 4 - #bytes left over.
87d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  switch (Pos - Size) {
88d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  case 1: V = (V << 8) | (unsigned char)String[Size - 3]; // Fall thru.
89d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  case 2: V = (V << 8) | (unsigned char)String[Size - 2]; // Fall thru.
90d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  case 3: V = (V << 8) | (unsigned char)String[Size - 1]; break;
91d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  default: return; // Nothing left.
9258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
9358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
9458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  Bits.push_back(V);
9558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
9658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
9758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)/// ComputeHash - Compute a strong hash value for this FoldingSetNodeID, used to
9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)/// lookup the node in the FoldingSetImpl.
9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)unsigned FoldingSetNodeID::ComputeHash() const {
10058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // This is adapted from SuperFastHash by Paul Hsieh.
10158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  unsigned Hash = Bits.size();
10258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  for (const unsigned *BP = &Bits[0], *E = BP+Bits.size(); BP != E; ++BP) {
10358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    unsigned Data = *BP;
10458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    Hash         += Data & 0xFFFF;
10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    unsigned Tmp  = ((Data >> 16) << 11) ^ Hash;
10658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    Hash          = (Hash << 16) ^ Tmp;
10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    Hash         += Hash >> 11;
10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
10958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
11058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Force "avalanching" of final 127 bits.
11158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  Hash ^= Hash << 3;
11258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  Hash += Hash >> 5;
11358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  Hash ^= Hash << 4;
11458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  Hash += Hash >> 17;
11558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  Hash ^= Hash << 25;
11658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  Hash += Hash >> 6;
11758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return Hash;
11868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
11958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/// operator== - Used to compare two nodes to each other.
12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)///
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool FoldingSetNodeID::operator==(const FoldingSetNodeID &RHS)const{
123d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (Bits.size() != RHS.Bits.size()) return false;
124d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return memcmp(&Bits[0], &RHS.Bits[0], Bits.size()*sizeof(Bits[0])) == 0;
125d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
126d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
12758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
12858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)//===----------------------------------------------------------------------===//
12958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)/// Helper functions for FoldingSetImpl.
13058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
13158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)/// GetNextPtr - In order to save space, each bucket is a
13258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)/// singly-linked-list. In order to make deletion more efficient, we make
13358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)/// the list circular, so we can delete a node without computing its hash.
13458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)/// The problem with this is that the start of the hash buckets are not
13558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)/// Nodes.  If NextInBucketPtr is a bucket pointer, this method returns null:
13658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)/// use GetBucketPtr when this happens.
13758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)static FoldingSetImpl::Node *GetNextPtr(void *NextInBucketPtr) {
13858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // The low bit is set if this is the pointer back to the bucket.
13958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (reinterpret_cast<intptr_t>(NextInBucketPtr) & 1)
14058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return 0;
14158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
14258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return static_cast<FoldingSetImpl::Node*>(NextInBucketPtr);
14358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
14458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
14558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
14658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)/// testing.
14758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)static void **GetBucketPtr(void *NextInBucketPtr) {
14858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  intptr_t Ptr = reinterpret_cast<intptr_t>(NextInBucketPtr);
14958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  assert((Ptr & 1) && "Not a bucket pointer");
15068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return reinterpret_cast<void**>(Ptr & ~intptr_t(1));
15158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
15258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
15358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)/// GetBucketFor - Hash the specified node ID and return the hash bucket for
15458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)/// the specified ID.
155d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)static void **GetBucketFor(const FoldingSetNodeID &ID,
156d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                           void **Buckets, unsigned NumBuckets) {
15758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // NumBuckets is always a power of 2.
15858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  unsigned BucketNum = ID.ComputeHash() & (NumBuckets-1);
15958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return Buckets + BucketNum;
1601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
16158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
16258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)//===----------------------------------------------------------------------===//
16358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// FoldingSetImpl Implementation
16458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
16558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)FoldingSetImpl::FoldingSetImpl(unsigned Log2InitSize) : NumNodes(0) {
1661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  assert(5 < Log2InitSize && Log2InitSize < 32 &&
1671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)         "Initial hash table size out of range");
1681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  NumBuckets = 1 << Log2InitSize;
1691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  Buckets = new void*[NumBuckets+1];
1701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  memset(Buckets, 0, NumBuckets*sizeof(void*));
1711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Set the very last bucket to be a non-null "pointer".
1731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  Buckets[NumBuckets] = reinterpret_cast<void*>(-2);
17458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
17558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)FoldingSetImpl::~FoldingSetImpl() {
17658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  delete [] Buckets;
17758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
17858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)/// GrowHashTable - Double the size of the hash table and rehash everything.
1801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)///
18158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void FoldingSetImpl::GrowHashTable() {
18258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  void **OldBuckets = Buckets;
183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  unsigned OldNumBuckets = NumBuckets;
18458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  NumBuckets <<= 1;
18558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
18658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Reset the node count to zero: we're going to reinsert everything.
18758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  NumNodes = 0;
18858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
18958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Clear out new buckets.
19058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  Buckets = new void*[NumBuckets+1];
19158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  memset(Buckets, 0, NumBuckets*sizeof(void*));
19258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
19358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Set the very last bucket to be a non-null "pointer".
19458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  Buckets[NumBuckets] = reinterpret_cast<void*>(-1);
19558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
19658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Walk the old buckets, rehashing nodes into their new place.
19758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  for (unsigned i = 0; i != OldNumBuckets; ++i) {
198f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    void *Probe = OldBuckets[i];
19958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (!Probe) continue;
200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    while (Node *NodeInBucket = GetNextPtr(Probe)) {
201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // Figure out the next link, remove NodeInBucket from the old link.
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      Probe = NodeInBucket->getNextInBucket();
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      NodeInBucket->SetNextInBucket(0);
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Insert the node into the new bucket, after recomputing the hash.
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      FoldingSetNodeID ID;
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      GetNodeProfile(ID, NodeInBucket);
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      InsertNode(NodeInBucket, GetBucketFor(ID, Buckets, NumBuckets));
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  delete[] OldBuckets;
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/// FindNodeOrInsertPos - Look up the node specified by ID.  If it exists,
216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/// return it.  If not, return the insertion token that will make insertion
217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/// faster.
218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)FoldingSetImpl::Node
219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)*FoldingSetImpl::FindNodeOrInsertPos(const FoldingSetNodeID &ID,
220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                     void *&InsertPos) {
221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  void **Bucket = GetBucketFor(ID, Buckets, NumBuckets);
223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  void *Probe = *Bucket;
224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  InsertPos = 0;
226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  while (Node *NodeInBucket = GetNextPtr(Probe)) {
228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    FoldingSetNodeID OtherID;
229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    GetNodeProfile(OtherID, NodeInBucket);
230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (OtherID == ID)
231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return NodeInBucket;
232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Probe = NodeInBucket->getNextInBucket();
234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Didn't find the node, return null with the bucket as the InsertPos.
237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  InsertPos = Bucket;
238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return 0;
239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
240cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/// InsertNode - Insert the specified node into the folding set, knowing that it
242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/// is not already in the map.  InsertPos must be obtained from
243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/// FindNodeOrInsertPos.
244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void FoldingSetImpl::InsertNode(Node *N, void *InsertPos) {
245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  assert(N->getNextInBucket() == 0);
246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Do we need to grow the hashtable?
247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (NumNodes+1 > NumBuckets*2) {
248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    GrowHashTable();
249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    FoldingSetNodeID ID;
250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    GetNodeProfile(ID, N);
251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    InsertPos = GetBucketFor(ID, Buckets, NumBuckets);
252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ++NumNodes;
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  /// The insert position is actually a bucket pointer.
257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  void **Bucket = static_cast<void**>(InsertPos);
25858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
25958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  void *Next = *Bucket;
260d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
261d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // If this is the first insertion into this bucket, its next pointer will be
262d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // null.  Pretend as if it pointed to itself, setting the low bit to indicate
263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // that it is a pointer to the bucket.
264d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (Next == 0)
265d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    Next = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(Bucket)|1);
266d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
267d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Set the node's next pointer, and make the bucket point to the node.
268d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  N->SetNextInBucket(Next);
2694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  *Bucket = N;
2704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/// RemoveNode - Remove a node from the folding set, returning true if one was
2734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/// removed or false if the node was not in the folding set.
2744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool FoldingSetImpl::RemoveNode(Node *N) {
2754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Because each bucket is a circular list, we don't need to compute N's hash
2764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // to remove it.
2774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  void *Ptr = N->getNextInBucket();
2784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (Ptr == 0) return false;  // Not in folding set.
2794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  --NumNodes;
2814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  N->SetNextInBucket(0);
2824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Remember what N originally pointed to, either a bucket or another node.
2844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  void *NodeNextPtr = Ptr;
2854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Chase around the list until we find the node (or bucket) which points to N.
2874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  while (true) {
2884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (Node *NodeInBucket = GetNextPtr(Ptr)) {
2894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // Advance pointer.
2904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      Ptr = NodeInBucket->getNextInBucket();
2914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // We found a node that points to N, change it to point to N's next node,
2934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // removing N from the list.
2944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      if (Ptr == N) {
2954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        NodeInBucket->SetNextInBucket(NodeNextPtr);
2964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        return true;
2974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      }
2984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    } else {
2994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      void **Bucket = GetBucketPtr(Ptr);
3004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      Ptr = *Bucket;
3014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // If we found that the bucket points to N, update the bucket to point to
3034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // whatever is next.
3044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      if (Ptr == N) {
3054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        *Bucket = NodeNextPtr;
3064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        return true;
3074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      }
3084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
3094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
3104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/// GetOrInsertNode - If there is an existing simple Node exactly
3134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/// equal to the specified node, return it.  Otherwise, insert 'N' and it
3144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/// instead.
3154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)FoldingSetImpl::Node *FoldingSetImpl::GetOrInsertNode(FoldingSetImpl::Node *N) {
3164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  FoldingSetNodeID ID;
3174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  GetNodeProfile(ID, N);
3184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  void *IP;
3191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (Node *E = FindNodeOrInsertPos(ID, IP))
3201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return E;
3211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  InsertNode(N, IP);
3221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return N;
3231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
3244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)//===----------------------------------------------------------------------===//
3264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// FoldingSetIteratorImpl Implementation
3274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)FoldingSetIteratorImpl::FoldingSetIteratorImpl(void **Bucket) {
3294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Skip to the first non-null non-self-cycle bucket.
3306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  while (*Bucket != reinterpret_cast<void*>(-1) &&
3316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)         (*Bucket == 0 || GetNextPtr(*Bucket) == 0))
3326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    ++Bucket;
3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  NodePtr = static_cast<FoldingSetNode*>(*Bucket);
3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void FoldingSetIteratorImpl::advance() {
3384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // If there is another link within this bucket, go to it.
3394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  void *Probe = NodePtr->getNextInBucket();
3404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (FoldingSetNode *NextNodeInBucket = GetNextPtr(Probe))
3424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    NodePtr = NextNodeInBucket;
3434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  else {
3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Otherwise, this is the last link in this bucket.
3454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    void **Bucket = GetBucketPtr(Probe);
3464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Skip to the next non-null non-self-cycle bucket.
3484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    do {
3494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      ++Bucket;
350010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    } while (*Bucket != reinterpret_cast<void*>(-1) &&
351010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)             (*Bucket == 0 || GetNextPtr(*Bucket) == 0));
3524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    NodePtr = static_cast<FoldingSetNode*>(*Bucket);
3544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
3554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)//===----------------------------------------------------------------------===//
358010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// FoldingSetBucketIteratorImpl Implementation
359010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
3604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)FoldingSetBucketIteratorImpl::FoldingSetBucketIteratorImpl(void **Bucket) {
3614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Ptr = (*Bucket == 0 || GetNextPtr(*Bucket) == 0) ? (void*) Bucket : *Bucket;
3624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)