Fix a limitation of SmallPtrSet. Before it would assert if the smallsize
[oota-llvm.git] / include / llvm / ADT / SmallPtrSet.h
1 //===- llvm/ADT/SmallPtrSet.h - 'Normally small' pointer set ----*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by Chris Lattner and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines the SmallPtrSet class.  See the doxygen comment for
11 // SmallPtrSetImpl for more details on the algorithm used.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #ifndef LLVM_ADT_SMALLPTRSET_H
16 #define LLVM_ADT_SMALLPTRSET_H
17
18 #include <cassert>
19 #include <cstring>
20
21 namespace llvm {
22
23 /// SmallPtrSetImpl - This is the common code shared among all the
24 /// SmallPtrSet<>'s, which is almost everything.  SmallPtrSet has two modes, one
25 /// for small and one for large sets.
26 ///
27 /// Small sets use an array of pointers allocated in the SmallPtrSet object,
28 /// which is treated as a simple array of pointers.  When a pointer is added to
29 /// the set, the array is scanned to see if the element already exists, if not
30 /// the element is 'pushed back' onto the array.  If we run out of space in the
31 /// array, we grow into the 'large set' case.  SmallSet should be used when the
32 /// sets are often small.  In this case, no memory allocation is used, and only
33 /// light-weight and cache-efficient scanning is used.
34 ///
35 /// Large sets use a classic exponentially-probed hash table.  Empty buckets are
36 /// represented with an illegal pointer value (-1) to allow null pointers to be
37 /// inserted.  Tombstones are represented with another illegal pointer value
38 /// (-2), to allow deletion.  The hash table is resized when the table is 3/4 or
39 /// more.  When this happens, the table is doubled in size.
40 ///
41 class SmallPtrSetImpl {
42 protected:
43   /// CurArray - This is the current set of buckets.  If it points to
44   /// SmallArray, then the set is in 'small mode'.
45   void **CurArray;
46   /// CurArraySize - The allocated size of CurArray, always a power of two.
47   /// Note that CurArray points to an array that has CurArraySize+1 elements in
48   /// it, so that the end iterator actually points to valid memory.
49   unsigned CurArraySize;
50   
51   // If small, this is # elts allocated consequtively
52   unsigned NumElements;
53   void *SmallArray[1];  // Must be last ivar.
54 public:
55   SmallPtrSetImpl(unsigned SmallSize) {
56     assert(SmallSize && (SmallSize & (SmallSize-1)) == 0 &&
57            "Initial size must be a power of two!");
58     CurArray = &SmallArray[0];
59     CurArraySize = SmallSize;
60     // The end pointer, always valid, is set to a valid element to help the
61     // iterator.
62     CurArray[SmallSize] = 0;
63     clear();
64   }
65   ~SmallPtrSetImpl() {
66     if (!isSmall())
67       delete[] CurArray;
68   }
69   
70   bool isSmall() const { return CurArray == &SmallArray[0]; }
71
72   static void *getTombstoneMarker() { return reinterpret_cast<void*>(-2); }
73   static void *getEmptyMarker() {
74     // Note that -1 is chosen to make clear() efficiently implementable with
75     // memset and because it's not a valid pointer value.
76     return reinterpret_cast<void*>(-1);
77   }
78   
79   void clear() {
80     // Fill the array with empty markers.
81     memset(CurArray, -1, CurArraySize*sizeof(void*));
82     NumElements = 0;
83   }
84   
85   /// insert - This returns true if the pointer was new to the set, false if it
86   /// was already in the set.
87   bool insert(void *Ptr);
88   
89   bool count(void *Ptr) const {
90     if (isSmall()) {
91       // Linear search for the item.
92       for (void *const *APtr = SmallArray, *const *E = SmallArray+NumElements;
93            APtr != E; ++APtr)
94         if (*APtr == Ptr)
95           return true;
96       return false;
97     }
98     
99     // Big set case.
100     return *FindBucketFor(Ptr) == Ptr;
101   }
102   
103 private:
104   unsigned Hash(void *Ptr) const {
105     return ((uintptr_t)Ptr >> 4) & (CurArraySize-1);
106   }
107   void * const *FindBucketFor(void *Ptr) const;
108   
109   /// Grow - Allocate a larger backing store for the buckets and move it over.
110   void Grow();
111 };
112
113 /// SmallPtrSetIteratorImpl - This is the common base class shared between all
114 /// instances of SmallPtrSetIterator.
115 class SmallPtrSetIteratorImpl {
116 protected:
117   void *const *Bucket;
118 public:
119   SmallPtrSetIteratorImpl(void *const *BP) : Bucket(BP) {
120     AdvanceIfNotValid();
121   }
122   
123   bool operator==(const SmallPtrSetIteratorImpl &RHS) const {
124     return Bucket == RHS.Bucket;
125   }
126   bool operator!=(const SmallPtrSetIteratorImpl &RHS) const {
127     return Bucket != RHS.Bucket;
128   }
129   
130 protected:
131   /// AdvanceIfNotValid - If the current bucket isn't valid, advance to a bucket
132   /// that is.   This is guaranteed to stop because the end() bucket is marked
133   /// valid.
134   void AdvanceIfNotValid() {
135     while (*Bucket == SmallPtrSetImpl::getEmptyMarker() ||
136            *Bucket == SmallPtrSetImpl::getTombstoneMarker())
137       ++Bucket;
138   }
139 };
140
141 /// SmallPtrSetIterator - This implements a const_iterator for SmallPtrSet.
142 template<typename PtrTy>
143 class SmallPtrSetIterator : public SmallPtrSetIteratorImpl {
144 public:
145   SmallPtrSetIterator(void *const *BP) : SmallPtrSetIteratorImpl(BP) {}
146
147   // Most methods provided by baseclass.
148   
149   PtrTy operator*() const {
150     return static_cast<PtrTy>(*Bucket);
151   }
152   
153   inline SmallPtrSetIterator& operator++() {          // Preincrement
154     ++Bucket;
155     AdvanceIfNotValid();
156     return *this;
157   }
158   
159   SmallPtrSetIterator operator++(int) {        // Postincrement
160     SmallPtrSetIterator tmp = *this; ++*this; return tmp;
161   }
162 };
163
164 /// NextPowerOfTwo - This is a helper template that rounds N up to the next
165 /// power of two.
166 template<unsigned N>
167 struct NextPowerOfTwo;
168
169 /// NextPowerOfTwoH - If N is not a power of two, increase it.  This is a helper
170 /// template used to implement NextPowerOfTwo.
171 template<unsigned N, bool isPowerTwo>
172 struct NextPowerOfTwoH {
173   enum { Val = N };
174 };
175 template<unsigned N>
176 struct NextPowerOfTwoH<N, false> {
177   enum {
178     // We could just use NextVal = N+1, but this converges faster.  N|(N-1) sets
179     // the right-most zero bits to one all at once, e.g. 0b0011000 -> 0b0011111.
180     NextVal = (N|(N-1)) + 1,
181     Val = NextPowerOfTwo<NextVal>::Val
182   };
183 };
184
185 template<unsigned N>
186 struct NextPowerOfTwo {
187   enum { Val = NextPowerOfTwoH<N, (N&(N-1)) == 0>::Val };
188 };
189
190
191 /// SmallPtrSet - This class implements 
192 template<class PtrType, unsigned SmallSize>
193 class SmallPtrSet : public SmallPtrSetImpl {
194   // Make sure that SmallSize is a power of two, round up if not.
195   enum { SmallSizePowTwo = NextPowerOfTwo<SmallSize>::Val };
196   void *SmallArray[SmallSizePowTwo];
197 public:
198   SmallPtrSet() : SmallPtrSetImpl(NextPowerOfTwo<SmallSizePowTwo>::Val) {}
199   
200   typedef SmallPtrSetIterator<PtrType> iterator;
201   typedef SmallPtrSetIterator<PtrType> const_iterator;
202   inline iterator begin() const {
203     return iterator(CurArray);
204   }
205   inline iterator end() const {
206     return iterator(CurArray+CurArraySize);
207   }
208 };
209
210 }
211
212 #endif