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>;
100 using KeyT = std::remove_reference_t<
decltype(Dst->getFirst())>;
101 using ValueT = std::remove_reference_t<
decltype(Dst->getSecond())>;
102 ::new (&Dst->getFirst())
KeyT(std::move(Src->getFirst()));
103 ::new (&Dst->getSecond()) ValueT(std::move(Src->getSecond()));
104 Src->getSecond().~ValueT();
105 Src->getFirst().~KeyT();
113 "bucket count must be zero or a power of two");
114 return (
N + 31) / 32;
118 return (U[
I >> 5] >> (
I & 31)) & 1;
122 U[
I >> 5] &= ~(
UsedT(1) << (
I & 31));
131template <
typename Fn>
135 for (
unsigned W = 0; W != NW; ++W) {
148 return std::max(
alignof(BucketT),
alignof(
UsedT));
151 return BucketSize *
static_cast<size_t>(Num) +
usedWords(Num) *
sizeof(
UsedT);
157 assert(BucketSize *
static_cast<size_t>(Num) %
alignof(
UsedT) == 0 &&
158 "used array would be misaligned");
159 return reinterpret_cast<UsedT *
>(
static_cast<char *
>(Buckets) +
160 BucketSize *
static_cast<size_t>(Num));
172template <
typename KeyT,
typename KeyInfoT,
typename =
void>
177 std::enable_if_t<std::is_same_v<
186 return [](
const void *
Key) ->
unsigned {
187 return KeyInfoT::getHashValue(*
static_cast<const KeyT *
>(
Key));
194 unsigned DstNumBuckets,
const void *Src,
195 const UsedT *SrcUsed,
unsigned SrcNumBuckets,
201 unsigned OldNumBuckets,
unsigned NewNumBuckets,
202 size_t BucketSize,
size_t Align,
215 BucketT *Buckets =
nullptr;
216 UsedT *Used =
nullptr;
217 unsigned NumEntries = 0;
218 unsigned NumBuckets = 0;
237 Buckets =
static_cast<BucketT *
>(Storage);
238 Used =
usedFor(Storage,
sizeof(BucketT), Num);
273 return std::max(64u, MinNumBuckets);
280 unsigned NewNumBuckets = 0;
282 NewNumBuckets = std::max(64u, 1u << (
Log2_32_Ceil(NumEntries) + 1));
283 if (NewNumBuckets == NumBuckets)
285 return {
true, NewNumBuckets};
294template <
typename BucketT,
unsigned InlineBuckets = 4>
297 "InlineBuckets must be a power of 2.");
300 static constexpr unsigned InlineUsedWords =
usedWords(InlineBuckets);
303 unsigned NumEntries : 31;
307 alignas(BucketT)
char Buckets[
sizeof(BucketT) * InlineBuckets];
308 UsedT Used[InlineUsedWords];
322 const BucketT *getInlineBuckets()
const {
327 return reinterpret_cast<const BucketT *
>(storage.Inline.Buckets);
330 BucketT *getInlineBuckets() {
332 return reinterpret_cast<BucketT *
>(storage.Inline.Buckets);
335 const UsedT *getInlineUsed()
const {
337 return storage.Inline.Used;
340 UsedT *getInlineUsed() {
342 return storage.Inline.Used;
345 void setLarge(
void *Storage,
unsigned NumBuckets) {
347 storage.Large = {
static_cast<BucketT *
>(Storage),
348 usedFor(Storage,
sizeof(BucketT), NumBuckets), NumBuckets};
356 assert(Num < (1U << 31) &&
"Cannot support more than 1<<31 entries");
361 return Small ? getInlineBuckets() : storage.Large.Buckets;
365 return const_cast<BucketT *
>(
370 return Small ? getInlineUsed() : storage.Large.Used;
374 return const_cast<UsedT *
>(
379 return Small ? InlineBuckets : storage.Large.NumBuckets;
384 return {getInlineBuckets(), getInlineUsed(), InlineBuckets};
385 return {storage.Large.Buckets, storage.Large.Used,
386 storage.Large.NumBuckets};
390 unsigned TmpNumEntries =
RHS.NumEntries;
391 RHS.NumEntries = NumEntries;
392 NumEntries = TmpNumEntries;
394 if (Small &&
RHS.Small) {
398 UsedT *LU = getInlineUsed(), *RU =
RHS.getInlineUsed();
399 BucketT *LB = getInlineBuckets(), *RB =
RHS.getInlineBuckets();
400 for (
unsigned I = 0;
I != InlineBuckets; ++
I) {
401 bool L =
used(LU,
I);
402 bool R =
used(RU,
I);
405 alignas(BucketT)
char Tmp[
sizeof(BucketT)];
406 BucketT *
T =
reinterpret_cast<BucketT *
>(Tmp);
416 for (
unsigned W = 0; W != InlineUsedWords; ++W)
420 if (!Small && !
RHS.Small) {
431 LargeRep TmpRep = LargeSide.storage.
Large;
432 LargeSide.Small =
true;
434 UsedT *SU = SmallSide.getInlineUsed(), *LU = LargeSide.getInlineUsed();
435 BucketT *SB = SmallSide.getInlineBuckets(),
436 *LB = LargeSide.getInlineBuckets();
437 for (
unsigned I = 0;
I != InlineBuckets; ++
I)
440 for (
unsigned W = 0; W != InlineUsedWords; ++W)
443 SmallSide.Small =
false;
444 SmallSide.storage.
Large = TmpRep;
450 if (Small && NewNumBuckets <= InlineBuckets) {
451 InlineRep Old = storage.Inline;
452 clearUsed(getInlineUsed(), InlineBuckets);
454 Old.Buckets, Old.Used, InlineBuckets,
sizeof(BucketT),
461 setLarge(Storage, NewNumBuckets);
474 if (Num <= InlineBuckets) {
484 if (MinNumBuckets <= InlineBuckets)
485 return InlineBuckets;
486 return std::max(64u, MinNumBuckets);
493 unsigned NewNumBuckets = 0;
496 if (NewNumBuckets > InlineBuckets)
497 NewNumBuckets = std::max(64u, NewNumBuckets);
499 bool Reuse = Small ? NewNumBuckets <= InlineBuckets
500 : NewNumBuckets == storage.Large.NumBuckets;
503 return {
true, NewNumBuckets};
511 NumEntries =
Other.NumEntries;
512 storage.Large =
Other.storage.Large;
519template <
typename KeyT,
typename ValueT,
522 bool IsConst =
false>
524 friend class DenseMapIterator<
KeyT, ValueT, KeyInfoT, Bucket,
true>;
525 friend class DenseMapIterator<
KeyT, ValueT, KeyInfoT, Bucket,
false>;
531 using value_type = std::conditional_t<IsConst, const Bucket, Bucket>;
538 std::conditional_t<shouldReverseIterate<KeyT>(),
539 std::reverse_iterator<pointer>,
pointer>;
546 const UsedT *Used = {};
549 const UsedT *U,
const DebugEpochBase &Epoch)
550 : DebugEpochBase::
HandleBase(&Epoch), Ptr(Pos), End(
E),
551 Buckets(BucketsBase), Used(
U) {
559 unsigned NumBuckets,
bool IsEmpty,
564 return makeEnd(Buckets, Used, NumBuckets, Epoch);
566 DenseMapIterator Iter(R.begin(), R.end(), Buckets, Used, Epoch);
567 Iter.AdvancePastEmptyBuckets();
579 const UsedT *Used,
unsigned NumBuckets,
590 template <
bool IsConstSrc,
591 typename = std::enable_if_t<!IsConstSrc && IsConst>>
593 const DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, IsConstSrc> &
I)
595 Buckets(
I.Buckets), Used(
I.Used) {}
599 assert(Ptr != End &&
"dereferencing end() iterator");
605 const DenseMapIterator &
RHS) {
606 assert(
LHS.isComparableWith(
RHS) &&
"incomparable iterators!");
607 return LHS.Ptr ==
RHS.Ptr;
611 const DenseMapIterator &
RHS) {
617 assert(Ptr != End &&
"incrementing end() iterator");
619 AdvancePastEmptyBuckets();
624 DenseMapIterator tmp = *
this;
630 void AdvancePastEmptyBuckets() {
637 const size_t N = End - Buckets;
638 size_t I = Ptr - Buckets;
645 UsedT
Bits = Used[
W] & (~UsedT(0) << (
I & 31));
665template <
typename StorageT,
typename KeyT,
typename ValueT,
typename KeyInfoT,
668 template <
typename T>
700 [[nodiscard]]
inline auto keys() {
701 return map_range(*
this, [](
const BucketT &
P) {
return P.getFirst(); });
706 return map_range(*
this, [](
const BucketT &
P) {
return P.getSecond(); });
709 [[nodiscard]]
inline auto keys()
const {
710 return map_range(*
this, [](
const BucketT &
P) {
return P.getFirst(); });
713 [[nodiscard]]
inline auto values()
const {
714 return map_range(*
this, [](
const BucketT &
P) {
return P.getSecond(); });
717 [[nodiscard]]
bool empty()
const {
return getNumEntries() == 0; }
718 [[nodiscard]]
unsigned size()
const {
return getNumEntries(); }
723 auto NumBuckets = getMinBucketToReserveForEntries(NumEntries);
725 if (NumBuckets > getNumBuckets())
731 if (getNumEntries() == 0)
736 if (getNumEntries() * 4 < getNumBuckets() && getNumBuckets() > 64) {
747 auto [Reallocate, NewNumBuckets] = Storage.planShrinkAndClear();
753 Storage.deallocateBuckets();
754 initWithExactBucketCount(Storage, NewNumBuckets);
758 [[nodiscard]]
bool contains(const_arg_type_t<KeyT> Val)
const {
759 return doFind(Val) !=
nullptr;
779 template <
class LookupKeyT>
781 if (BucketT *Bucket = doFind(Val))
782 return makeIterator(Bucket);
785 template <
class LookupKeyT>
787 if (
const BucketT *Bucket = doFind(Val))
788 return makeConstIterator(Bucket);
794 [[nodiscard]] ValueT
lookup(const_arg_type_t<KeyT> Val)
const {
795 if (
const BucketT *Bucket = doFind(Val))
796 return Bucket->getSecond();
803 template <
typename U = std::remove_cv_t<ValueT>>
804 [[nodiscard]] ValueT
lookup_or(const_arg_type_t<KeyT> Val,
806 if (
const BucketT *Bucket = doFind(Val))
807 return Bucket->getSecond();
812 [[nodiscard]] ValueT &
at(const_arg_type_t<KeyT> Val) {
813 auto Iter = this->
find(std::move(Val));
814 assert(Iter != this->
end() &&
"DenseMap::at failed due to a missing key");
819 [[nodiscard]]
const ValueT &
at(const_arg_type_t<KeyT> Val)
const {
820 auto Iter = this->
find(std::move(Val));
821 assert(Iter != this->
end() &&
"DenseMap::at failed due to a missing key");
828 std::pair<iterator, bool>
insert(
const std::pair<KeyT, ValueT> &KV) {
829 return try_emplace_impl(KV.first, KV.second);
835 std::pair<iterator, bool>
insert(std::pair<KeyT, ValueT> &&KV) {
836 return try_emplace_impl(std::move(KV.first), std::move(KV.second));
840 typename B = BucketT,
841 typename = std::enable_if_t<!std::is_same_v<B, std::pair<KeyT, ValueT>>>>
842 std::pair<iterator, bool>
insert(
const BucketT &KV) {
843 return try_emplace_impl(KV.first, KV.second);
847 typename B = BucketT,
848 typename = std::enable_if_t<!std::is_same_v<B, std::pair<KeyT, ValueT>>>>
849 std::pair<iterator, bool>
insert(BucketT &&KV) {
850 return try_emplace_impl(std::move(KV.first), std::move(KV.second));
856 template <
typename... Ts>
858 return try_emplace_impl(std::move(
Key), std::forward<Ts>(Args)...);
864 template <
typename... Ts>
866 return try_emplace_impl(
Key, std::forward<Ts>(Args)...);
874 template <
typename LookupKeyT>
875 std::pair<iterator, bool>
insert_as(std::pair<KeyT, ValueT> &&KV,
876 const LookupKeyT &Val) {
878 if (LookupBucketFor(Val, TheBucket))
879 return {makeIterator(TheBucket),
false};
882 TheBucket = findBucketForInsertion(Val, TheBucket);
883 ::new (&TheBucket->getFirst())
KeyT(std::move(KV.first));
884 ::new (&TheBucket->getSecond()) ValueT(std::move(KV.second));
885 return {makeIterator(TheBucket),
true};
889 template <
typename InputIt>
void insert(InputIt
I, InputIt
E) {
899 template <
typename V>
903 Ret.first->second = std::forward<V>(Val);
907 template <
typename V>
911 Ret.first->second = std::forward<V>(Val);
915 template <
typename... Ts>
919 Ret.first->second = ValueT(std::forward<Ts>(Args)...);
923 template <
typename... Ts>
925 auto Ret =
try_emplace(std::move(
Key), std::forward<Ts>(Args)...);
927 Ret.first->second = ValueT(std::forward<Ts>(Args)...);
932 BucketT *TheBucket = doFind(Val);
936 eraseFromFilledBucket(TheBucket);
948 UsedT *U = getUsed();
949 unsigned NumBuckets = getNumBuckets();
950 BucketT *
B = getBuckets();
951 bool Removed =
false;
952 for (
unsigned I = 0;
I != NumBuckets; ++
I) {
956 B[
I].getSecond().~ValueT();
957 B[
I].getFirst().~KeyT();
959 decrementNumEntries();
965 this->grow(NumBuckets);
971 return lookupOrInsertIntoBucket(
Key).first->second;
975 return lookupOrInsertIntoBucket(std::move(
Key)).first->second;
981 Storage.swap(
RHS.Storage);
989 initWithExactBucketCount(
990 Storage, getMinBucketToReserveForEntries(NumElementsToReserve));
994 this->copyFrom(other);
999 template <
typename InputIt>
1005 template <
typename RangeT>
1014 Storage.deallocateBuckets();
1019 this->copyFrom(other);
1025 Storage.deallocateBuckets();
1026 initWithExactBucketCount(Storage, 0);
1044 static void initEmpty(StorageT &S) {
1047 assert((S.getNumBuckets() & (S.getNumBuckets() - 1)) == 0 &&
1048 "# initial buckets must be a power of two!");
1049 if (S.getNumBuckets())
1053 static void initWithExactBucketCount(StorageT &S,
unsigned NewNumBuckets) {
1054 if (S.allocateBuckets(NewNumBuckets))
1063 if constexpr (std::is_trivially_destructible_v<BucketT>)
1066 if (getNumBuckets() == 0)
1069 BucketT *
B = getBuckets();
1070 const UsedT *
U = getUsed();
1071 const unsigned E = getNumBuckets();
1073 B[
I].getSecond().~ValueT();
1074 B[
I].getFirst().~KeyT();
1080 unsigned getMinBucketToReserveForEntries(
unsigned NumEntries) {
1082 if (NumEntries == 0)
1095 assert(Dst.getNumEntries() == 0 &&
1096 "moveFrom requires an empty destination");
1097 BucketT *SrcB = Src.getBuckets();
1098 UsedT *SrcU = Src.getUsed();
1099 const unsigned E = Src.getNumBuckets();
1100 UsedT *
U = Dst.getUsed();
1101 BucketT *
B = Dst.getBuckets();
1102 const unsigned Mask = Dst.getNumBuckets() - 1;
1106 unsigned BucketNo = KeyInfoT::getHashValue(SrcB[
I].getFirst()) &
Mask;
1108 BucketNo = (BucketNo + 1) & Mask;
1112 Dst.setNumEntries(Src.getNumEntries());
1113 Src.deallocateBuckets();
1118 Storage.deallocateBuckets();
1120 if (!Storage.allocateBuckets(other.getNumBuckets())) {
1126 assert(getNumBuckets() == other.getNumBuckets());
1128 setNumEntries(other.getNumEntries());
1130 BucketT *Buckets = getBuckets();
1131 const BucketT *OtherBuckets = other.getBuckets();
1132 const unsigned NumBuckets = getNumBuckets();
1133 UsedT *
U = getUsed();
1134 const UsedT *OtherU = other.getUsed();
1135 std::memcpy(U, OtherU,
1138 memcpy(
reinterpret_cast<void *
>(Buckets), OtherBuckets,
1139 NumBuckets *
sizeof(BucketT));
1142 ::new (&Buckets[
I].getFirst()) KeyT(OtherBuckets[
I].getFirst());
1143 ::new (&Buckets[
I].getSecond()) ValueT(OtherBuckets[
I].getSecond());
1152 TheBucket->getSecond().~ValueT();
1153 TheBucket->getFirst().~KeyT();
1154 decrementNumEntries();
1156 BucketT *BucketsPtr = getBuckets();
1157 UsedT *
U = getUsed();
1158 const unsigned Mask = getNumBuckets() - 1;
1159 unsigned I = TheBucket - BucketsPtr;
1163 BucketT &BJ = BucketsPtr[J];
1166 auto Ideal = KeyInfoT::getHashValue(BJ.getFirst());
1169 if (((
I - Ideal) & Mask) < ((J - Ideal) & Mask)) {
1177 template <
typename KeyArgT,
typename... Ts>
1178 std::pair<BucketT *, bool> lookupOrInsertIntoBucket(KeyArgT &&
Key,
1180 BucketT *TheBucket =
nullptr;
1181 if (LookupBucketFor(
Key, TheBucket))
1182 return {TheBucket,
false};
1185 TheBucket = findBucketForInsertion(
Key, TheBucket);
1186 ::new (&TheBucket->getFirst()) KeyT(std::forward<KeyArgT>(
Key));
1187 ::new (&TheBucket->getSecond()) ValueT(std::forward<Ts>(Args)...);
1188 return {TheBucket,
true};
1191 template <
typename KeyArgT,
typename... Ts>
1192 std::pair<iterator, bool> try_emplace_impl(KeyArgT &&
Key, Ts &&...Args) {
1193 auto [Bucket,
Inserted] = lookupOrInsertIntoBucket(
1194 std::forward<KeyArgT>(
Key), std::forward<Ts>(Args)...);
1195 return {makeIterator(Bucket),
Inserted};
1198 iterator makeIterator(BucketT *TheBucket) {
1200 getNumBuckets(), *
this);
1203 const_iterator makeConstIterator(
const BucketT *TheBucket)
const {
1205 getNumBuckets(), *
this);
1208 unsigned getNumEntries()
const {
return Storage.getNumEntries(); }
1210 void setNumEntries(
unsigned Num) { Storage.setNumEntries(Num); }
1212 void incrementNumEntries() { setNumEntries(getNumEntries() + 1); }
1214 void decrementNumEntries() { setNumEntries(getNumEntries() - 1); }
1216 const BucketT *getBuckets()
const {
return Storage.getBuckets(); }
1218 BucketT *getBuckets() {
return Storage.getBuckets(); }
1220 Rep getRep()
const {
return Storage.getRep(); }
1222 const UsedT *getUsed()
const {
return Storage.getUsed(); }
1224 UsedT *getUsed() {
return Storage.getUsed(); }
1226 unsigned getNumBuckets()
const {
return Storage.getNumBuckets(); }
1230 "bucket count must be zero or a power of two");
1232 Storage.grow(MinNumBuckets, hasher());
1234 unsigned NumBuckets = StorageT::roundUpNumBuckets(MinNumBuckets);
1236 initWithExactBucketCount(Tmp, NumBuckets);
1237 moveFrom(Tmp, Storage);
1238 if (Storage.maybeMoveFast(std::move(Tmp)))
1240 initWithExactBucketCount(Storage, NumBuckets);
1241 moveFrom(Storage, Tmp);
1245 template <
typename LookupKeyT>
1246 BucketT *findBucketForInsertion(
const LookupKeyT &
Lookup,
1247 BucketT *TheBucket) {
1254 unsigned NewNumEntries = getNumEntries() + 1;
1255 unsigned NumBuckets = getNumBuckets();
1257 this->grow(NumBuckets * 2);
1258 LookupBucketFor(
Lookup, TheBucket);
1267 incrementNumEntries();
1271 template <
typename LookupKeyT>
1272 const BucketT *doFind(
const LookupKeyT &Val)
const {
1275 auto [BucketsPtr,
U, NumBuckets] = getRep();
1277 const unsigned Mask = NumBuckets - 1;
1278 unsigned BucketNo = KeyInfoT::getHashValue(Val) &
Mask;
1283 const BucketT *Bucket = BucketsPtr + BucketNo;
1284 if (
LLVM_LIKELY(KeyInfoT::isEqual(Val, Bucket->getFirst())))
1288 BucketNo = (BucketNo + 1) & Mask;
1292 template <
typename LookupKeyT> BucketT *doFind(
const LookupKeyT &Val) {
1293 return const_cast<BucketT *
>(
1300 template <
typename LookupKeyT>
1301 bool LookupBucketFor(
const LookupKeyT &Val, BucketT *&FoundBucket) {
1302 auto [CBuckets,
U, NumBuckets] = getRep();
1303 if (NumBuckets == 0) {
1304 FoundBucket =
nullptr;
1309 BucketT *BucketsPtr =
const_cast<BucketT *
>(CBuckets);
1311 const unsigned Mask = NumBuckets - 1;
1312 unsigned BucketNo = KeyInfoT::getHashValue(Val) &
Mask;
1314 BucketT *ThisBucket = BucketsPtr + BucketNo;
1318 FoundBucket = ThisBucket;
1323 if (
LLVM_LIKELY(KeyInfoT::isEqual(Val, ThisBucket->getFirst()))) {
1324 FoundBucket = ThisBucket;
1329 BucketNo = (BucketNo + 1) & Mask;
1340template <
typename Storage1T,
typename Storage2T,
typename KeyT,
1341 typename ValueT,
typename KeyInfoT,
typename BucketT>
1345 if (
LHS.size() !=
RHS.size())
1348 for (
auto &KV :
LHS) {
1349 auto I =
RHS.find(KV.first);
1350 if (
I ==
RHS.end() ||
I->second != KV.second)
1360template <
typename Storage1T,
typename Storage2T,
typename KeyT,
1361 typename ValueT,
typename KeyInfoT,
typename BucketT>
1368template <
typename KeyT,
typename ValueT,
1369 typename KeyInfoT = DenseMapInfo<KeyT>,
1372 KeyT, ValueT, KeyInfoT, BucketT> {
1374 ValueT, KeyInfoT, BucketT>;
1380template <
typename KeyT,
typename ValueT,
unsigned InlineBuckets = 4,
1385 densemap::detail::SmallDenseMapStorage<BucketT, InlineBuckets>, KeyT,
1386 ValueT, KeyInfoT, BucketT> {
1389 ValueT, KeyInfoT, BucketT>;
1395template <
typename KeyT,
typename ValueT,
typename KeyInfoT>
1396[[nodiscard]]
inline size_t
1398 return X.getMemorySize();
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 int Lookup(ArrayRef< TableEntry > Table, unsigned Opcode)
bool isHandleInSync() const
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > emplace_or_assign(const KeyT &Key, Ts &&...Args)
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT, true > const_iterator
void insert_range(Range &&R)
Inserts range of 'std::pair<KeyT, ValueT>' values into the map.
void insert(InputIt I, InputIt E)
Range insertion of pairs.
std::pair< iterator, bool > try_emplace(const KeyT &Key, Ts &&...Args)
std::pair< iterator, bool > insert_or_assign(const KeyT &Key, V &&Val)
ValueT & at(const_arg_type_t< KeyT > Val)
Return the entry for the specified key, or abort if no such entry exists.
void reserve(size_type NumEntries)
Grow the densemap so that it can contain at least NumEntries items before resizing again.
ValueT lookup_or(const_arg_type_t< KeyT > Val, U &&Default) const
std::pair< iterator, bool > insert(BucketT &&KV)
const_iterator find(const_arg_type_t< KeyT > Val) const
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,...
std::pair< iterator, bool > insert(const BucketT &KV)
ValueT & operator[](const KeyT &Key)
DenseMapBase(const InputIt &I, const InputIt &E)
std::pair< iterator, bool > emplace_or_assign(KeyT &&Key, Ts &&...Args)
const_iterator begin() const
DenseMapBase(unsigned NumElementsToReserve)
Create a DenseMap with an optional NumElementsToReserve to guarantee that this number of elements can...
std::pair< iterator, bool > insert(std::pair< KeyT, ValueT > &&KV)
bool erase(const KeyT &Val)
DenseMapBase(llvm::from_range_t, const RangeT &Range)
const_iterator find_as(const LookupKeyT &Val) const
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT > iterator
DenseMapBase(const DenseMapBase &other)
std::pair< iterator, bool > insert_or_assign(KeyT &&Key, V &&Val)
DenseMapBase & operator=(const DenseMapBase &other)
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_as(const LookupKeyT &Val)
Alternate version of find() which allows a different, and possibly less expensive,...
const_iterator end() const
void swap(DenseMapBase &RHS)
bool remove_if(Predicate Pred)
Remove entries that match the given predicate.
DenseMapBase(std::initializer_list< value_type > Vals)
const ValueT & at(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or abort if no such entry exists.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
size_t getMemorySize() const
Return the approximate size (in bytes) of the actual map.
DenseMapBase(DenseMapBase &&other)
DenseMapBase & operator=(DenseMapBase &&other)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
ValueT & operator[](KeyT &&Key)
std::conditional_t< IsConst, const Bucket, Bucket > value_type
friend bool operator!=(const DenseMapIterator &LHS, const DenseMapIterator &RHS)
DenseMapIterator & operator++()
pointer operator->() const
reference operator*() const
DenseMapIterator()=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)
LLVM Value Representation.
StorageRep< BucketT > getRep() const
static unsigned roundUpNumBuckets(unsigned MinNumBuckets)
bool maybeMoveFast(DenseMapStorage &&Other)
void setStorage(void *Storage, unsigned Num)
unsigned getNumEntries() const
BucketT * getBuckets() const
unsigned getNumBuckets() const
void setNumEntries(unsigned Num)
void swap(DenseMapStorage &RHS)
std::pair< bool, unsigned > planShrinkAndClear() const
bool allocateBuckets(unsigned Num)
void grow(unsigned MinNumBuckets, BucketHasher Hasher)
StorageRep< BucketT > getRep() const
unsigned getNumEntries() const
std::pair< bool, unsigned > planShrinkAndClear() const
void grow(unsigned MinNumBuckets, BucketHasher Hasher)
void swap(SmallDenseMapStorage &RHS)
bool allocateBuckets(unsigned Num)
void setNumEntries(unsigned Num)
const BucketT * getBuckets() const
bool maybeMoveFast(SmallDenseMapStorage &&Other)
unsigned getNumBuckets() const
static unsigned roundUpNumBuckets(unsigned MinNumBuckets)
const UsedT * getUsed() const
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)
UsedT * usedFor(void *Buckets, size_t BucketSize, unsigned Num)
constexpr bool hashesPointerValue
void clearUsed(UsedT *U, unsigned Num)
constexpr size_t usedWords(size_t N)
LLVM_ATTRIBUTE_ALWAYS_INLINE void forEachUsed(const UsedT *U, unsigned N, Fn Func)
size_t allocBytes(size_t BucketSize, unsigned Num)
unsigned(*)(const void *Key) BucketHasher
Hashes the key, at offset 0 in a bucket.
constexpr size_t allocAlign()
constexpr BucketHasher hasherFor()
void relocateBucket(BucketT *Dst, BucketT *Src)
LLVM_ABI void * growRelocatable(void *OldBuckets, const UsedT *OldUsed, unsigned OldNumBuckets, unsigned NewNumBuckets, size_t BucketSize, size_t Align, BucketHasher Hasher, bool FreeOld)
Allocate a table of NewNumBuckets buckets and rehash the OldNumBuckets buckets at OldBuckets into it,...
bool used(const UsedT *U, size_t I)
void unsetUsed(UsedT *U, size_t I)
LLVM_ABI void rehashRelocatable(void *Dst, UsedT *DstUsed, unsigned DstNumBuckets, const void *Src, const UsedT *SrcUsed, unsigned SrcNumBuckets, size_t BucketSize, BucketHasher Hasher)
Rehash the live buckets of Src into the empty Dst, which must have room for all of them.
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.
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 isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
constexpr bool shouldReverseIterate()
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
iterator_range(Container &&) -> iterator_range< llvm::detail::IterOfRange< Container > >
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
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.
This struct is a compact representation of a valid (non-zero power of two) alignment.
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)