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;
93template <
typename BucketT>
95 std::is_trivially_copy_constructible_v<BucketT> &&
96 std::is_trivially_destructible_v<BucketT>;
103 "bucket count must be zero or a power of two");
104 return (
N + 31) / 32;
108 return (U[
I >> 5] >> (
I & 31)) & 1;
112 U[
I >> 5] &= ~(
UsedT(1) << (
I & 31));
118template <
typename Fn>
122 for (
unsigned W = 0; W != NW; ++W) {
135 return std::max(
alignof(BucketT),
alignof(
UsedT));
138 return sizeof(BucketT) *
static_cast<size_t>(Num) +
148template <
typename KeyT,
typename ValueT,
151 bool IsConst =
false>
154template <
typename DerivedT,
typename KeyT,
typename ValueT,
typename KeyInfoT,
157 template <
typename T>
189 [[nodiscard]]
inline auto keys() {
190 return map_range(*
this, [](
const BucketT &
P) {
return P.getFirst(); });
195 return map_range(*
this, [](
const BucketT &
P) {
return P.getSecond(); });
198 [[nodiscard]]
inline auto keys()
const {
199 return map_range(*
this, [](
const BucketT &
P) {
return P.getFirst(); });
202 [[nodiscard]]
inline auto values()
const {
203 return map_range(*
this, [](
const BucketT &
P) {
return P.getSecond(); });
206 [[nodiscard]]
bool empty()
const {
return getNumEntries() == 0; }
207 [[nodiscard]]
unsigned size()
const {
return getNumEntries(); }
214 if (NumBuckets > getNumBuckets())
220 if (getNumEntries() == 0)
225 if (getNumEntries() * 4 < getNumBuckets() && getNumBuckets() > 64) {
231 std::memset(getUsed(), 0,
238 auto [Reallocate, NewNumBuckets] = derived().planShrinkAndClear();
244 derived().deallocateBuckets();
249 [[nodiscard]]
bool contains(const_arg_type_t<KeyT> Val)
const {
250 return doFind(Val) !=
nullptr;
270 template <
class LookupKeyT>
272 if (BucketT *Bucket = doFind(Val))
273 return makeIterator(Bucket);
276 template <
class LookupKeyT>
278 if (
const BucketT *Bucket = doFind(Val))
279 return makeConstIterator(Bucket);
285 [[nodiscard]] ValueT
lookup(const_arg_type_t<KeyT> Val)
const {
286 if (
const BucketT *Bucket = doFind(Val))
287 return Bucket->getSecond();
294 template <
typename U = std::remove_cv_t<ValueT>>
295 [[nodiscard]] ValueT
lookup_or(const_arg_type_t<KeyT> Val,
297 if (
const BucketT *Bucket = doFind(Val))
298 return Bucket->getSecond();
303 [[nodiscard]] ValueT &
at(const_arg_type_t<KeyT> Val) {
304 auto Iter = this->
find(std::move(Val));
305 assert(Iter != this->
end() &&
"DenseMap::at failed due to a missing key");
310 [[nodiscard]]
const ValueT &
at(const_arg_type_t<KeyT> Val)
const {
311 auto Iter = this->
find(std::move(Val));
312 assert(Iter != this->
end() &&
"DenseMap::at failed due to a missing key");
319 std::pair<iterator, bool>
insert(
const std::pair<KeyT, ValueT> &KV) {
320 return try_emplace_impl(KV.first, KV.second);
326 std::pair<iterator, bool>
insert(std::pair<KeyT, ValueT> &&KV) {
327 return try_emplace_impl(std::move(KV.first), std::move(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(
const BucketT &KV) {
334 return try_emplace_impl(KV.first, KV.second);
338 typename B = BucketT,
339 typename = std::enable_if_t<!std::is_same_v<B, std::pair<KeyT, ValueT>>>>
340 std::pair<iterator, bool>
insert(BucketT &&KV) {
341 return try_emplace_impl(std::move(KV.first), std::move(KV.second));
347 template <
typename... Ts>
349 return try_emplace_impl(std::move(
Key), std::forward<Ts>(Args)...);
355 template <
typename... Ts>
357 return try_emplace_impl(
Key, std::forward<Ts>(Args)...);
365 template <
typename LookupKeyT>
366 std::pair<iterator, bool>
insert_as(std::pair<KeyT, ValueT> &&KV,
367 const LookupKeyT &Val) {
369 if (LookupBucketFor(Val, TheBucket))
370 return {makeIterator(TheBucket),
false};
373 TheBucket = findBucketForInsertion(Val, TheBucket);
374 ::new (&TheBucket->getFirst())
KeyT(std::move(KV.first));
375 ::new (&TheBucket->getSecond()) ValueT(std::move(KV.second));
376 return {makeIterator(TheBucket),
true};
380 template <
typename InputIt>
void insert(InputIt
I, InputIt
E) {
390 template <
typename V>
394 Ret.first->second = std::forward<V>(Val);
398 template <
typename V>
402 Ret.first->second = std::forward<V>(Val);
406 template <
typename... Ts>
410 Ret.first->second = ValueT(std::forward<Ts>(Args)...);
414 template <
typename... Ts>
416 auto Ret =
try_emplace(std::move(
Key), std::forward<Ts>(Args)...);
418 Ret.first->second = ValueT(std::forward<Ts>(Args)...);
427 BucketT *TheBucket = doFind(Val);
443 UsedT *U = getUsed();
444 unsigned NumBuckets = getNumBuckets();
445 BucketT *
B = getBuckets();
446 bool Removed =
false;
447 for (
unsigned I = 0;
I != NumBuckets; ++
I) {
451 B[
I].getSecond().~ValueT();
452 B[
I].getFirst().~KeyT();
454 decrementNumEntries();
460 this->grow(NumBuckets);
466 return lookupOrInsertIntoBucket(
Key).first->second;
470 return lookupOrInsertIntoBucket(std::move(
Key)).first->second;
476 return Ptr >= getBuckets() && Ptr < getBucketsEnd();
488 RHS.incrementEpoch();
489 derived().swapImpl(
RHS);
507 if (derived().allocateBuckets(NewNumBuckets))
516 if constexpr (std::is_trivially_destructible_v<BucketT>)
519 if (getNumBuckets() == 0)
522 BucketT *
B = getBuckets();
523 const UsedT *U = getUsed();
524 const unsigned E = getNumBuckets();
526 B[
I].getSecond().~ValueT();
527 B[
I].getFirst().~KeyT();
532 static_assert(std::is_base_of_v<DenseMapBase, DerivedT>,
533 "Must pass the derived type to this template!");
536 assert((getNumBuckets() & (getNumBuckets() - 1)) == 0 &&
537 "# initial buckets must be a power of two!");
538 if (getNumBuckets()) {
539 std::memset(getUsed(), 0,
559 assert(getNumEntries() == 0 &&
"moveFrom requires an empty destination");
560 BucketT *OtherB =
Other.getBuckets();
561 UsedT *OtherU =
Other.getUsed();
562 const unsigned E =
Other.getNumBuckets();
563 UsedT *U = getUsed();
564 BucketT *
B = getBuckets();
565 const unsigned Mask = getNumBuckets() - 1;
569 unsigned BucketNo = KeyInfoT::getHashValue(OtherB[
I].getFirst()) & Mask;
571 BucketNo = (BucketNo + 1) & Mask;
572 BucketT *DestBucket =
B + BucketNo;
573 ::new (&DestBucket->getFirst())
KeyT(std::move(OtherB[
I].getFirst()));
574 ::new (&DestBucket->getSecond()) ValueT(std::move(OtherB[
I].getSecond()));
578 OtherB[
I].getSecond().~ValueT();
579 OtherB[
I].getFirst().~KeyT();
581 setNumEntries(
Other.getNumEntries());
582 Other.derived().kill();
587 derived().deallocateBuckets();
589 if (!derived().allocateBuckets(other.getNumBuckets())) {
595 assert(getNumBuckets() == other.getNumBuckets());
597 setNumEntries(other.getNumEntries());
599 BucketT *Buckets = getBuckets();
600 const BucketT *OtherBuckets = other.getBuckets();
601 const unsigned NumBuckets = getNumBuckets();
602 UsedT *U = getUsed();
603 const UsedT *OtherU = other.getUsed();
604 std::memcpy(U, OtherU,
607 memcpy(
reinterpret_cast<void *
>(Buckets), OtherBuckets,
608 NumBuckets *
sizeof(BucketT));
611 ::new (&Buckets[
I].getFirst())
KeyT(OtherBuckets[
I].getFirst());
612 ::new (&Buckets[
I].getSecond()) ValueT(OtherBuckets[
I].getSecond());
626 template <
typename OnMovedT>
628 OnMovedT &&OnMoved) {
630 TheBucket->getSecond().~ValueT();
631 TheBucket->getFirst().~KeyT();
632 decrementNumEntries();
634 BucketT *BucketsPtr = getBuckets();
635 UsedT *U = getUsed();
636 const unsigned Mask = getNumBuckets() - 1;
637 unsigned I = TheBucket - BucketsPtr;
641 BucketT &BJ = BucketsPtr[J];
644 auto Ideal = KeyInfoT::getHashValue(BJ.getFirst());
647 if (((
I - Ideal) & Mask) < ((J - Ideal) & Mask)) {
648 BucketT &BI = BucketsPtr[
I];
649 ::new (&BI.getFirst())
KeyT(
std::
move(BJ.getFirst()));
650 ::new (&BI.getSecond()) ValueT(
std::
move(BJ.getSecond()));
651 BJ.getSecond().~ValueT();
652 BJ.getFirst().~
KeyT();
663 template <typename OnMovedT>
bool erase(
const KeyT &Val, OnMovedT &&OnMoved) {
664 BucketT *TheBucket = doFind(Val);
671 DerivedT &derived() {
return *
static_cast<DerivedT *
>(
this); }
672 const DerivedT &derived()
const {
673 return *
static_cast<const DerivedT *
>(
this);
676 template <
typename KeyArgT,
typename... Ts>
677 std::pair<BucketT *, bool> lookupOrInsertIntoBucket(KeyArgT &&
Key,
679 BucketT *TheBucket =
nullptr;
680 if (LookupBucketFor(
Key, TheBucket))
681 return {TheBucket,
false};
684 TheBucket = findBucketForInsertion(
Key, TheBucket);
685 ::new (&TheBucket->getFirst()) KeyT(std::forward<KeyArgT>(
Key));
686 ::new (&TheBucket->getSecond()) ValueT(std::forward<Ts>(Args)...);
687 return {TheBucket,
true};
690 template <
typename KeyArgT,
typename... Ts>
691 std::pair<iterator, bool> try_emplace_impl(KeyArgT &&
Key, Ts &&...Args) {
692 auto [Bucket,
Inserted] = lookupOrInsertIntoBucket(
693 std::forward<KeyArgT>(
Key), std::forward<Ts>(Args)...);
694 return {makeIterator(Bucket),
Inserted};
697 iterator makeIterator(BucketT *TheBucket) {
699 getNumBuckets(), *
this);
702 const_iterator makeConstIterator(
const BucketT *TheBucket)
const {
704 getNumBuckets(), *
this);
707 unsigned getNumEntries()
const {
return derived().getNumEntries(); }
709 void setNumEntries(
unsigned Num) { derived().setNumEntries(Num); }
711 void incrementNumEntries() { setNumEntries(getNumEntries() + 1); }
713 void decrementNumEntries() { setNumEntries(getNumEntries() - 1); }
715 const BucketT *getBuckets()
const {
return derived().getBuckets(); }
717 BucketT *getBuckets() {
return derived().getBuckets(); }
719 Rep getRep()
const {
return derived().getRep(); }
721 const UsedT *getUsed()
const {
return derived().getUsed(); }
723 UsedT *getUsed() {
return derived().getUsed(); }
725 unsigned getNumBuckets()
const {
return derived().getNumBuckets(); }
727 BucketT *getBucketsEnd() {
return getBuckets() + getNumBuckets(); }
729 const BucketT *getBucketsEnd()
const {
730 return getBuckets() + getNumBuckets();
734 unsigned NumBuckets = DerivedT::roundUpNumBuckets(MinNumBuckets);
736 Tmp.moveFrom(derived());
737 if (derived().maybeMoveFast(std::move(Tmp)))
743 template <
typename LookupKeyT>
744 BucketT *findBucketForInsertion(
const LookupKeyT &
Lookup,
745 BucketT *TheBucket) {
752 unsigned NewNumEntries = getNumEntries() + 1;
753 unsigned NumBuckets = getNumBuckets();
755 this->grow(NumBuckets * 2);
756 LookupBucketFor(
Lookup, TheBucket);
765 incrementNumEntries();
769 template <
typename LookupKeyT>
770 const BucketT *doFind(
const LookupKeyT &Val)
const {
773 auto [BucketsPtr,
U, NumBuckets] = getRep();
775 const unsigned Mask = NumBuckets - 1;
776 unsigned BucketNo = KeyInfoT::getHashValue(Val) &
Mask;
781 const BucketT *Bucket = BucketsPtr + BucketNo;
782 if (
LLVM_LIKELY(KeyInfoT::isEqual(Val, Bucket->getFirst())))
786 BucketNo = (BucketNo + 1) & Mask;
790 template <
typename LookupKeyT> BucketT *doFind(
const LookupKeyT &Val) {
791 return const_cast<BucketT *
>(
798 template <
typename LookupKeyT>
799 bool LookupBucketFor(
const LookupKeyT &Val, BucketT *&FoundBucket) {
800 auto [CBuckets,
U, NumBuckets] = getRep();
801 if (NumBuckets == 0) {
802 FoundBucket =
nullptr;
807 BucketT *BucketsPtr =
const_cast<BucketT *
>(CBuckets);
809 const unsigned Mask = NumBuckets - 1;
810 unsigned BucketNo = KeyInfoT::getHashValue(Val) &
Mask;
812 BucketT *ThisBucket = BucketsPtr + BucketNo;
816 FoundBucket = ThisBucket;
821 if (
LLVM_LIKELY(KeyInfoT::isEqual(Val, ThisBucket->getFirst()))) {
822 FoundBucket = ThisBucket;
827 BucketNo = (BucketNo + 1) & Mask;
847template <
typename DerivedT,
typename KeyT,
typename ValueT,
typename KeyInfoT,
852 if (
LHS.size() !=
RHS.size())
855 for (
auto &KV :
LHS) {
856 auto I =
RHS.find(KV.first);
857 if (
I ==
RHS.end() ||
I->second != KV.second)
867template <
typename DerivedT,
typename KeyT,
typename ValueT,
typename KeyInfoT,
875template <
typename KeyT,
typename ValueT,
876 typename KeyInfoT = DenseMapInfo<KeyT>,
878class DenseMap :
public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>,
879 KeyT, ValueT, KeyInfoT, BucketT> {
887 BucketT *Buckets =
nullptr;
888 UsedT *Used =
nullptr;
889 unsigned NumEntries = 0;
890 unsigned NumBuckets = 0;
892 explicit DenseMap(
unsigned NumBuckets,
typename BaseT::ExactBucketCount) {
899 explicit DenseMap(
unsigned NumElementsToReserve = 0)
901 typename BaseT::ExactBucketCount{}) {}
903 DenseMap(
const DenseMap &other) : DenseMap() { this->copyFrom(other); }
905 DenseMap(DenseMap &&other) : DenseMap() { this->swap(other); }
907 template <
typename InputIt>
912 template <
typename RangeT>
916 DenseMap(std::initializer_list<typename BaseT::value_type> Vals)
917 : DenseMap(Vals.begin(), Vals.end()) {}
926 this->copyFrom(other);
933 this->initWithExactBucketCount(0);
946 unsigned getNumEntries()
const {
return NumEntries; }
948 void setNumEntries(
unsigned Num) {
NumEntries = Num; }
950 BucketT *getBuckets()
const {
return Buckets; }
952 typename BaseT::Rep getRep()
const {
return {Buckets,
Used, NumBuckets}; }
956 unsigned getNumBuckets()
const {
return NumBuckets; }
958 void deallocateBuckets() {
969 bool allocateBuckets(
unsigned Num) {
971 if (NumBuckets == 0) {
977 auto *Storage =
static_cast<char *
>(
980 Buckets =
reinterpret_cast<BucketT *
>(Storage);
983 assert(
sizeof(BucketT) * NumBuckets %
alignof(UsedT) == 0 &&
984 "used array would be misaligned");
985 Used =
reinterpret_cast<UsedT *
>(Storage +
sizeof(BucketT) * NumBuckets);
991 void kill() { deallocateBuckets(); }
993 static unsigned roundUpNumBuckets(
unsigned MinNumBuckets) {
995 static_cast<unsigned>(
NextPowerOf2(MinNumBuckets - 1)));
998 bool maybeMoveFast(DenseMap &&Other) {
1006 std::pair<bool, unsigned> planShrinkAndClear()
const {
1007 unsigned NewNumBuckets = 0;
1009 NewNumBuckets = std::max(64u, 1u << (
Log2_32_Ceil(NumEntries) + 1));
1010 if (NewNumBuckets == NumBuckets)
1012 return {
true, NewNumBuckets};
1016template <
typename KeyT,
typename ValueT,
unsigned InlineBuckets = 4,
1017 typename KeyInfoT = DenseMapInfo<KeyT>,
1021 SmallDenseMap<KeyT, ValueT, InlineBuckets, KeyInfoT, BucketT>, KeyT,
1022 ValueT, KeyInfoT, BucketT> {
1031 "InlineBuckets must be a power of 2.");
1034 static constexpr unsigned InlineUsedWords =
1038 unsigned NumEntries : 31;
1042 alignas(BucketT)
char Buckets[
sizeof(BucketT) * InlineBuckets];
1043 UsedT Used[InlineUsedWords];
1048 unsigned NumBuckets;
1057 SmallDenseMap(
unsigned NumBuckets,
typename BaseT::ExactBucketCount) {
1058 this->initWithExactBucketCount(NumBuckets);
1073 template <
typename InputIt>
1075 : SmallDenseMap(
std::distance(
I,
E)) {
1079 template <
typename RangeT>
1084 : SmallDenseMap(Vals.
begin(), Vals.
end()) {}
1088 deallocateBuckets();
1099 deallocateBuckets();
1107 static void relocateBucket(BucketT *Dst, BucketT *Src) {
1108 ::new (&Dst->getFirst())
KeyT(
std::
move(Src->getFirst()));
1109 ::new (&Dst->getSecond()) ValueT(
std::
move(Src->getSecond()));
1110 Src->getSecond().~ValueT();
1111 Src->getFirst().~
KeyT();
1115 unsigned TmpNumEntries =
RHS.NumEntries;
1116 RHS.NumEntries = NumEntries;
1117 NumEntries = TmpNumEntries;
1119 if (Small &&
RHS.Small) {
1123 UsedT *LU = getInlineUsed(), *RU = RHS.getInlineUsed();
1124 BucketT *LB = getInlineBuckets(), *RB = RHS.getInlineBuckets();
1125 for (unsigned I = 0; I != InlineBuckets; ++I) {
1126 bool L = llvm::densemap::detail::used(LU, I);
1127 bool R = llvm::densemap::detail::used(RU, I);
1130 alignas(BucketT) char Tmp[sizeof(BucketT)];
1131 BucketT *T = reinterpret_cast<BucketT *>(Tmp);
1132 relocateBucket(T, &LB[I]);
1133 relocateBucket(&LB[I], &RB[I]);
1134 relocateBucket(&RB[I], T);
1136 relocateBucket(&RB[I], &LB[I]);
1138 relocateBucket(&LB[I], &RB[I]);
1141 for (
unsigned W = 0; W != InlineUsedWords; ++W)
1145 if (!Small && !
RHS.Small) {
1150 SmallDenseMap &SmallSide =
Small ? *this :
RHS;
1151 SmallDenseMap &LargeSide =
Small ?
RHS : *
this;
1156 LargeRep TmpRep = LargeSide.storage.Large;
1157 LargeSide.Small =
true;
1159 UsedT *SU = SmallSide.getInlineUsed(), *LU = LargeSide.getInlineUsed();
1160 BucketT *SB = SmallSide.getInlineBuckets(),
1161 *LB = LargeSide.getInlineBuckets();
1162 for (
unsigned I = 0;
I != InlineBuckets; ++
I)
1164 relocateBucket(&LB[
I], &SB[
I]);
1165 for (
unsigned W = 0;
W != InlineUsedWords; ++
W)
1168 SmallSide.Small =
false;
1169 SmallSide.storage.Large = TmpRep;
1172 unsigned getNumEntries()
const {
return NumEntries; }
1174 void setNumEntries(
unsigned Num) {
1176 assert(Num < (1U << 31) &&
"Cannot support more than 1<<31 entries");
1180 const BucketT *getInlineBuckets()
const {
1185 return reinterpret_cast<const BucketT *
>(storage.Inline.Buckets);
1188 BucketT *getInlineBuckets() {
1190 return reinterpret_cast<BucketT *
>(storage.Inline.Buckets);
1193 const UsedT *getInlineUsed()
const {
1195 return storage.Inline.Used;
1198 UsedT *getInlineUsed() {
1200 return storage.Inline.Used;
1203 const BucketT *getBuckets()
const {
1204 return Small ? getInlineBuckets() : storage.
Large.Buckets;
1207 typename BaseT::Rep getRep()
const {
1209 return {getInlineBuckets(), getInlineUsed(), InlineBuckets};
1210 return {storage.Large.Buckets, storage.Large.Used,
1211 storage.Large.NumBuckets};
1214 BucketT *getBuckets() {
1215 return const_cast<BucketT *
>(
1216 const_cast<const SmallDenseMap *
>(
this)->getBuckets());
1219 const UsedT *getUsed()
const {
1224 return const_cast<UsedT *
>(
1225 const_cast<const SmallDenseMap *
>(
this)->getUsed());
1228 unsigned getNumBuckets()
const {
1229 return Small ? InlineBuckets : storage.Large.NumBuckets;
1232 void deallocateBuckets() {
1235 if (Small || storage.Large.NumBuckets == 0)
1239 storage.Large.Buckets,
1242 storage.Large.NumBuckets = 0;
1245 bool allocateBuckets(
unsigned Num) {
1246 if (Num <= InlineBuckets) {
1251 auto *S =
static_cast<char *
>(
1254 storage.Large.Buckets =
reinterpret_cast<BucketT *
>(S);
1255 storage.Large.Used =
reinterpret_cast<UsedT *
>(S +
sizeof(BucketT) * Num);
1256 storage.Large.NumBuckets = Num;
1262 deallocateBuckets();
1264 storage.Large = LargeRep{
nullptr,
nullptr, 0};
1267 static unsigned roundUpNumBuckets(
unsigned MinNumBuckets) {
1268 if (MinNumBuckets <= InlineBuckets)
1269 return InlineBuckets;
1270 return std::max(64u,
1271 static_cast<unsigned>(
NextPowerOf2(MinNumBuckets - 1)));
1274 bool maybeMoveFast(SmallDenseMap &&Other) {
1280 storage.Large =
Other.storage.Large;
1281 Other.storage.Large.NumBuckets = 0;
1288 std::pair<bool, unsigned> planShrinkAndClear()
const {
1289 unsigned NewNumBuckets = 0;
1290 if (!this->
empty()) {
1292 if (NewNumBuckets > InlineBuckets)
1293 NewNumBuckets = std::max(64u, NewNumBuckets);
1295 bool Reuse =
Small ? NewNumBuckets <= InlineBuckets
1296 : NewNumBuckets == storage.Large.NumBuckets;
1299 return {
true, NewNumBuckets};
1303template <
typename KeyT,
typename ValueT,
typename KeyInfoT,
typename Bucket,
1306 friend class DenseMapIterator<
KeyT, ValueT, KeyInfoT, Bucket,
true>;
1307 friend class DenseMapIterator<
KeyT, ValueT, KeyInfoT, Bucket,
false>;
1313 using value_type = std::conditional_t<IsConst, const Bucket, Bucket>;
1320 std::conditional_t<shouldReverseIterate<KeyT>(),
1321 std::reverse_iterator<pointer>,
pointer>;
1323 BucketItTy Ptr = {};
1324 BucketItTy End = {};
1327 pointer Buckets = {};
1330 DenseMapIterator(BucketItTy Pos, BucketItTy
E, pointer BucketsBase,
1331 const UsedT *U,
const DebugEpochBase &Epoch)
1332 : DebugEpochBase::HandleBase(&Epoch), Ptr(Pos), End(
E),
1333 Buckets(BucketsBase),
Used(
U) {
1334 assert(isHandleInSync() &&
"invalid construction!");
1341 unsigned NumBuckets,
bool IsEmpty,
1346 return makeEnd(Buckets, Used, NumBuckets, Epoch);
1348 DenseMapIterator Iter(R.begin(), R.end(), Buckets, Used, Epoch);
1349 Iter.AdvancePastEmptyBuckets();
1354 unsigned NumBuckets,
1357 return DenseMapIterator(R.end(), R.end(), Buckets, Used, Epoch);
1361 const UsedT *Used,
unsigned NumBuckets,
1365 return DenseMapIterator(BucketItTy(
P +
Offset), R.end(), Buckets, Used,
1372 template <
bool IsConstSrc,
1373 typename = std::enable_if_t<!IsConstSrc && IsConst>>
1375 const DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, IsConstSrc> &
I)
1377 Buckets(
I.Buckets), Used(
I.Used) {}
1381 assert(Ptr != End &&
"dereferencing end() iterator");
1387 const DenseMapIterator &
RHS) {
1388 assert(
LHS.isComparableWith(
RHS) &&
"incomparable iterators!");
1389 return LHS.Ptr ==
RHS.Ptr;
1393 const DenseMapIterator &
RHS) {
1399 assert(Ptr != End &&
"incrementing end() iterator");
1401 AdvancePastEmptyBuckets();
1406 DenseMapIterator tmp = *
this;
1412 void AdvancePastEmptyBuckets() {
1419 const size_t N = End - Buckets;
1420 size_t I = Ptr - Buckets;
1439 static auto maybeReverse(iterator_range<pointer>
Range) {
1440 if constexpr (shouldReverseIterate<KeyT>())
1447template <
typename KeyT,
typename ValueT,
typename KeyInfoT>
1448[[nodiscard]]
inline size_t
1450 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)
constexpr bool isRelocatableBucket
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)