LLVM 24.0.0git
DenseMap.h
Go to the documentation of this file.
1//===- llvm/ADT/DenseMap.h - Dense probed hash table ------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file defines the DenseMap class.
11///
12/// The hash table is linear-probing open addressing with tombstone-free
13/// deletion (Knuth TAOCP 6.4 Algorithm R), power-of-two capacity, and a 0.75
14/// maximum load factor. No sentinel key. Occupancy is stored in a packed
15/// 1-bit-per-bucket "used" array.
16///
17/// `SmallDenseMap` adds an inline small buffer optimization.
18///
19//===----------------------------------------------------------------------===//
20
21#ifndef LLVM_ADT_DENSEMAP_H
22#define LLVM_ADT_DENSEMAP_H
23
24#include "llvm/ADT/ADL.h"
27#include "llvm/ADT/STLExtras.h"
34#include <algorithm>
35#include <cassert>
36#include <cstddef>
37#include <cstring>
38#include <initializer_list>
39#include <iterator>
40#include <new>
41#include <type_traits>
42#include <utility>
43
44namespace llvm {
45
46namespace detail {
47// A bucket holds a key and a value. Don't use std::pair, which has a
48// non-trivial copy assignment, which costs is_trivially_copyable.
49template <typename KeyT, typename ValueT> struct DenseMapPair {
51 using second_type = ValueT;
52
54 ValueT second;
55
57 DenseMapPair(const KeyT &Key, const ValueT &Value)
58 : first(Key), second(Value) {}
60 : first(std::move(Key)), second(std::move(Value)) {}
61 DenseMapPair(const std::pair<KeyT, ValueT> &P)
62 : first(P.first), second(P.second) {}
63 DenseMapPair(std::pair<KeyT, ValueT> &&P)
65 template <typename U1, typename U2>
68 template <typename U1, typename U2>
71
72 operator std::pair<KeyT, ValueT>() const { return {first, second}; }
73 operator std::pair<const KeyT, ValueT>() const { return {first, second}; }
74
75 friend bool operator==(const DenseMapPair &LHS, const DenseMapPair &RHS) {
76 return LHS.first == RHS.first && LHS.second == RHS.second;
77 }
78 friend bool operator!=(const DenseMapPair &LHS, const DenseMapPair &RHS) {
79 return !(LHS == RHS);
80 }
81
82 KeyT &getFirst() { return first; }
83 const KeyT &getFirst() const { return first; }
84 ValueT &getSecond() { return second; }
85 const ValueT &getSecond() const { return second; }
86};
87
88} // end namespace detail
89
91// Relocating copy-constructs and runs no destructor, so it does not need
92// trivial assignment, which a std::pair value type lacks.
93template <typename BucketT>
94inline constexpr bool isRelocatableBucket =
95 std::is_trivially_copy_constructible_v<BucketT> &&
96 std::is_trivially_destructible_v<BucketT>;
97
98// Move-construct *Dst from *Src, then destroy *Src. Dst is raw storage.
99template <typename BucketT> void relocateBucket(BucketT *Dst, BucketT *Src) {
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();
106}
107
109
110// Number of used words backing N buckets where N is zero or a power of two.
111constexpr size_t usedWords(size_t N) {
112 assert((N == 0 || isPowerOf2_64(N)) &&
113 "bucket count must be zero or a power of two");
114 return (N + 31) / 32;
115}
116
117inline bool used(const UsedT *U, size_t I) {
118 return (U[I >> 5] >> (I & 31)) & 1;
119}
120inline void setUsed(UsedT *U, size_t I) { U[I >> 5] |= UsedT(1) << (I & 31); }
121inline void unsetUsed(UsedT *U, size_t I) {
122 U[I >> 5] &= ~(UsedT(1) << (I & 31));
123}
124inline void clearUsed(UsedT *U, unsigned Num) {
125 std::memset(U, 0, usedWords(Num) * sizeof(UsedT));
126}
127
128// Invoke Func(I) for each occupied bucket index I in [0, N). Set always_inline;
129// otherwise, for a heavy caller such as moveFrom's rehash, the inliner can
130// leave it out of line and the per-element call dwarfs the work.
131template <typename Fn>
133 Fn Func) {
134 const unsigned NW = usedWords(N);
135 for (unsigned W = 0; W != NW; ++W) {
136 UsedT Bits = U[W];
137 while (Bits) {
138 Func((W << 5) + llvm::countr_zero(Bits));
139 Bits &= Bits - 1;
140 }
141 }
142}
143
144// Buckets and the used array share one allocation: the bucket array first, then
145// the used words. NumBuckets is a power of two >= 4, so the bucket region size
146// is a multiple of sizeof(UsedT) and the trailing used words are aligned.
147template <typename BucketT> constexpr size_t allocAlign() {
148 return std::max(alignof(BucketT), alignof(UsedT));
149}
150inline size_t allocBytes(size_t BucketSize, unsigned Num) {
151 return BucketSize * static_cast<size_t>(Num) + usedWords(Num) * sizeof(UsedT);
152}
153template <typename BucketT> size_t allocBytes(unsigned Num) {
154 return allocBytes(sizeof(BucketT), Num);
155}
156inline UsedT *usedFor(void *Buckets, size_t BucketSize, unsigned Num) {
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));
161}
162
163/// Hashes the key, at offset 0 in a bucket. Null asks the out-of-line rehash
164/// loop in DenseMap.cpp to inline the pointer hash.
165using BucketHasher = unsigned (*)(const void *Key);
166
167// True when the map hashes a pointer key by its value: the primary
168// DenseMapInfo<T *> declares PointerValueHash naming itself, which a
169// specialization or derived info for one pointer type does not. Only the
170// primary is asked, since GCC without DR1170 errors on a lookup that reaches a
171// private base, as clang::WeakInfo's info has.
172template <typename KeyT, typename KeyInfoT, typename = void>
173inline constexpr bool hashesPointerValue = false;
174template <typename T>
175inline constexpr bool hashesPointerValue<
177 std::enable_if_t<std::is_same_v<
179 true;
180
181// Kept out of DenseMapBase so that map types sharing a key share one thunk.
182template <typename KeyT, typename KeyInfoT> constexpr BucketHasher hasherFor() {
184 return nullptr;
185 else
186 return [](const void *Key) -> unsigned {
187 return KeyInfoT::getHashValue(*static_cast<const KeyT *>(Key));
188 };
189}
190
191/// Rehash the live buckets of \p Src into the empty \p Dst, which must have
192/// room for all of them.
193LLVM_ABI void rehashRelocatable(void *Dst, UsedT *DstUsed,
194 unsigned DstNumBuckets, const void *Src,
195 const UsedT *SrcUsed, unsigned SrcNumBuckets,
196 size_t BucketSize, BucketHasher Hasher);
197
198/// Allocate a table of \p NewNumBuckets buckets and rehash the \p OldNumBuckets
199/// buckets at \p OldBuckets into it, freeing them if \p FreeOld.
200LLVM_ABI void *growRelocatable(void *OldBuckets, const UsedT *OldUsed,
201 unsigned OldNumBuckets, unsigned NewNumBuckets,
202 size_t BucketSize, size_t Align,
203 BucketHasher Hasher, bool FreeOld);
204
205// A snapshot of the three fields the hot lookup paths need. Fetching them
206// together lets SmallDenseMap test its Small discriminator once rather than
207// once per accessor; for plain DenseMap it is three member loads either way.
208template <typename BucketT> struct StorageRep {
209 const BucketT *Buckets;
210 const UsedT *Used;
211 unsigned NumBuckets;
212};
213
214template <typename BucketT> class DenseMapStorage {
215 BucketT *Buckets = nullptr;
216 UsedT *Used = nullptr;
217 unsigned NumEntries = 0;
218 unsigned NumBuckets = 0;
219
220public:
221 unsigned getNumEntries() const { return NumEntries; }
222 void setNumEntries(unsigned Num) { NumEntries = Num; }
223
224 BucketT *getBuckets() const { return Buckets; }
225 UsedT *getUsed() const { return Used; }
226 unsigned getNumBuckets() const { return NumBuckets; }
227 StorageRep<BucketT> getRep() const { return {Buckets, Used, NumBuckets}; }
228
230 std::swap(Buckets, RHS.Buckets);
231 std::swap(Used, RHS.Used);
232 std::swap(NumEntries, RHS.NumEntries);
233 std::swap(NumBuckets, RHS.NumBuckets);
234 }
235
236 void setStorage(void *Storage, unsigned Num) {
237 Buckets = static_cast<BucketT *>(Storage);
238 Used = usedFor(Storage, sizeof(BucketT), Num);
239 NumBuckets = Num;
240 }
241
242 void grow(unsigned MinNumBuckets, BucketHasher Hasher) {
243 unsigned NewNumBuckets = roundUpNumBuckets(MinNumBuckets);
244 setStorage(growRelocatable(Buckets, Used, NumBuckets, NewNumBuckets,
245 sizeof(BucketT), allocAlign<BucketT>(), Hasher,
246 /*FreeOld=*/true),
247 NewNumBuckets);
248 }
249
251 if (NumBuckets == 0)
252 return;
253 deallocate_buffer(Buckets, allocBytes<BucketT>(NumBuckets),
255 Buckets = nullptr;
256 Used = nullptr;
257 NumBuckets = 0;
258 }
259
260 bool allocateBuckets(unsigned Num) {
261 if (Num == 0) {
262 Buckets = nullptr;
263 Used = nullptr;
264 NumBuckets = 0;
265 return false;
266 }
268 Num);
269 return true;
270 }
271
272 static unsigned roundUpNumBuckets(unsigned MinNumBuckets) {
273 return std::max(64u, MinNumBuckets);
274 }
275
276 // Plan how to shrink the bucket table. Return:
277 // - {false, 0} to reuse the existing bucket table
278 // - {true, N} to reallocate a bucket table with N entries
279 std::pair<bool, unsigned> planShrinkAndClear() const {
280 unsigned NewNumBuckets = 0;
281 if (NumEntries)
282 NewNumBuckets = std::max(64u, 1u << (Log2_32_Ceil(NumEntries) + 1));
283 if (NewNumBuckets == NumBuckets)
284 return {false, 0}; // Reuse.
285 return {true, NewNumBuckets}; // Reallocate.
286 }
287
289 *this = Other;
290 return true;
291 }
292};
293
294template <typename BucketT, unsigned InlineBuckets = 4>
296 static_assert(isPowerOf2_64(InlineBuckets),
297 "InlineBuckets must be a power of 2.");
298
299 // Number of used words backing the inline buckets (>= 1).
300 static constexpr unsigned InlineUsedWords = usedWords(InlineBuckets);
301
302 unsigned Small : 1;
303 unsigned NumEntries : 31;
304
305 // Inline storage: the bucket array followed by the parallel used words.
306 struct InlineRep {
307 alignas(BucketT) char Buckets[sizeof(BucketT) * InlineBuckets];
308 UsedT Used[InlineUsedWords];
309 };
310 struct LargeRep {
311 BucketT *Buckets;
312 UsedT *Used;
313 unsigned NumBuckets;
314 };
315
316 // Discriminated by the Small bit.
317 union {
318 InlineRep Inline;
319 LargeRep Large;
320 } storage;
321
322 const BucketT *getInlineBuckets() const {
323 assert(Small);
324 // Note that this cast does not violate aliasing rules as we assert that
325 // the memory's dynamic type is the small, inline bucket buffer, and the
326 // 'storage' is a POD containing a char buffer.
327 return reinterpret_cast<const BucketT *>(storage.Inline.Buckets);
328 }
329
330 BucketT *getInlineBuckets() {
331 assert(Small);
332 return reinterpret_cast<BucketT *>(storage.Inline.Buckets);
333 }
334
335 const UsedT *getInlineUsed() const {
336 assert(Small);
337 return storage.Inline.Used;
338 }
339
340 UsedT *getInlineUsed() {
341 assert(Small);
342 return storage.Inline.Used;
343 }
344
345 void setLarge(void *Storage, unsigned NumBuckets) {
346 Small = false;
347 storage.Large = {static_cast<BucketT *>(Storage),
348 usedFor(Storage, sizeof(BucketT), NumBuckets), NumBuckets};
349 }
350
351public:
352 unsigned getNumEntries() const { return NumEntries; }
353
354 void setNumEntries(unsigned Num) {
355 // NumEntries is hardcoded to be 31 bits wide.
356 assert(Num < (1U << 31) && "Cannot support more than 1<<31 entries");
357 NumEntries = Num;
358 }
359
360 const BucketT *getBuckets() const {
361 return Small ? getInlineBuckets() : storage.Large.Buckets;
362 }
363
364 BucketT *getBuckets() {
365 return const_cast<BucketT *>(
366 const_cast<const SmallDenseMapStorage *>(this)->getBuckets());
367 }
368
369 const UsedT *getUsed() const {
370 return Small ? getInlineUsed() : storage.Large.Used;
371 }
372
374 return const_cast<UsedT *>(
375 const_cast<const SmallDenseMapStorage *>(this)->getUsed());
376 }
377
378 unsigned getNumBuckets() const {
379 return Small ? InlineBuckets : storage.Large.NumBuckets;
380 }
381
383 if (Small)
384 return {getInlineBuckets(), getInlineUsed(), InlineBuckets};
385 return {storage.Large.Buckets, storage.Large.Used,
386 storage.Large.NumBuckets};
387 }
388
390 unsigned TmpNumEntries = RHS.NumEntries;
391 RHS.NumEntries = NumEntries;
392 NumEntries = TmpNumEntries;
393
394 if (Small && RHS.Small) {
395 // Both inline: swap the live bucket contents slot by slot, then the used
396 // words. Buckets are raw storage, so a value may only move in one
397 // direction when exactly one side is occupied.
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);
403 if (L && R) {
404 // Both occupied: exchange through a temporary.
405 alignas(BucketT) char Tmp[sizeof(BucketT)];
406 BucketT *T = reinterpret_cast<BucketT *>(Tmp);
407 relocateBucket(T, &LB[I]);
408 relocateBucket(&LB[I], &RB[I]);
409 relocateBucket(&RB[I], T);
410 } else if (L) {
411 relocateBucket(&RB[I], &LB[I]);
412 } else if (R) {
413 relocateBucket(&LB[I], &RB[I]);
414 }
415 }
416 for (unsigned W = 0; W != InlineUsedWords; ++W)
417 std::swap(LU[W], RU[W]);
418 return;
419 }
420 if (!Small && !RHS.Small) {
421 std::swap(storage.Large, RHS.storage.Large);
422 return;
423 }
424
425 SmallDenseMapStorage &SmallSide = Small ? *this : RHS;
426 SmallDenseMapStorage &LargeSide = Small ? RHS : *this;
427
428 // Stash the large rep, then move the small side's inline contents into the
429 // large side (which becomes inline), and finally install the rep on the
430 // small side (which becomes large).
431 LargeRep TmpRep = LargeSide.storage.Large;
432 LargeSide.Small = true;
433 {
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)
438 if (used(SU, I))
439 relocateBucket(&LB[I], &SB[I]);
440 for (unsigned W = 0; W != InlineUsedWords; ++W)
441 LU[W] = SU[W];
442 }
443 SmallSide.Small = false;
444 SmallSide.storage.Large = TmpRep;
445 }
446
447 void grow(unsigned MinNumBuckets, BucketHasher Hasher) {
448 unsigned NewNumBuckets = roundUpNumBuckets(MinNumBuckets);
449 // remove_if asks for the count it already has: rehash in place.
450 if (Small && NewNumBuckets <= InlineBuckets) {
451 InlineRep Old = storage.Inline;
452 clearUsed(getInlineUsed(), InlineBuckets);
453 rehashRelocatable(getInlineBuckets(), getInlineUsed(), InlineBuckets,
454 Old.Buckets, Old.Used, InlineBuckets, sizeof(BucketT),
455 Hasher);
456 return;
457 }
458 void *Storage = growRelocatable(
459 getBuckets(), getUsed(), getNumBuckets(), NewNumBuckets,
460 sizeof(BucketT), allocAlign<BucketT>(), Hasher, /*FreeOld=*/!Small);
461 setLarge(Storage, NewNumBuckets);
462 }
463
465 if (Small)
466 return;
467
468 deallocate_buffer(storage.Large.Buckets,
469 allocBytes<BucketT>(storage.Large.NumBuckets),
471 }
472
473 bool allocateBuckets(unsigned Num) {
474 if (Num <= InlineBuckets) {
475 Small = true;
476 return true;
477 }
479 Num);
480 return true;
481 }
482
483 static unsigned roundUpNumBuckets(unsigned MinNumBuckets) {
484 if (MinNumBuckets <= InlineBuckets)
485 return InlineBuckets;
486 return std::max(64u, MinNumBuckets);
487 }
488
489 // Plan how to shrink the bucket table. Return:
490 // - {false, 0} to reuse the existing bucket table
491 // - {true, N} to reallocate a bucket table with N entries
492 std::pair<bool, unsigned> planShrinkAndClear() const {
493 unsigned NewNumBuckets = 0;
494 if (NumEntries) {
495 NewNumBuckets = 1u << (Log2_32_Ceil(NumEntries) + 1);
496 if (NewNumBuckets > InlineBuckets)
497 NewNumBuckets = std::max(64u, NewNumBuckets);
498 }
499 bool Reuse = Small ? NewNumBuckets <= InlineBuckets
500 : NewNumBuckets == storage.Large.NumBuckets;
501 if (Reuse)
502 return {false, 0}; // Reuse.
503 return {true, NewNumBuckets}; // Reallocate.
504 }
505
507 if (Other.Small)
508 return false;
509
510 Small = false;
511 NumEntries = Other.NumEntries;
512 storage.Large = Other.storage.Large;
513 return true;
514 }
515};
516
517} // namespace densemap::detail
518
519template <typename KeyT, typename ValueT,
520 typename KeyInfoT = DenseMapInfo<KeyT>,
522 bool IsConst = false>
523class DenseMapIterator : DebugEpochBase::HandleBase {
524 friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true>;
525 friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, false>;
526
527 using UsedT = llvm::densemap::detail::UsedT;
528
529public:
531 using value_type = std::conditional_t<IsConst, const Bucket, Bucket>;
534 using iterator_category = std::forward_iterator_tag;
535
536private:
537 using BucketItTy =
538 std::conditional_t<shouldReverseIterate<KeyT>(),
539 std::reverse_iterator<pointer>, pointer>;
540
541 BucketItTy Ptr = {};
542 BucketItTy End = {};
543 // The non-reversed bucket base and the parallel used array. They map a
544 // bucket back to its index so AdvancePastEmptyBuckets can consult the bits.
545 pointer Buckets = {};
546 const UsedT *Used = {};
547
548 DenseMapIterator(BucketItTy Pos, BucketItTy E, pointer BucketsBase,
549 const UsedT *U, const DebugEpochBase &Epoch)
550 : DebugEpochBase::HandleBase(&Epoch), Ptr(Pos), End(E),
551 Buckets(BucketsBase), Used(U) {
552 assert(isHandleInSync() && "invalid construction!");
553 }
554
555public:
556 DenseMapIterator() = default;
557
558 static DenseMapIterator makeBegin(pointer Buckets, const UsedT *Used,
559 unsigned NumBuckets, bool IsEmpty,
560 const DebugEpochBase &Epoch) {
561 // When the map is empty, avoid the overhead of advancing/retreating past
562 // empty buckets.
563 if (IsEmpty)
564 return makeEnd(Buckets, Used, NumBuckets, Epoch);
565 auto R = maybeReverse(llvm::make_range(Buckets, Buckets + NumBuckets));
566 DenseMapIterator Iter(R.begin(), R.end(), Buckets, Used, Epoch);
567 Iter.AdvancePastEmptyBuckets();
568 return Iter;
569 }
570
571 static DenseMapIterator makeEnd(pointer Buckets, const UsedT *Used,
572 unsigned NumBuckets,
573 const DebugEpochBase &Epoch) {
574 auto R = maybeReverse(llvm::make_range(Buckets, Buckets + NumBuckets));
575 return DenseMapIterator(R.end(), R.end(), Buckets, Used, Epoch);
576 }
577
578 static DenseMapIterator makeIterator(pointer P, pointer Buckets,
579 const UsedT *Used, unsigned NumBuckets,
580 const DebugEpochBase &Epoch) {
581 auto R = maybeReverse(llvm::make_range(Buckets, Buckets + NumBuckets));
582 constexpr int Offset = shouldReverseIterate<KeyT>() ? 1 : 0;
583 return DenseMapIterator(BucketItTy(P + Offset), R.end(), Buckets, Used,
584 Epoch);
585 }
586
587 // Converting ctor from non-const iterators to const iterators. SFINAE'd out
588 // for const iterator destinations so it doesn't end up as a user defined copy
589 // constructor.
590 template <bool IsConstSrc,
591 typename = std::enable_if_t<!IsConstSrc && IsConst>>
593 const DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, IsConstSrc> &I)
594 : DebugEpochBase::HandleBase(I), Ptr(I.Ptr), End(I.End),
595 Buckets(I.Buckets), Used(I.Used) {}
596
597 [[nodiscard]] reference operator*() const {
598 assert(isHandleInSync() && "invalid iterator access!");
599 assert(Ptr != End && "dereferencing end() iterator");
600 return *Ptr;
601 }
602 [[nodiscard]] pointer operator->() const { return &operator*(); }
603
604 [[nodiscard]] friend bool operator==(const DenseMapIterator &LHS,
605 const DenseMapIterator &RHS) {
606 assert(LHS.isComparableWith(RHS) && "incomparable iterators!");
607 return LHS.Ptr == RHS.Ptr;
608 }
609
610 [[nodiscard]] friend bool operator!=(const DenseMapIterator &LHS,
611 const DenseMapIterator &RHS) {
612 return !(LHS == RHS);
613 }
614
615 inline DenseMapIterator &operator++() { // Preincrement
616 assert(isHandleInSync() && "invalid iterator access!");
617 assert(Ptr != End && "incrementing end() iterator");
618 ++Ptr;
619 AdvancePastEmptyBuckets();
620 return *this;
621 }
622 DenseMapIterator operator++(int) { // Postincrement
623 assert(isHandleInSync() && "invalid iterator access!");
624 DenseMapIterator tmp = *this;
625 ++*this;
626 return tmp;
627 }
628
629private:
630 void AdvancePastEmptyBuckets() {
631 if constexpr (shouldReverseIterate<KeyT>()) {
632 while (Ptr != End && !llvm::densemap::detail::used(Used, &*Ptr - Buckets))
633 ++Ptr;
634 } else {
635 // Forward iteration skips empty buckets a used-word (32 buckets) at a
636 // time: scan from the current index for the next set occupancy bit.
637 const size_t N = End - Buckets;
638 size_t I = Ptr - Buckets;
639 if (I >= N) {
640 Ptr = End;
641 return;
642 }
643 const size_t NW = llvm::densemap::detail::usedWords(N);
644 size_t W = I >> 5;
645 UsedT Bits = Used[W] & (~UsedT(0) << (I & 31));
646 while (Bits == 0) {
647 if (++W == NW) {
648 Ptr = End;
649 return;
650 }
651 Bits = Used[W];
652 }
653 Ptr = Buckets + ((W << 5) + llvm::countr_zero(Bits));
654 }
655 }
656
657 static auto maybeReverse(iterator_range<pointer> Range) {
658 if constexpr (shouldReverseIterate<KeyT>())
659 return reverse(Range);
660 else
661 return Range;
662 }
663};
664
665template <typename StorageT, typename KeyT, typename ValueT, typename KeyInfoT,
666 typename BucketT>
668 template <typename T>
669 using const_arg_type_t = typename const_pointer_or_const_ref<T>::type;
670
671 using UsedT = llvm::densemap::detail::UsedT;
672
673public:
675 using key_type = KeyT;
676 using mapped_type = ValueT;
677 using value_type = BucketT;
678
682
683 [[nodiscard]] inline iterator begin() {
684 return iterator::makeBegin(getBuckets(), getUsed(), getNumBuckets(),
685 empty(), *this);
686 }
687 [[nodiscard]] inline iterator end() {
688 return iterator::makeEnd(getBuckets(), getUsed(), getNumBuckets(), *this);
689 }
690 [[nodiscard]] inline const_iterator begin() const {
691 return const_iterator::makeBegin(getBuckets(), getUsed(), getNumBuckets(),
692 empty(), *this);
693 }
694 [[nodiscard]] inline const_iterator end() const {
695 return const_iterator::makeEnd(getBuckets(), getUsed(), getNumBuckets(),
696 *this);
697 }
698
699 // Return an iterator to iterate over keys in the map.
700 [[nodiscard]] inline auto keys() {
701 return map_range(*this, [](const BucketT &P) { return P.getFirst(); });
702 }
703
704 // Return an iterator to iterate over values in the map.
705 [[nodiscard]] inline auto values() {
706 return map_range(*this, [](const BucketT &P) { return P.getSecond(); });
707 }
708
709 [[nodiscard]] inline auto keys() const {
710 return map_range(*this, [](const BucketT &P) { return P.getFirst(); });
711 }
712
713 [[nodiscard]] inline auto values() const {
714 return map_range(*this, [](const BucketT &P) { return P.getSecond(); });
715 }
716
717 [[nodiscard]] bool empty() const { return getNumEntries() == 0; }
718 [[nodiscard]] unsigned size() const { return getNumEntries(); }
719
720 /// Grow the densemap so that it can contain at least \p NumEntries items
721 /// before resizing again.
722 void reserve(size_type NumEntries) {
723 auto NumBuckets = getMinBucketToReserveForEntries(NumEntries);
725 if (NumBuckets > getNumBuckets())
726 grow(NumBuckets);
727 }
728
729 void clear() {
731 if (getNumEntries() == 0)
732 return;
733
734 // If the capacity of the array is huge, and the # elements used is small,
735 // shrink the array.
736 if (getNumEntries() * 4 < getNumBuckets() && getNumBuckets() > 64) {
738 return;
739 }
740
741 destroyAll();
742 llvm::densemap::detail::clearUsed(getUsed(), getNumBuckets());
743 setNumEntries(0);
744 }
745
747 auto [Reallocate, NewNumBuckets] = Storage.planShrinkAndClear();
748 destroyAll();
749 if (!Reallocate) {
750 initEmpty(Storage);
751 return;
752 }
753 Storage.deallocateBuckets();
754 initWithExactBucketCount(Storage, NewNumBuckets);
755 }
756
757 /// Return true if the specified key is in the map, false otherwise.
758 [[nodiscard]] bool contains(const_arg_type_t<KeyT> Val) const {
759 return doFind(Val) != nullptr;
760 }
761
762 /// Return 1 if the specified key is in the map, 0 otherwise.
763 [[nodiscard]] size_type count(const_arg_type_t<KeyT> Val) const {
764 return contains(Val) ? 1 : 0;
765 }
766
767 [[nodiscard]] iterator find(const_arg_type_t<KeyT> Val) {
768 return find_as(Val);
769 }
770 [[nodiscard]] const_iterator find(const_arg_type_t<KeyT> Val) const {
771 return find_as(Val);
772 }
773
774 /// Alternate version of find() which allows a different, and possibly
775 /// less expensive, key type.
776 /// The DenseMapInfo is responsible for supplying methods
777 /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key
778 /// type used.
779 template <class LookupKeyT>
780 [[nodiscard]] iterator find_as(const LookupKeyT &Val) {
781 if (BucketT *Bucket = doFind(Val))
782 return makeIterator(Bucket);
783 return end();
784 }
785 template <class LookupKeyT>
786 [[nodiscard]] const_iterator find_as(const LookupKeyT &Val) const {
787 if (const BucketT *Bucket = doFind(Val))
788 return makeConstIterator(Bucket);
789 return end();
790 }
791
792 /// Return the entry for the specified key, or a default constructed value if
793 /// no such entry exists.
794 [[nodiscard]] ValueT lookup(const_arg_type_t<KeyT> Val) const {
795 if (const BucketT *Bucket = doFind(Val))
796 return Bucket->getSecond();
797 return ValueT();
798 }
799
800 // Return the entry with the specified key, or \p Default. This variant is
801 // useful, because `lookup` cannot be used with non-default-constructible
802 // values.
803 template <typename U = std::remove_cv_t<ValueT>>
804 [[nodiscard]] ValueT lookup_or(const_arg_type_t<KeyT> Val,
805 U &&Default) const {
806 if (const BucketT *Bucket = doFind(Val))
807 return Bucket->getSecond();
808 return Default;
809 }
810
811 /// Return the entry for the specified key, or abort if no such entry exists.
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");
815 return Iter->second;
816 }
817
818 /// Return the entry for the specified key, or abort if no such entry exists.
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");
822 return Iter->second;
823 }
824
825 // Inserts key,value pair into the map if the key isn't already in the map.
826 // If the key is already in the map, it returns false and doesn't update the
827 // value.
828 std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) {
829 return try_emplace_impl(KV.first, KV.second);
830 }
831
832 // Inserts key,value pair into the map if the key isn't already in the map.
833 // If the key is already in the map, it returns false and doesn't update the
834 // value.
835 std::pair<iterator, bool> insert(std::pair<KeyT, ValueT> &&KV) {
836 return try_emplace_impl(std::move(KV.first), std::move(KV.second));
837 }
838
839 template <
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);
844 }
845
846 template <
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));
851 }
852
853 // Inserts key,value pair into the map if the key isn't already in the map.
854 // The value is constructed in-place if the key is not in the map, otherwise
855 // it is not moved.
856 template <typename... Ts>
857 std::pair<iterator, bool> try_emplace(KeyT &&Key, Ts &&...Args) {
858 return try_emplace_impl(std::move(Key), std::forward<Ts>(Args)...);
859 }
860
861 // Inserts key,value pair into the map if the key isn't already in the map.
862 // The value is constructed in-place if the key is not in the map, otherwise
863 // it is not moved.
864 template <typename... Ts>
865 std::pair<iterator, bool> try_emplace(const KeyT &Key, Ts &&...Args) {
866 return try_emplace_impl(Key, std::forward<Ts>(Args)...);
867 }
868
869 /// Alternate version of insert() which allows a different, and possibly
870 /// less expensive, key type.
871 /// The DenseMapInfo is responsible for supplying methods
872 /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key
873 /// type used.
874 template <typename LookupKeyT>
875 std::pair<iterator, bool> insert_as(std::pair<KeyT, ValueT> &&KV,
876 const LookupKeyT &Val) {
877 BucketT *TheBucket;
878 if (LookupBucketFor(Val, TheBucket))
879 return {makeIterator(TheBucket), false}; // Already in map.
880
881 // Otherwise, insert the new element.
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};
886 }
887
888 /// Range insertion of pairs.
889 template <typename InputIt> void insert(InputIt I, InputIt E) {
890 for (; I != E; ++I)
891 insert(*I);
892 }
893
894 /// Inserts range of 'std::pair<KeyT, ValueT>' values into the map.
895 template <typename Range> void insert_range(Range &&R) {
896 insert(adl_begin(R), adl_end(R));
897 }
898
899 template <typename V>
900 std::pair<iterator, bool> insert_or_assign(const KeyT &Key, V &&Val) {
901 auto Ret = try_emplace(Key, std::forward<V>(Val));
902 if (!Ret.second)
903 Ret.first->second = std::forward<V>(Val);
904 return Ret;
905 }
906
907 template <typename V>
908 std::pair<iterator, bool> insert_or_assign(KeyT &&Key, V &&Val) {
909 auto Ret = try_emplace(std::move(Key), std::forward<V>(Val));
910 if (!Ret.second)
911 Ret.first->second = std::forward<V>(Val);
912 return Ret;
913 }
914
915 template <typename... Ts>
916 std::pair<iterator, bool> emplace_or_assign(const KeyT &Key, Ts &&...Args) {
917 auto Ret = try_emplace(Key, std::forward<Ts>(Args)...);
918 if (!Ret.second)
919 Ret.first->second = ValueT(std::forward<Ts>(Args)...);
920 return Ret;
921 }
922
923 template <typename... Ts>
924 std::pair<iterator, bool> emplace_or_assign(KeyT &&Key, Ts &&...Args) {
925 auto Ret = try_emplace(std::move(Key), std::forward<Ts>(Args)...);
926 if (!Ret.second)
927 Ret.first->second = ValueT(std::forward<Ts>(Args)...);
928 return Ret;
929 }
930
931 bool erase(const KeyT &Val) {
932 BucketT *TheBucket = doFind(Val);
933 if (!TheBucket)
934 return false; // not in map.
935
936 eraseFromFilledBucket(TheBucket);
937 return true;
938 }
939 void erase(iterator I) { eraseFromFilledBucket(&*I); }
940
941 /// Remove entries that match the given predicate. \p Pred is invoked
942 /// with a reference to each live bucket and must not access the map being
943 /// modified. This is the safe replacement for erase-while-iterating.
944 ///
945 /// Returns whether anything was removed. If so, all iterators and references
946 /// into the map are invalidated.
947 template <typename Predicate> bool remove_if(Predicate Pred) {
948 UsedT *U = getUsed();
949 unsigned NumBuckets = getNumBuckets();
950 BucketT *B = getBuckets();
951 bool Removed = false;
952 for (unsigned I = 0; I != NumBuckets; ++I) {
954 continue;
955 if (Pred(B[I])) {
956 B[I].getSecond().~ValueT();
957 B[I].getFirst().~KeyT();
959 decrementNumEntries();
960 Removed = true;
961 }
962 }
963 if (Removed) {
965 this->grow(NumBuckets);
966 }
967 return Removed;
968 }
969
970 ValueT &operator[](const KeyT &Key) {
971 return lookupOrInsertIntoBucket(Key).first->second;
972 }
973
974 ValueT &operator[](KeyT &&Key) {
975 return lookupOrInsertIntoBucket(std::move(Key)).first->second;
976 }
977
979 this->incrementEpoch();
980 RHS.incrementEpoch();
981 Storage.swap(RHS.Storage);
982 }
983
985
986 /// Create a DenseMap with an optional \p NumElementsToReserve to guarantee
987 /// that this number of elements can be inserted in the map without grow().
988 explicit DenseMapBase(unsigned NumElementsToReserve) {
989 initWithExactBucketCount(
990 Storage, getMinBucketToReserveForEntries(NumElementsToReserve));
991 }
992
994 this->copyFrom(other);
995 }
996
997 DenseMapBase(DenseMapBase &&other) : DenseMapBase() { this->swap(other); }
998
999 template <typename InputIt>
1000 DenseMapBase(const InputIt &I, const InputIt &E)
1001 : DenseMapBase(std::distance(I, E)) {
1002 this->insert(I, E);
1003 }
1004
1005 template <typename RangeT>
1008
1009 DenseMapBase(std::initializer_list<value_type> Vals)
1010 : DenseMapBase(Vals.begin(), Vals.end()) {}
1011
1013 this->destroyAll();
1014 Storage.deallocateBuckets();
1015 }
1016
1018 if (&other != this)
1019 this->copyFrom(other);
1020 return *this;
1021 }
1022
1024 this->destroyAll();
1025 Storage.deallocateBuckets();
1026 initWithExactBucketCount(Storage, 0);
1027 this->swap(other);
1028 return *this;
1029 }
1030
1031 /// Return the approximate size (in bytes) of the actual map.
1032 /// This is just the raw memory used by DenseMap.
1033 /// If entries are pointers to objects, the size of the referenced objects
1034 /// are not included.
1035 [[nodiscard]] size_t getMemorySize() const {
1036 return llvm::densemap::detail::allocBytes<BucketT>(getNumBuckets());
1037 }
1038
1039private:
1040 StorageT Storage;
1041
1043
1044 static void initEmpty(StorageT &S) {
1045 S.setNumEntries(0);
1046
1047 assert((S.getNumBuckets() & (S.getNumBuckets() - 1)) == 0 &&
1048 "# initial buckets must be a power of two!");
1049 if (S.getNumBuckets())
1050 llvm::densemap::detail::clearUsed(S.getUsed(), S.getNumBuckets());
1051 }
1052
1053 static void initWithExactBucketCount(StorageT &S, unsigned NewNumBuckets) {
1054 if (S.allocateBuckets(NewNumBuckets))
1055 initEmpty(S);
1056 else
1057 S.setNumEntries(0);
1058 }
1059
1060 void destroyAll() {
1061 // No need to iterate through the buckets if the bucket is trivially
1062 // destructible.
1063 if constexpr (std::is_trivially_destructible_v<BucketT>)
1064 return;
1065
1066 if (getNumBuckets() == 0) // Nothing to do.
1067 return;
1068
1069 BucketT *B = getBuckets();
1070 const UsedT *U = getUsed();
1071 const unsigned E = getNumBuckets();
1072 llvm::densemap::detail::forEachUsed(U, E, [&](unsigned I) {
1073 B[I].getSecond().~ValueT();
1074 B[I].getFirst().~KeyT();
1075 });
1076 }
1077
1078 /// Returns the number of buckets to allocate to ensure that the DenseMap can
1079 /// accommodate \p NumEntries without need to grow().
1080 unsigned getMinBucketToReserveForEntries(unsigned NumEntries) {
1081 // Ensure that "NumEntries * 4 < NumBuckets * 3"
1082 if (NumEntries == 0)
1083 return 0;
1084 // +1 is required because of the strict inequality.
1085 // For example, if NumEntries is 48, we need to return 128.
1086 return NextPowerOf2(NumEntries * 4 / 3 + 1);
1087 }
1088
1089 static constexpr llvm::densemap::detail::BucketHasher hasher() {
1091 }
1092
1093 // Move key/value from Src to Dst.
1094 static LLVM_ATTRIBUTE_NOINLINE void moveFrom(StorageT &Dst, StorageT &Src) {
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;
1103 llvm::densemap::detail::forEachUsed(SrcU, E, [&](unsigned I) {
1104 // Find the first empty slot on this key's probe chain; there is no equal
1105 // key in the destination, so nothing to compare against.
1106 unsigned BucketNo = KeyInfoT::getHashValue(SrcB[I].getFirst()) & Mask;
1107 while (llvm::densemap::detail::used(U, BucketNo))
1108 BucketNo = (BucketNo + 1) & Mask;
1109 llvm::densemap::detail::relocateBucket(B + BucketNo, &SrcB[I]);
1111 });
1112 Dst.setNumEntries(Src.getNumEntries());
1113 Src.deallocateBuckets();
1114 }
1115
1116 LLVM_ATTRIBUTE_NOINLINE void copyFrom(const DenseMapBase &other) {
1117 this->destroyAll();
1118 Storage.deallocateBuckets();
1119 setNumEntries(0);
1120 if (!Storage.allocateBuckets(other.getNumBuckets())) {
1121 // The bucket list is empty. No work to do.
1122 return;
1123 }
1124
1125 assert(&other != this);
1126 assert(getNumBuckets() == other.getNumBuckets());
1127
1128 setNumEntries(other.getNumEntries());
1129
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,
1136 llvm::densemap::detail::usedWords(NumBuckets) * sizeof(UsedT));
1138 memcpy(reinterpret_cast<void *>(Buckets), OtherBuckets,
1139 NumBuckets * sizeof(BucketT));
1140 } else {
1141 llvm::densemap::detail::forEachUsed(U, NumBuckets, [&](unsigned I) {
1142 ::new (&Buckets[I].getFirst()) KeyT(OtherBuckets[I].getFirst());
1143 ::new (&Buckets[I].getSecond()) ValueT(OtherBuckets[I].getSecond());
1144 });
1145 }
1146 }
1147
1148 /// Erase the entry at \p TheBucket and close the resulting hole via Knuth
1149 /// TAOCP 6.4 Algorithm R.
1150 LLVM_ATTRIBUTE_NOINLINE void eraseFromFilledBucket(BucketT *TheBucket) {
1152 TheBucket->getSecond().~ValueT();
1153 TheBucket->getFirst().~KeyT();
1154 decrementNumEntries();
1155
1156 BucketT *BucketsPtr = getBuckets();
1157 UsedT *U = getUsed();
1158 const unsigned Mask = getNumBuckets() - 1;
1159 unsigned I = TheBucket - BucketsPtr;
1160 unsigned J = I;
1161 while (true) {
1162 J = (J + 1) & Mask;
1163 BucketT &BJ = BucketsPtr[J];
1165 break;
1166 auto Ideal = KeyInfoT::getHashValue(BJ.getFirst());
1167 // If the hole (I) lies on the linear-probe chain from the home bucket
1168 // (Ideal) to J, shift J into the hole and make J the new hole.
1169 if (((I - Ideal) & Mask) < ((J - Ideal) & Mask)) {
1170 llvm::densemap::detail::relocateBucket(&BucketsPtr[I], &BJ);
1171 I = J;
1172 }
1173 }
1175 }
1176
1177 template <typename KeyArgT, typename... Ts>
1178 std::pair<BucketT *, bool> lookupOrInsertIntoBucket(KeyArgT &&Key,
1179 Ts &&...Args) {
1180 BucketT *TheBucket = nullptr;
1181 if (LookupBucketFor(Key, TheBucket))
1182 return {TheBucket, false}; // Already in the map.
1183
1184 // Otherwise, insert the new element.
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};
1189 }
1190
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};
1196 }
1197
1198 iterator makeIterator(BucketT *TheBucket) {
1199 return iterator::makeIterator(TheBucket, getBuckets(), getUsed(),
1200 getNumBuckets(), *this);
1201 }
1202
1203 const_iterator makeConstIterator(const BucketT *TheBucket) const {
1204 return const_iterator::makeIterator(TheBucket, getBuckets(), getUsed(),
1205 getNumBuckets(), *this);
1206 }
1207
1208 unsigned getNumEntries() const { return Storage.getNumEntries(); }
1209
1210 void setNumEntries(unsigned Num) { Storage.setNumEntries(Num); }
1211
1212 void incrementNumEntries() { setNumEntries(getNumEntries() + 1); }
1213
1214 void decrementNumEntries() { setNumEntries(getNumEntries() - 1); }
1215
1216 const BucketT *getBuckets() const { return Storage.getBuckets(); }
1217
1218 BucketT *getBuckets() { return Storage.getBuckets(); }
1219
1220 Rep getRep() const { return Storage.getRep(); }
1221
1222 const UsedT *getUsed() const { return Storage.getUsed(); }
1223
1224 UsedT *getUsed() { return Storage.getUsed(); }
1225
1226 unsigned getNumBuckets() const { return Storage.getNumBuckets(); }
1227
1228 LLVM_ATTRIBUTE_NOINLINE void grow(unsigned MinNumBuckets) {
1229 assert((MinNumBuckets == 0 || isPowerOf2_32(MinNumBuckets)) &&
1230 "bucket count must be zero or a power of two");
1232 Storage.grow(MinNumBuckets, hasher());
1233 } else {
1234 unsigned NumBuckets = StorageT::roundUpNumBuckets(MinNumBuckets);
1235 StorageT Tmp;
1236 initWithExactBucketCount(Tmp, NumBuckets);
1237 moveFrom(Tmp, Storage);
1238 if (Storage.maybeMoveFast(std::move(Tmp)))
1239 return;
1240 initWithExactBucketCount(Storage, NumBuckets);
1241 moveFrom(Storage, Tmp);
1242 }
1243 }
1244
1245 template <typename LookupKeyT>
1246 BucketT *findBucketForInsertion(const LookupKeyT &Lookup,
1247 BucketT *TheBucket) {
1249
1250 // Grow the table if the load factor would exceed 3/4 after insertion.
1251 // Linear probing with gap-closing deletion (Knuth Algorithm R) keeps
1252 // every chain compact and bounded by the table's empty-bucket count,
1253 // so no tombstone-driven resize is needed.
1254 unsigned NewNumEntries = getNumEntries() + 1;
1255 unsigned NumBuckets = getNumBuckets();
1256 if (LLVM_UNLIKELY(NewNumEntries * 4 >= NumBuckets * 3)) {
1257 this->grow(NumBuckets * 2);
1258 LookupBucketFor(Lookup, TheBucket);
1259 }
1260 assert(TheBucket);
1261
1262 // Mark used. The caller will placement-construct the raw key/value.
1263 llvm::densemap::detail::setUsed(getUsed(), TheBucket - getBuckets());
1264
1265 // Only update the state after we've grown our bucket space appropriately
1266 // so that when growing buckets we have self-consistent entry count.
1267 incrementNumEntries();
1268 return TheBucket;
1269 }
1270
1271 template <typename LookupKeyT>
1272 const BucketT *doFind(const LookupKeyT &Val) const {
1273 if (empty())
1274 return nullptr;
1275 auto [BucketsPtr, U, NumBuckets] = getRep();
1276
1277 const unsigned Mask = NumBuckets - 1;
1278 unsigned BucketNo = KeyInfoT::getHashValue(Val) & Mask;
1279 while (true) {
1280 // An empty bucket terminates the probe: the key isn't in the map.
1281 if (LLVM_LIKELY(!llvm::densemap::detail::used(U, BucketNo)))
1282 return nullptr;
1283 const BucketT *Bucket = BucketsPtr + BucketNo;
1284 if (LLVM_LIKELY(KeyInfoT::isEqual(Val, Bucket->getFirst())))
1285 return Bucket;
1286
1287 // Hash collision: continue linear probing.
1288 BucketNo = (BucketNo + 1) & Mask;
1289 }
1290 }
1291
1292 template <typename LookupKeyT> BucketT *doFind(const LookupKeyT &Val) {
1293 return const_cast<BucketT *>(
1294 static_cast<const DenseMapBase *>(this)->doFind(Val));
1295 }
1296
1297 /// Lookup the appropriate bucket for Val, returning it in FoundBucket. If the
1298 /// bucket contains the key and a value, this returns true, otherwise it
1299 /// returns a bucket with an empty marker and returns false.
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;
1305 return false;
1306 }
1307 // getRep() yields const pointers; this object is non-const, so recovering
1308 // a mutable bucket pointer is safe (mirrors the non-const getBuckets()).
1309 BucketT *BucketsPtr = const_cast<BucketT *>(CBuckets);
1310
1311 const unsigned Mask = NumBuckets - 1;
1312 unsigned BucketNo = KeyInfoT::getHashValue(Val) & Mask;
1313 while (true) {
1314 BucketT *ThisBucket = BucketsPtr + BucketNo;
1315 // If we found an empty bucket, the key doesn't exist in the set.
1316 // Return it as the insertion point.
1317 if (LLVM_LIKELY(!llvm::densemap::detail::used(U, BucketNo))) {
1318 FoundBucket = ThisBucket;
1319 return false;
1320 }
1321
1322 // Found Val's bucket? If so, return it.
1323 if (LLVM_LIKELY(KeyInfoT::isEqual(Val, ThisBucket->getFirst()))) {
1324 FoundBucket = ThisBucket;
1325 return true;
1326 }
1327
1328 // Hash collision: continue linear probing.
1329 BucketNo = (BucketNo + 1) & Mask;
1330 }
1331 }
1332};
1333
1334/// Equality comparison for DenseMap.
1335///
1336/// Iterates over elements of LHS confirming that each (key, value) pair in LHS
1337/// is also in RHS, and that no additional pairs are in RHS.
1338/// Equivalent to N calls to RHS.find and N value comparisons. Amortized
1339/// complexity is linear, worst case is O(N^2) (if every hash collides).
1340template <typename Storage1T, typename Storage2T, typename KeyT,
1341 typename ValueT, typename KeyInfoT, typename BucketT>
1342[[nodiscard]] bool operator==(
1345 if (LHS.size() != RHS.size())
1346 return false;
1347
1348 for (auto &KV : LHS) {
1349 auto I = RHS.find(KV.first);
1350 if (I == RHS.end() || I->second != KV.second)
1351 return false;
1352 }
1353
1354 return true;
1355}
1356
1357/// Inequality comparison for DenseMap.
1358///
1359/// Equivalent to !(LHS == RHS). See operator== for performance notes.
1360template <typename Storage1T, typename Storage2T, typename KeyT,
1361 typename ValueT, typename KeyInfoT, typename BucketT>
1367
1368template <typename KeyT, typename ValueT,
1369 typename KeyInfoT = DenseMapInfo<KeyT>,
1371class DenseMap : public DenseMapBase<densemap::detail::DenseMapStorage<BucketT>,
1372 KeyT, ValueT, KeyInfoT, BucketT> {
1374 ValueT, KeyInfoT, BucketT>;
1375
1376public:
1377 using BaseT::BaseT;
1378};
1379
1380template <typename KeyT, typename ValueT, unsigned InlineBuckets = 4,
1381 typename KeyInfoT = DenseMapInfo<KeyT>,
1384 : public DenseMapBase<
1385 densemap::detail::SmallDenseMapStorage<BucketT, InlineBuckets>, KeyT,
1386 ValueT, KeyInfoT, BucketT> {
1387 using BaseT = DenseMapBase<
1389 ValueT, KeyInfoT, BucketT>;
1390
1391public:
1392 using BaseT::BaseT;
1393};
1394
1395template <typename KeyT, typename ValueT, typename KeyInfoT>
1396[[nodiscard]] inline size_t
1398 return X.getMemorySize();
1399}
1400
1401} // end namespace llvm
1402
1403#endif // LLVM_ADT_DENSEMAP_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define X(NUM, ENUM, NAME)
Definition ELF.h:857
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_UNLIKELY(EXPR)
Definition Compiler.h:352
#define LLVM_ATTRIBUTE_ALWAYS_INLINE
LLVM_ATTRIBUTE_ALWAYS_INLINE - On compilers where we have a directive to do so, mark a method "always...
Definition Compiler.h:372
#define LLVM_ABI
Definition Compiler.h:215
#define LLVM_ATTRIBUTE_NOINLINE
LLVM_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so, mark a method "not for inl...
Definition Compiler.h:362
#define LLVM_LIKELY(EXPR)
Definition Compiler.h:351
This file defines DenseMapInfo traits for DenseMap.
This file defines the DebugEpochBase and DebugEpochBase::HandleBase classes.
#define I(x, y, z)
Definition MD5.cpp:57
This file defines counterparts of C library allocation functions defined in the namespace 'std'.
#define T
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
#define P(N)
This file contains some templates that are useful if you are working with the STL at all.
This file contains library features backported from future STL versions.
static int Lookup(ArrayRef< TableEntry > Table, unsigned Opcode)
Value * RHS
Value * LHS
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
Definition DenseMap.h:758
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Definition DenseMap.h:763
bool empty() const
Definition DenseMap.h:717
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:767
std::pair< iterator, bool > emplace_or_assign(const KeyT &Key, Ts &&...Args)
Definition DenseMap.h:916
auto keys() const
Definition DenseMap.h:709
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT, true > const_iterator
Definition DenseMap.h:680
void insert_range(Range &&R)
Inserts range of 'std::pair<KeyT, ValueT>' values into the map.
Definition DenseMap.h:895
void insert(InputIt I, InputIt E)
Range insertion of pairs.
Definition DenseMap.h:889
std::pair< iterator, bool > try_emplace(const KeyT &Key, Ts &&...Args)
Definition DenseMap.h:865
std::pair< iterator, bool > insert_or_assign(const KeyT &Key, V &&Val)
Definition DenseMap.h:900
ValueT & at(const_arg_type_t< KeyT > Val)
Return the entry for the specified key, or abort if no such entry exists.
Definition DenseMap.h:812
void erase(iterator I)
Definition DenseMap.h:939
void reserve(size_type NumEntries)
Grow the densemap so that it can contain at least NumEntries items before resizing again.
Definition DenseMap.h:722
ValueT lookup_or(const_arg_type_t< KeyT > Val, U &&Default) const
Definition DenseMap.h:804
std::pair< iterator, bool > insert(BucketT &&KV)
Definition DenseMap.h:849
const_iterator find(const_arg_type_t< KeyT > Val) const
Definition DenseMap.h:770
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,...
Definition DenseMap.h:875
iterator end()
Definition DenseMap.h:687
std::pair< iterator, bool > insert(const BucketT &KV)
Definition DenseMap.h:842
ValueT & operator[](const KeyT &Key)
Definition DenseMap.h:970
DenseMapBase(const InputIt &I, const InputIt &E)
Definition DenseMap.h:1000
unsigned size() const
Definition DenseMap.h:718
std::pair< iterator, bool > emplace_or_assign(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:924
const_iterator begin() const
Definition DenseMap.h:690
DenseMapBase(unsigned NumElementsToReserve)
Create a DenseMap with an optional NumElementsToReserve to guarantee that this number of elements can...
Definition DenseMap.h:988
std::pair< iterator, bool > insert(std::pair< KeyT, ValueT > &&KV)
Definition DenseMap.h:835
bool erase(const KeyT &Val)
Definition DenseMap.h:931
DenseMapBase(llvm::from_range_t, const RangeT &Range)
Definition DenseMap.h:1006
const_iterator find_as(const LookupKeyT &Val) const
Definition DenseMap.h:786
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT > iterator
Definition DenseMap.h:679
unsigned size_type
Definition DenseMap.h:674
DenseMapBase(const DenseMapBase &other)
Definition DenseMap.h:993
std::pair< iterator, bool > insert_or_assign(KeyT &&Key, V &&Val)
Definition DenseMap.h:908
DenseMapBase & operator=(const DenseMapBase &other)
Definition DenseMap.h:1017
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.
Definition DenseMap.h:794
iterator find_as(const LookupKeyT &Val)
Alternate version of find() which allows a different, and possibly less expensive,...
Definition DenseMap.h:780
const_iterator end() const
Definition DenseMap.h:694
void swap(DenseMapBase &RHS)
Definition DenseMap.h:978
bool remove_if(Predicate Pred)
Remove entries that match the given predicate.
Definition DenseMap.h:947
DenseMapBase(std::initializer_list< value_type > Vals)
Definition DenseMap.h:1009
iterator begin()
Definition DenseMap.h:683
const ValueT & at(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or abort if no such entry exists.
Definition DenseMap.h:819
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:828
size_t getMemorySize() const
Return the approximate size (in bytes) of the actual map.
Definition DenseMap.h:1035
DenseMapBase(DenseMapBase &&other)
Definition DenseMap.h:997
DenseMapBase & operator=(DenseMapBase &&other)
Definition DenseMap.h:1023
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:857
auto values() const
Definition DenseMap.h:713
void shrink_and_clear()
Definition DenseMap.h:746
ValueT & operator[](KeyT &&Key)
Definition DenseMap.h:974
std::conditional_t< IsConst, const Bucket, Bucket > value_type
Definition DenseMap.h:531
friend bool operator!=(const DenseMapIterator &LHS, const DenseMapIterator &RHS)
Definition DenseMap.h:610
value_type * pointer
Definition DenseMap.h:532
DenseMapIterator & operator++()
Definition DenseMap.h:615
pointer operator->() const
Definition DenseMap.h:602
reference operator*() const
Definition DenseMap.h:597
DenseMapIterator operator++(int)
Definition DenseMap.h:622
DenseMapIterator(const DenseMapIterator< KeyT, ValueT, KeyInfoT, Bucket, IsConstSrc > &I)
Definition DenseMap.h:592
static DenseMapIterator makeIterator(pointer P, pointer Buckets, const UsedT *Used, unsigned NumBuckets, const DebugEpochBase &Epoch)
Definition DenseMap.h:578
ptrdiff_t difference_type
Definition DenseMap.h:530
friend bool operator==(const DenseMapIterator &LHS, const DenseMapIterator &RHS)
Definition DenseMap.h:604
std::forward_iterator_tag iterator_category
Definition DenseMap.h:534
static DenseMapIterator makeBegin(pointer Buckets, const UsedT *Used, unsigned NumBuckets, bool IsEmpty, const DebugEpochBase &Epoch)
Definition DenseMap.h:558
value_type & reference
Definition DenseMap.h:533
static DenseMapIterator makeEnd(pointer Buckets, const UsedT *Used, unsigned NumBuckets, const DebugEpochBase &Epoch)
Definition DenseMap.h:571
LLVM Value Representation.
Definition Value.h:75
StorageRep< BucketT > getRep() const
Definition DenseMap.h:227
static unsigned roundUpNumBuckets(unsigned MinNumBuckets)
Definition DenseMap.h:272
bool maybeMoveFast(DenseMapStorage &&Other)
Definition DenseMap.h:288
void setStorage(void *Storage, unsigned Num)
Definition DenseMap.h:236
void swap(DenseMapStorage &RHS)
Definition DenseMap.h:229
std::pair< bool, unsigned > planShrinkAndClear() const
Definition DenseMap.h:279
void grow(unsigned MinNumBuckets, BucketHasher Hasher)
Definition DenseMap.h:242
StorageRep< BucketT > getRep() const
Definition DenseMap.h:382
std::pair< bool, unsigned > planShrinkAndClear() const
Definition DenseMap.h:492
void grow(unsigned MinNumBuckets, BucketHasher Hasher)
Definition DenseMap.h:447
void swap(SmallDenseMapStorage &RHS)
Definition DenseMap.h:389
bool maybeMoveFast(SmallDenseMapStorage &&Other)
Definition DenseMap.h:506
static unsigned roundUpNumBuckets(unsigned MinNumBuckets)
Definition DenseMap.h:483
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)
Definition DenseMap.h:120
UsedT * usedFor(void *Buckets, size_t BucketSize, unsigned Num)
Definition DenseMap.h:156
constexpr bool hashesPointerValue
Definition DenseMap.h:173
void clearUsed(UsedT *U, unsigned Num)
Definition DenseMap.h:124
constexpr size_t usedWords(size_t N)
Definition DenseMap.h:111
LLVM_ATTRIBUTE_ALWAYS_INLINE void forEachUsed(const UsedT *U, unsigned N, Fn Func)
Definition DenseMap.h:132
size_t allocBytes(size_t BucketSize, unsigned Num)
Definition DenseMap.h:150
unsigned(*)(const void *Key) BucketHasher
Hashes the key, at offset 0 in a bucket.
Definition DenseMap.h:165
constexpr size_t allocAlign()
Definition DenseMap.h:147
constexpr BucketHasher hasherFor()
Definition DenseMap.h:182
void relocateBucket(BucketT *Dst, BucketT *Src)
Definition DenseMap.h:99
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,...
Definition DenseMap.cpp:85
bool used(const UsedT *U, size_t I)
Definition DenseMap.h:117
void unsetUsed(UsedT *U, size_t I)
Definition DenseMap.h:121
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.
Definition DenseMap.cpp:71
constexpr bool isRelocatableBucket
Definition DenseMap.h:94
A self-contained host- and target-independent arbitrary-precision floating-point software implementat...
Definition ADL.h:123
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.
Definition MathExtras.h:339
@ Offset
Definition DWP.cpp:577
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...
Definition ADL.h:78
BitVector::size_type capacity_in_bytes(const BitVector &X)
Definition BitVector.h:863
bool operator!=(uint64_t V1, const APInt &V2)
Definition APInt.h:2139
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.)
Definition MathExtras.h:285
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...
Definition ADL.h:86
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.
Definition STLExtras.h:366
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
Definition bit.h:204
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.
Definition MemAlloc.cpp:15
auto reverse(ContainerTy &&C)
Definition STLExtras.h:408
LLVM_ABI void deallocate_buffer(void *Ptr, size_t Size, size_t Alignment)
Deallocate a buffer of memory with the given size and alignment.
Definition MemAlloc.cpp:27
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:280
constexpr bool shouldReverseIterate()
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
iterator_range(Container &&) -> iterator_range< llvm::detail::IterOfRange< Container > >
@ Other
Any other memory.
Definition ModRef.h:68
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1933
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
Definition MathExtras.h:368
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
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
Definition type_traits.h:53
friend bool operator!=(const DenseMapPair &LHS, const DenseMapPair &RHS)
Definition DenseMap.h:78
DenseMapPair(const KeyT &Key, const ValueT &Value)
Definition DenseMap.h:57
DenseMapPair(KeyT &&Key, ValueT &&Value)
Definition DenseMap.h:59
DenseMapPair(std::pair< KeyT, ValueT > &&P)
Definition DenseMap.h:63
DenseMapPair(DenseMapPair< U1, U2 > &&P)
Definition DenseMap.h:69
DenseMapPair(const std::pair< KeyT, ValueT > &P)
Definition DenseMap.h:61
const ValueT & getSecond() const
Definition DenseMap.h:85
friend bool operator==(const DenseMapPair &LHS, const DenseMapPair &RHS)
Definition DenseMap.h:75
const KeyT & getFirst() const
Definition DenseMap.h:83
DenseMapPair(const DenseMapPair< U1, U2 > &P)
Definition DenseMap.h:66