21#ifndef LLVM_ADT_DENSEMAP_H
22#define LLVM_ADT_DENSEMAP_H
38#include <initializer_list>
50template <
typename KeyT,
typename ValueT>
52 using std::pair<
KeyT, ValueT>::pair;
55 const KeyT &
getFirst()
const {
return std::pair<KeyT, ValueT>::first; }
56 ValueT &
getSecond() {
return std::pair<KeyT, ValueT>::second; }
57 const ValueT &
getSecond()
const {
return std::pair<KeyT, ValueT>::second; }
68 "bucket count must be zero or a power of two");
73 return (U[
I >> 5] >> (
I & 31)) & 1;
77 U[
I >> 5] &= ~(
UsedT(1) << (
I & 31));
87 for (
unsigned W = 0; W != NW; ++W) {
99template <
typename BucketT>
constexpr size_t allocAlign() {
100 return std::max(
alignof(BucketT),
alignof(
UsedT));
103 return sizeof(BucketT) *
static_cast<size_t>(Num) +
113template <
typename KeyT,
typename ValueT,
116 bool IsConst =
false>
119template <
typename DerivedT,
typename KeyT,
typename ValueT,
typename KeyInfoT,
122 template <
typename T>
154 [[nodiscard]]
inline auto keys() {
155 return map_range(*
this, [](
const BucketT &
P) {
return P.getFirst(); });
160 return map_range(*
this, [](
const BucketT &
P) {
return P.getSecond(); });
163 [[nodiscard]]
inline auto keys()
const {
164 return map_range(*
this, [](
const BucketT &
P) {
return P.getFirst(); });
167 [[nodiscard]]
inline auto values()
const {
168 return map_range(*
this, [](
const BucketT &
P) {
return P.getSecond(); });
171 [[nodiscard]]
bool empty()
const {
return getNumEntries() == 0; }
172 [[nodiscard]]
unsigned size()
const {
return getNumEntries(); }
179 if (NumBuckets > getNumBuckets())
185 if (getNumEntries() == 0)
190 if (getNumEntries() * 4 < getNumBuckets() && getNumBuckets() > 64) {
196 std::memset(getUsed(), 0,
203 auto [Reallocate, NewNumBuckets] = derived().planShrinkAndClear();
209 derived().deallocateBuckets();
214 [[nodiscard]]
bool contains(const_arg_type_t<KeyT> Val)
const {
215 return doFind(Val) !=
nullptr;
235 template <
class LookupKeyT>
237 if (BucketT *Bucket = doFind(Val))
238 return makeIterator(Bucket);
241 template <
class LookupKeyT>
243 if (
const BucketT *Bucket = doFind(Val))
244 return makeConstIterator(Bucket);
250 [[nodiscard]] ValueT
lookup(const_arg_type_t<KeyT> Val)
const {
251 if (
const BucketT *Bucket = doFind(Val))
252 return Bucket->getSecond();
259 template <
typename U = std::remove_cv_t<ValueT>>
260 [[nodiscard]] ValueT
lookup_or(const_arg_type_t<KeyT> Val,
262 if (
const BucketT *Bucket = doFind(Val))
263 return Bucket->getSecond();
268 [[nodiscard]] ValueT &
at(const_arg_type_t<KeyT> Val) {
269 auto Iter = this->
find(std::move(Val));
270 assert(Iter != this->
end() &&
"DenseMap::at failed due to a missing key");
275 [[nodiscard]]
const ValueT &
at(const_arg_type_t<KeyT> Val)
const {
276 auto Iter = this->
find(std::move(Val));
277 assert(Iter != this->
end() &&
"DenseMap::at failed due to a missing key");
284 std::pair<iterator, bool>
insert(
const std::pair<KeyT, ValueT> &KV) {
285 return try_emplace_impl(KV.first, KV.second);
291 std::pair<iterator, bool>
insert(std::pair<KeyT, ValueT> &&KV) {
292 return try_emplace_impl(std::move(KV.first), std::move(KV.second));
298 template <
typename... Ts>
300 return try_emplace_impl(std::move(
Key), std::forward<Ts>(Args)...);
306 template <
typename... Ts>
308 return try_emplace_impl(
Key, std::forward<Ts>(Args)...);
316 template <
typename LookupKeyT>
317 std::pair<iterator, bool>
insert_as(std::pair<KeyT, ValueT> &&KV,
318 const LookupKeyT &Val) {
320 if (LookupBucketFor(Val, TheBucket))
321 return {makeIterator(TheBucket),
false};
324 TheBucket = findBucketForInsertion(Val, TheBucket);
325 ::new (&TheBucket->getFirst())
KeyT(std::move(KV.first));
326 ::new (&TheBucket->getSecond()) ValueT(std::move(KV.second));
327 return {makeIterator(TheBucket),
true};
331 template <
typename InputIt>
void insert(InputIt
I, InputIt
E) {
341 template <
typename V>
345 Ret.first->second = std::forward<V>(Val);
349 template <
typename V>
353 Ret.first->second = std::forward<V>(Val);
357 template <
typename... Ts>
361 Ret.first->second = ValueT(std::forward<Ts>(Args)...);
365 template <
typename... Ts>
367 auto Ret =
try_emplace(std::move(
Key), std::forward<Ts>(Args)...);
369 Ret.first->second = ValueT(std::forward<Ts>(Args)...);
378 BucketT *TheBucket = doFind(Val);
394 UsedT *U = getUsed();
395 unsigned NumBuckets = getNumBuckets();
396 BucketT *
B = getBuckets();
397 bool Removed =
false;
398 for (
unsigned I = 0;
I != NumBuckets; ++
I) {
402 B[
I].getSecond().~ValueT();
403 B[
I].getFirst().~KeyT();
405 decrementNumEntries();
411 this->grow(NumBuckets);
417 return lookupOrInsertIntoBucket(
Key).first->second;
421 return lookupOrInsertIntoBucket(std::move(
Key)).first->second;
427 return Ptr >= getBuckets() && Ptr < getBucketsEnd();
439 RHS.incrementEpoch();
440 derived().swapImpl(
RHS);
458 if (derived().allocateBuckets(NewNumBuckets))
467 if constexpr (std::is_trivially_destructible_v<KeyT> &&
468 std::is_trivially_destructible_v<ValueT>)
471 if (getNumBuckets() == 0)
474 BucketT *
B = getBuckets();
475 const UsedT *U = getUsed();
476 const unsigned E = getNumBuckets();
478 B[
I].getSecond().~ValueT();
479 B[
I].getFirst().~KeyT();
484 static_assert(std::is_base_of_v<DenseMapBase, DerivedT>,
485 "Must pass the derived type to this template!");
488 assert((getNumBuckets() & (getNumBuckets() - 1)) == 0 &&
489 "# initial buckets must be a power of two!");
490 if (getNumBuckets()) {
491 std::memset(getUsed(), 0,
511 assert(getNumEntries() == 0 &&
"moveFrom requires an empty destination");
512 BucketT *OtherB =
Other.getBuckets();
513 UsedT *OtherU =
Other.getUsed();
514 const unsigned E =
Other.getNumBuckets();
515 UsedT *U = getUsed();
516 BucketT *
B = getBuckets();
517 const unsigned Mask = getNumBuckets() - 1;
521 unsigned BucketNo = KeyInfoT::getHashValue(OtherB[
I].getFirst()) & Mask;
523 BucketNo = (BucketNo + 1) & Mask;
524 BucketT *DestBucket =
B + BucketNo;
525 ::new (&DestBucket->getFirst())
KeyT(std::move(OtherB[
I].getFirst()));
526 ::new (&DestBucket->getSecond()) ValueT(std::move(OtherB[
I].getSecond()));
530 OtherB[
I].getSecond().~ValueT();
531 OtherB[
I].getFirst().~KeyT();
533 setNumEntries(
Other.getNumEntries());
534 Other.derived().kill();
539 derived().deallocateBuckets();
541 if (!derived().allocateBuckets(other.getNumBuckets())) {
547 assert(getNumBuckets() == other.getNumBuckets());
549 setNumEntries(other.getNumEntries());
551 BucketT *Buckets = getBuckets();
552 const BucketT *OtherBuckets = other.getBuckets();
553 const unsigned NumBuckets = getNumBuckets();
554 UsedT *U = getUsed();
555 const UsedT *OtherU = other.getUsed();
556 std::memcpy(U, OtherU,
558 if constexpr (std::is_trivially_copyable_v<KeyT> &&
559 std::is_trivially_copyable_v<ValueT>) {
560 memcpy(
reinterpret_cast<void *
>(Buckets), OtherBuckets,
561 NumBuckets *
sizeof(BucketT));
564 ::new (&Buckets[
I].getFirst())
KeyT(OtherBuckets[
I].getFirst());
565 ::new (&Buckets[
I].getSecond()) ValueT(OtherBuckets[
I].getSecond());
579 template <
typename OnMovedT>
581 OnMovedT &&OnMoved) {
583 TheBucket->getSecond().~ValueT();
584 TheBucket->getFirst().~KeyT();
585 decrementNumEntries();
587 BucketT *BucketsPtr = getBuckets();
588 UsedT *U = getUsed();
589 const unsigned Mask = getNumBuckets() - 1;
590 unsigned I = TheBucket - BucketsPtr;
594 BucketT &BJ = BucketsPtr[J];
597 auto Ideal = KeyInfoT::getHashValue(BJ.getFirst());
600 if (((
I - Ideal) & Mask) < ((J - Ideal) & Mask)) {
601 BucketT &BI = BucketsPtr[
I];
602 ::new (&BI.getFirst())
KeyT(
std::
move(BJ.getFirst()));
603 ::new (&BI.getSecond()) ValueT(
std::
move(BJ.getSecond()));
604 BJ.getSecond().~ValueT();
605 BJ.getFirst().~
KeyT();
616 template <typename OnMovedT>
bool erase(
const KeyT &Val, OnMovedT &&OnMoved) {
617 BucketT *TheBucket = doFind(Val);
624 DerivedT &derived() {
return *
static_cast<DerivedT *
>(
this); }
625 const DerivedT &derived()
const {
626 return *
static_cast<const DerivedT *
>(
this);
629 template <
typename KeyArgT,
typename... Ts>
630 std::pair<BucketT *, bool> lookupOrInsertIntoBucket(KeyArgT &&
Key,
632 BucketT *TheBucket =
nullptr;
633 if (LookupBucketFor(
Key, TheBucket))
634 return {TheBucket,
false};
637 TheBucket = findBucketForInsertion(
Key, TheBucket);
638 ::new (&TheBucket->getFirst()) KeyT(std::forward<KeyArgT>(
Key));
639 ::new (&TheBucket->getSecond()) ValueT(std::forward<Ts>(Args)...);
640 return {TheBucket,
true};
643 template <
typename KeyArgT,
typename... Ts>
644 std::pair<iterator, bool> try_emplace_impl(KeyArgT &&
Key, Ts &&...Args) {
645 auto [Bucket,
Inserted] = lookupOrInsertIntoBucket(
646 std::forward<KeyArgT>(
Key), std::forward<Ts>(Args)...);
647 return {makeIterator(Bucket),
Inserted};
650 iterator makeIterator(BucketT *TheBucket) {
652 getNumBuckets(), *
this);
655 const_iterator makeConstIterator(
const BucketT *TheBucket)
const {
657 getNumBuckets(), *
this);
660 unsigned getNumEntries()
const {
return derived().getNumEntries(); }
662 void setNumEntries(
unsigned Num) { derived().setNumEntries(Num); }
664 void incrementNumEntries() { setNumEntries(getNumEntries() + 1); }
666 void decrementNumEntries() { setNumEntries(getNumEntries() - 1); }
668 const BucketT *getBuckets()
const {
return derived().getBuckets(); }
670 BucketT *getBuckets() {
return derived().getBuckets(); }
672 Rep getRep()
const {
return derived().getRep(); }
674 const UsedT *getUsed()
const {
return derived().getUsed(); }
676 UsedT *getUsed() {
return derived().getUsed(); }
678 unsigned getNumBuckets()
const {
return derived().getNumBuckets(); }
680 BucketT *getBucketsEnd() {
return getBuckets() + getNumBuckets(); }
682 const BucketT *getBucketsEnd()
const {
683 return getBuckets() + getNumBuckets();
687 unsigned NumBuckets = DerivedT::roundUpNumBuckets(MinNumBuckets);
689 Tmp.moveFrom(derived());
690 if (derived().maybeMoveFast(std::move(Tmp)))
696 template <
typename LookupKeyT>
697 BucketT *findBucketForInsertion(
const LookupKeyT &
Lookup,
698 BucketT *TheBucket) {
705 unsigned NewNumEntries = getNumEntries() + 1;
706 unsigned NumBuckets = getNumBuckets();
708 this->grow(NumBuckets * 2);
709 LookupBucketFor(
Lookup, TheBucket);
718 incrementNumEntries();
722 template <
typename LookupKeyT>
723 const BucketT *doFind(
const LookupKeyT &Val)
const {
724 auto [BucketsPtr,
U, NumBuckets] = getRep();
728 const unsigned Mask = NumBuckets - 1;
729 unsigned BucketNo = KeyInfoT::getHashValue(Val) &
Mask;
734 const BucketT *Bucket = BucketsPtr + BucketNo;
735 if (
LLVM_LIKELY(KeyInfoT::isEqual(Val, Bucket->getFirst())))
739 BucketNo = (BucketNo + 1) & Mask;
743 template <
typename LookupKeyT> BucketT *doFind(
const LookupKeyT &Val) {
744 return const_cast<BucketT *
>(
751 template <
typename LookupKeyT>
752 bool LookupBucketFor(
const LookupKeyT &Val, BucketT *&FoundBucket) {
753 auto [CBuckets,
U, NumBuckets] = getRep();
754 if (NumBuckets == 0) {
755 FoundBucket =
nullptr;
760 BucketT *BucketsPtr =
const_cast<BucketT *
>(CBuckets);
762 const unsigned Mask = NumBuckets - 1;
763 unsigned BucketNo = KeyInfoT::getHashValue(Val) &
Mask;
765 BucketT *ThisBucket = BucketsPtr + BucketNo;
769 FoundBucket = ThisBucket;
774 if (
LLVM_LIKELY(KeyInfoT::isEqual(Val, ThisBucket->getFirst()))) {
775 FoundBucket = ThisBucket;
780 BucketNo = (BucketNo + 1) & Mask;
800template <
typename DerivedT,
typename KeyT,
typename ValueT,
typename KeyInfoT,
805 if (
LHS.size() !=
RHS.size())
808 for (
auto &KV :
LHS) {
809 auto I =
RHS.find(KV.first);
810 if (
I ==
RHS.end() ||
I->second != KV.second)
820template <
typename DerivedT,
typename KeyT,
typename ValueT,
typename KeyInfoT,
828template <
typename KeyT,
typename ValueT,
829 typename KeyInfoT = DenseMapInfo<KeyT>,
831class DenseMap :
public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>,
832 KeyT, ValueT, KeyInfoT, BucketT> {
840 BucketT *Buckets =
nullptr;
841 UsedT *Used =
nullptr;
842 unsigned NumEntries = 0;
843 unsigned NumBuckets = 0;
845 explicit DenseMap(
unsigned NumBuckets,
typename BaseT::ExactBucketCount) {
852 explicit DenseMap(
unsigned NumElementsToReserve = 0)
854 typename BaseT::ExactBucketCount{}) {}
856 DenseMap(
const DenseMap &other) : DenseMap() { this->copyFrom(other); }
858 DenseMap(DenseMap &&other) : DenseMap() { this->swap(other); }
860 template <
typename InputIt>
865 template <
typename RangeT>
869 DenseMap(std::initializer_list<typename BaseT::value_type> Vals)
870 : DenseMap(Vals.begin(), Vals.end()) {}
879 this->copyFrom(other);
886 this->initWithExactBucketCount(0);
899 unsigned getNumEntries()
const {
return NumEntries; }
901 void setNumEntries(
unsigned Num) {
NumEntries = Num; }
903 BucketT *getBuckets()
const {
return Buckets; }
905 typename BaseT::Rep getRep()
const {
return {Buckets,
Used, NumBuckets}; }
909 unsigned getNumBuckets()
const {
return NumBuckets; }
911 void deallocateBuckets() {
922 bool allocateBuckets(
unsigned Num) {
924 if (NumBuckets == 0) {
930 auto *Storage =
static_cast<char *
>(
933 Buckets =
reinterpret_cast<BucketT *
>(Storage);
936 assert(
sizeof(BucketT) * NumBuckets %
alignof(UsedT) == 0 &&
937 "used array would be misaligned");
938 Used =
reinterpret_cast<UsedT *
>(Storage +
sizeof(BucketT) * NumBuckets);
944 void kill() { deallocateBuckets(); }
946 static unsigned roundUpNumBuckets(
unsigned MinNumBuckets) {
948 static_cast<unsigned>(
NextPowerOf2(MinNumBuckets - 1)));
951 bool maybeMoveFast(DenseMap &&Other) {
959 std::pair<bool, unsigned> planShrinkAndClear()
const {
960 unsigned NewNumBuckets = 0;
962 NewNumBuckets = std::max(64u, 1u << (
Log2_32_Ceil(NumEntries) + 1));
963 if (NewNumBuckets == NumBuckets)
965 return {
true, NewNumBuckets};
969template <
typename KeyT,
typename ValueT,
unsigned InlineBuckets = 4,
970 typename KeyInfoT = DenseMapInfo<KeyT>,
974 SmallDenseMap<KeyT, ValueT, InlineBuckets, KeyInfoT, BucketT>, KeyT,
975 ValueT, KeyInfoT, BucketT> {
984 "InlineBuckets must be a power of 2.");
987 static constexpr unsigned InlineUsedWords =
991 unsigned NumEntries : 31;
995 alignas(BucketT)
char Buckets[
sizeof(BucketT) * InlineBuckets];
996 UsedT Used[InlineUsedWords];
1001 unsigned NumBuckets;
1010 SmallDenseMap(
unsigned NumBuckets,
typename BaseT::ExactBucketCount) {
1011 this->initWithExactBucketCount(NumBuckets);
1026 template <
typename InputIt>
1028 : SmallDenseMap(
std::distance(
I,
E)) {
1032 template <
typename RangeT>
1037 : SmallDenseMap(Vals.
begin(), Vals.
end()) {}
1041 deallocateBuckets();
1052 deallocateBuckets();
1060 static void relocateBucket(BucketT *Dst, BucketT *Src) {
1061 ::new (&Dst->getFirst())
KeyT(
std::
move(Src->getFirst()));
1062 ::new (&Dst->getSecond()) ValueT(
std::
move(Src->getSecond()));
1063 Src->getSecond().~ValueT();
1064 Src->getFirst().~
KeyT();
1068 unsigned TmpNumEntries =
RHS.NumEntries;
1069 RHS.NumEntries = NumEntries;
1070 NumEntries = TmpNumEntries;
1072 if (Small &&
RHS.Small) {
1076 UsedT *LU = getInlineUsed(), *RU = RHS.getInlineUsed();
1077 BucketT *LB = getInlineBuckets(), *RB = RHS.getInlineBuckets();
1078 for (unsigned I = 0; I != InlineBuckets; ++I) {
1079 bool L = llvm::densemap::detail::used(LU, I);
1080 bool R = llvm::densemap::detail::used(RU, I);
1083 alignas(BucketT) char Tmp[sizeof(BucketT)];
1084 BucketT *T = reinterpret_cast<BucketT *>(Tmp);
1085 relocateBucket(T, &LB[I]);
1086 relocateBucket(&LB[I], &RB[I]);
1087 relocateBucket(&RB[I], T);
1089 relocateBucket(&RB[I], &LB[I]);
1091 relocateBucket(&LB[I], &RB[I]);
1094 for (
unsigned W = 0; W != InlineUsedWords; ++W)
1098 if (!Small && !
RHS.Small) {
1103 SmallDenseMap &SmallSide =
Small ? *this :
RHS;
1104 SmallDenseMap &LargeSide =
Small ?
RHS : *
this;
1109 LargeRep TmpRep = LargeSide.storage.Large;
1110 LargeSide.Small =
true;
1112 UsedT *SU = SmallSide.getInlineUsed(), *LU = LargeSide.getInlineUsed();
1113 BucketT *SB = SmallSide.getInlineBuckets(),
1114 *LB = LargeSide.getInlineBuckets();
1115 for (
unsigned I = 0;
I != InlineBuckets; ++
I)
1117 relocateBucket(&LB[
I], &SB[
I]);
1118 for (
unsigned W = 0;
W != InlineUsedWords; ++
W)
1121 SmallSide.Small =
false;
1122 SmallSide.storage.Large = TmpRep;
1125 unsigned getNumEntries()
const {
return NumEntries; }
1127 void setNumEntries(
unsigned Num) {
1129 assert(Num < (1U << 31) &&
"Cannot support more than 1<<31 entries");
1133 const BucketT *getInlineBuckets()
const {
1138 return reinterpret_cast<const BucketT *
>(storage.Inline.Buckets);
1141 BucketT *getInlineBuckets() {
1143 return reinterpret_cast<BucketT *
>(storage.Inline.Buckets);
1146 const UsedT *getInlineUsed()
const {
1148 return storage.Inline.Used;
1151 UsedT *getInlineUsed() {
1153 return storage.Inline.Used;
1156 const BucketT *getBuckets()
const {
1157 return Small ? getInlineBuckets() : storage.
Large.Buckets;
1160 typename BaseT::Rep getRep()
const {
1162 return {getInlineBuckets(), getInlineUsed(), InlineBuckets};
1163 return {storage.Large.Buckets, storage.Large.Used,
1164 storage.Large.NumBuckets};
1167 BucketT *getBuckets() {
1168 return const_cast<BucketT *
>(
1169 const_cast<const SmallDenseMap *
>(
this)->getBuckets());
1172 const UsedT *getUsed()
const {
1177 return const_cast<UsedT *
>(
1178 const_cast<const SmallDenseMap *
>(
this)->getUsed());
1181 unsigned getNumBuckets()
const {
1182 return Small ? InlineBuckets : storage.Large.NumBuckets;
1185 void deallocateBuckets() {
1188 if (Small || storage.Large.NumBuckets == 0)
1192 storage.Large.Buckets,
1195 storage.Large.NumBuckets = 0;
1198 bool allocateBuckets(
unsigned Num) {
1199 if (Num <= InlineBuckets) {
1204 auto *S =
static_cast<char *
>(
1207 storage.Large.Buckets =
reinterpret_cast<BucketT *
>(S);
1208 storage.Large.Used =
reinterpret_cast<UsedT *
>(S +
sizeof(BucketT) * Num);
1209 storage.Large.NumBuckets = Num;
1215 deallocateBuckets();
1217 storage.Large = LargeRep{
nullptr,
nullptr, 0};
1220 static unsigned roundUpNumBuckets(
unsigned MinNumBuckets) {
1221 if (MinNumBuckets <= InlineBuckets)
1222 return InlineBuckets;
1223 return std::max(64u,
1224 static_cast<unsigned>(
NextPowerOf2(MinNumBuckets - 1)));
1227 bool maybeMoveFast(SmallDenseMap &&Other) {
1233 storage.Large =
Other.storage.Large;
1234 Other.storage.Large.NumBuckets = 0;
1241 std::pair<bool, unsigned> planShrinkAndClear()
const {
1242 unsigned NewNumBuckets = 0;
1243 if (!this->
empty()) {
1245 if (NewNumBuckets > InlineBuckets)
1246 NewNumBuckets = std::max(64u, NewNumBuckets);
1248 bool Reuse =
Small ? NewNumBuckets <= InlineBuckets
1249 : NewNumBuckets == storage.Large.NumBuckets;
1252 return {
true, NewNumBuckets};
1256template <
typename KeyT,
typename ValueT,
typename KeyInfoT,
typename Bucket,
1259 friend class DenseMapIterator<
KeyT, ValueT, KeyInfoT, Bucket,
true>;
1260 friend class DenseMapIterator<
KeyT, ValueT, KeyInfoT, Bucket,
false>;
1266 using value_type = std::conditional_t<IsConst, const Bucket, Bucket>;
1273 std::conditional_t<shouldReverseIterate<KeyT>(),
1274 std::reverse_iterator<pointer>,
pointer>;
1276 BucketItTy Ptr = {};
1277 BucketItTy End = {};
1280 pointer Buckets = {};
1283 DenseMapIterator(BucketItTy Pos, BucketItTy
E, pointer BucketsBase,
1284 const UsedT *U,
const DebugEpochBase &Epoch)
1285 : DebugEpochBase::HandleBase(&Epoch), Ptr(Pos), End(
E),
1286 Buckets(BucketsBase),
Used(
U) {
1287 assert(isHandleInSync() &&
"invalid construction!");
1294 unsigned NumBuckets,
bool IsEmpty,
1299 return makeEnd(Buckets, Used, NumBuckets, Epoch);
1301 DenseMapIterator Iter(R.begin(), R.end(), Buckets, Used, Epoch);
1302 Iter.AdvancePastEmptyBuckets();
1307 unsigned NumBuckets,
1310 return DenseMapIterator(R.end(), R.end(), Buckets, Used, Epoch);
1314 const UsedT *Used,
unsigned NumBuckets,
1318 return DenseMapIterator(BucketItTy(
P +
Offset), R.end(), Buckets, Used,
1325 template <
bool IsConstSrc,
1326 typename = std::enable_if_t<!IsConstSrc && IsConst>>
1328 const DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, IsConstSrc> &
I)
1330 Buckets(
I.Buckets), Used(
I.Used) {}
1334 assert(Ptr != End &&
"dereferencing end() iterator");
1340 const DenseMapIterator &
RHS) {
1341 assert((!
LHS.getEpochAddress() ||
LHS.isHandleInSync()) &&
1342 "handle not in sync!");
1343 assert((!
RHS.getEpochAddress() ||
RHS.isHandleInSync()) &&
1344 "handle not in sync!");
1345 assert(
LHS.getEpochAddress() ==
RHS.getEpochAddress() &&
1346 "comparing incomparable iterators!");
1347 return LHS.Ptr ==
RHS.Ptr;
1351 const DenseMapIterator &
RHS) {
1357 assert(Ptr != End &&
"incrementing end() iterator");
1359 AdvancePastEmptyBuckets();
1364 DenseMapIterator tmp = *
this;
1370 void AdvancePastEmptyBuckets() {
1377 const size_t N = End - Buckets;
1378 size_t I = Ptr - Buckets;
1397 static auto maybeReverse(iterator_range<pointer>
Range) {
1398 if constexpr (shouldReverseIterate<KeyT>())
1405template <
typename KeyT,
typename ValueT,
typename KeyInfoT>
1406[[nodiscard]]
inline size_t
1408 return X.getMemorySize();
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_UNLIKELY(EXPR)
#define LLVM_ATTRIBUTE_ALWAYS_INLINE
LLVM_ATTRIBUTE_ALWAYS_INLINE - On compilers where we have a directive to do so, mark a method "always...
#define LLVM_ATTRIBUTE_NOINLINE
LLVM_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so, mark a method "not for inl...
#define LLVM_LIKELY(EXPR)
This file defines DenseMapInfo traits for DenseMap.
This file defines the DebugEpochBase and DebugEpochBase::HandleBase classes.
This file defines counterparts of C library allocation functions defined in the namespace 'std'.
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
This file contains library features backported from future STL versions.
static unsigned getMinBucketToReserveForEntries(unsigned NumEntries)
Returns the number of buckets to allocate to ensure that the DenseMap can accommodate NumEntries with...
static int Lookup(ArrayRef< TableEntry > Table, unsigned Opcode)
bool isHandleInSync() const
ValueT & at(const_arg_type_t< KeyT > Val)
Return the entry for the specified key, or abort if no such entry exists.
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
std::pair< iterator, bool > insert(std::pair< KeyT, ValueT > &&KV)
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
friend class ValueHandleBase
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
std::pair< iterator, bool > emplace_or_assign(const KeyT &Key, Ts &&...Args)
void insert(InputIt I, InputIt E)
Range insertion of pairs.
LLVM_ATTRIBUTE_NOINLINE void copyFrom(const DerivedT &other)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT, true > const_iterator
bool remove_if(Predicate Pred)
Remove entries that match the given predicate.
LLVM_ATTRIBUTE_NOINLINE void moveFrom(DerivedT &Other)
const ValueT & at(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or abort if no such entry exists.
bool isPointerIntoBucketsArray(const void *Ptr) const
Return true if the specified pointer points somewhere into the DenseMap's array of buckets (i....
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
std::pair< iterator, bool > try_emplace(const KeyT &Key, Ts &&...Args)
const_iterator begin() const
std::pair< iterator, bool > emplace_or_assign(KeyT &&Key, Ts &&...Args)
void insert_range(Range &&R)
Inserts range of 'std::pair<KeyT, ValueT>' values into the map.
const void * getPointerIntoBucketsArray() const
getPointerIntoBucketsArray() - Return an opaque pointer into the buckets array.
std::pair< iterator, bool > insert_or_assign(KeyT &&Key, V &&Val)
ValueT lookup_or(const_arg_type_t< KeyT > Val, U &&Default) const
unsigned getMinBucketToReserveForEntries(unsigned NumEntries)
Returns the number of buckets to allocate to ensure that the DenseMap can accommodate NumEntries with...
ValueT & operator[](const KeyT &Key)
void initWithExactBucketCount(unsigned NewNumBuckets)
void eraseFromFilledBucket(BucketT *TheBucket)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
std::pair< iterator, bool > insert_or_assign(const KeyT &Key, V &&Val)
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 BucketT, BucketT > value_type
friend bool operator!=(const DenseMapIterator &LHS, const DenseMapIterator &RHS)
DenseMapIterator & operator++()
pointer operator->() const
reference operator*() const
DenseMapIterator()=default
DenseMapIterator operator++(int)
DenseMapIterator(const DenseMapIterator< KeyT, ValueT, KeyInfoT, Bucket, IsConstSrc > &I)
static DenseMapIterator makeIterator(pointer P, pointer Buckets, const UsedT *Used, unsigned NumBuckets, const DebugEpochBase &Epoch)
ptrdiff_t difference_type
friend bool operator==(const DenseMapIterator &LHS, const DenseMapIterator &RHS)
std::forward_iterator_tag iterator_category
static DenseMapIterator makeBegin(pointer Buckets, const UsedT *Used, unsigned NumBuckets, bool IsEmpty, const DebugEpochBase &Epoch)
static DenseMapIterator makeEnd(pointer Buckets, const UsedT *Used, unsigned NumBuckets, const DebugEpochBase &Epoch)
DenseMap(std::initializer_list< typename BaseT::value_type > Vals)
DenseMap(unsigned NumElementsToReserve=0)
Create a DenseMap with an optional NumElementsToReserve to guarantee that this number of elements can...
DenseMap & operator=(DenseMap &&other)
DenseMap(llvm::from_range_t, const RangeT &Range)
DenseMap(const DenseMap &other)
DenseMap(const InputIt &I, const InputIt &E)
DenseMap(DenseMap &&other)
DenseMap & operator=(const DenseMap &other)
SmallDenseMap(const InputIt &I, const InputIt &E)
SmallDenseMap & operator=(SmallDenseMap &&other)
SmallDenseMap & operator=(const SmallDenseMap &other)
SmallDenseMap(unsigned NumElementsToReserve=0)
SmallDenseMap(std::initializer_list< typename BaseT::value_type > Vals)
SmallDenseMap(SmallDenseMap &&other)
SmallDenseMap(const SmallDenseMap &other)
SmallDenseMap(llvm::from_range_t, const RangeT &Range)
This is the common base class of value handles.
constexpr char IsConst[]
Key for Kernel::Arg::Metadata::mIsConst.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
void setUsed(UsedT *U, size_t I)
constexpr size_t usedWords(size_t N)
LLVM_ATTRIBUTE_ALWAYS_INLINE void forEachUsed(const UsedT *U, unsigned N, Fn Func)
constexpr size_t allocAlign()
size_t allocBytes(unsigned Num)
bool used(const UsedT *U, size_t I)
void unsetUsed(UsedT *U, size_t I)
A self-contained host- and target-independent arbitrary-precision floating-point software implementat...
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.
constexpr auto adl_begin(RangeT &&range) -> decltype(adl_detail::begin_impl(std::forward< RangeT >(range)))
Returns the begin iterator to range using std::begin and function found through Argument-Dependent Lo...
BitVector::size_type capacity_in_bytes(const BitVector &X)
bool operator!=(uint64_t V1, const APInt &V2)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
constexpr auto adl_end(RangeT &&range) -> decltype(adl_detail::end_impl(std::forward< RangeT >(range)))
Returns the end iterator to range using std::end and functions found through Argument-Dependent Looku...
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
auto map_range(ContainerTy &&C, FuncTy F)
Return a range that applies F to the elements of C.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
LLVM_ABI 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.
auto reverse(ContainerTy &&C)
LLVM_ABI void deallocate_buffer(void *Ptr, size_t Size, size_t Alignment)
Deallocate a buffer of memory with the given size and alignment.
constexpr bool shouldReverseIterate()
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
@ Default
The result value is uniform if and only if all operands are uniform.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
Implement std::hash so that hash_code can be used in STL containers.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
An information struct used to provide DenseMap with the various necessary components for a given valu...
std::conditional_t< std::is_pointer_v< T >, typename add_const_past_pointer< T >::type, const T & > type
const ValueT & getSecond() const
const KeyT & getFirst() const