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};
296 "InlineBuckets must be a power of 2.");
299 static constexpr unsigned InlineUsedWords =
usedWords(InlineBuckets);
302 unsigned NumEntries : 31;
306 alignas(BucketT)
char Buckets[
sizeof(BucketT) * InlineBuckets];
307 UsedT Used[InlineUsedWords];
321 const BucketT *getInlineBuckets()
const {
326 return reinterpret_cast<const BucketT *
>(storage.Inline.Buckets);
329 BucketT *getInlineBuckets() {
331 return reinterpret_cast<BucketT *
>(storage.Inline.Buckets);
334 const UsedT *getInlineUsed()
const {
336 return storage.Inline.Used;
339 UsedT *getInlineUsed() {
341 return storage.Inline.Used;
344 void setLarge(
void *Storage,
unsigned NumBuckets) {
346 storage.Large = {
static_cast<BucketT *
>(Storage),
347 usedFor(Storage,
sizeof(BucketT), NumBuckets), NumBuckets};
355 assert(Num < (1U << 31) &&
"Cannot support more than 1<<31 entries");
360 return Small ? getInlineBuckets() : storage.Large.Buckets;
364 return const_cast<BucketT *
>(
369 return Small ? getInlineUsed() : storage.Large.Used;
373 return const_cast<UsedT *
>(
378 return Small ? InlineBuckets : storage.Large.NumBuckets;
383 return {getInlineBuckets(), getInlineUsed(), InlineBuckets};
384 return {storage.Large.Buckets, storage.Large.Used,
385 storage.Large.NumBuckets};
389 unsigned TmpNumEntries =
RHS.NumEntries;
390 RHS.NumEntries = NumEntries;
391 NumEntries = TmpNumEntries;
393 if (Small &&
RHS.Small) {
397 UsedT *LU = getInlineUsed(), *RU =
RHS.getInlineUsed();
398 BucketT *LB = getInlineBuckets(), *RB =
RHS.getInlineBuckets();
399 for (
unsigned I = 0;
I != InlineBuckets; ++
I) {
400 bool L =
used(LU,
I);
401 bool R =
used(RU,
I);
404 alignas(BucketT)
char Tmp[
sizeof(BucketT)];
405 BucketT *
T =
reinterpret_cast<BucketT *
>(Tmp);
415 for (
unsigned W = 0; W != InlineUsedWords; ++W)
419 if (!Small && !
RHS.Small) {
430 LargeRep TmpRep = LargeSide.storage.
Large;
431 LargeSide.Small =
true;
433 UsedT *SU = SmallSide.getInlineUsed(), *LU = LargeSide.getInlineUsed();
434 BucketT *SB = SmallSide.getInlineBuckets(),
435 *LB = LargeSide.getInlineBuckets();
436 for (
unsigned I = 0;
I != InlineBuckets; ++
I)
439 for (
unsigned W = 0; W != InlineUsedWords; ++W)
442 SmallSide.Small =
false;
443 SmallSide.storage.
Large = TmpRep;
449 if (Small && NewNumBuckets <= InlineBuckets) {
450 InlineRep Old = storage.Inline;
451 clearUsed(getInlineUsed(), InlineBuckets);
453 Old.Buckets, Old.Used, InlineBuckets,
sizeof(BucketT),
460 setLarge(Storage, NewNumBuckets);
473 if (Num <= InlineBuckets) {
483 if (MinNumBuckets <= InlineBuckets)
484 return InlineBuckets;
485 return std::max(64u, MinNumBuckets);
492 unsigned NewNumBuckets = 0;
495 if (NewNumBuckets > InlineBuckets)
496 NewNumBuckets = std::max(64u, NewNumBuckets);
498 bool Reuse = Small ? NewNumBuckets <= InlineBuckets
499 : NewNumBuckets == storage.Large.NumBuckets;
502 return {
true, NewNumBuckets};
510 NumEntries =
Other.NumEntries;
511 storage.Large =
Other.storage.Large;
518template <
typename KeyT,
typename ValueT,
521 bool IsConst =
false>
523 friend class DenseMapIterator<
KeyT, ValueT, KeyInfoT, Bucket,
true>;
524 friend class DenseMapIterator<
KeyT, ValueT, KeyInfoT, Bucket,
false>;
530 using value_type = std::conditional_t<IsConst, const Bucket, Bucket>;
537 std::conditional_t<shouldReverseIterate<KeyT>(),
538 std::reverse_iterator<pointer>,
pointer>;
545 const UsedT *Used = {};
548 const UsedT *U,
const DebugEpochBase &Epoch)
549 : DebugEpochBase::
HandleBase(&Epoch), Ptr(Pos), End(
E),
550 Buckets(BucketsBase), Used(
U) {
558 unsigned NumBuckets,
bool IsEmpty,
563 return makeEnd(Buckets, Used, NumBuckets, Epoch);
565 DenseMapIterator Iter(R.begin(), R.end(), Buckets, Used, Epoch);
566 Iter.AdvancePastEmptyBuckets();
578 const UsedT *Used,
unsigned NumBuckets,
589 template <
bool IsConstSrc,
590 typename = std::enable_if_t<!IsConstSrc && IsConst>>
592 const DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, IsConstSrc> &
I)
594 Buckets(
I.Buckets), Used(
I.Used) {}
598 assert(Ptr != End &&
"dereferencing end() iterator");
604 const DenseMapIterator &
RHS) {
605 assert(
LHS.isComparableWith(
RHS) &&
"incomparable iterators!");
606 return LHS.Ptr ==
RHS.Ptr;
610 const DenseMapIterator &
RHS) {
616 assert(Ptr != End &&
"incrementing end() iterator");
618 AdvancePastEmptyBuckets();
623 DenseMapIterator tmp = *
this;
629 void AdvancePastEmptyBuckets() {
636 const size_t N =
End - Buckets;
637 size_t I = Ptr - Buckets;
644 UsedT
Bits = Used[
W] & (~UsedT(0) << (
I & 31));
664template <
typename StorageT,
typename KeyT,
typename ValueT,
typename KeyInfoT,
667 template <
typename T>
699 [[nodiscard]]
inline auto keys() {
700 return map_range(*
this, [](
const BucketT &
P) {
return P.getFirst(); });
705 return map_range(*
this, [](
const BucketT &
P) {
return P.getSecond(); });
708 [[nodiscard]]
inline auto keys()
const {
709 return map_range(*
this, [](
const BucketT &
P) {
return P.getFirst(); });
712 [[nodiscard]]
inline auto values()
const {
713 return map_range(*
this, [](
const BucketT &
P) {
return P.getSecond(); });
716 [[nodiscard]]
bool empty()
const {
return getNumEntries() == 0; }
717 [[nodiscard]]
unsigned size()
const {
return getNumEntries(); }
722 auto NumBuckets = getMinBucketToReserveForEntries(NumEntries);
724 if (NumBuckets > getNumBuckets())
730 if (getNumEntries() == 0)
735 if (getNumEntries() * 4 < getNumBuckets() && getNumBuckets() > 64) {
746 auto [Reallocate, NewNumBuckets] = Storage.planShrinkAndClear();
752 Storage.deallocateBuckets();
753 initWithExactBucketCount(Storage, NewNumBuckets);
757 [[nodiscard]]
bool contains(const_arg_type_t<KeyT> Val)
const {
758 return doFind(Val) !=
nullptr;
778 template <
class LookupKeyT>
780 if (BucketT *Bucket = doFind(Val))
781 return makeIterator(Bucket);
784 template <
class LookupKeyT>
786 if (
const BucketT *Bucket = doFind(Val))
787 return makeConstIterator(Bucket);
793 [[nodiscard]] ValueT
lookup(const_arg_type_t<KeyT> Val)
const {
794 if (
const BucketT *Bucket = doFind(Val))
795 return Bucket->getSecond();
802 template <
typename U = std::remove_cv_t<ValueT>>
803 [[nodiscard]] ValueT
lookup_or(const_arg_type_t<KeyT> Val,
805 if (
const BucketT *Bucket = doFind(Val))
806 return Bucket->getSecond();
811 [[nodiscard]] ValueT &
at(const_arg_type_t<KeyT> Val) {
812 auto Iter =
find(std::move(Val));
813 assert(Iter !=
end() &&
"DenseMap::at failed due to a missing key");
818 [[nodiscard]]
const ValueT &
at(const_arg_type_t<KeyT> Val)
const {
819 auto Iter =
find(std::move(Val));
820 assert(Iter !=
end() &&
"DenseMap::at failed due to a missing key");
827 std::pair<iterator, bool>
insert(
const std::pair<KeyT, ValueT> &KV) {
828 return try_emplace_impl(KV.first, KV.second);
834 std::pair<iterator, bool>
insert(std::pair<KeyT, ValueT> &&KV) {
835 return try_emplace_impl(std::move(KV.first), std::move(KV.second));
839 typename B = BucketT,
840 typename = std::enable_if_t<!std::is_same_v<B, std::pair<KeyT, ValueT>>>>
841 std::pair<iterator, bool>
insert(
const BucketT &KV) {
842 return try_emplace_impl(KV.first, KV.second);
846 typename B = BucketT,
847 typename = std::enable_if_t<!std::is_same_v<B, std::pair<KeyT, ValueT>>>>
848 std::pair<iterator, bool>
insert(BucketT &&KV) {
849 return try_emplace_impl(std::move(KV.first), std::move(KV.second));
855 template <
typename... Ts>
857 return try_emplace_impl(std::move(
Key), std::forward<Ts>(Args)...);
863 template <
typename... Ts>
865 return try_emplace_impl(
Key, std::forward<Ts>(Args)...);
873 template <
typename LookupKeyT>
874 std::pair<iterator, bool>
insert_as(std::pair<KeyT, ValueT> &&KV,
875 const LookupKeyT &Val) {
877 if (LookupBucketFor(Val, TheBucket))
878 return {makeIterator(TheBucket),
false};
881 TheBucket = findBucketForInsertion(Val, TheBucket);
882 ::new (&TheBucket->getFirst())
KeyT(std::move(KV.first));
883 ::new (&TheBucket->getSecond()) ValueT(std::move(KV.second));
884 return {makeIterator(TheBucket),
true};
888 template <
typename InputIt>
void insert(InputIt
I, InputIt
E) {
898 template <
typename V>
902 Ret.first->second = std::forward<V>(Val);
906 template <
typename V>
910 Ret.first->second = std::forward<V>(Val);
914 template <
typename... Ts>
918 Ret.first->second = ValueT(std::forward<Ts>(Args)...);
922 template <
typename... Ts>
924 auto Ret =
try_emplace(std::move(
Key), std::forward<Ts>(Args)...);
926 Ret.first->second = ValueT(std::forward<Ts>(Args)...);
931 BucketT *TheBucket = doFind(Val);
935 eraseFromFilledBucket(TheBucket);
947 UsedT *U = getUsed();
948 unsigned NumBuckets = getNumBuckets();
949 BucketT *
B = getBuckets();
950 bool Removed =
false;
951 for (
unsigned I = 0;
I != NumBuckets; ++
I) {
955 B[
I].getSecond().~ValueT();
956 B[
I].getFirst().~KeyT();
958 decrementNumEntries();
970 return lookupOrInsertIntoBucket(
Key).first->second;
974 return lookupOrInsertIntoBucket(std::move(
Key)).first->second;
979 RHS.incrementEpoch();
980 Storage.swap(
RHS.Storage);
988 initWithExactBucketCount(
989 Storage, getMinBucketToReserveForEntries(NumElementsToReserve));
996 template <
typename InputIt>
1002 template <
typename RangeT>
1011 Storage.deallocateBuckets();
1022 Storage.deallocateBuckets();
1023 initWithExactBucketCount(Storage, 0);
1041 static void initEmpty(StorageT &S) {
1044 assert((S.getNumBuckets() & (S.getNumBuckets() - 1)) == 0 &&
1045 "# initial buckets must be a power of two!");
1046 if (S.getNumBuckets())
1050 static void initWithExactBucketCount(StorageT &S,
unsigned NewNumBuckets) {
1051 if (S.allocateBuckets(NewNumBuckets))
1060 if constexpr (std::is_trivially_destructible_v<BucketT>)
1063 if (getNumBuckets() == 0)
1066 BucketT *
B = getBuckets();
1067 const UsedT *
U = getUsed();
1068 const unsigned E = getNumBuckets();
1070 B[
I].getSecond().~ValueT();
1071 B[
I].getFirst().~KeyT();
1077 static unsigned getMinBucketToReserveForEntries(
unsigned NumEntries) {
1079 if (NumEntries == 0)
1088 assert(Dst.getNumEntries() == 0 &&
1089 "moveFrom requires an empty destination");
1090 BucketT *SrcB = Src.getBuckets();
1091 UsedT *SrcU = Src.getUsed();
1092 const unsigned E = Src.getNumBuckets();
1093 UsedT *
U = Dst.getUsed();
1094 BucketT *
B = Dst.getBuckets();
1095 const unsigned Mask = Dst.getNumBuckets() - 1;
1099 unsigned BucketNo = KeyInfoT::getHashValue(SrcB[
I].getFirst()) &
Mask;
1101 BucketNo = (BucketNo + 1) & Mask;
1105 Dst.setNumEntries(Src.getNumEntries());
1106 Src.deallocateBuckets();
1111 Storage.deallocateBuckets();
1113 if (!Storage.allocateBuckets(other.getNumBuckets())) {
1119 assert(getNumBuckets() == other.getNumBuckets());
1121 setNumEntries(other.getNumEntries());
1123 BucketT *Buckets = getBuckets();
1124 const BucketT *OtherBuckets = other.getBuckets();
1125 const unsigned NumBuckets = getNumBuckets();
1126 UsedT *
U = getUsed();
1127 const UsedT *OtherU = other.getUsed();
1128 std::memcpy(U, OtherU,
1131 memcpy(
reinterpret_cast<void *
>(Buckets), OtherBuckets,
1132 NumBuckets *
sizeof(BucketT));
1135 ::new (&Buckets[
I].getFirst()) KeyT(OtherBuckets[
I].getFirst());
1136 ::new (&Buckets[
I].getSecond()) ValueT(OtherBuckets[
I].getSecond());
1145 TheBucket->getSecond().~ValueT();
1146 TheBucket->getFirst().~KeyT();
1147 decrementNumEntries();
1149 BucketT *BucketsPtr = getBuckets();
1150 UsedT *
U = getUsed();
1151 const unsigned Mask = getNumBuckets() - 1;
1152 unsigned I = TheBucket - BucketsPtr;
1156 BucketT &BJ = BucketsPtr[J];
1159 auto Ideal = KeyInfoT::getHashValue(BJ.getFirst());
1162 if (((
I - Ideal) & Mask) < ((J - Ideal) & Mask)) {
1170 template <
typename KeyArgT,
typename... Ts>
1171 std::pair<BucketT *, bool> lookupOrInsertIntoBucket(KeyArgT &&
Key,
1173 BucketT *TheBucket =
nullptr;
1174 if (LookupBucketFor(
Key, TheBucket))
1175 return {TheBucket,
false};
1178 TheBucket = findBucketForInsertion(
Key, TheBucket);
1179 ::new (&TheBucket->getFirst()) KeyT(std::forward<KeyArgT>(
Key));
1180 ::new (&TheBucket->getSecond()) ValueT(std::forward<Ts>(Args)...);
1181 return {TheBucket,
true};
1184 template <
typename KeyArgT,
typename... Ts>
1185 std::pair<iterator, bool> try_emplace_impl(KeyArgT &&
Key, Ts &&...Args) {
1186 auto [Bucket,
Inserted] = lookupOrInsertIntoBucket(
1187 std::forward<KeyArgT>(
Key), std::forward<Ts>(Args)...);
1188 return {makeIterator(Bucket),
Inserted};
1191 iterator makeIterator(BucketT *TheBucket) {
1193 getNumBuckets(), *
this);
1196 const_iterator makeConstIterator(
const BucketT *TheBucket)
const {
1198 getNumBuckets(), *
this);
1201 unsigned getNumEntries()
const {
return Storage.getNumEntries(); }
1203 void setNumEntries(
unsigned Num) { Storage.setNumEntries(Num); }
1205 void incrementNumEntries() { setNumEntries(getNumEntries() + 1); }
1207 void decrementNumEntries() { setNumEntries(getNumEntries() - 1); }
1209 const BucketT *getBuckets()
const {
return Storage.getBuckets(); }
1211 BucketT *getBuckets() {
return Storage.getBuckets(); }
1213 Rep getRep()
const {
return Storage.getRep(); }
1215 const UsedT *getUsed()
const {
return Storage.getUsed(); }
1217 UsedT *getUsed() {
return Storage.getUsed(); }
1219 unsigned getNumBuckets()
const {
return Storage.getNumBuckets(); }
1223 "bucket count must be zero or a power of two");
1225 Storage.grow(MinNumBuckets,
1228 unsigned NumBuckets = StorageT::roundUpNumBuckets(MinNumBuckets);
1230 initWithExactBucketCount(Tmp, NumBuckets);
1231 moveFrom(Tmp, Storage);
1232 if (Storage.maybeMoveFast(std::move(Tmp)))
1234 initWithExactBucketCount(Storage, NumBuckets);
1235 moveFrom(Storage, Tmp);
1239 template <
typename LookupKeyT>
1240 BucketT *findBucketForInsertion(
const LookupKeyT &
Lookup,
1241 BucketT *TheBucket) {
1248 unsigned NewNumEntries = getNumEntries() + 1;
1249 unsigned NumBuckets = getNumBuckets();
1251 grow(NumBuckets * 2);
1252 LookupBucketFor(
Lookup, TheBucket);
1261 incrementNumEntries();
1265 template <
typename LookupKeyT>
1266 const BucketT *doFind(
const LookupKeyT &Val)
const {
1269 auto [BucketsPtr,
U, NumBuckets] = getRep();
1271 const unsigned Mask = NumBuckets - 1;
1272 unsigned BucketNo = KeyInfoT::getHashValue(Val) &
Mask;
1277 const BucketT *Bucket = BucketsPtr + BucketNo;
1278 if (
LLVM_LIKELY(KeyInfoT::isEqual(Val, Bucket->getFirst())))
1282 BucketNo = (BucketNo + 1) & Mask;
1286 template <
typename LookupKeyT> BucketT *doFind(
const LookupKeyT &Val) {
1287 return const_cast<BucketT *
>(
1294 template <
typename LookupKeyT>
1295 bool LookupBucketFor(
const LookupKeyT &Val, BucketT *&FoundBucket) {
1296 auto [CBuckets,
U, NumBuckets] = getRep();
1297 if (NumBuckets == 0) {
1298 FoundBucket =
nullptr;
1303 BucketT *BucketsPtr =
const_cast<BucketT *
>(CBuckets);
1305 const unsigned Mask = NumBuckets - 1;
1306 unsigned BucketNo = KeyInfoT::getHashValue(Val) &
Mask;
1308 BucketT *ThisBucket = BucketsPtr + BucketNo;
1312 FoundBucket = ThisBucket;
1317 if (
LLVM_LIKELY(KeyInfoT::isEqual(Val, ThisBucket->getFirst()))) {
1318 FoundBucket = ThisBucket;
1323 BucketNo = (BucketNo + 1) & Mask;
1334template <
typename Storage1T,
typename Storage2T,
typename KeyT,
1335 typename ValueT,
typename KeyInfoT,
typename BucketT>
1339 if (
LHS.size() !=
RHS.size())
1342 for (
auto &KV :
LHS) {
1343 auto I =
RHS.find(KV.first);
1344 if (
I ==
RHS.end() ||
I->second != KV.second)
1354template <
typename Storage1T,
typename Storage2T,
typename KeyT,
1355 typename ValueT,
typename KeyInfoT,
typename BucketT>
1362template <
typename KeyT,
typename ValueT,
1363 typename KeyInfoT = DenseMapInfo<KeyT>,
1366 KeyT, ValueT, KeyInfoT, BucketT> {
1368 ValueT, KeyInfoT, BucketT>;
1374template <
typename KeyT,
typename ValueT,
unsigned InlineBuckets = 4,
1379 densemap::detail::SmallDenseMapStorage<BucketT, InlineBuckets>, KeyT,
1380 ValueT, KeyInfoT, BucketT> {
1383 ValueT, KeyInfoT, BucketT>;
1389template <
typename KeyT,
typename ValueT,
typename KeyInfoT>
1390[[nodiscard]]
inline size_t
1392 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 a 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.
@ End
Run the machine verifier once, at the end of the pipeline.
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)