21#ifndef LLVM_ADT_DENSEMAP_H
22#define LLVM_ADT_DENSEMAP_H
38#include <initializer_list>
65 template <
typename U1,
typename U2>
68 template <
typename U1,
typename U2>
72 operator std::pair<KeyT, ValueT>()
const {
return {
first,
second}; }
73 operator std::pair<const KeyT, ValueT>()
const {
return {
first,
second}; }
76 return LHS.first ==
RHS.first &&
LHS.second ==
RHS.second;
96 "bucket count must be zero or a power of two");
101 return (U[
I >> 5] >> (
I & 31)) & 1;
105 U[
I >> 5] &= ~(
UsedT(1) << (
I & 31));
111template <
typename Fn>
115 for (
unsigned W = 0; W != NW; ++W) {
128 return std::max(
alignof(BucketT),
alignof(
UsedT));
131 return sizeof(BucketT) *
static_cast<size_t>(Num) +
141template <
typename KeyT,
typename ValueT,
144 bool IsConst =
false>
147template <
typename DerivedT,
typename KeyT,
typename ValueT,
typename KeyInfoT,
150 template <
typename T>
182 [[nodiscard]]
inline auto keys() {
183 return map_range(*
this, [](
const BucketT &
P) {
return P.getFirst(); });
188 return map_range(*
this, [](
const BucketT &
P) {
return P.getSecond(); });
191 [[nodiscard]]
inline auto keys()
const {
192 return map_range(*
this, [](
const BucketT &
P) {
return P.getFirst(); });
195 [[nodiscard]]
inline auto values()
const {
196 return map_range(*
this, [](
const BucketT &
P) {
return P.getSecond(); });
199 [[nodiscard]]
bool empty()
const {
return getNumEntries() == 0; }
200 [[nodiscard]]
unsigned size()
const {
return getNumEntries(); }
207 if (NumBuckets > getNumBuckets())
213 if (getNumEntries() == 0)
218 if (getNumEntries() * 4 < getNumBuckets() && getNumBuckets() > 64) {
224 std::memset(getUsed(), 0,
231 auto [Reallocate, NewNumBuckets] = derived().planShrinkAndClear();
237 derived().deallocateBuckets();
242 [[nodiscard]]
bool contains(const_arg_type_t<KeyT> Val)
const {
243 return doFind(Val) !=
nullptr;
263 template <
class LookupKeyT>
265 if (BucketT *Bucket = doFind(Val))
266 return makeIterator(Bucket);
269 template <
class LookupKeyT>
271 if (
const BucketT *Bucket = doFind(Val))
272 return makeConstIterator(Bucket);
278 [[nodiscard]] ValueT
lookup(const_arg_type_t<KeyT> Val)
const {
279 if (
const BucketT *Bucket = doFind(Val))
280 return Bucket->getSecond();
287 template <
typename U = std::remove_cv_t<ValueT>>
288 [[nodiscard]] ValueT
lookup_or(const_arg_type_t<KeyT> Val,
290 if (
const BucketT *Bucket = doFind(Val))
291 return Bucket->getSecond();
296 [[nodiscard]] ValueT &
at(const_arg_type_t<KeyT> Val) {
297 auto Iter = this->
find(std::move(Val));
298 assert(Iter != this->
end() &&
"DenseMap::at failed due to a missing key");
303 [[nodiscard]]
const ValueT &
at(const_arg_type_t<KeyT> Val)
const {
304 auto Iter = this->
find(std::move(Val));
305 assert(Iter != this->
end() &&
"DenseMap::at failed due to a missing key");
312 std::pair<iterator, bool>
insert(
const std::pair<KeyT, ValueT> &KV) {
313 return try_emplace_impl(KV.first, KV.second);
319 std::pair<iterator, bool>
insert(std::pair<KeyT, ValueT> &&KV) {
320 return try_emplace_impl(std::move(KV.first), std::move(KV.second));
324 typename B = BucketT,
325 typename = std::enable_if_t<!std::is_same_v<B, std::pair<KeyT, ValueT>>>>
326 std::pair<iterator, bool>
insert(
const BucketT &KV) {
327 return try_emplace_impl(KV.first, KV.second);
331 typename B = BucketT,
332 typename = std::enable_if_t<!std::is_same_v<B, std::pair<KeyT, ValueT>>>>
333 std::pair<iterator, bool>
insert(BucketT &&KV) {
334 return try_emplace_impl(std::move(KV.first), std::move(KV.second));
340 template <
typename... Ts>
342 return try_emplace_impl(std::move(
Key), std::forward<Ts>(Args)...);
348 template <
typename... Ts>
350 return try_emplace_impl(
Key, std::forward<Ts>(Args)...);
358 template <
typename LookupKeyT>
359 std::pair<iterator, bool>
insert_as(std::pair<KeyT, ValueT> &&KV,
360 const LookupKeyT &Val) {
362 if (LookupBucketFor(Val, TheBucket))
363 return {makeIterator(TheBucket),
false};
366 TheBucket = findBucketForInsertion(Val, TheBucket);
367 ::new (&TheBucket->getFirst())
KeyT(std::move(KV.first));
368 ::new (&TheBucket->getSecond()) ValueT(std::move(KV.second));
369 return {makeIterator(TheBucket),
true};
373 template <
typename InputIt>
void insert(InputIt
I, InputIt
E) {
383 template <
typename V>
387 Ret.first->second = std::forward<V>(Val);
391 template <
typename V>
395 Ret.first->second = std::forward<V>(Val);
399 template <
typename... Ts>
403 Ret.first->second = ValueT(std::forward<Ts>(Args)...);
407 template <
typename... Ts>
409 auto Ret =
try_emplace(std::move(
Key), std::forward<Ts>(Args)...);
411 Ret.first->second = ValueT(std::forward<Ts>(Args)...);
420 BucketT *TheBucket = doFind(Val);
436 UsedT *U = getUsed();
437 unsigned NumBuckets = getNumBuckets();
438 BucketT *
B = getBuckets();
439 bool Removed =
false;
440 for (
unsigned I = 0;
I != NumBuckets; ++
I) {
444 B[
I].getSecond().~ValueT();
445 B[
I].getFirst().~KeyT();
447 decrementNumEntries();
453 this->grow(NumBuckets);
459 return lookupOrInsertIntoBucket(
Key).first->second;
463 return lookupOrInsertIntoBucket(std::move(
Key)).first->second;
469 return Ptr >= getBuckets() && Ptr < getBucketsEnd();
481 RHS.incrementEpoch();
482 derived().swapImpl(
RHS);
500 if (derived().allocateBuckets(NewNumBuckets))
509 if constexpr (std::is_trivially_destructible_v<BucketT>)
512 if (getNumBuckets() == 0)
515 BucketT *
B = getBuckets();
516 const UsedT *U = getUsed();
517 const unsigned E = getNumBuckets();
519 B[
I].getSecond().~ValueT();
520 B[
I].getFirst().~KeyT();
525 static_assert(std::is_base_of_v<DenseMapBase, DerivedT>,
526 "Must pass the derived type to this template!");
529 assert((getNumBuckets() & (getNumBuckets() - 1)) == 0 &&
530 "# initial buckets must be a power of two!");
531 if (getNumBuckets()) {
532 std::memset(getUsed(), 0,
552 assert(getNumEntries() == 0 &&
"moveFrom requires an empty destination");
553 BucketT *OtherB =
Other.getBuckets();
554 UsedT *OtherU =
Other.getUsed();
555 const unsigned E =
Other.getNumBuckets();
556 UsedT *U = getUsed();
557 BucketT *
B = getBuckets();
558 const unsigned Mask = getNumBuckets() - 1;
562 unsigned BucketNo = KeyInfoT::getHashValue(OtherB[
I].getFirst()) & Mask;
564 BucketNo = (BucketNo + 1) & Mask;
565 BucketT *DestBucket =
B + BucketNo;
566 ::new (&DestBucket->getFirst())
KeyT(std::move(OtherB[
I].getFirst()));
567 ::new (&DestBucket->getSecond()) ValueT(std::move(OtherB[
I].getSecond()));
571 OtherB[
I].getSecond().~ValueT();
572 OtherB[
I].getFirst().~KeyT();
574 setNumEntries(
Other.getNumEntries());
575 Other.derived().kill();
580 derived().deallocateBuckets();
582 if (!derived().allocateBuckets(other.getNumBuckets())) {
588 assert(getNumBuckets() == other.getNumBuckets());
590 setNumEntries(other.getNumEntries());
592 BucketT *Buckets = getBuckets();
593 const BucketT *OtherBuckets = other.getBuckets();
594 const unsigned NumBuckets = getNumBuckets();
595 UsedT *U = getUsed();
596 const UsedT *OtherU = other.getUsed();
597 std::memcpy(U, OtherU,
599 if constexpr (std::is_trivially_copyable_v<BucketT>) {
600 memcpy(
reinterpret_cast<void *
>(Buckets), OtherBuckets,
601 NumBuckets *
sizeof(BucketT));
604 ::new (&Buckets[
I].getFirst())
KeyT(OtherBuckets[
I].getFirst());
605 ::new (&Buckets[
I].getSecond()) ValueT(OtherBuckets[
I].getSecond());
619 template <
typename OnMovedT>
621 OnMovedT &&OnMoved) {
623 TheBucket->getSecond().~ValueT();
624 TheBucket->getFirst().~KeyT();
625 decrementNumEntries();
627 BucketT *BucketsPtr = getBuckets();
628 UsedT *U = getUsed();
629 const unsigned Mask = getNumBuckets() - 1;
630 unsigned I = TheBucket - BucketsPtr;
634 BucketT &BJ = BucketsPtr[J];
637 auto Ideal = KeyInfoT::getHashValue(BJ.getFirst());
640 if (((
I - Ideal) & Mask) < ((J - Ideal) & Mask)) {
641 BucketT &BI = BucketsPtr[
I];
642 ::new (&BI.getFirst())
KeyT(
std::
move(BJ.getFirst()));
643 ::new (&BI.getSecond()) ValueT(
std::
move(BJ.getSecond()));
644 BJ.getSecond().~ValueT();
645 BJ.getFirst().~
KeyT();
656 template <typename OnMovedT>
bool erase(
const KeyT &Val, OnMovedT &&OnMoved) {
657 BucketT *TheBucket = doFind(Val);
664 DerivedT &derived() {
return *
static_cast<DerivedT *
>(
this); }
665 const DerivedT &derived()
const {
666 return *
static_cast<const DerivedT *
>(
this);
669 template <
typename KeyArgT,
typename... Ts>
670 std::pair<BucketT *, bool> lookupOrInsertIntoBucket(KeyArgT &&
Key,
672 BucketT *TheBucket =
nullptr;
673 if (LookupBucketFor(
Key, TheBucket))
674 return {TheBucket,
false};
677 TheBucket = findBucketForInsertion(
Key, TheBucket);
678 ::new (&TheBucket->getFirst()) KeyT(std::forward<KeyArgT>(
Key));
679 ::new (&TheBucket->getSecond()) ValueT(std::forward<Ts>(Args)...);
680 return {TheBucket,
true};
683 template <
typename KeyArgT,
typename... Ts>
684 std::pair<iterator, bool> try_emplace_impl(KeyArgT &&
Key, Ts &&...Args) {
685 auto [Bucket,
Inserted] = lookupOrInsertIntoBucket(
686 std::forward<KeyArgT>(
Key), std::forward<Ts>(Args)...);
687 return {makeIterator(Bucket),
Inserted};
690 iterator makeIterator(BucketT *TheBucket) {
692 getNumBuckets(), *
this);
695 const_iterator makeConstIterator(
const BucketT *TheBucket)
const {
697 getNumBuckets(), *
this);
700 unsigned getNumEntries()
const {
return derived().getNumEntries(); }
702 void setNumEntries(
unsigned Num) { derived().setNumEntries(Num); }
704 void incrementNumEntries() { setNumEntries(getNumEntries() + 1); }
706 void decrementNumEntries() { setNumEntries(getNumEntries() - 1); }
708 const BucketT *getBuckets()
const {
return derived().getBuckets(); }
710 BucketT *getBuckets() {
return derived().getBuckets(); }
712 Rep getRep()
const {
return derived().getRep(); }
714 const UsedT *getUsed()
const {
return derived().getUsed(); }
716 UsedT *getUsed() {
return derived().getUsed(); }
718 unsigned getNumBuckets()
const {
return derived().getNumBuckets(); }
720 BucketT *getBucketsEnd() {
return getBuckets() + getNumBuckets(); }
722 const BucketT *getBucketsEnd()
const {
723 return getBuckets() + getNumBuckets();
727 unsigned NumBuckets = DerivedT::roundUpNumBuckets(MinNumBuckets);
729 Tmp.moveFrom(derived());
730 if (derived().maybeMoveFast(std::move(Tmp)))
736 template <
typename LookupKeyT>
737 BucketT *findBucketForInsertion(
const LookupKeyT &
Lookup,
738 BucketT *TheBucket) {
745 unsigned NewNumEntries = getNumEntries() + 1;
746 unsigned NumBuckets = getNumBuckets();
748 this->grow(NumBuckets * 2);
749 LookupBucketFor(
Lookup, TheBucket);
758 incrementNumEntries();
762 template <
typename LookupKeyT>
763 const BucketT *doFind(
const LookupKeyT &Val)
const {
766 auto [BucketsPtr,
U, NumBuckets] = getRep();
768 const unsigned Mask = NumBuckets - 1;
769 unsigned BucketNo = KeyInfoT::getHashValue(Val) &
Mask;
774 const BucketT *Bucket = BucketsPtr + BucketNo;
775 if (
LLVM_LIKELY(KeyInfoT::isEqual(Val, Bucket->getFirst())))
779 BucketNo = (BucketNo + 1) & Mask;
783 template <
typename LookupKeyT> BucketT *doFind(
const LookupKeyT &Val) {
784 return const_cast<BucketT *
>(
791 template <
typename LookupKeyT>
792 bool LookupBucketFor(
const LookupKeyT &Val, BucketT *&FoundBucket) {
793 auto [CBuckets,
U, NumBuckets] = getRep();
794 if (NumBuckets == 0) {
795 FoundBucket =
nullptr;
800 BucketT *BucketsPtr =
const_cast<BucketT *
>(CBuckets);
802 const unsigned Mask = NumBuckets - 1;
803 unsigned BucketNo = KeyInfoT::getHashValue(Val) &
Mask;
805 BucketT *ThisBucket = BucketsPtr + BucketNo;
809 FoundBucket = ThisBucket;
814 if (
LLVM_LIKELY(KeyInfoT::isEqual(Val, ThisBucket->getFirst()))) {
815 FoundBucket = ThisBucket;
820 BucketNo = (BucketNo + 1) & Mask;
840template <
typename DerivedT,
typename KeyT,
typename ValueT,
typename KeyInfoT,
845 if (
LHS.size() !=
RHS.size())
848 for (
auto &KV :
LHS) {
849 auto I =
RHS.find(KV.first);
850 if (
I ==
RHS.end() ||
I->second != KV.second)
860template <
typename DerivedT,
typename KeyT,
typename ValueT,
typename KeyInfoT,
868template <
typename KeyT,
typename ValueT,
869 typename KeyInfoT = DenseMapInfo<KeyT>,
871class DenseMap :
public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>,
872 KeyT, ValueT, KeyInfoT, BucketT> {
880 BucketT *Buckets =
nullptr;
881 UsedT *Used =
nullptr;
882 unsigned NumEntries = 0;
883 unsigned NumBuckets = 0;
885 explicit DenseMap(
unsigned NumBuckets,
typename BaseT::ExactBucketCount) {
892 explicit DenseMap(
unsigned NumElementsToReserve = 0)
894 typename BaseT::ExactBucketCount{}) {}
896 DenseMap(
const DenseMap &other) : DenseMap() { this->copyFrom(other); }
898 DenseMap(DenseMap &&other) : DenseMap() { this->swap(other); }
900 template <
typename InputIt>
905 template <
typename RangeT>
909 DenseMap(std::initializer_list<typename BaseT::value_type> Vals)
910 : DenseMap(Vals.begin(), Vals.end()) {}
919 this->copyFrom(other);
926 this->initWithExactBucketCount(0);
939 unsigned getNumEntries()
const {
return NumEntries; }
941 void setNumEntries(
unsigned Num) {
NumEntries = Num; }
943 BucketT *getBuckets()
const {
return Buckets; }
945 typename BaseT::Rep getRep()
const {
return {Buckets,
Used, NumBuckets}; }
949 unsigned getNumBuckets()
const {
return NumBuckets; }
951 void deallocateBuckets() {
962 bool allocateBuckets(
unsigned Num) {
964 if (NumBuckets == 0) {
970 auto *Storage =
static_cast<char *
>(
973 Buckets =
reinterpret_cast<BucketT *
>(Storage);
976 assert(
sizeof(BucketT) * NumBuckets %
alignof(UsedT) == 0 &&
977 "used array would be misaligned");
978 Used =
reinterpret_cast<UsedT *
>(Storage +
sizeof(BucketT) * NumBuckets);
984 void kill() { deallocateBuckets(); }
986 static unsigned roundUpNumBuckets(
unsigned MinNumBuckets) {
988 static_cast<unsigned>(
NextPowerOf2(MinNumBuckets - 1)));
991 bool maybeMoveFast(DenseMap &&Other) {
999 std::pair<bool, unsigned> planShrinkAndClear()
const {
1000 unsigned NewNumBuckets = 0;
1002 NewNumBuckets = std::max(64u, 1u << (
Log2_32_Ceil(NumEntries) + 1));
1003 if (NewNumBuckets == NumBuckets)
1005 return {
true, NewNumBuckets};
1009template <
typename KeyT,
typename ValueT,
unsigned InlineBuckets = 4,
1010 typename KeyInfoT = DenseMapInfo<KeyT>,
1014 SmallDenseMap<KeyT, ValueT, InlineBuckets, KeyInfoT, BucketT>, KeyT,
1015 ValueT, KeyInfoT, BucketT> {
1024 "InlineBuckets must be a power of 2.");
1027 static constexpr unsigned InlineUsedWords =
1031 unsigned NumEntries : 31;
1035 alignas(BucketT)
char Buckets[
sizeof(BucketT) * InlineBuckets];
1036 UsedT Used[InlineUsedWords];
1041 unsigned NumBuckets;
1050 SmallDenseMap(
unsigned NumBuckets,
typename BaseT::ExactBucketCount) {
1051 this->initWithExactBucketCount(NumBuckets);
1066 template <
typename InputIt>
1068 : SmallDenseMap(
std::distance(
I,
E)) {
1072 template <
typename RangeT>
1077 : SmallDenseMap(Vals.
begin(), Vals.
end()) {}
1081 deallocateBuckets();
1092 deallocateBuckets();
1100 static void relocateBucket(BucketT *Dst, BucketT *Src) {
1101 ::new (&Dst->getFirst())
KeyT(
std::
move(Src->getFirst()));
1102 ::new (&Dst->getSecond()) ValueT(
std::
move(Src->getSecond()));
1103 Src->getSecond().~ValueT();
1104 Src->getFirst().~
KeyT();
1108 unsigned TmpNumEntries =
RHS.NumEntries;
1109 RHS.NumEntries = NumEntries;
1110 NumEntries = TmpNumEntries;
1112 if (Small &&
RHS.Small) {
1116 UsedT *LU = getInlineUsed(), *RU = RHS.getInlineUsed();
1117 BucketT *LB = getInlineBuckets(), *RB = RHS.getInlineBuckets();
1118 for (unsigned I = 0; I != InlineBuckets; ++I) {
1119 bool L = llvm::densemap::detail::used(LU, I);
1120 bool R = llvm::densemap::detail::used(RU, I);
1123 alignas(BucketT) char Tmp[sizeof(BucketT)];
1124 BucketT *T = reinterpret_cast<BucketT *>(Tmp);
1125 relocateBucket(T, &LB[I]);
1126 relocateBucket(&LB[I], &RB[I]);
1127 relocateBucket(&RB[I], T);
1129 relocateBucket(&RB[I], &LB[I]);
1131 relocateBucket(&LB[I], &RB[I]);
1134 for (
unsigned W = 0; W != InlineUsedWords; ++W)
1138 if (!Small && !
RHS.Small) {
1143 SmallDenseMap &SmallSide =
Small ? *this :
RHS;
1144 SmallDenseMap &LargeSide =
Small ?
RHS : *
this;
1149 LargeRep TmpRep = LargeSide.storage.Large;
1150 LargeSide.Small =
true;
1152 UsedT *SU = SmallSide.getInlineUsed(), *LU = LargeSide.getInlineUsed();
1153 BucketT *SB = SmallSide.getInlineBuckets(),
1154 *LB = LargeSide.getInlineBuckets();
1155 for (
unsigned I = 0;
I != InlineBuckets; ++
I)
1157 relocateBucket(&LB[
I], &SB[
I]);
1158 for (
unsigned W = 0;
W != InlineUsedWords; ++
W)
1161 SmallSide.Small =
false;
1162 SmallSide.storage.Large = TmpRep;
1165 unsigned getNumEntries()
const {
return NumEntries; }
1167 void setNumEntries(
unsigned Num) {
1169 assert(Num < (1U << 31) &&
"Cannot support more than 1<<31 entries");
1173 const BucketT *getInlineBuckets()
const {
1178 return reinterpret_cast<const BucketT *
>(storage.Inline.Buckets);
1181 BucketT *getInlineBuckets() {
1183 return reinterpret_cast<BucketT *
>(storage.Inline.Buckets);
1186 const UsedT *getInlineUsed()
const {
1188 return storage.Inline.Used;
1191 UsedT *getInlineUsed() {
1193 return storage.Inline.Used;
1196 const BucketT *getBuckets()
const {
1197 return Small ? getInlineBuckets() : storage.
Large.Buckets;
1200 typename BaseT::Rep getRep()
const {
1202 return {getInlineBuckets(), getInlineUsed(), InlineBuckets};
1203 return {storage.Large.Buckets, storage.Large.Used,
1204 storage.Large.NumBuckets};
1207 BucketT *getBuckets() {
1208 return const_cast<BucketT *
>(
1209 const_cast<const SmallDenseMap *
>(
this)->getBuckets());
1212 const UsedT *getUsed()
const {
1217 return const_cast<UsedT *
>(
1218 const_cast<const SmallDenseMap *
>(
this)->getUsed());
1221 unsigned getNumBuckets()
const {
1222 return Small ? InlineBuckets : storage.Large.NumBuckets;
1225 void deallocateBuckets() {
1228 if (Small || storage.Large.NumBuckets == 0)
1232 storage.Large.Buckets,
1235 storage.Large.NumBuckets = 0;
1238 bool allocateBuckets(
unsigned Num) {
1239 if (Num <= InlineBuckets) {
1244 auto *S =
static_cast<char *
>(
1247 storage.Large.Buckets =
reinterpret_cast<BucketT *
>(S);
1248 storage.Large.Used =
reinterpret_cast<UsedT *
>(S +
sizeof(BucketT) * Num);
1249 storage.Large.NumBuckets = Num;
1255 deallocateBuckets();
1257 storage.Large = LargeRep{
nullptr,
nullptr, 0};
1260 static unsigned roundUpNumBuckets(
unsigned MinNumBuckets) {
1261 if (MinNumBuckets <= InlineBuckets)
1262 return InlineBuckets;
1263 return std::max(64u,
1264 static_cast<unsigned>(
NextPowerOf2(MinNumBuckets - 1)));
1267 bool maybeMoveFast(SmallDenseMap &&Other) {
1273 storage.Large =
Other.storage.Large;
1274 Other.storage.Large.NumBuckets = 0;
1281 std::pair<bool, unsigned> planShrinkAndClear()
const {
1282 unsigned NewNumBuckets = 0;
1283 if (!this->
empty()) {
1285 if (NewNumBuckets > InlineBuckets)
1286 NewNumBuckets = std::max(64u, NewNumBuckets);
1288 bool Reuse =
Small ? NewNumBuckets <= InlineBuckets
1289 : NewNumBuckets == storage.Large.NumBuckets;
1292 return {
true, NewNumBuckets};
1296template <
typename KeyT,
typename ValueT,
typename KeyInfoT,
typename Bucket,
1299 friend class DenseMapIterator<
KeyT, ValueT, KeyInfoT, Bucket,
true>;
1300 friend class DenseMapIterator<
KeyT, ValueT, KeyInfoT, Bucket,
false>;
1306 using value_type = std::conditional_t<IsConst, const Bucket, Bucket>;
1313 std::conditional_t<shouldReverseIterate<KeyT>(),
1314 std::reverse_iterator<pointer>,
pointer>;
1316 BucketItTy Ptr = {};
1317 BucketItTy End = {};
1320 pointer Buckets = {};
1323 DenseMapIterator(BucketItTy Pos, BucketItTy
E, pointer BucketsBase,
1324 const UsedT *U,
const DebugEpochBase &Epoch)
1325 : DebugEpochBase::HandleBase(&Epoch), Ptr(Pos), End(
E),
1326 Buckets(BucketsBase),
Used(
U) {
1327 assert(isHandleInSync() &&
"invalid construction!");
1334 unsigned NumBuckets,
bool IsEmpty,
1339 return makeEnd(Buckets, Used, NumBuckets, Epoch);
1341 DenseMapIterator Iter(R.begin(), R.end(), Buckets, Used, Epoch);
1342 Iter.AdvancePastEmptyBuckets();
1347 unsigned NumBuckets,
1350 return DenseMapIterator(R.end(), R.end(), Buckets, Used, Epoch);
1354 const UsedT *Used,
unsigned NumBuckets,
1358 return DenseMapIterator(BucketItTy(
P +
Offset), R.end(), Buckets, Used,
1365 template <
bool IsConstSrc,
1366 typename = std::enable_if_t<!IsConstSrc && IsConst>>
1368 const DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, IsConstSrc> &
I)
1370 Buckets(
I.Buckets), Used(
I.Used) {}
1374 assert(Ptr != End &&
"dereferencing end() iterator");
1380 const DenseMapIterator &
RHS) {
1381 assert(
LHS.isComparableWith(
RHS) &&
"incomparable iterators!");
1382 return LHS.Ptr ==
RHS.Ptr;
1386 const DenseMapIterator &
RHS) {
1392 assert(Ptr != End &&
"incrementing end() iterator");
1394 AdvancePastEmptyBuckets();
1399 DenseMapIterator tmp = *
this;
1405 void AdvancePastEmptyBuckets() {
1412 const size_t N = End - Buckets;
1413 size_t I = Ptr - Buckets;
1432 static auto maybeReverse(iterator_range<pointer>
Range) {
1433 if constexpr (shouldReverseIterate<KeyT>())
1440template <
typename KeyT,
typename ValueT,
typename KeyInfoT>
1441[[nodiscard]]
inline size_t
1443 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)
std::pair< iterator, bool > insert(const BucketT &KV)
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(BucketT &&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.
LLVM Value Representation.
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
friend bool operator!=(const DenseMapPair &LHS, const DenseMapPair &RHS)
DenseMapPair(const KeyT &Key, const ValueT &Value)
DenseMapPair(KeyT &&Key, ValueT &&Value)
DenseMapPair(std::pair< KeyT, ValueT > &&P)
DenseMapPair(DenseMapPair< U1, U2 > &&P)
DenseMapPair(const std::pair< KeyT, ValueT > &P)
const ValueT & getSecond() const
friend bool operator==(const DenseMapPair &LHS, const DenseMapPair &RHS)
const KeyT & getFirst() const
DenseMapPair(const DenseMapPair< U1, U2 > &P)