xref: /aosp_15_r20/external/swiftshader/third_party/llvm-subzero/include/llvm/ADT/DenseMap.h (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1 //===- llvm/ADT/DenseMap.h - Dense probed hash table ------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // 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/ADT/DenseMapInfo.h"
18 #include "llvm/ADT/EpochTracker.h"
19 #include "llvm/Support/AlignOf.h"
20 #include "llvm/Support/Compiler.h"
21 #include "llvm/Support/MathExtras.h"
22 #include "llvm/Support/type_traits.h"
23 #include <algorithm>
24 #include <cassert>
25 #include <cstddef>
26 #include <cstring>
27 #include <iterator>
28 #include <limits>
29 #include <new>
30 #include <utility>
31 
32 namespace llvm {
33 
34 namespace detail {
35 
36 // We extend a pair to allow users to override the bucket type with their own
37 // implementation without requiring two members.
38 template <typename KeyT, typename ValueT>
39 struct DenseMapPair : public std::pair<KeyT, ValueT> {
getFirstDenseMapPair40   KeyT &getFirst() { return std::pair<KeyT, ValueT>::first; }
getFirstDenseMapPair41   const KeyT &getFirst() const { return std::pair<KeyT, ValueT>::first; }
getSecondDenseMapPair42   ValueT &getSecond() { return std::pair<KeyT, ValueT>::second; }
getSecondDenseMapPair43   const ValueT &getSecond() const { return std::pair<KeyT, ValueT>::second; }
44 };
45 
46 } // end namespace detail
47 
48 template <
49     typename KeyT, typename ValueT, typename KeyInfoT = DenseMapInfo<KeyT>,
50     typename Bucket = detail::DenseMapPair<KeyT, ValueT>, bool IsConst = false>
51 class DenseMapIterator;
52 
53 template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
54           typename BucketT>
55 class DenseMapBase : public DebugEpochBase {
56 public:
57   typedef unsigned size_type;
58   typedef KeyT key_type;
59   typedef ValueT mapped_type;
60   typedef BucketT value_type;
61 
62   typedef DenseMapIterator<KeyT, ValueT, KeyInfoT, BucketT> iterator;
63   typedef DenseMapIterator<KeyT, ValueT, KeyInfoT, BucketT, true>
64       const_iterator;
begin()65   inline iterator begin() {
66     // When the map is empty, avoid the overhead of AdvancePastEmptyBuckets().
67     return empty() ? end() : iterator(getBuckets(), getBucketsEnd(), *this);
68   }
end()69   inline iterator end() {
70     return iterator(getBucketsEnd(), getBucketsEnd(), *this, true);
71   }
begin()72   inline const_iterator begin() const {
73     return empty() ? end()
74                    : const_iterator(getBuckets(), getBucketsEnd(), *this);
75   }
end()76   inline const_iterator end() const {
77     return const_iterator(getBucketsEnd(), getBucketsEnd(), *this, true);
78   }
79 
empty()80   LLVM_NODISCARD bool empty() const {
81     return getNumEntries() == 0;
82   }
size()83   unsigned size() const { return getNumEntries(); }
84 
85   /// Grow the densemap so that it can contain at least \p NumEntries items
86   /// before resizing again.
reserve(size_type NumEntries)87   void reserve(size_type NumEntries) {
88     auto NumBuckets = getMinBucketToReserveForEntries(NumEntries);
89     incrementEpoch();
90     if (NumBuckets > getNumBuckets())
91       grow(NumBuckets);
92   }
93 
clear()94   void clear() {
95     incrementEpoch();
96     if (getNumEntries() == 0 && getNumTombstones() == 0) return;
97 
98     // If the capacity of the array is huge, and the # elements used is small,
99     // shrink the array.
100     if (getNumEntries() * 4 < getNumBuckets() && getNumBuckets() > 64) {
101       shrink_and_clear();
102       return;
103     }
104 
105     const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();
106     unsigned NumEntries = getNumEntries();
107     for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) {
108       if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey)) {
109         if (!KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) {
110           P->getSecond().~ValueT();
111           --NumEntries;
112         }
113         P->getFirst() = EmptyKey;
114       }
115     }
116     (void) NumEntries;
117     assert(NumEntries == 0 && "Node count imbalance!");
118     setNumEntries(0);
119     setNumTombstones(0);
120   }
121 
122   /// Return 1 if the specified key is in the map, 0 otherwise.
count(const KeyT & Val)123   size_type count(const KeyT &Val) const {
124     const BucketT *TheBucket;
125     return LookupBucketFor(Val, TheBucket) ? 1 : 0;
126   }
127 
find(const KeyT & Val)128   iterator find(const KeyT &Val) {
129     BucketT *TheBucket;
130     if (LookupBucketFor(Val, TheBucket))
131       return iterator(TheBucket, getBucketsEnd(), *this, true);
132     return end();
133   }
find(const KeyT & Val)134   const_iterator find(const KeyT &Val) const {
135     const BucketT *TheBucket;
136     if (LookupBucketFor(Val, TheBucket))
137       return const_iterator(TheBucket, getBucketsEnd(), *this, true);
138     return end();
139   }
140 
141   /// Alternate version of find() which allows a different, and possibly
142   /// less expensive, key type.
143   /// The DenseMapInfo is responsible for supplying methods
144   /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key
145   /// type used.
146   template<class LookupKeyT>
find_as(const LookupKeyT & Val)147   iterator find_as(const LookupKeyT &Val) {
148     BucketT *TheBucket;
149     if (LookupBucketFor(Val, TheBucket))
150       return iterator(TheBucket, getBucketsEnd(), *this, true);
151     return end();
152   }
153   template<class LookupKeyT>
find_as(const LookupKeyT & Val)154   const_iterator find_as(const LookupKeyT &Val) const {
155     const BucketT *TheBucket;
156     if (LookupBucketFor(Val, TheBucket))
157       return const_iterator(TheBucket, getBucketsEnd(), *this, true);
158     return end();
159   }
160 
161   /// lookup - Return the entry for the specified key, or a default
162   /// constructed value if no such entry exists.
lookup(const KeyT & Val)163   ValueT lookup(const KeyT &Val) const {
164     const BucketT *TheBucket;
165     if (LookupBucketFor(Val, TheBucket))
166       return TheBucket->getSecond();
167     return ValueT();
168   }
169 
170   // Inserts key,value pair into the map if the key isn't already in the map.
171   // If the key is already in the map, it returns false and doesn't update the
172   // value.
insert(const std::pair<KeyT,ValueT> & KV)173   std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) {
174     return try_emplace(KV.first, KV.second);
175   }
176 
177   // Inserts key,value pair into the map if the key isn't already in the map.
178   // If the key is already in the map, it returns false and doesn't update the
179   // value.
insert(std::pair<KeyT,ValueT> && KV)180   std::pair<iterator, bool> insert(std::pair<KeyT, ValueT> &&KV) {
181     return try_emplace(std::move(KV.first), std::move(KV.second));
182   }
183 
184   // Inserts key,value pair into the map if the key isn't already in the map.
185   // The value is constructed in-place if the key is not in the map, otherwise
186   // it is not moved.
187   template <typename... Ts>
try_emplace(KeyT && Key,Ts &&...Args)188   std::pair<iterator, bool> try_emplace(KeyT &&Key, Ts &&... Args) {
189     BucketT *TheBucket;
190     if (LookupBucketFor(Key, TheBucket))
191       return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
192                             false); // Already in map.
193 
194     // Otherwise, insert the new element.
195     TheBucket =
196         InsertIntoBucket(TheBucket, std::move(Key), std::forward<Ts>(Args)...);
197     return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
198                           true);
199   }
200 
201   // Inserts key,value pair into the map if the key isn't already in the map.
202   // The value is constructed in-place if the key is not in the map, otherwise
203   // it is not moved.
204   template <typename... Ts>
try_emplace(const KeyT & Key,Ts &&...Args)205   std::pair<iterator, bool> try_emplace(const KeyT &Key, Ts &&... Args) {
206     BucketT *TheBucket;
207     if (LookupBucketFor(Key, TheBucket))
208       return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
209                             false); // Already in map.
210 
211     // Otherwise, insert the new element.
212     TheBucket = InsertIntoBucket(TheBucket, Key, std::forward<Ts>(Args)...);
213     return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
214                           true);
215   }
216 
217   /// Alternate version of insert() which allows a different, and possibly
218   /// less expensive, key type.
219   /// The DenseMapInfo is responsible for supplying methods
220   /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key
221   /// type used.
222   template <typename LookupKeyT>
insert_as(std::pair<KeyT,ValueT> && KV,const LookupKeyT & Val)223   std::pair<iterator, bool> insert_as(std::pair<KeyT, ValueT> &&KV,
224                                       const LookupKeyT &Val) {
225     BucketT *TheBucket;
226     if (LookupBucketFor(Val, TheBucket))
227       return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
228                             false); // Already in map.
229 
230     // Otherwise, insert the new element.
231     TheBucket = InsertIntoBucketWithLookup(TheBucket, std::move(KV.first),
232                                            std::move(KV.second), Val);
233     return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
234                           true);
235   }
236 
237   /// insert - Range insertion of pairs.
238   template<typename InputIt>
insert(InputIt I,InputIt E)239   void insert(InputIt I, InputIt E) {
240     for (; I != E; ++I)
241       insert(*I);
242   }
243 
erase(const KeyT & Val)244   bool erase(const KeyT &Val) {
245     BucketT *TheBucket;
246     if (!LookupBucketFor(Val, TheBucket))
247       return false; // not in map.
248 
249     TheBucket->getSecond().~ValueT();
250     TheBucket->getFirst() = getTombstoneKey();
251     decrementNumEntries();
252     incrementNumTombstones();
253     return true;
254   }
erase(iterator I)255   void erase(iterator I) {
256     BucketT *TheBucket = &*I;
257     TheBucket->getSecond().~ValueT();
258     TheBucket->getFirst() = getTombstoneKey();
259     decrementNumEntries();
260     incrementNumTombstones();
261   }
262 
FindAndConstruct(const KeyT & Key)263   value_type& FindAndConstruct(const KeyT &Key) {
264     BucketT *TheBucket;
265     if (LookupBucketFor(Key, TheBucket))
266       return *TheBucket;
267 
268     return *InsertIntoBucket(TheBucket, Key);
269   }
270 
271   ValueT &operator[](const KeyT &Key) {
272     return FindAndConstruct(Key).second;
273   }
274 
FindAndConstruct(KeyT && Key)275   value_type& FindAndConstruct(KeyT &&Key) {
276     BucketT *TheBucket;
277     if (LookupBucketFor(Key, TheBucket))
278       return *TheBucket;
279 
280     return *InsertIntoBucket(TheBucket, std::move(Key));
281   }
282 
283   ValueT &operator[](KeyT &&Key) {
284     return FindAndConstruct(std::move(Key)).second;
285   }
286 
287   /// isPointerIntoBucketsArray - Return true if the specified pointer points
288   /// somewhere into the DenseMap's array of buckets (i.e. either to a key or
289   /// value in the DenseMap).
isPointerIntoBucketsArray(const void * Ptr)290   bool isPointerIntoBucketsArray(const void *Ptr) const {
291     return Ptr >= getBuckets() && Ptr < getBucketsEnd();
292   }
293 
294   /// getPointerIntoBucketsArray() - Return an opaque pointer into the buckets
295   /// array.  In conjunction with the previous method, this can be used to
296   /// determine whether an insertion caused the DenseMap to reallocate.
getPointerIntoBucketsArray()297   const void *getPointerIntoBucketsArray() const { return getBuckets(); }
298 
299 protected:
300   DenseMapBase() = default;
301 
destroyAll()302   void destroyAll() {
303     if (getNumBuckets() == 0) // Nothing to do.
304       return;
305 
306     const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();
307     for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) {
308       if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey) &&
309           !KeyInfoT::isEqual(P->getFirst(), TombstoneKey))
310         P->getSecond().~ValueT();
311       P->getFirst().~KeyT();
312     }
313   }
314 
initEmpty()315   void initEmpty() {
316     setNumEntries(0);
317     setNumTombstones(0);
318 
319     assert((getNumBuckets() & (getNumBuckets()-1)) == 0 &&
320            "# initial buckets must be a power of two!");
321     const KeyT EmptyKey = getEmptyKey();
322     for (BucketT *B = getBuckets(), *E = getBucketsEnd(); B != E; ++B)
323       ::new (&B->getFirst()) KeyT(EmptyKey);
324   }
325 
326   /// Returns the number of buckets to allocate to ensure that the DenseMap can
327   /// accommodate \p NumEntries without need to grow().
getMinBucketToReserveForEntries(unsigned NumEntries)328   unsigned getMinBucketToReserveForEntries(unsigned NumEntries) {
329     // Ensure that "NumEntries * 4 < NumBuckets * 3"
330     if (NumEntries == 0)
331       return 0;
332     // +1 is required because of the strict equality.
333     // For example if NumEntries is 48, we need to return 401.
334     return NextPowerOf2(NumEntries * 4 / 3 + 1);
335   }
336 
moveFromOldBuckets(BucketT * OldBucketsBegin,BucketT * OldBucketsEnd)337   void moveFromOldBuckets(BucketT *OldBucketsBegin, BucketT *OldBucketsEnd) {
338     initEmpty();
339 
340     // Insert all the old elements.
341     const KeyT EmptyKey = getEmptyKey();
342     const KeyT TombstoneKey = getTombstoneKey();
343     for (BucketT *B = OldBucketsBegin, *E = OldBucketsEnd; B != E; ++B) {
344       if (!KeyInfoT::isEqual(B->getFirst(), EmptyKey) &&
345           !KeyInfoT::isEqual(B->getFirst(), TombstoneKey)) {
346         // Insert the key/value into the new table.
347         BucketT *DestBucket;
348         bool FoundVal = LookupBucketFor(B->getFirst(), DestBucket);
349         (void)FoundVal; // silence warning.
350         assert(!FoundVal && "Key already in new map?");
351         DestBucket->getFirst() = std::move(B->getFirst());
352         ::new (&DestBucket->getSecond()) ValueT(std::move(B->getSecond()));
353         incrementNumEntries();
354 
355         // Free the value.
356         B->getSecond().~ValueT();
357       }
358       B->getFirst().~KeyT();
359     }
360   }
361 
362   template <typename OtherBaseT>
copyFrom(const DenseMapBase<OtherBaseT,KeyT,ValueT,KeyInfoT,BucketT> & other)363   void copyFrom(
364       const DenseMapBase<OtherBaseT, KeyT, ValueT, KeyInfoT, BucketT> &other) {
365     assert(&other != this);
366     assert(getNumBuckets() == other.getNumBuckets());
367 
368     setNumEntries(other.getNumEntries());
369     setNumTombstones(other.getNumTombstones());
370 
371     if (isPodLike<KeyT>::value && isPodLike<ValueT>::value)
372       memcpy(getBuckets(), other.getBuckets(),
373              getNumBuckets() * sizeof(BucketT));
374     else
375       for (size_t i = 0; i < getNumBuckets(); ++i) {
376         ::new (&getBuckets()[i].getFirst())
377             KeyT(other.getBuckets()[i].getFirst());
378         if (!KeyInfoT::isEqual(getBuckets()[i].getFirst(), getEmptyKey()) &&
379             !KeyInfoT::isEqual(getBuckets()[i].getFirst(), getTombstoneKey()))
380           ::new (&getBuckets()[i].getSecond())
381               ValueT(other.getBuckets()[i].getSecond());
382       }
383   }
384 
getHashValue(const KeyT & Val)385   static unsigned getHashValue(const KeyT &Val) {
386     return KeyInfoT::getHashValue(Val);
387   }
388   template<typename LookupKeyT>
getHashValue(const LookupKeyT & Val)389   static unsigned getHashValue(const LookupKeyT &Val) {
390     return KeyInfoT::getHashValue(Val);
391   }
getEmptyKey()392   static const KeyT getEmptyKey() {
393     return KeyInfoT::getEmptyKey();
394   }
getTombstoneKey()395   static const KeyT getTombstoneKey() {
396     return KeyInfoT::getTombstoneKey();
397   }
398 
399 private:
getNumEntries()400   unsigned getNumEntries() const {
401     return static_cast<const DerivedT *>(this)->getNumEntries();
402   }
setNumEntries(unsigned Num)403   void setNumEntries(unsigned Num) {
404     static_cast<DerivedT *>(this)->setNumEntries(Num);
405   }
incrementNumEntries()406   void incrementNumEntries() {
407     setNumEntries(getNumEntries() + 1);
408   }
decrementNumEntries()409   void decrementNumEntries() {
410     setNumEntries(getNumEntries() - 1);
411   }
getNumTombstones()412   unsigned getNumTombstones() const {
413     return static_cast<const DerivedT *>(this)->getNumTombstones();
414   }
setNumTombstones(unsigned Num)415   void setNumTombstones(unsigned Num) {
416     static_cast<DerivedT *>(this)->setNumTombstones(Num);
417   }
incrementNumTombstones()418   void incrementNumTombstones() {
419     setNumTombstones(getNumTombstones() + 1);
420   }
decrementNumTombstones()421   void decrementNumTombstones() {
422     setNumTombstones(getNumTombstones() - 1);
423   }
getBuckets()424   const BucketT *getBuckets() const {
425     return static_cast<const DerivedT *>(this)->getBuckets();
426   }
getBuckets()427   BucketT *getBuckets() {
428     return static_cast<DerivedT *>(this)->getBuckets();
429   }
getNumBuckets()430   unsigned getNumBuckets() const {
431     return static_cast<const DerivedT *>(this)->getNumBuckets();
432   }
getBucketsEnd()433   BucketT *getBucketsEnd() {
434     return getBuckets() + getNumBuckets();
435   }
getBucketsEnd()436   const BucketT *getBucketsEnd() const {
437     return getBuckets() + getNumBuckets();
438   }
439 
grow(unsigned AtLeast)440   void grow(unsigned AtLeast) {
441     static_cast<DerivedT *>(this)->grow(AtLeast);
442   }
443 
shrink_and_clear()444   void shrink_and_clear() {
445     static_cast<DerivedT *>(this)->shrink_and_clear();
446   }
447 
448   template <typename KeyArg, typename... ValueArgs>
InsertIntoBucket(BucketT * TheBucket,KeyArg && Key,ValueArgs &&...Values)449   BucketT *InsertIntoBucket(BucketT *TheBucket, KeyArg &&Key,
450                             ValueArgs &&... Values) {
451     TheBucket = InsertIntoBucketImpl(Key, Key, TheBucket);
452 
453     TheBucket->getFirst() = std::forward<KeyArg>(Key);
454     ::new (&TheBucket->getSecond()) ValueT(std::forward<ValueArgs>(Values)...);
455     return TheBucket;
456   }
457 
458   template <typename LookupKeyT>
InsertIntoBucketWithLookup(BucketT * TheBucket,KeyT && Key,ValueT && Value,LookupKeyT & Lookup)459   BucketT *InsertIntoBucketWithLookup(BucketT *TheBucket, KeyT &&Key,
460                                       ValueT &&Value, LookupKeyT &Lookup) {
461     TheBucket = InsertIntoBucketImpl(Key, Lookup, TheBucket);
462 
463     TheBucket->getFirst() = std::move(Key);
464     ::new (&TheBucket->getSecond()) ValueT(std::move(Value));
465     return TheBucket;
466   }
467 
468   template <typename LookupKeyT>
InsertIntoBucketImpl(const KeyT & Key,const LookupKeyT & Lookup,BucketT * TheBucket)469   BucketT *InsertIntoBucketImpl(const KeyT &Key, const LookupKeyT &Lookup,
470                                 BucketT *TheBucket) {
471     incrementEpoch();
472 
473     // If the load of the hash table is more than 3/4, or if fewer than 1/8 of
474     // the buckets are empty (meaning that many are filled with tombstones),
475     // grow the table.
476     //
477     // The later case is tricky.  For example, if we had one empty bucket with
478     // tons of tombstones, failing lookups (e.g. for insertion) would have to
479     // probe almost the entire table until it found the empty bucket.  If the
480     // table completely filled with tombstones, no lookup would ever succeed,
481     // causing infinite loops in lookup.
482     unsigned NewNumEntries = getNumEntries() + 1;
483     unsigned NumBuckets = getNumBuckets();
484     if (LLVM_UNLIKELY(NewNumEntries * 4 >= NumBuckets * 3)) {
485       this->grow(NumBuckets * 2);
486       LookupBucketFor(Lookup, TheBucket);
487       NumBuckets = getNumBuckets();
488     } else if (LLVM_UNLIKELY(NumBuckets-(NewNumEntries+getNumTombstones()) <=
489                              NumBuckets/8)) {
490       this->grow(NumBuckets);
491       LookupBucketFor(Lookup, TheBucket);
492     }
493     assert(TheBucket);
494 
495     // Only update the state after we've grown our bucket space appropriately
496     // so that when growing buckets we have self-consistent entry count.
497     incrementNumEntries();
498 
499     // If we are writing over a tombstone, remember this.
500     const KeyT EmptyKey = getEmptyKey();
501     if (!KeyInfoT::isEqual(TheBucket->getFirst(), EmptyKey))
502       decrementNumTombstones();
503 
504     return TheBucket;
505   }
506 
507   /// LookupBucketFor - Lookup the appropriate bucket for Val, returning it in
508   /// FoundBucket.  If the bucket contains the key and a value, this returns
509   /// true, otherwise it returns a bucket with an empty marker or tombstone and
510   /// returns false.
511   template<typename LookupKeyT>
LookupBucketFor(const LookupKeyT & Val,const BucketT * & FoundBucket)512   bool LookupBucketFor(const LookupKeyT &Val,
513                        const BucketT *&FoundBucket) const {
514     const BucketT *BucketsPtr = getBuckets();
515     const unsigned NumBuckets = getNumBuckets();
516 
517     if (NumBuckets == 0) {
518       FoundBucket = nullptr;
519       return false;
520     }
521 
522     // FoundTombstone - Keep track of whether we find a tombstone while probing.
523     const BucketT *FoundTombstone = nullptr;
524     const KeyT EmptyKey = getEmptyKey();
525     const KeyT TombstoneKey = getTombstoneKey();
526     assert(!KeyInfoT::isEqual(Val, EmptyKey) &&
527            !KeyInfoT::isEqual(Val, TombstoneKey) &&
528            "Empty/Tombstone value shouldn't be inserted into map!");
529 
530     unsigned BucketNo = getHashValue(Val) & (NumBuckets-1);
531     unsigned ProbeAmt = 1;
532     while (true) {
533       const BucketT *ThisBucket = BucketsPtr + BucketNo;
534       // Found Val's bucket?  If so, return it.
535       if (LLVM_LIKELY(KeyInfoT::isEqual(Val, ThisBucket->getFirst()))) {
536         FoundBucket = ThisBucket;
537         return true;
538       }
539 
540       // If we found an empty bucket, the key doesn't exist in the set.
541       // Insert it and return the default value.
542       if (LLVM_LIKELY(KeyInfoT::isEqual(ThisBucket->getFirst(), EmptyKey))) {
543         // If we've already seen a tombstone while probing, fill it in instead
544         // of the empty bucket we eventually probed to.
545         FoundBucket = FoundTombstone ? FoundTombstone : ThisBucket;
546         return false;
547       }
548 
549       // If this is a tombstone, remember it.  If Val ends up not in the map, we
550       // prefer to return it than something that would require more probing.
551       if (KeyInfoT::isEqual(ThisBucket->getFirst(), TombstoneKey) &&
552           !FoundTombstone)
553         FoundTombstone = ThisBucket;  // Remember the first tombstone found.
554 
555       // Otherwise, it's a hash collision or a tombstone, continue quadratic
556       // probing.
557       BucketNo += ProbeAmt++;
558       BucketNo &= (NumBuckets-1);
559     }
560   }
561 
562   template <typename LookupKeyT>
LookupBucketFor(const LookupKeyT & Val,BucketT * & FoundBucket)563   bool LookupBucketFor(const LookupKeyT &Val, BucketT *&FoundBucket) {
564     const BucketT *ConstFoundBucket;
565     bool Result = const_cast<const DenseMapBase *>(this)
566       ->LookupBucketFor(Val, ConstFoundBucket);
567     FoundBucket = const_cast<BucketT *>(ConstFoundBucket);
568     return Result;
569   }
570 
571 public:
572   /// Return the approximate size (in bytes) of the actual map.
573   /// This is just the raw memory used by DenseMap.
574   /// If entries are pointers to objects, the size of the referenced objects
575   /// are not included.
getMemorySize()576   size_t getMemorySize() const {
577     return getNumBuckets() * sizeof(BucketT);
578   }
579 };
580 
581 template <typename KeyT, typename ValueT,
582           typename KeyInfoT = DenseMapInfo<KeyT>,
583           typename BucketT = detail::DenseMapPair<KeyT, ValueT>>
584 class DenseMap : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>,
585                                      KeyT, ValueT, KeyInfoT, BucketT> {
586   // Lift some types from the dependent base class into this class for
587   // simplicity of referring to them.
588   typedef DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT> BaseT;
589   friend class DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT>;
590 
591   BucketT *Buckets;
592   unsigned NumEntries;
593   unsigned NumTombstones;
594   unsigned NumBuckets;
595 
596 public:
597   /// Create a DenseMap wth an optional \p InitialReserve that guarantee that
598   /// this number of elements can be inserted in the map without grow()
599   explicit DenseMap(unsigned InitialReserve = 0) { init(InitialReserve); }
600 
DenseMap(const DenseMap & other)601   DenseMap(const DenseMap &other) : BaseT() {
602     init(0);
603     copyFrom(other);
604   }
605 
DenseMap(DenseMap && other)606   DenseMap(DenseMap &&other) : BaseT() {
607     init(0);
608     swap(other);
609   }
610 
611   template<typename InputIt>
DenseMap(const InputIt & I,const InputIt & E)612   DenseMap(const InputIt &I, const InputIt &E) {
613     init(std::distance(I, E));
614     this->insert(I, E);
615   }
616 
~DenseMap()617   ~DenseMap() {
618     this->destroyAll();
619     operator delete(Buckets);
620   }
621 
swap(DenseMap & RHS)622   void swap(DenseMap& RHS) {
623     this->incrementEpoch();
624     RHS.incrementEpoch();
625     std::swap(Buckets, RHS.Buckets);
626     std::swap(NumEntries, RHS.NumEntries);
627     std::swap(NumTombstones, RHS.NumTombstones);
628     std::swap(NumBuckets, RHS.NumBuckets);
629   }
630 
631   DenseMap& operator=(const DenseMap& other) {
632     if (&other != this)
633       copyFrom(other);
634     return *this;
635   }
636 
637   DenseMap& operator=(DenseMap &&other) {
638     this->destroyAll();
639     operator delete(Buckets);
640     init(0);
641     swap(other);
642     return *this;
643   }
644 
copyFrom(const DenseMap & other)645   void copyFrom(const DenseMap& other) {
646     this->destroyAll();
647     operator delete(Buckets);
648     if (allocateBuckets(other.NumBuckets)) {
649       this->BaseT::copyFrom(other);
650     } else {
651       NumEntries = 0;
652       NumTombstones = 0;
653     }
654   }
655 
init(unsigned InitNumEntries)656   void init(unsigned InitNumEntries) {
657     auto InitBuckets = BaseT::getMinBucketToReserveForEntries(InitNumEntries);
658     if (allocateBuckets(InitBuckets)) {
659       this->BaseT::initEmpty();
660     } else {
661       NumEntries = 0;
662       NumTombstones = 0;
663     }
664   }
665 
grow(unsigned AtLeast)666   void grow(unsigned AtLeast) {
667     unsigned OldNumBuckets = NumBuckets;
668     BucketT *OldBuckets = Buckets;
669 
670     allocateBuckets(std::max<unsigned>(64, static_cast<unsigned>(NextPowerOf2(AtLeast-1))));
671     assert(Buckets);
672     if (!OldBuckets) {
673       this->BaseT::initEmpty();
674       return;
675     }
676 
677     this->moveFromOldBuckets(OldBuckets, OldBuckets+OldNumBuckets);
678 
679     // Free the old table.
680     operator delete(OldBuckets);
681   }
682 
shrink_and_clear()683   void shrink_and_clear() {
684     unsigned OldNumEntries = NumEntries;
685     this->destroyAll();
686 
687     // Reduce the number of buckets.
688     unsigned NewNumBuckets = 0;
689     if (OldNumEntries)
690       NewNumBuckets = std::max(64, 1 << (Log2_32_Ceil(OldNumEntries) + 1));
691     if (NewNumBuckets == NumBuckets) {
692       this->BaseT::initEmpty();
693       return;
694     }
695 
696     operator delete(Buckets);
697     init(NewNumBuckets);
698   }
699 
700 private:
getNumEntries()701   unsigned getNumEntries() const {
702     return NumEntries;
703   }
setNumEntries(unsigned Num)704   void setNumEntries(unsigned Num) {
705     NumEntries = Num;
706   }
707 
getNumTombstones()708   unsigned getNumTombstones() const {
709     return NumTombstones;
710   }
setNumTombstones(unsigned Num)711   void setNumTombstones(unsigned Num) {
712     NumTombstones = Num;
713   }
714 
getBuckets()715   BucketT *getBuckets() const {
716     return Buckets;
717   }
718 
getNumBuckets()719   unsigned getNumBuckets() const {
720     return NumBuckets;
721   }
722 
allocateBuckets(unsigned Num)723   bool allocateBuckets(unsigned Num) {
724     NumBuckets = Num;
725     if (NumBuckets == 0) {
726       Buckets = nullptr;
727       return false;
728     }
729 
730     Buckets = static_cast<BucketT*>(operator new(sizeof(BucketT) * NumBuckets));
731     return true;
732   }
733 };
734 
735 template <typename KeyT, typename ValueT, unsigned InlineBuckets = 4,
736           typename KeyInfoT = DenseMapInfo<KeyT>,
737           typename BucketT = detail::DenseMapPair<KeyT, ValueT>>
738 class SmallDenseMap
739     : public DenseMapBase<
740           SmallDenseMap<KeyT, ValueT, InlineBuckets, KeyInfoT, BucketT>, KeyT,
741           ValueT, KeyInfoT, BucketT> {
742   // Lift some types from the dependent base class into this class for
743   // simplicity of referring to them.
744   typedef DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT, BucketT> BaseT;
745   friend class DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT, BucketT>;
746   static_assert(isPowerOf2_64(InlineBuckets),
747                 "InlineBuckets must be a power of 2.");
748 
749   unsigned Small : 1;
750   unsigned NumEntries : 31;
751   unsigned NumTombstones;
752 
753   struct LargeRep {
754     BucketT *Buckets;
755     unsigned NumBuckets;
756   };
757 
758   /// A "union" of an inline bucket array and the struct representing
759   /// a large bucket. This union will be discriminated by the 'Small' bit.
760   AlignedCharArrayUnion<BucketT[InlineBuckets], LargeRep> storage;
761 
762 public:
763   explicit SmallDenseMap(unsigned NumInitBuckets = 0) {
764     init(NumInitBuckets);
765   }
766 
SmallDenseMap(const SmallDenseMap & other)767   SmallDenseMap(const SmallDenseMap &other) : BaseT() {
768     init(0);
769     copyFrom(other);
770   }
771 
SmallDenseMap(SmallDenseMap && other)772   SmallDenseMap(SmallDenseMap &&other) : BaseT() {
773     init(0);
774     swap(other);
775   }
776 
777   template<typename InputIt>
SmallDenseMap(const InputIt & I,const InputIt & E)778   SmallDenseMap(const InputIt &I, const InputIt &E) {
779     init(NextPowerOf2(std::distance(I, E)));
780     this->insert(I, E);
781   }
782 
~SmallDenseMap()783   ~SmallDenseMap() {
784     this->destroyAll();
785     deallocateBuckets();
786   }
787 
swap(SmallDenseMap & RHS)788   void swap(SmallDenseMap& RHS) {
789     unsigned TmpNumEntries = RHS.NumEntries;
790     RHS.NumEntries = NumEntries;
791     NumEntries = TmpNumEntries;
792     std::swap(NumTombstones, RHS.NumTombstones);
793 
794     const KeyT EmptyKey = this->getEmptyKey();
795     const KeyT TombstoneKey = this->getTombstoneKey();
796     if (Small && RHS.Small) {
797       // If we're swapping inline bucket arrays, we have to cope with some of
798       // the tricky bits of DenseMap's storage system: the buckets are not
799       // fully initialized. Thus we swap every key, but we may have
800       // a one-directional move of the value.
801       for (unsigned i = 0, e = InlineBuckets; i != e; ++i) {
802         BucketT *LHSB = &getInlineBuckets()[i],
803                 *RHSB = &RHS.getInlineBuckets()[i];
804         bool hasLHSValue = (!KeyInfoT::isEqual(LHSB->getFirst(), EmptyKey) &&
805                             !KeyInfoT::isEqual(LHSB->getFirst(), TombstoneKey));
806         bool hasRHSValue = (!KeyInfoT::isEqual(RHSB->getFirst(), EmptyKey) &&
807                             !KeyInfoT::isEqual(RHSB->getFirst(), TombstoneKey));
808         if (hasLHSValue && hasRHSValue) {
809           // Swap together if we can...
810           std::swap(*LHSB, *RHSB);
811           continue;
812         }
813         // Swap separately and handle any assymetry.
814         std::swap(LHSB->getFirst(), RHSB->getFirst());
815         if (hasLHSValue) {
816           ::new (&RHSB->getSecond()) ValueT(std::move(LHSB->getSecond()));
817           LHSB->getSecond().~ValueT();
818         } else if (hasRHSValue) {
819           ::new (&LHSB->getSecond()) ValueT(std::move(RHSB->getSecond()));
820           RHSB->getSecond().~ValueT();
821         }
822       }
823       return;
824     }
825     if (!Small && !RHS.Small) {
826       std::swap(getLargeRep()->Buckets, RHS.getLargeRep()->Buckets);
827       std::swap(getLargeRep()->NumBuckets, RHS.getLargeRep()->NumBuckets);
828       return;
829     }
830 
831     SmallDenseMap &SmallSide = Small ? *this : RHS;
832     SmallDenseMap &LargeSide = Small ? RHS : *this;
833 
834     // First stash the large side's rep and move the small side across.
835     LargeRep TmpRep = std::move(*LargeSide.getLargeRep());
836     LargeSide.getLargeRep()->~LargeRep();
837     LargeSide.Small = true;
838     // This is similar to the standard move-from-old-buckets, but the bucket
839     // count hasn't actually rotated in this case. So we have to carefully
840     // move construct the keys and values into their new locations, but there
841     // is no need to re-hash things.
842     for (unsigned i = 0, e = InlineBuckets; i != e; ++i) {
843       BucketT *NewB = &LargeSide.getInlineBuckets()[i],
844               *OldB = &SmallSide.getInlineBuckets()[i];
845       ::new (&NewB->getFirst()) KeyT(std::move(OldB->getFirst()));
846       OldB->getFirst().~KeyT();
847       if (!KeyInfoT::isEqual(NewB->getFirst(), EmptyKey) &&
848           !KeyInfoT::isEqual(NewB->getFirst(), TombstoneKey)) {
849         ::new (&NewB->getSecond()) ValueT(std::move(OldB->getSecond()));
850         OldB->getSecond().~ValueT();
851       }
852     }
853 
854     // The hard part of moving the small buckets across is done, just move
855     // the TmpRep into its new home.
856     SmallSide.Small = false;
857     new (SmallSide.getLargeRep()) LargeRep(std::move(TmpRep));
858   }
859 
860   SmallDenseMap& operator=(const SmallDenseMap& other) {
861     if (&other != this)
862       copyFrom(other);
863     return *this;
864   }
865 
866   SmallDenseMap& operator=(SmallDenseMap &&other) {
867     this->destroyAll();
868     deallocateBuckets();
869     init(0);
870     swap(other);
871     return *this;
872   }
873 
copyFrom(const SmallDenseMap & other)874   void copyFrom(const SmallDenseMap& other) {
875     this->destroyAll();
876     deallocateBuckets();
877     Small = true;
878     if (other.getNumBuckets() > InlineBuckets) {
879       Small = false;
880       new (getLargeRep()) LargeRep(allocateBuckets(other.getNumBuckets()));
881     }
882     this->BaseT::copyFrom(other);
883   }
884 
init(unsigned InitBuckets)885   void init(unsigned InitBuckets) {
886     Small = true;
887     if (InitBuckets > InlineBuckets) {
888       Small = false;
889       new (getLargeRep()) LargeRep(allocateBuckets(InitBuckets));
890     }
891     this->BaseT::initEmpty();
892   }
893 
grow(unsigned AtLeast)894   void grow(unsigned AtLeast) {
895     if (AtLeast >= InlineBuckets)
896       AtLeast = std::max<unsigned>(64, NextPowerOf2(AtLeast-1));
897 
898     if (Small) {
899       if (AtLeast < InlineBuckets)
900         return; // Nothing to do.
901 
902       // First move the inline buckets into a temporary storage.
903       AlignedCharArrayUnion<BucketT[InlineBuckets]> TmpStorage;
904       BucketT *TmpBegin = reinterpret_cast<BucketT *>(TmpStorage.buffer);
905       BucketT *TmpEnd = TmpBegin;
906 
907       // Loop over the buckets, moving non-empty, non-tombstones into the
908       // temporary storage. Have the loop move the TmpEnd forward as it goes.
909       const KeyT EmptyKey = this->getEmptyKey();
910       const KeyT TombstoneKey = this->getTombstoneKey();
911       for (BucketT *P = getBuckets(), *E = P + InlineBuckets; P != E; ++P) {
912         if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey) &&
913             !KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) {
914           assert(size_t(TmpEnd - TmpBegin) < InlineBuckets &&
915                  "Too many inline buckets!");
916           ::new (&TmpEnd->getFirst()) KeyT(std::move(P->getFirst()));
917           ::new (&TmpEnd->getSecond()) ValueT(std::move(P->getSecond()));
918           ++TmpEnd;
919           P->getSecond().~ValueT();
920         }
921         P->getFirst().~KeyT();
922       }
923 
924       // Now make this map use the large rep, and move all the entries back
925       // into it.
926       Small = false;
927       new (getLargeRep()) LargeRep(allocateBuckets(AtLeast));
928       this->moveFromOldBuckets(TmpBegin, TmpEnd);
929       return;
930     }
931 
932     LargeRep OldRep = std::move(*getLargeRep());
933     getLargeRep()->~LargeRep();
934     if (AtLeast <= InlineBuckets) {
935       Small = true;
936     } else {
937       new (getLargeRep()) LargeRep(allocateBuckets(AtLeast));
938     }
939 
940     this->moveFromOldBuckets(OldRep.Buckets, OldRep.Buckets+OldRep.NumBuckets);
941 
942     // Free the old table.
943     operator delete(OldRep.Buckets);
944   }
945 
shrink_and_clear()946   void shrink_and_clear() {
947     unsigned OldSize = this->size();
948     this->destroyAll();
949 
950     // Reduce the number of buckets.
951     unsigned NewNumBuckets = 0;
952     if (OldSize) {
953       NewNumBuckets = 1 << (Log2_32_Ceil(OldSize) + 1);
954       if (NewNumBuckets > InlineBuckets && NewNumBuckets < 64u)
955         NewNumBuckets = 64;
956     }
957     if ((Small && NewNumBuckets <= InlineBuckets) ||
958         (!Small && NewNumBuckets == getLargeRep()->NumBuckets)) {
959       this->BaseT::initEmpty();
960       return;
961     }
962 
963     deallocateBuckets();
964     init(NewNumBuckets);
965   }
966 
967 private:
getNumEntries()968   unsigned getNumEntries() const {
969     return NumEntries;
970   }
setNumEntries(unsigned Num)971   void setNumEntries(unsigned Num) {
972     // NumEntries is hardcoded to be 31 bits wide.
973     assert(Num < (1U << 31) && "Cannot support more than 1<<31 entries");
974     NumEntries = Num;
975   }
976 
getNumTombstones()977   unsigned getNumTombstones() const {
978     return NumTombstones;
979   }
setNumTombstones(unsigned Num)980   void setNumTombstones(unsigned Num) {
981     NumTombstones = Num;
982   }
983 
getInlineBuckets()984   const BucketT *getInlineBuckets() const {
985     assert(Small);
986     // Note that this cast does not violate aliasing rules as we assert that
987     // the memory's dynamic type is the small, inline bucket buffer, and the
988     // 'storage.buffer' static type is 'char *'.
989     return reinterpret_cast<const BucketT *>(storage.buffer);
990   }
getInlineBuckets()991   BucketT *getInlineBuckets() {
992     return const_cast<BucketT *>(
993       const_cast<const SmallDenseMap *>(this)->getInlineBuckets());
994   }
getLargeRep()995   const LargeRep *getLargeRep() const {
996     assert(!Small);
997     // Note, same rule about aliasing as with getInlineBuckets.
998     return reinterpret_cast<const LargeRep *>(storage.buffer);
999   }
getLargeRep()1000   LargeRep *getLargeRep() {
1001     return const_cast<LargeRep *>(
1002       const_cast<const SmallDenseMap *>(this)->getLargeRep());
1003   }
1004 
getBuckets()1005   const BucketT *getBuckets() const {
1006     return Small ? getInlineBuckets() : getLargeRep()->Buckets;
1007   }
getBuckets()1008   BucketT *getBuckets() {
1009     return const_cast<BucketT *>(
1010       const_cast<const SmallDenseMap *>(this)->getBuckets());
1011   }
getNumBuckets()1012   unsigned getNumBuckets() const {
1013     return Small ? InlineBuckets : getLargeRep()->NumBuckets;
1014   }
1015 
deallocateBuckets()1016   void deallocateBuckets() {
1017     if (Small)
1018       return;
1019 
1020     operator delete(getLargeRep()->Buckets);
1021     getLargeRep()->~LargeRep();
1022   }
1023 
allocateBuckets(unsigned Num)1024   LargeRep allocateBuckets(unsigned Num) {
1025     assert(Num > InlineBuckets && "Must allocate more buckets than are inline");
1026     LargeRep Rep = {
1027       static_cast<BucketT*>(operator new(sizeof(BucketT) * Num)), Num
1028     };
1029     return Rep;
1030   }
1031 };
1032 
1033 template <typename KeyT, typename ValueT, typename KeyInfoT, typename Bucket,
1034           bool IsConst>
1035 class DenseMapIterator : DebugEpochBase::HandleBase {
1036   typedef DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true> ConstIterator;
1037   friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true>;
1038   friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, false>;
1039 
1040 public:
1041   typedef ptrdiff_t difference_type;
1042   typedef typename std::conditional<IsConst, const Bucket, Bucket>::type
1043   value_type;
1044   typedef value_type *pointer;
1045   typedef value_type &reference;
1046   typedef std::forward_iterator_tag iterator_category;
1047 
1048 private:
1049   pointer Ptr, End;
1050 
1051 public:
DenseMapIterator()1052   DenseMapIterator() : Ptr(nullptr), End(nullptr) {}
1053 
1054   DenseMapIterator(pointer Pos, pointer E, const DebugEpochBase &Epoch,
1055                    bool NoAdvance = false)
1056       : DebugEpochBase::HandleBase(&Epoch), Ptr(Pos), End(E) {
1057     assert(isHandleInSync() && "invalid construction!");
1058     if (!NoAdvance) AdvancePastEmptyBuckets();
1059   }
1060 
1061   // Converting ctor from non-const iterators to const iterators. SFINAE'd out
1062   // for const iterator destinations so it doesn't end up as a user defined copy
1063   // constructor.
1064   template <bool IsConstSrc,
1065             typename = typename std::enable_if<!IsConstSrc && IsConst>::type>
DenseMapIterator(const DenseMapIterator<KeyT,ValueT,KeyInfoT,Bucket,IsConstSrc> & I)1066   DenseMapIterator(
1067       const DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, IsConstSrc> &I)
1068       : DebugEpochBase::HandleBase(I), Ptr(I.Ptr), End(I.End) {}
1069 
1070   reference operator*() const {
1071     assert(isHandleInSync() && "invalid iterator access!");
1072     return *Ptr;
1073   }
1074   pointer operator->() const {
1075     assert(isHandleInSync() && "invalid iterator access!");
1076     return Ptr;
1077   }
1078 
1079   bool operator==(const ConstIterator &RHS) const {
1080     assert((!Ptr || isHandleInSync()) && "handle not in sync!");
1081     assert((!RHS.Ptr || RHS.isHandleInSync()) && "handle not in sync!");
1082     assert(getEpochAddress() == RHS.getEpochAddress() &&
1083            "comparing incomparable iterators!");
1084     return Ptr == RHS.Ptr;
1085   }
1086   bool operator!=(const ConstIterator &RHS) const {
1087     assert((!Ptr || isHandleInSync()) && "handle not in sync!");
1088     assert((!RHS.Ptr || RHS.isHandleInSync()) && "handle not in sync!");
1089     assert(getEpochAddress() == RHS.getEpochAddress() &&
1090            "comparing incomparable iterators!");
1091     return Ptr != RHS.Ptr;
1092   }
1093 
1094   inline DenseMapIterator& operator++() {  // Preincrement
1095     assert(isHandleInSync() && "invalid iterator access!");
1096     ++Ptr;
1097     AdvancePastEmptyBuckets();
1098     return *this;
1099   }
1100   DenseMapIterator operator++(int) {  // Postincrement
1101     assert(isHandleInSync() && "invalid iterator access!");
1102     DenseMapIterator tmp = *this; ++*this; return tmp;
1103   }
1104 
1105 private:
AdvancePastEmptyBuckets()1106   void AdvancePastEmptyBuckets() {
1107     const KeyT Empty = KeyInfoT::getEmptyKey();
1108     const KeyT Tombstone = KeyInfoT::getTombstoneKey();
1109 
1110     while (Ptr != End && (KeyInfoT::isEqual(Ptr->getFirst(), Empty) ||
1111                           KeyInfoT::isEqual(Ptr->getFirst(), Tombstone)))
1112       ++Ptr;
1113   }
1114 };
1115 
1116 template<typename KeyT, typename ValueT, typename KeyInfoT>
1117 static inline size_t
capacity_in_bytes(const DenseMap<KeyT,ValueT,KeyInfoT> & X)1118 capacity_in_bytes(const DenseMap<KeyT, ValueT, KeyInfoT> &X) {
1119   return X.getMemorySize();
1120 }
1121 
1122 } // end namespace llvm
1123 
1124 #endif // LLVM_ADT_DENSEMAP_H
1125