14 #ifndef LLVM_ADT_DENSEMAP_H
15 #define LLVM_ADT_DENSEMAP_H
34 template<
typename KeyT,
typename ValueT,
35 typename KeyInfoT = DenseMapInfo<KeyT>,
39 template<
typename DerivedT,
40 typename KeyT,
typename ValueT,
typename KeyInfoT>
58 return iterator(getBucketsEnd(), getBucketsEnd(),
true);
68 return getNumEntries() == 0;
70 unsigned size()
const {
return getNumEntries(); }
74 if (Size > getNumBuckets())
79 if (getNumEntries() == 0 && getNumTombstones() == 0)
return;
83 if (getNumEntries() * 4 < getNumBuckets() && getNumBuckets() > 64) {
89 for (
BucketT *
P = getBuckets(), *E = getBucketsEnd();
P != E; ++
P) {
90 if (!KeyInfoT::isEqual(
P->first, EmptyKey)) {
91 if (!KeyInfoT::isEqual(
P->first, TombstoneKey)) {
93 decrementNumEntries();
98 assert(getNumEntries() == 0 &&
"Node count imbalance!");
105 return LookupBucketFor(Val, TheBucket);
110 if (LookupBucketFor(Val, TheBucket))
111 return iterator(TheBucket, getBucketsEnd(),
true);
116 if (LookupBucketFor(Val, TheBucket))
126 template<
class LookupKeyT>
129 if (LookupBucketFor(Val, TheBucket))
130 return iterator(TheBucket, getBucketsEnd(),
true);
133 template<
class LookupKeyT>
136 if (LookupBucketFor(Val, TheBucket))
145 if (LookupBucketFor(Val, TheBucket))
146 return TheBucket->second;
153 std::pair<iterator, bool>
insert(
const std::pair<KeyT, ValueT> &KV) {
155 if (LookupBucketFor(KV.first, TheBucket))
156 return std::make_pair(
iterator(TheBucket, getBucketsEnd(),
true),
160 TheBucket = InsertIntoBucket(KV.first, KV.second, TheBucket);
161 return std::make_pair(
iterator(TheBucket, getBucketsEnd(),
true),
true);
164 #if LLVM_HAS_RVALUE_REFERENCES
168 std::pair<iterator, bool>
insert(std::pair<KeyT, ValueT> &&KV) {
170 if (LookupBucketFor(KV.first, TheBucket))
171 return std::make_pair(
iterator(TheBucket, getBucketsEnd(),
true),
175 TheBucket = InsertIntoBucket(std::move(KV.first),
176 std::move(KV.second),
178 return std::make_pair(
iterator(TheBucket, getBucketsEnd(),
true),
true);
183 template<
typename InputIt>
192 if (!LookupBucketFor(Val, TheBucket))
195 TheBucket->second.~ValueT();
197 decrementNumEntries();
198 incrementNumTombstones();
203 TheBucket->second.~ValueT();
205 decrementNumEntries();
206 incrementNumTombstones();
211 if (LookupBucketFor(Key, TheBucket))
214 return *InsertIntoBucket(Key, ValueT(), TheBucket);
221 #if LLVM_HAS_RVALUE_REFERENCES
224 if (LookupBucketFor(Key, TheBucket))
227 return *InsertIntoBucket(std::move(Key), ValueT(), TheBucket);
239 return Ptr >= getBuckets() && Ptr < getBucketsEnd();
251 if (getNumBuckets() == 0)
255 for (
BucketT *
P = getBuckets(), *E = getBucketsEnd();
P != E; ++
P) {
256 if (!KeyInfoT::isEqual(
P->first, EmptyKey) &&
257 !KeyInfoT::isEqual(
P->first, TombstoneKey))
263 memset((
void*)getBuckets(), 0x5a,
sizeof(
BucketT)*getNumBuckets());
271 assert((getNumBuckets() & (getNumBuckets()-1)) == 0 &&
272 "# initial buckets must be a power of two!");
274 for (
BucketT *B = getBuckets(), *E = getBucketsEnd(); B != E; ++B)
275 new (&B->first)
KeyT(EmptyKey);
284 for (
BucketT *B = OldBucketsBegin, *E = OldBucketsEnd; B != E; ++B) {
285 if (!KeyInfoT::isEqual(B->first, EmptyKey) &&
286 !KeyInfoT::isEqual(B->first, TombstoneKey)) {
289 bool FoundVal = LookupBucketFor(B->first, DestBucket);
291 assert(!FoundVal &&
"Key already in new map?");
293 new (&DestBucket->second) ValueT(
llvm_move(B->second));
294 incrementNumEntries();
303 if (OldBucketsBegin != OldBucketsEnd)
304 memset((
void*)OldBucketsBegin, 0x5a,
305 sizeof(
BucketT) * (OldBucketsEnd - OldBucketsBegin));
309 template <
typename OtherBaseT>
311 assert(getNumBuckets() == other.getNumBuckets());
313 setNumEntries(other.getNumEntries());
314 setNumTombstones(other.getNumTombstones());
317 memcpy(getBuckets(), other.getBuckets(),
318 getNumBuckets() *
sizeof(
BucketT));
320 for (
size_t i = 0; i < getNumBuckets(); ++i) {
321 new (&getBuckets()[i].first)
KeyT(other.getBuckets()[i].first);
322 if (!KeyInfoT::isEqual(getBuckets()[i].first,
getEmptyKey()) &&
324 new (&getBuckets()[i].second) ValueT(other.getBuckets()[i].second);
329 std::swap(getNumEntries(), RHS.getNumEntries());
330 std::swap(getNumTombstones(), RHS.getNumTombstones());
334 return KeyInfoT::getHashValue(Val);
336 template<
typename LookupKeyT>
338 return KeyInfoT::getHashValue(Val);
341 return KeyInfoT::getEmptyKey();
344 return KeyInfoT::getTombstoneKey();
348 unsigned getNumEntries()
const {
349 return static_cast<const DerivedT *
>(
this)->getNumEntries();
351 void setNumEntries(
unsigned Num) {
352 static_cast<DerivedT *
>(
this)->setNumEntries(Num);
354 void incrementNumEntries() {
355 setNumEntries(getNumEntries() + 1);
357 void decrementNumEntries() {
358 setNumEntries(getNumEntries() - 1);
360 unsigned getNumTombstones()
const {
361 return static_cast<const DerivedT *
>(
this)->getNumTombstones();
363 void setNumTombstones(
unsigned Num) {
364 static_cast<DerivedT *
>(
this)->setNumTombstones(Num);
366 void incrementNumTombstones() {
367 setNumTombstones(getNumTombstones() + 1);
369 void decrementNumTombstones() {
370 setNumTombstones(getNumTombstones() - 1);
372 const BucketT *getBuckets()
const {
373 return static_cast<const DerivedT *
>(
this)->getBuckets();
376 return static_cast<DerivedT *
>(
this)->getBuckets();
378 unsigned getNumBuckets()
const {
379 return static_cast<const DerivedT *
>(
this)->getNumBuckets();
382 return getBuckets() + getNumBuckets();
384 const BucketT *getBucketsEnd()
const {
385 return getBuckets() + getNumBuckets();
388 void grow(
unsigned AtLeast) {
389 static_cast<DerivedT *
>(
this)->grow(AtLeast);
392 void shrink_and_clear() {
393 static_cast<DerivedT *
>(
this)->shrink_and_clear();
397 BucketT *InsertIntoBucket(
const KeyT &Key,
const ValueT &Value,
399 TheBucket = InsertIntoBucketImpl(Key, TheBucket);
401 TheBucket->first = Key;
402 new (&TheBucket->second) ValueT(Value);
406 #if LLVM_HAS_RVALUE_REFERENCES
407 BucketT *InsertIntoBucket(
const KeyT &Key, ValueT &&Value,
409 TheBucket = InsertIntoBucketImpl(Key, TheBucket);
411 TheBucket->first = Key;
412 new (&TheBucket->second) ValueT(std::move(Value));
417 TheBucket = InsertIntoBucketImpl(Key, TheBucket);
419 TheBucket->first = std::move(Key);
420 new (&TheBucket->second) ValueT(std::move(Value));
435 unsigned NewNumEntries = getNumEntries() + 1;
436 unsigned NumBuckets = getNumBuckets();
437 if (NewNumEntries*4 >= NumBuckets*3) {
438 this->grow(NumBuckets * 2);
439 LookupBucketFor(Key, TheBucket);
440 NumBuckets = getNumBuckets();
441 }
else if (NumBuckets-(NewNumEntries+getNumTombstones()) <= NumBuckets/8) {
442 this->grow(NumBuckets);
443 LookupBucketFor(Key, TheBucket);
449 incrementNumEntries();
453 if (!KeyInfoT::isEqual(TheBucket->first, EmptyKey))
454 decrementNumTombstones();
463 template<
typename LookupKeyT>
464 bool LookupBucketFor(
const LookupKeyT &Val,
465 const BucketT *&FoundBucket)
const {
466 const BucketT *BucketsPtr = getBuckets();
467 const unsigned NumBuckets = getNumBuckets();
469 if (NumBuckets == 0) {
475 const BucketT *FoundTombstone = 0;
478 assert(!KeyInfoT::isEqual(Val, EmptyKey) &&
479 !KeyInfoT::isEqual(Val, TombstoneKey) &&
480 "Empty/Tombstone value shouldn't be inserted into map!");
483 unsigned ProbeAmt = 1;
485 const BucketT *ThisBucket = BucketsPtr + BucketNo;
487 if (KeyInfoT::isEqual(Val, ThisBucket->first)) {
488 FoundBucket = ThisBucket;
494 if (KeyInfoT::isEqual(ThisBucket->first, EmptyKey)) {
497 FoundBucket = FoundTombstone ? FoundTombstone : ThisBucket;
503 if (KeyInfoT::isEqual(ThisBucket->first, TombstoneKey) && !FoundTombstone)
504 FoundTombstone = ThisBucket;
508 BucketNo += ProbeAmt++;
509 BucketNo &= (NumBuckets-1);
513 template <
typename LookupKeyT>
514 bool LookupBucketFor(
const LookupKeyT &Val,
BucketT *&FoundBucket) {
515 const BucketT *ConstFoundBucket;
517 ->LookupBucketFor(Val, ConstFoundBucket);
518 FoundBucket =
const_cast<BucketT *
>(ConstFoundBucket);
528 return getNumBuckets() *
sizeof(
BucketT);
532 template<
typename KeyT,
typename ValueT,
533 typename KeyInfoT = DenseMapInfo<KeyT> >
536 KeyT, ValueT, KeyInfoT> {
545 unsigned NumTombstones;
550 init(NumInitBuckets);
558 #if LLVM_HAS_RVALUE_REFERENCES
565 template<
typename InputIt>
573 operator delete(Buckets);
579 std::swap(NumTombstones, RHS.NumTombstones);
588 #if LLVM_HAS_RVALUE_REFERENCES
591 operator delete(Buckets);
600 operator delete(Buckets);
601 if (allocateBuckets(other.NumBuckets)) {
609 void init(
unsigned InitBuckets) {
610 if (allocateBuckets(InitBuckets)) {
619 unsigned OldNumBuckets = NumBuckets;
622 allocateBuckets(std::max<unsigned>(64, static_cast<unsigned>(
NextPowerOf2(AtLeast-1))));
632 operator delete(OldBuckets);
636 unsigned OldNumEntries = NumEntries;
640 unsigned NewNumBuckets = 0;
642 NewNumBuckets = std::max(64, 1 << (
Log2_32_Ceil(OldNumEntries) + 1));
643 if (NewNumBuckets == NumBuckets) {
648 operator delete(Buckets);
653 unsigned getNumEntries()
const {
656 void setNumEntries(
unsigned Num) {
660 unsigned getNumTombstones()
const {
661 return NumTombstones;
663 void setNumTombstones(
unsigned Num) {
667 BucketT *getBuckets()
const {
671 unsigned getNumBuckets()
const {
675 bool allocateBuckets(
unsigned Num) {
677 if (NumBuckets == 0) {
682 Buckets =
static_cast<BucketT*
>(
operator new(
sizeof(BucketT) * NumBuckets));
687 template<
typename KeyT,
typename ValueT,
688 unsigned InlineBuckets = 4,
689 typename KeyInfoT = DenseMapInfo<KeyT> >
691 :
public DenseMapBase<SmallDenseMap<KeyT, ValueT, InlineBuckets, KeyInfoT>,
692 KeyT, ValueT, KeyInfoT> {
700 unsigned NumEntries : 31;
701 unsigned NumTombstones;
714 init(NumInitBuckets);
722 #if LLVM_HAS_RVALUE_REFERENCES
729 template<
typename InputIt>
741 unsigned TmpNumEntries = RHS.NumEntries;
742 RHS.NumEntries = NumEntries;
743 NumEntries = TmpNumEntries;
744 std::swap(NumTombstones, RHS.NumTombstones);
748 if (Small && RHS.Small) {
753 for (
unsigned i = 0, e = InlineBuckets; i != e; ++i) {
754 BucketT *LHSB = &getInlineBuckets()[i],
755 *RHSB = &RHS.getInlineBuckets()[i];
756 bool hasLHSValue = (!KeyInfoT::isEqual(LHSB->first, EmptyKey) &&
757 !KeyInfoT::isEqual(LHSB->first, TombstoneKey));
758 bool hasRHSValue = (!KeyInfoT::isEqual(RHSB->first, EmptyKey) &&
759 !KeyInfoT::isEqual(RHSB->first, TombstoneKey));
760 if (hasLHSValue && hasRHSValue) {
768 new (&RHSB->second) ValueT(
llvm_move(LHSB->second));
769 LHSB->second.~ValueT();
770 }
else if (hasRHSValue) {
771 new (&LHSB->second) ValueT(
llvm_move(RHSB->second));
772 RHSB->second.~ValueT();
777 if (!Small && !RHS.Small) {
778 std::swap(getLargeRep()->Buckets, RHS.getLargeRep()->Buckets);
779 std::swap(getLargeRep()->NumBuckets, RHS.getLargeRep()->NumBuckets);
787 LargeRep TmpRep =
llvm_move(*LargeSide.getLargeRep());
788 LargeSide.getLargeRep()->~LargeRep();
789 LargeSide.Small =
true;
794 for (
unsigned i = 0, e = InlineBuckets; i != e; ++i) {
795 BucketT *NewB = &LargeSide.getInlineBuckets()[i],
796 *OldB = &SmallSide.getInlineBuckets()[i];
799 if (!KeyInfoT::isEqual(NewB->first, EmptyKey) &&
800 !KeyInfoT::isEqual(NewB->first, TombstoneKey)) {
801 new (&NewB->second) ValueT(
llvm_move(OldB->second));
802 OldB->second.~ValueT();
808 SmallSide.Small =
false;
809 new (SmallSide.getLargeRep()) LargeRep(
llvm_move(TmpRep));
817 #if LLVM_HAS_RVALUE_REFERENCES
831 if (other.getNumBuckets() > InlineBuckets) {
833 allocateBuckets(other.getNumBuckets());
838 void init(
unsigned InitBuckets) {
840 if (InitBuckets > InlineBuckets) {
842 new (getLargeRep()) LargeRep(allocateBuckets(InitBuckets));
848 if (AtLeast >= InlineBuckets)
849 AtLeast = std::max<unsigned>(64,
NextPowerOf2(AtLeast-1));
852 if (AtLeast < InlineBuckets)
857 BucketT *TmpBegin =
reinterpret_cast<BucketT *
>(TmpStorage.buffer);
864 for (
BucketT *
P = getBuckets(), *E =
P + InlineBuckets;
P != E; ++
P) {
865 if (!KeyInfoT::isEqual(
P->first, EmptyKey) &&
866 !KeyInfoT::isEqual(
P->first, TombstoneKey)) {
867 assert(
size_t(TmpEnd - TmpBegin) < InlineBuckets &&
868 "Too many inline buckets!");
870 new (&TmpEnd->second) ValueT(
llvm_move(
P->second));
880 new (getLargeRep()) LargeRep(allocateBuckets(AtLeast));
885 LargeRep OldRep =
llvm_move(*getLargeRep());
886 getLargeRep()->~LargeRep();
887 if (AtLeast <= InlineBuckets) {
890 new (getLargeRep()) LargeRep(allocateBuckets(AtLeast));
896 operator delete(OldRep.Buckets);
900 unsigned OldSize = this->
size();
904 unsigned NewNumBuckets = 0;
907 if (NewNumBuckets > InlineBuckets && NewNumBuckets < 64u)
910 if ((Small && NewNumBuckets <= InlineBuckets) ||
911 (!Small && NewNumBuckets == getLargeRep()->NumBuckets)) {
921 unsigned getNumEntries()
const {
924 void setNumEntries(
unsigned Num) {
925 assert(Num < INT_MAX &&
"Cannot support more than INT_MAX entries");
929 unsigned getNumTombstones()
const {
930 return NumTombstones;
932 void setNumTombstones(
unsigned Num) {
936 const BucketT *getInlineBuckets()
const {
941 return reinterpret_cast<const BucketT *
>(storage.buffer);
943 BucketT *getInlineBuckets() {
944 return const_cast<BucketT *
>(
945 const_cast<const SmallDenseMap *
>(
this)->getInlineBuckets());
947 const LargeRep *getLargeRep()
const {
950 return reinterpret_cast<const LargeRep *
>(storage.buffer);
952 LargeRep *getLargeRep() {
953 return const_cast<LargeRep *
>(
957 const BucketT *getBuckets()
const {
958 return Small ? getInlineBuckets() : getLargeRep()->Buckets;
960 BucketT *getBuckets() {
961 return const_cast<BucketT *
>(
964 unsigned getNumBuckets()
const {
965 return Small ? InlineBuckets : getLargeRep()->NumBuckets;
968 void deallocateBuckets() {
972 operator delete(getLargeRep()->Buckets);
973 getLargeRep()->~LargeRep();
976 LargeRep allocateBuckets(
unsigned Num) {
977 assert(Num > InlineBuckets &&
"Must allocate more buckets than are inline");
979 static_cast<BucketT*
>(
operator new(
sizeof(BucketT) * Num)), Num
985 template<
typename KeyT,
typename ValueT,
986 typename KeyInfoT,
bool IsConst>
987 class DenseMapIterator {
988 typedef std::pair<KeyT, ValueT> Bucket;
989 typedef DenseMapIterator<
KeyT, ValueT,
990 KeyInfoT,
true> ConstIterator;
1004 : Ptr(Pos), End(E) {
1005 if (!NoAdvance) AdvancePastEmptyBuckets();
1012 KeyInfoT,
false>&
I)
1013 : Ptr(
I.Ptr), End(
I.End) {}
1023 return Ptr == RHS.operator->();
1026 return Ptr != RHS.operator->();
1031 AdvancePastEmptyBuckets();
1039 void AdvancePastEmptyBuckets() {
1040 const KeyT Empty = KeyInfoT::getEmptyKey();
1041 const KeyT Tombstone = KeyInfoT::getTombstoneKey();
1043 while (Ptr != End &&
1044 (KeyInfoT::isEqual(Ptr->first, Empty) ||
1045 KeyInfoT::isEqual(Ptr->first, Tombstone)))
1050 template<
typename KeyT,
typename ValueT,
typename KeyInfoT>
1051 static inline size_t
std::forward_iterator_tag iterator_category
bool isPointerIntoBucketsArray(const void *Ptr) const
unsigned Log2_32_Ceil(uint32_t Value)
DenseMapIterator operator++(int)
#define LLVM_ATTRIBUTE_UNUSED_RESULT
const_iterator end() const
static unsigned getHashValue(const KeyT &Val)
const_iterator find(const KeyT &Val) const
void init(unsigned InitBuckets)
SmallDenseMap(const InputIt &I, const InputIt &E)
DenseMap & operator=(const DenseMap &other)
DenseMapIterator(const DenseMapIterator< KeyT, ValueT, KeyInfoT, false > &I)
size_t getMemorySize() const
void copyFrom(const DenseMapBase< OtherBaseT, KeyT, ValueT, KeyInfoT > &other)
iterator find_as(const LookupKeyT &Val)
static unsigned getHashValue(const LookupKeyT &Val)
void moveFromOldBuckets(BucketT *OldBucketsBegin, BucketT *OldBucketsEnd)
SmallDenseMap & operator=(const SmallDenseMap &other)
DenseMap(const InputIt &I, const InputIt &E)
pointer operator->() const
bool operator==(const ConstIterator &RHS) const
const void * getPointerIntoBucketsArray() const
SmallDenseMap(unsigned NumInitBuckets=0)
void insert(InputIt I, InputIt E)
insert - Range insertion of pairs.
static const KeyT getEmptyKey()
ValueT & operator[](const KeyT &Key)
bool operator!=(const ConstIterator &RHS) const
void resize(size_t Size)
Grow the densemap so that it has at least Size buckets. Does not shrink.
const_iterator begin() const
const_iterator find_as(const LookupKeyT &Val) const
bool count(const KeyT &Val) const
count - Return true if the specified key is in the map.
uint64_t NextPowerOf2(uint64_t A)
ptrdiff_t difference_type
void grow(unsigned AtLeast)
void grow(unsigned AtLeast)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
DenseMapIterator< KeyT, ValueT, KeyInfoT, true > const_iterator
DenseMapIterator & operator++()
static size_t capacity_in_bytes(const DenseMap< KeyT, ValueT, KeyInfoT > &X)
void copyFrom(const SmallDenseMap &other)
DenseMap(const DenseMap &other)
bool erase(const KeyT &Val)
conditional< IsConst, const Bucket, Bucket >::type value_type
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
DenseMapIterator(pointer Pos, pointer E, bool NoAdvance=false)
DenseMapIterator< KeyT, ValueT, KeyInfoT > iterator
void copyFrom(const DenseMap &other)
void swap(SmallDenseMap &RHS)
value_type & FindAndConstruct(const KeyT &Key)
bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const
void init(unsigned InitBuckets)
std::pair< KeyT, ValueT > BucketT
reference operator*() const
ValueT lookup(const KeyT &Val) const
static const KeyT getTombstoneKey()
void swap(DenseMapBase &RHS)
DenseMap(unsigned NumInitBuckets=0)
iterator find(const KeyT &Val)
SmallDenseMap(const SmallDenseMap &other)
static RegisterPass< NVPTXAllocaHoisting > X("alloca-hoisting","Hoisting alloca instructions in non-entry ""blocks to the entry block")