14#ifndef LLVM_ADT_DENSEMAP_H
15#define LLVM_ADT_DENSEMAP_H
29#include <initializer_list>
41template <
typename KeyT,
typename ValueT>
46 const KeyT &
getFirst()
const {
return std::pair<KeyT, ValueT>::first; }
54 typename KeyInfoT = DenseMapInfo<KeyT>,
57class DenseMapIterator;
59template <
typename DerivedT,
typename KeyT,
typename ValueT,
typename KeyInfoT,
80 if (shouldReverseIterate<KeyT>())
81 return makeIterator(getBucketsEnd() - 1, getBuckets(), *
this);
82 return makeIterator(getBuckets(), getBucketsEnd(), *
this);
85 return makeIterator(getBucketsEnd(), getBucketsEnd(), *
this,
true);
90 if (shouldReverseIterate<KeyT>())
91 return makeConstIterator(getBucketsEnd() - 1, getBuckets(), *
this);
92 return makeConstIterator(getBuckets(), getBucketsEnd(), *
this);
95 return makeConstIterator(getBucketsEnd(), getBucketsEnd(), *
this,
true);
98 [[nodiscard]]
bool empty()
const {
return getNumEntries() == 0; }
99 unsigned size()
const {
return getNumEntries(); }
106 if (NumBuckets > getNumBuckets())
112 if (getNumEntries() == 0 && getNumTombstones() == 0)
return;
116 if (getNumEntries() * 4 < getNumBuckets() && getNumBuckets() > 64) {
122 if (std::is_trivially_destructible<ValueT>::value) {
124 for (BucketT *
P = getBuckets(), *
E = getBucketsEnd();
P !=
E; ++
P)
125 P->getFirst() = EmptyKey;
127 unsigned NumEntries = getNumEntries();
128 for (BucketT *
P = getBuckets(), *
E = getBucketsEnd();
P !=
E; ++
P) {
129 if (!KeyInfoT::isEqual(
P->getFirst(), EmptyKey)) {
130 if (!KeyInfoT::isEqual(
P->getFirst(), TombstoneKey)) {
131 P->getSecond().~ValueT();
134 P->getFirst() = EmptyKey;
137 assert(NumEntries == 0 &&
"Node count imbalance!");
146 const BucketT *TheBucket;
147 return LookupBucketFor(Val, TheBucket);
157 if (LookupBucketFor(Val, TheBucket))
158 return makeIterator(TheBucket,
159 shouldReverseIterate<KeyT>() ? getBuckets()
165 const BucketT *TheBucket;
166 if (LookupBucketFor(Val, TheBucket))
167 return makeConstIterator(TheBucket,
168 shouldReverseIterate<KeyT>() ? getBuckets()
179 template<
class LookupKeyT>
182 if (LookupBucketFor(Val, TheBucket))
183 return makeIterator(TheBucket,
184 shouldReverseIterate<KeyT>() ? getBuckets()
189 template<
class LookupKeyT>
191 const BucketT *TheBucket;
192 if (LookupBucketFor(Val, TheBucket))
193 return makeConstIterator(TheBucket,
194 shouldReverseIterate<KeyT>() ? getBuckets()
203 const BucketT *TheBucket;
204 if (LookupBucketFor(Val, TheBucket))
205 return TheBucket->getSecond();
211 const ValueT &
at(const_arg_type_t<KeyT> Val)
const {
212 auto Iter = this->
find(std::move(Val));
213 assert(Iter != this->
end() &&
"DenseMap::at failed due to a missing key");
220 std::pair<iterator, bool>
insert(
const std::pair<KeyT, ValueT> &KV) {
227 std::pair<iterator, bool>
insert(std::pair<KeyT, ValueT> &&KV) {
228 return try_emplace(std::move(KV.first), std::move(KV.second));
234 template <
typename... Ts>
237 if (LookupBucketFor(Key, TheBucket))
238 return std::make_pair(makeIterator(TheBucket,
239 shouldReverseIterate<KeyT>()
247 InsertIntoBucket(TheBucket, std::move(Key), std::forward<Ts>(Args)...);
248 return std::make_pair(makeIterator(TheBucket,
249 shouldReverseIterate<KeyT>()
259 template <
typename... Ts>
262 if (LookupBucketFor(Key, TheBucket))
263 return std::make_pair(makeIterator(TheBucket,
264 shouldReverseIterate<KeyT>()
271 TheBucket = InsertIntoBucket(TheBucket, Key, std::forward<Ts>(Args)...);
272 return std::make_pair(makeIterator(TheBucket,
273 shouldReverseIterate<KeyT>()
285 template <
typename LookupKeyT>
286 std::pair<iterator, bool>
insert_as(std::pair<KeyT, ValueT> &&KV,
287 const LookupKeyT &Val) {
289 if (LookupBucketFor(Val, TheBucket))
290 return std::make_pair(makeIterator(TheBucket,
291 shouldReverseIterate<KeyT>()
298 TheBucket = InsertIntoBucketWithLookup(TheBucket, std::move(KV.first),
299 std::move(KV.second), Val);
300 return std::make_pair(makeIterator(TheBucket,
301 shouldReverseIterate<KeyT>()
309 template<
typename InputIt>
331 if (!LookupBucketFor(Val, TheBucket))
334 TheBucket->getSecond().~ValueT();
336 decrementNumEntries();
337 incrementNumTombstones();
341 BucketT *TheBucket = &*
I;
342 TheBucket->getSecond().~ValueT();
344 decrementNumEntries();
345 incrementNumTombstones();
350 if (LookupBucketFor(Key, TheBucket))
353 return *InsertIntoBucket(TheBucket, Key);
362 if (LookupBucketFor(Key, TheBucket))
365 return *InsertIntoBucket(TheBucket, std::move(Key));
376 return Ptr >= getBuckets() &&
Ptr < getBucketsEnd();
388 if (getNumBuckets() == 0)
392 for (BucketT *
P = getBuckets(), *
E = getBucketsEnd();
P !=
E; ++
P) {
393 if (!KeyInfoT::isEqual(
P->getFirst(), EmptyKey) &&
394 !KeyInfoT::isEqual(
P->getFirst(), TombstoneKey))
395 P->getSecond().~ValueT();
396 P->getFirst().~KeyT();
404 assert((getNumBuckets() & (getNumBuckets()-1)) == 0 &&
405 "# initial buckets must be a power of two!");
407 for (BucketT *
B = getBuckets(), *
E = getBucketsEnd();
B !=
E; ++
B)
408 ::new (&
B->getFirst())
KeyT(EmptyKey);
428 for (BucketT *
B = OldBucketsBegin, *
E = OldBucketsEnd;
B !=
E; ++
B) {
429 if (!KeyInfoT::isEqual(
B->getFirst(), EmptyKey) &&
430 !KeyInfoT::isEqual(
B->getFirst(), TombstoneKey)) {
433 bool FoundVal = LookupBucketFor(
B->getFirst(), DestBucket);
435 assert(!FoundVal &&
"Key already in new map?");
436 DestBucket->getFirst() = std::move(
B->getFirst());
437 ::new (&DestBucket->getSecond())
ValueT(std::move(
B->getSecond()));
438 incrementNumEntries();
441 B->getSecond().~ValueT();
443 B->getFirst().~KeyT();
447 template <
typename OtherBaseT>
451 assert(getNumBuckets() == other.getNumBuckets());
453 setNumEntries(other.getNumEntries());
454 setNumTombstones(other.getNumTombstones());
456 if (std::is_trivially_copyable<KeyT>::value &&
457 std::is_trivially_copyable<ValueT>::value)
458 memcpy(
reinterpret_cast<void *
>(getBuckets()), other.getBuckets(),
459 getNumBuckets() *
sizeof(BucketT));
461 for (
size_t i = 0; i < getNumBuckets(); ++i) {
462 ::new (&getBuckets()[i].getFirst())
463 KeyT(other.getBuckets()[i].getFirst());
464 if (!KeyInfoT::isEqual(getBuckets()[i].getFirst(),
getEmptyKey()) &&
466 ::new (&getBuckets()[i].getSecond())
467 ValueT(other.getBuckets()[i].getSecond());
472 return KeyInfoT::getHashValue(Val);
475 template<
typename LookupKeyT>
477 return KeyInfoT::getHashValue(Val);
481 static_assert(std::is_base_of<DenseMapBase, DerivedT>::value,
482 "Must pass the derived type to this template!");
483 return KeyInfoT::getEmptyKey();
487 return KeyInfoT::getTombstoneKey();
493 bool NoAdvance=
false) {
494 if (shouldReverseIterate<KeyT>()) {
495 BucketT *
B =
P == getBucketsEnd() ? getBuckets() :
P + 1;
502 const DebugEpochBase &Epoch,
503 const bool NoAdvance=
false)
const {
504 if (shouldReverseIterate<KeyT>()) {
505 const BucketT *
B =
P == getBucketsEnd() ? getBuckets() :
P + 1;
511 unsigned getNumEntries()
const {
512 return static_cast<const DerivedT *
>(
this)->getNumEntries();
515 void setNumEntries(
unsigned Num) {
516 static_cast<DerivedT *
>(
this)->setNumEntries(Num);
519 void incrementNumEntries() {
520 setNumEntries(getNumEntries() + 1);
523 void decrementNumEntries() {
524 setNumEntries(getNumEntries() - 1);
527 unsigned getNumTombstones()
const {
528 return static_cast<const DerivedT *
>(
this)->getNumTombstones();
531 void setNumTombstones(
unsigned Num) {
532 static_cast<DerivedT *
>(
this)->setNumTombstones(Num);
535 void incrementNumTombstones() {
536 setNumTombstones(getNumTombstones() + 1);
539 void decrementNumTombstones() {
540 setNumTombstones(getNumTombstones() - 1);
543 const BucketT *getBuckets()
const {
544 return static_cast<const DerivedT *
>(
this)->getBuckets();
547 BucketT *getBuckets() {
548 return static_cast<DerivedT *
>(
this)->getBuckets();
551 unsigned getNumBuckets()
const {
552 return static_cast<const DerivedT *
>(
this)->getNumBuckets();
555 BucketT *getBucketsEnd() {
556 return getBuckets() + getNumBuckets();
559 const BucketT *getBucketsEnd()
const {
560 return getBuckets() + getNumBuckets();
563 void grow(
unsigned AtLeast) {
564 static_cast<DerivedT *
>(
this)->grow(AtLeast);
567 void shrink_and_clear() {
568 static_cast<DerivedT *
>(
this)->shrink_and_clear();
571 template <
typename KeyArg,
typename... ValueArgs>
572 BucketT *InsertIntoBucket(BucketT *TheBucket, KeyArg &&Key,
573 ValueArgs &&... Values) {
574 TheBucket = InsertIntoBucketImpl(Key, Key, TheBucket);
576 TheBucket->getFirst() = std::forward<KeyArg>(Key);
577 ::new (&TheBucket->getSecond())
ValueT(
std::forward<ValueArgs>(Values)...);
581 template <typename LookupKeyT>
582 BucketT *InsertIntoBucketWithLookup(BucketT *TheBucket,
KeyT &&Key,
584 TheBucket = InsertIntoBucketImpl(Key,
Lookup, TheBucket);
586 TheBucket->getFirst() = std::move(Key);
591 template <typename LookupKeyT>
593 BucketT *TheBucket) {
605 unsigned NewNumEntries = getNumEntries() + 1;
606 unsigned NumBuckets = getNumBuckets();
608 this->grow(NumBuckets * 2);
609 LookupBucketFor(
Lookup, TheBucket);
610 NumBuckets = getNumBuckets();
611 }
else if (
LLVM_UNLIKELY(NumBuckets-(NewNumEntries+getNumTombstones()) <=
613 this->grow(NumBuckets);
614 LookupBucketFor(
Lookup, TheBucket);
620 incrementNumEntries();
624 if (!KeyInfoT::isEqual(TheBucket->getFirst(), EmptyKey))
625 decrementNumTombstones();
634 template<
typename LookupKeyT>
635 bool LookupBucketFor(
const LookupKeyT &Val,
636 const BucketT *&FoundBucket)
const {
637 const BucketT *BucketsPtr = getBuckets();
638 const unsigned NumBuckets = getNumBuckets();
640 if (NumBuckets == 0) {
641 FoundBucket =
nullptr;
646 const BucketT *FoundTombstone =
nullptr;
649 assert(!KeyInfoT::isEqual(Val, EmptyKey) &&
650 !KeyInfoT::isEqual(Val, TombstoneKey) &&
651 "Empty/Tombstone value shouldn't be inserted into map!");
654 unsigned ProbeAmt = 1;
656 const BucketT *ThisBucket = BucketsPtr + BucketNo;
658 if (
LLVM_LIKELY(KeyInfoT::isEqual(Val, ThisBucket->getFirst()))) {
659 FoundBucket = ThisBucket;
665 if (
LLVM_LIKELY(KeyInfoT::isEqual(ThisBucket->getFirst(), EmptyKey))) {
668 FoundBucket = FoundTombstone ? FoundTombstone : ThisBucket;
674 if (KeyInfoT::isEqual(ThisBucket->getFirst(), TombstoneKey) &&
676 FoundTombstone = ThisBucket;
680 BucketNo += ProbeAmt++;
681 BucketNo &= (NumBuckets-1);
685 template <
typename LookupKeyT>
686 bool LookupBucketFor(
const LookupKeyT &Val, BucketT *&FoundBucket) {
687 const BucketT *ConstFoundBucket;
689 ->LookupBucketFor(Val, ConstFoundBucket);
690 FoundBucket =
const_cast<BucketT *
>(ConstFoundBucket);
700 return getNumBuckets() *
sizeof(BucketT);
710template <
typename DerivedT,
typename KeyT,
typename ValueT,
typename KeyInfoT,
715 if (
LHS.size() !=
RHS.size())
718 for (
auto &KV :
LHS) {
719 auto I =
RHS.find(KV.first);
720 if (
I ==
RHS.end() ||
I->second != KV.second)
730template <
typename DerivedT,
typename KeyT,
typename ValueT,
typename KeyInfoT,
739 typename KeyInfoT = DenseMapInfo<KeyT>,
742 KeyT, ValueT, KeyInfoT, BucketT> {
751 unsigned NumTombstones;
757 explicit DenseMap(
unsigned InitialReserve = 0) { init(InitialReserve); }
769 template<
typename InputIt>
771 init(std::distance(
I,
E));
775 DenseMap(std::initializer_list<typename BaseT::value_type> Vals) {
777 this->insert(Vals.begin(), Vals.end());
786 this->incrementEpoch();
787 RHS.incrementEpoch();
811 if (allocateBuckets(other.NumBuckets)) {
812 this->BaseT::copyFrom(other);
819 void init(
unsigned InitNumEntries) {
820 auto InitBuckets = BaseT::getMinBucketToReserveForEntries(InitNumEntries);
821 if (allocateBuckets(InitBuckets)) {
822 this->BaseT::initEmpty();
830 unsigned OldNumBuckets = NumBuckets;
831 BucketT *OldBuckets = Buckets;
833 allocateBuckets(std::max<unsigned>(64,
static_cast<unsigned>(
NextPowerOf2(AtLeast-1))));
836 this->BaseT::initEmpty();
840 this->moveFromOldBuckets(OldBuckets, OldBuckets+OldNumBuckets);
848 unsigned OldNumBuckets = NumBuckets;
849 unsigned OldNumEntries = NumEntries;
853 unsigned NewNumBuckets = 0;
855 NewNumBuckets = std::max(64, 1 << (
Log2_32_Ceil(OldNumEntries) + 1));
856 if (NewNumBuckets == NumBuckets) {
857 this->BaseT::initEmpty();
867 unsigned getNumEntries()
const {
871 void setNumEntries(
unsigned Num) {
875 unsigned getNumTombstones()
const {
876 return NumTombstones;
879 void setNumTombstones(
unsigned Num) {
883 BucketT *getBuckets()
const {
887 unsigned getNumBuckets()
const {
891 bool allocateBuckets(
unsigned Num) {
893 if (NumBuckets == 0) {
898 Buckets =
static_cast<BucketT *
>(
904template <
typename KeyT,
typename ValueT,
unsigned InlineBuckets = 4,
905 typename KeyInfoT = DenseMapInfo<KeyT>,
909 SmallDenseMap<KeyT, ValueT, InlineBuckets, KeyInfoT, BucketT>, KeyT,
910 ValueT, KeyInfoT, BucketT> {
918 "InlineBuckets must be a power of 2.");
921 unsigned NumEntries : 31;
922 unsigned NumTombstones;
935 if (NumInitBuckets > InlineBuckets)
937 init(NumInitBuckets);
950 template<
typename InputIt>
965 unsigned TmpNumEntries =
RHS.NumEntries;
966 RHS.NumEntries = NumEntries;
967 NumEntries = TmpNumEntries;
970 const KeyT EmptyKey = this->getEmptyKey();
971 const KeyT TombstoneKey = this->getTombstoneKey();
972 if (Small &&
RHS.Small) {
977 for (
unsigned i = 0, e = InlineBuckets; i != e; ++i) {
978 BucketT *LHSB = &getInlineBuckets()[i],
979 *RHSB = &
RHS.getInlineBuckets()[i];
980 bool hasLHSValue = (!KeyInfoT::isEqual(LHSB->getFirst(), EmptyKey) &&
981 !KeyInfoT::isEqual(LHSB->getFirst(), TombstoneKey));
982 bool hasRHSValue = (!KeyInfoT::isEqual(RHSB->getFirst(), EmptyKey) &&
983 !KeyInfoT::isEqual(RHSB->getFirst(), TombstoneKey));
984 if (hasLHSValue && hasRHSValue) {
990 std::swap(LHSB->getFirst(), RHSB->getFirst());
992 ::new (&RHSB->getSecond())
ValueT(std::move(LHSB->getSecond()));
993 LHSB->getSecond().~ValueT();
994 }
else if (hasRHSValue) {
995 ::new (&LHSB->getSecond())
ValueT(std::move(RHSB->getSecond()));
996 RHSB->getSecond().~ValueT();
1001 if (!Small && !
RHS.Small) {
1002 std::swap(getLargeRep()->Buckets,
RHS.getLargeRep()->Buckets);
1003 std::swap(getLargeRep()->NumBuckets,
RHS.getLargeRep()->NumBuckets);
1011 LargeRep TmpRep = std::move(*LargeSide.getLargeRep());
1012 LargeSide.getLargeRep()->~LargeRep();
1013 LargeSide.Small =
true;
1018 for (
unsigned i = 0, e = InlineBuckets; i != e; ++i) {
1019 BucketT *NewB = &LargeSide.getInlineBuckets()[i],
1020 *OldB = &SmallSide.getInlineBuckets()[i];
1021 ::new (&NewB->getFirst())
KeyT(std::move(OldB->getFirst()));
1022 OldB->getFirst().~KeyT();
1023 if (!KeyInfoT::isEqual(NewB->getFirst(), EmptyKey) &&
1024 !KeyInfoT::isEqual(NewB->getFirst(), TombstoneKey)) {
1025 ::new (&NewB->getSecond())
ValueT(std::move(OldB->getSecond()));
1026 OldB->getSecond().~ValueT();
1032 SmallSide.Small =
false;
1033 new (SmallSide.getLargeRep()) LargeRep(std::move(TmpRep));
1044 deallocateBuckets();
1052 deallocateBuckets();
1054 if (other.getNumBuckets() > InlineBuckets) {
1056 new (getLargeRep()) LargeRep(allocateBuckets(other.getNumBuckets()));
1058 this->BaseT::copyFrom(other);
1063 if (InitBuckets > InlineBuckets) {
1065 new (getLargeRep()) LargeRep(allocateBuckets(InitBuckets));
1067 this->BaseT::initEmpty();
1071 if (AtLeast > InlineBuckets)
1072 AtLeast = std::max<unsigned>(64,
NextPowerOf2(AtLeast-1));
1077 BucketT *TmpBegin =
reinterpret_cast<BucketT *
>(&TmpStorage);
1078 BucketT *TmpEnd = TmpBegin;
1082 const KeyT EmptyKey = this->getEmptyKey();
1083 const KeyT TombstoneKey = this->getTombstoneKey();
1084 for (BucketT *
P = getBuckets(), *
E =
P + InlineBuckets;
P !=
E; ++
P) {
1085 if (!KeyInfoT::isEqual(
P->getFirst(), EmptyKey) &&
1086 !KeyInfoT::isEqual(
P->getFirst(), TombstoneKey)) {
1087 assert(
size_t(TmpEnd - TmpBegin) < InlineBuckets &&
1088 "Too many inline buckets!");
1089 ::new (&TmpEnd->getFirst())
KeyT(std::move(
P->getFirst()));
1090 ::new (&TmpEnd->getSecond())
ValueT(std::move(
P->getSecond()));
1092 P->getSecond().~ValueT();
1094 P->getFirst().~KeyT();
1100 if (AtLeast > InlineBuckets) {
1102 new (getLargeRep()) LargeRep(allocateBuckets(AtLeast));
1104 this->moveFromOldBuckets(TmpBegin, TmpEnd);
1108 LargeRep OldRep = std::move(*getLargeRep());
1109 getLargeRep()->~LargeRep();
1110 if (AtLeast <= InlineBuckets) {
1113 new (getLargeRep()) LargeRep(allocateBuckets(AtLeast));
1116 this->moveFromOldBuckets(OldRep.Buckets, OldRep.Buckets+OldRep.NumBuckets);
1124 unsigned OldSize = this->
size();
1128 unsigned NewNumBuckets = 0;
1131 if (NewNumBuckets > InlineBuckets && NewNumBuckets < 64u)
1134 if ((Small && NewNumBuckets <= InlineBuckets) ||
1135 (!Small && NewNumBuckets == getLargeRep()->NumBuckets)) {
1136 this->BaseT::initEmpty();
1140 deallocateBuckets();
1141 init(NewNumBuckets);
1145 unsigned getNumEntries()
const {
1149 void setNumEntries(
unsigned Num) {
1151 assert(Num < (1U << 31) &&
"Cannot support more than 1<<31 entries");
1155 unsigned getNumTombstones()
const {
1156 return NumTombstones;
1159 void setNumTombstones(
unsigned Num) {
1160 NumTombstones = Num;
1163 const BucketT *getInlineBuckets()
const {
1168 return reinterpret_cast<const BucketT *
>(&storage);
1171 BucketT *getInlineBuckets() {
1172 return const_cast<BucketT *
>(
1173 const_cast<const SmallDenseMap *
>(
this)->getInlineBuckets());
1176 const LargeRep *getLargeRep()
const {
1179 return reinterpret_cast<const LargeRep *
>(&storage);
1182 LargeRep *getLargeRep() {
1183 return const_cast<LargeRep *
>(
1184 const_cast<const SmallDenseMap *
>(
this)->getLargeRep());
1187 const BucketT *getBuckets()
const {
1188 return Small ? getInlineBuckets() : getLargeRep()->Buckets;
1191 BucketT *getBuckets() {
1192 return const_cast<BucketT *
>(
1193 const_cast<const SmallDenseMap *
>(
this)->getBuckets());
1196 unsigned getNumBuckets()
const {
1197 return Small ? InlineBuckets : getLargeRep()->NumBuckets;
1200 void deallocateBuckets() {
1205 sizeof(BucketT) * getLargeRep()->NumBuckets,
1207 getLargeRep()->~LargeRep();
1210 LargeRep allocateBuckets(
unsigned Num) {
1211 assert(Num > InlineBuckets &&
"Must allocate more buckets than are inline");
1213 sizeof(BucketT) * Num,
alignof(BucketT))),
1219template <
typename KeyT,
typename ValueT,
typename KeyInfoT,
typename Bucket,
1227 using value_type = std::conditional_t<IsConst, const Bucket, Bucket>;
1240 bool NoAdvance =
false)
1242 assert(isHandleInSync() &&
"invalid construction!");
1244 if (NoAdvance)
return;
1245 if (shouldReverseIterate<KeyT>()) {
1246 RetreatPastEmptyBuckets();
1249 AdvancePastEmptyBuckets();
1255 template <
bool IsConstSrc,
1256 typename = std::enable_if_t<!IsConstSrc && IsConst>>
1262 assert(isHandleInSync() &&
"invalid iterator access!");
1264 if (shouldReverseIterate<KeyT>())
1269 assert(isHandleInSync() &&
"invalid iterator access!");
1271 if (shouldReverseIterate<KeyT>())
1278 assert((!
LHS.Ptr ||
LHS.isHandleInSync()) &&
"handle not in sync!");
1279 assert((!
RHS.Ptr ||
RHS.isHandleInSync()) &&
"handle not in sync!");
1280 assert(
LHS.getEpochAddress() ==
RHS.getEpochAddress() &&
1281 "comparing incomparable iterators!");
1282 return LHS.Ptr ==
RHS.Ptr;
1291 assert(isHandleInSync() &&
"invalid iterator access!");
1293 if (shouldReverseIterate<KeyT>()) {
1295 RetreatPastEmptyBuckets();
1299 AdvancePastEmptyBuckets();
1303 assert(isHandleInSync() &&
"invalid iterator access!");
1308 void AdvancePastEmptyBuckets() {
1310 const KeyT Empty = KeyInfoT::getEmptyKey();
1311 const KeyT Tombstone = KeyInfoT::getTombstoneKey();
1313 while (
Ptr !=
End && (KeyInfoT::isEqual(
Ptr->getFirst(), Empty) ||
1314 KeyInfoT::isEqual(
Ptr->getFirst(), Tombstone)))
1318 void RetreatPastEmptyBuckets() {
1320 const KeyT Empty = KeyInfoT::getEmptyKey();
1321 const KeyT Tombstone = KeyInfoT::getTombstoneKey();
1323 while (
Ptr !=
End && (KeyInfoT::isEqual(
Ptr[-1].getFirst(), Empty) ||
1324 KeyInfoT::isEqual(
Ptr[-1].getFirst(), Tombstone)))
1329template <
typename KeyT,
typename ValueT,
typename KeyInfoT>
1331 return X.getMemorySize();
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_UNLIKELY(EXPR)
#define LLVM_LIKELY(EXPR)
This file defines DenseMapInfo traits for DenseMap.
This file defines the DebugEpochBase and DebugEpochBase::HandleBase classes.
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
This file defines counterparts of C library allocation functions defined in the namespace 'std'.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static int Lookup(ArrayRef< TableEntry > Table, unsigned Opcode)
ValueT & getOrInsertDefault(const KeyT &Key)
Returns the value associated to the key in the map if it exists.
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
iterator find(const_arg_type_t< KeyT > Val)
static unsigned getHashValue(const KeyT &Val)
static const KeyT getEmptyKey()
value_type & FindAndConstruct(KeyT &&Key)
std::pair< iterator, bool > insert(std::pair< KeyT, ValueT > &&KV)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&... Args)
bool erase(const KeyT &Val)
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT > iterator
std::pair< iterator, bool > insert_as(std::pair< KeyT, ValueT > &&KV, const LookupKeyT &Val)
Alternate version of insert() which allows a different, and possibly less expensive,...
const_iterator find_as(const LookupKeyT &Val) const
const_iterator end() const
std::pair< iterator, bool > try_emplace(const KeyT &Key, Ts &&... Args)
void moveFromOldBuckets(BucketT *OldBucketsBegin, BucketT *OldBucketsEnd)
iterator find_as(const LookupKeyT &Val)
Alternate version of find() which allows a different, and possibly less expensive,...
const_iterator find(const_arg_type_t< KeyT > Val) const
void insert(InputIt I, InputIt E)
insert - Range insertion of pairs.
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
static const KeyT getTombstoneKey()
const ValueT & at(const_arg_type_t< KeyT > Val) const
at - Return the entry for the specified key, or abort if no such entry exists.
bool isPointerIntoBucketsArray(const void *Ptr) const
isPointerIntoBucketsArray - Return true if the specified pointer points somewhere into the DenseMap's...
void copyFrom(const DenseMapBase< OtherBaseT, KeyT, ValueT, KeyInfoT, BucketT > &other)
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
value_type & FindAndConstruct(const KeyT &Key)
const_iterator begin() const
const void * getPointerIntoBucketsArray() const
getPointerIntoBucketsArray() - Return an opaque pointer into the buckets array.
unsigned getMinBucketToReserveForEntries(unsigned NumEntries)
Returns the number of buckets to allocate to ensure that the DenseMap can accommodate NumEntries with...
static unsigned getHashValue(const LookupKeyT &Val)
ValueT & operator[](const KeyT &Key)
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT, true > const_iterator
ValueT & getOrInsertDefault(KeyT &&Key)
Returns the value associated to the key in the map if it exists.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
void reserve(size_type NumEntries)
Grow the densemap so that it can contain at least NumEntries items before resizing again.
ValueT & operator[](KeyT &&Key)
size_t getMemorySize() const
Return the approximate size (in bytes) of the actual map.
std::conditional_t< IsConst, const Bucket, Bucket > value_type
friend bool operator!=(const DenseMapIterator &LHS, const DenseMapIterator &RHS)
DenseMapIterator & operator++()
pointer operator->() const
reference operator*() const
DenseMapIterator(pointer Pos, pointer E, const DebugEpochBase &Epoch, bool NoAdvance=false)
DenseMapIterator()=default
DenseMapIterator operator++(int)
DenseMapIterator(const DenseMapIterator< KeyT, ValueT, KeyInfoT, Bucket, IsConstSrc > &I)
friend bool operator==(const DenseMapIterator &LHS, const DenseMapIterator &RHS)
std::forward_iterator_tag iterator_category
DenseMap(std::initializer_list< typename BaseT::value_type > Vals)
void copyFrom(const DenseMap &other)
DenseMap & operator=(DenseMap &&other)
DenseMap(unsigned InitialReserve=0)
Create a DenseMap with an optional InitialReserve that guarantee that this number of elements can be ...
void grow(unsigned AtLeast)
void init(unsigned InitNumEntries)
DenseMap(const DenseMap &other)
DenseMap(const InputIt &I, const InputIt &E)
DenseMap(DenseMap &&other)
DenseMap & operator=(const DenseMap &other)
void grow(unsigned AtLeast)
SmallDenseMap(const InputIt &I, const InputIt &E)
void swap(SmallDenseMap &RHS)
void init(unsigned InitBuckets)
SmallDenseMap & operator=(SmallDenseMap &&other)
SmallDenseMap & operator=(const SmallDenseMap &other)
SmallDenseMap(unsigned NumInitBuckets=0)
SmallDenseMap(std::initializer_list< typename BaseT::value_type > Vals)
SmallDenseMap(SmallDenseMap &&other)
SmallDenseMap(const SmallDenseMap &other)
void copyFrom(const SmallDenseMap &other)
constexpr char IsConst[]
Key for Kernel::Arg::Metadata::mIsConst.
This is an optimization pass for GlobalISel generic memory operations.
unsigned Log2_32_Ceil(uint32_t Value)
Return the ceil log base 2 of the specified value, 32 if the value is zero.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
BitVector::size_type capacity_in_bytes(const BitVector &X)
bool operator!=(uint64_t V1, const APInt &V2)
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
T bit_ceil(T Value)
Returns the smallest integral power of two no smaller than Value if Value is nonzero.
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void * allocate_buffer(size_t Size, size_t Alignment)
Allocate a buffer of memory with the given size and alignment.
void deallocate_buffer(void *Ptr, size_t Size, size_t Alignment)
Deallocate a buffer of memory with the given size and alignment.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
A suitably aligned and sized character array member which can hold elements of any type.
const ValueT & getSecond() const
const KeyT & getFirst() const