Make the heuristic for shrinking DenseMap smarter.
[oota-llvm.git] / include / llvm / ADT / DenseMap.h
1 //===- llvm/ADT/DenseMap.h - Dense probed hash table ------------*- 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 DenseMap class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_ADT_DENSEMAP_H
15 #define LLVM_ADT_DENSEMAP_H
16
17 #include "llvm/Support/DataTypes.h"
18 #include "llvm/Support/MathExtras.h"
19 #include <cassert>
20 #include <utility>
21
22 namespace llvm {
23   
24 template<typename T>
25 struct DenseMapKeyInfo {
26   //static inline T getEmptyKey();
27   //static inline T getTombstoneKey();
28   //static unsigned getHashValue(const T &Val);
29   //static bool isPod()
30 };
31
32 // Provide DenseMapKeyInfo for all pointers.
33 template<typename T>
34 struct DenseMapKeyInfo<T*> {
35   static inline T* getEmptyKey() { return (T*)-1; }
36   static inline T* getTombstoneKey() { return (T*)-2; }
37   static unsigned getHashValue(const T *PtrVal) {
38     return (unsigned)((uintptr_t)PtrVal >> 4) ^
39            (unsigned)((uintptr_t)PtrVal >> 9);
40   }
41   static bool isPod() { return true; }
42 };
43
44 template<typename KeyT, typename ValueT, 
45          typename KeyInfoT = DenseMapKeyInfo<KeyT> >
46 class DenseMapIterator;
47 template<typename KeyT, typename ValueT,
48          typename KeyInfoT = DenseMapKeyInfo<KeyT> >
49 class DenseMapConstIterator;
50
51 template<typename KeyT, typename ValueT,
52          typename KeyInfoT = DenseMapKeyInfo<KeyT> >
53 class DenseMap {
54   typedef std::pair<KeyT, ValueT> BucketT;
55   unsigned NumBuckets;
56   BucketT *Buckets;
57   
58   unsigned NumEntries;
59   unsigned NumTombstones;
60   DenseMap(const DenseMap &); // not implemented.
61 public:
62   explicit DenseMap(unsigned NumInitBuckets = 64) {
63     init(NumInitBuckets);
64   }
65   ~DenseMap() {
66     const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();
67     for (BucketT *P = Buckets, *E = Buckets+NumBuckets; P != E; ++P) {
68       if (P->first != EmptyKey && P->first != TombstoneKey)
69         P->second.~ValueT();
70       P->first.~KeyT();
71     }
72     delete[] (char*)Buckets;
73   }
74   
75   typedef DenseMapIterator<KeyT, ValueT, KeyInfoT> iterator;
76   typedef DenseMapConstIterator<KeyT, ValueT, KeyInfoT> const_iterator;
77   inline iterator begin() {
78      return iterator(Buckets, Buckets+NumBuckets);
79   }
80   inline iterator end() {
81     return iterator(Buckets+NumBuckets, Buckets+NumBuckets);
82   }
83   inline const_iterator begin() const {
84     return const_iterator(Buckets, Buckets+NumBuckets);
85   }
86   inline const_iterator end() const {
87     return const_iterator(Buckets+NumBuckets, Buckets+NumBuckets);
88   }
89   
90   bool empty() const { return NumEntries == 0; }
91   unsigned size() const { return NumEntries; }
92   
93   void clear() {
94     if (NumEntries * 4 < NumBuckets && NumBuckets > 64) {
95       shrink_and_clear();
96       return;
97     }
98     
99     const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();
100     for (BucketT *P = Buckets, *E = Buckets+NumBuckets; P != E; ++P) {
101       if (P->first != EmptyKey && P->first != TombstoneKey) {
102         P->first = EmptyKey;
103         P->second.~ValueT();
104         --NumEntries;
105       }
106     }
107     assert(NumEntries == 0 && "Node count imbalance!");
108     NumTombstones = 0;
109   }
110
111   /// count - Return true if the specified key is in the map.
112   bool count(const KeyT &Val) const {
113     BucketT *TheBucket;
114     return LookupBucketFor(Val, TheBucket);
115   }
116   
117   iterator find(const KeyT &Val) {
118     BucketT *TheBucket;
119     if (LookupBucketFor(Val, TheBucket))
120       return iterator(TheBucket, Buckets+NumBuckets);
121     return end();
122   }
123   const_iterator find(const KeyT &Val) const {
124     BucketT *TheBucket;
125     if (LookupBucketFor(Val, TheBucket))
126       return const_iterator(TheBucket, Buckets+NumBuckets);
127     return end();
128   }
129   
130   bool insert(const std::pair<KeyT, ValueT> &KV) {
131     BucketT *TheBucket;
132     if (LookupBucketFor(KV.first, TheBucket))
133       return false; // Already in map.
134     
135     // Otherwise, insert the new element.
136     InsertIntoBucket(KV.first, KV.second, TheBucket);
137     return true;
138   }
139   
140   bool erase(const KeyT &Val) {
141     BucketT *TheBucket;
142     if (!LookupBucketFor(Val, TheBucket))
143       return false; // not in map.
144
145     TheBucket->second.~ValueT();
146     TheBucket->first = getTombstoneKey();
147     --NumEntries;
148     ++NumTombstones;
149     return true;
150   }
151   bool erase(iterator I) {
152     BucketT *TheBucket = &*I;
153     TheBucket->second.~ValueT();
154     TheBucket->first = getTombstoneKey();
155     --NumEntries;
156     ++NumTombstones;
157     return true;
158   }
159   
160   ValueT &operator[](const KeyT &Key) {
161     BucketT *TheBucket;
162     if (LookupBucketFor(Key, TheBucket))
163       return TheBucket->second;
164
165     return InsertIntoBucket(Key, ValueT(), TheBucket)->second;
166   }
167   
168 private:
169   BucketT *InsertIntoBucket(const KeyT &Key, const ValueT &Value,
170                             BucketT *TheBucket) {
171     // If the load of the hash table is more than 3/4, or if fewer than 1/8 of
172     // the buckets are empty (meaning that many are filled with tombstones),
173     // grow the table.
174     //
175     // The later case is tricky.  For example, if we had one empty bucket with
176     // tons of tombstones, failing lookups (e.g. for insertion) would have to
177     // probe almost the entire table until it found the empty bucket.  If the
178     // table completely filled with tombstones, no lookup would ever succeed,
179     // causing infinite loops in lookup.
180     if (NumEntries*4 >= NumBuckets*3 ||
181         NumBuckets-(NumEntries+NumTombstones) < NumBuckets/8) {        
182       this->grow();
183       LookupBucketFor(Key, TheBucket);
184     }
185     ++NumEntries;
186     
187     // If we are writing over a tombstone, remember this.
188     if (TheBucket->first != getEmptyKey())
189       --NumTombstones;
190     
191     TheBucket->first = Key;
192     new (&TheBucket->second) ValueT(Value);
193     return TheBucket;
194   }
195
196   static unsigned getHashValue(const KeyT &Val) {
197     return KeyInfoT::getHashValue(Val);
198   }
199   static const KeyT getEmptyKey() {
200     return KeyInfoT::getEmptyKey();
201   }
202   static const KeyT getTombstoneKey() {
203     return KeyInfoT::getTombstoneKey();
204   }
205   
206   /// LookupBucketFor - Lookup the appropriate bucket for Val, returning it in
207   /// FoundBucket.  If the bucket contains the key and a value, this returns
208   /// true, otherwise it returns a bucket with an empty marker or tombstone and
209   /// returns false.
210   bool LookupBucketFor(const KeyT &Val, BucketT *&FoundBucket) const {
211     unsigned BucketNo = getHashValue(Val);
212     unsigned ProbeAmt = 1;
213     BucketT *BucketsPtr = Buckets;
214     
215     // FoundTombstone - Keep track of whether we find a tombstone while probing.
216     BucketT *FoundTombstone = 0;
217     const KeyT EmptyKey = getEmptyKey();
218     const KeyT TombstoneKey = getTombstoneKey();
219     assert(Val != EmptyKey && Val != TombstoneKey &&
220            "Empty/Tombstone value shouldn't be inserted into map!");
221       
222     while (1) {
223       BucketT *ThisBucket = BucketsPtr + (BucketNo & (NumBuckets-1));
224       // Found Val's bucket?  If so, return it.
225       if (ThisBucket->first == Val) {
226         FoundBucket = ThisBucket;
227         return true;
228       }
229       
230       // If we found an empty bucket, the key doesn't exist in the set.
231       // Insert it and return the default value.
232       if (ThisBucket->first == EmptyKey) {
233         // If we've already seen a tombstone while probing, fill it in instead
234         // of the empty bucket we eventually probed to.
235         if (FoundTombstone) ThisBucket = FoundTombstone;
236         FoundBucket = FoundTombstone ? FoundTombstone : ThisBucket;
237         return false;
238       }
239       
240       // If this is a tombstone, remember it.  If Val ends up not in the map, we
241       // prefer to return it than something that would require more probing.
242       if (ThisBucket->first == TombstoneKey && !FoundTombstone)
243         FoundTombstone = ThisBucket;  // Remember the first tombstone found.
244       
245       // Otherwise, it's a hash collision or a tombstone, continue quadratic
246       // probing.
247       BucketNo += ProbeAmt++;
248     }
249   }
250
251   void init(unsigned InitBuckets) {
252     NumEntries = 0;
253     NumTombstones = 0;
254     NumBuckets = InitBuckets;
255     assert(InitBuckets && (InitBuckets & InitBuckets-1) == 0 &&
256            "# initial buckets must be a power of two!");
257     Buckets = (BucketT*)new char[sizeof(BucketT)*InitBuckets];
258     // Initialize all the keys to EmptyKey.
259     const KeyT EmptyKey = getEmptyKey();
260     for (unsigned i = 0; i != InitBuckets; ++i)
261       new (&Buckets[i].first) KeyT(EmptyKey);
262   }
263   
264   void grow() {
265     unsigned OldNumBuckets = NumBuckets;
266     BucketT *OldBuckets = Buckets;
267     
268     // Double the number of buckets.
269     NumBuckets <<= 1;
270     NumTombstones = 0;
271     Buckets = (BucketT*)new char[sizeof(BucketT)*NumBuckets];
272
273     // Initialize all the keys to EmptyKey.
274     const KeyT EmptyKey = getEmptyKey();
275     for (unsigned i = 0, e = NumBuckets; i != e; ++i)
276       new (&Buckets[i].first) KeyT(EmptyKey);
277
278     // Insert all the old elements.
279     const KeyT TombstoneKey = getTombstoneKey();
280     for (BucketT *B = OldBuckets, *E = OldBuckets+OldNumBuckets; B != E; ++B) {
281       if (B->first != EmptyKey && B->first != TombstoneKey) {
282         // Insert the key/value into the new table.
283         BucketT *DestBucket;
284         bool FoundVal = LookupBucketFor(B->first, DestBucket);
285         FoundVal = FoundVal; // silence warning.
286         assert(!FoundVal && "Key already in new map?");
287         DestBucket->first = B->first;
288         new (&DestBucket->second) ValueT(B->second);
289         
290         // Free the value.
291         B->second.~ValueT();
292       }
293       B->first.~KeyT();
294     }
295     
296     // Free the old table.
297     delete[] (char*)OldBuckets;
298   }
299   
300   void shrink_and_clear() {
301     unsigned OldNumBuckets = NumBuckets;
302     BucketT *OldBuckets = Buckets;
303     
304     // Reduce the number of buckets.
305     NumBuckets = NumEntries > 32 ? 1 << (Log2_32_Ceil(NumEntries) + 1)
306                                  : 64;
307     NumTombstones = 0;
308     Buckets = (BucketT*)new char[sizeof(BucketT)*NumBuckets];
309
310     // Initialize all the keys to EmptyKey.
311     const KeyT EmptyKey = getEmptyKey();
312     for (unsigned i = 0, e = NumBuckets; i != e; ++i)
313       new (&Buckets[i].first) KeyT(EmptyKey);
314
315     // Free the old buckets.
316     const KeyT TombstoneKey = getTombstoneKey();
317     for (BucketT *B = OldBuckets, *E = OldBuckets+OldNumBuckets; B != E; ++B) {
318       if (B->first != EmptyKey && B->first != TombstoneKey) {
319         // Free the value.
320         B->second.~ValueT();
321       }
322       B->first.~KeyT();
323     }
324     
325     // Free the old table.
326     delete[] (char*)OldBuckets;
327     
328     NumEntries = 0;
329   }
330 };
331
332 template<typename KeyT, typename ValueT, typename KeyInfoT>
333 class DenseMapIterator {
334   typedef std::pair<KeyT, ValueT> BucketT;
335 protected:
336   const BucketT *Ptr, *End;
337 public:
338   DenseMapIterator(const BucketT *Pos, const BucketT *E) : Ptr(Pos), End(E) {
339     AdvancePastEmptyBuckets();
340   }
341   
342   std::pair<KeyT, ValueT> &operator*() const {
343     return *const_cast<BucketT*>(Ptr);
344   }
345   std::pair<KeyT, ValueT> *operator->() const {
346     return const_cast<BucketT*>(Ptr);
347   }
348   
349   bool operator==(const DenseMapIterator &RHS) const {
350     return Ptr == RHS.Ptr;
351   }
352   bool operator!=(const DenseMapIterator &RHS) const {
353     return Ptr != RHS.Ptr;
354   }
355   
356   inline DenseMapIterator& operator++() {          // Preincrement
357     ++Ptr;
358     AdvancePastEmptyBuckets();
359     return *this;
360   }
361   DenseMapIterator operator++(int) {        // Postincrement
362     DenseMapIterator tmp = *this; ++*this; return tmp;
363   }
364   
365 private:
366   void AdvancePastEmptyBuckets() {
367     const KeyT Empty = KeyInfoT::getEmptyKey();
368     const KeyT Tombstone = KeyInfoT::getTombstoneKey();
369
370     while (Ptr != End && (Ptr->first == Empty || Ptr->first == Tombstone))
371       ++Ptr;
372   }
373 };
374
375 template<typename KeyT, typename ValueT, typename KeyInfoT>
376 class DenseMapConstIterator : public DenseMapIterator<KeyT, ValueT, KeyInfoT> {
377 public:
378   DenseMapConstIterator(const std::pair<KeyT, ValueT> *Pos,
379                         const std::pair<KeyT, ValueT> *E)
380     : DenseMapIterator<KeyT, ValueT, KeyInfoT>(Pos, E) {
381   }
382   const std::pair<KeyT, ValueT> &operator*() const {
383     return *this->Ptr;
384   }
385   const std::pair<KeyT, ValueT> *operator->() const {
386     return this->Ptr;
387   }
388 };
389
390 } // end namespace llvm
391
392 #endif