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> class SmallDenseMapStorage {
295 static_assert(isPowerOf2_64(InlineBuckets),
296 "InlineBuckets must be a power of 2.");
297
298 // Number of used words backing the inline buckets (>= 1).
299 static constexpr unsigned InlineUsedWords = usedWords(InlineBuckets);
300
301 unsigned Small : 1;
302 unsigned NumEntries : 31;
303
304 // Inline storage: the bucket array followed by the parallel used words.
305 struct InlineRep {
306 alignas(BucketT) char Buckets[sizeof(BucketT) * InlineBuckets];
307 UsedT Used[InlineUsedWords];
308 };
309 struct LargeRep {
310 BucketT *Buckets;
311 UsedT *Used;
312 unsigned NumBuckets;
313 };
314
315 // Discriminated by the Small bit.
316 union {
317 InlineRep Inline;
318 LargeRep Large;
319 } storage;
320
321 const BucketT *getInlineBuckets() const {
322 assert(Small);
323 // Note that this cast does not violate aliasing rules as we assert that
324 // the memory's dynamic type is the small, inline bucket buffer, and the
325 // 'storage' is a POD containing a char buffer.
326 return reinterpret_cast<const BucketT *>(storage.Inline.Buckets);
327 }
328
329 BucketT *getInlineBuckets() {
330 assert(Small);
331 return reinterpret_cast<BucketT *>(storage.Inline.Buckets);
332 }
333
334 const UsedT *getInlineUsed() const {
335 assert(Small);
336 return storage.Inline.Used;
337 }
338
339 UsedT *getInlineUsed() {
340 assert(Small);
341 return storage.Inline.Used;
342 }
343
344 void setLarge(void *Storage, unsigned NumBuckets) {
345 Small = false;
346 storage.Large = {static_cast<BucketT *>(Storage),
347 usedFor(Storage, sizeof(BucketT), NumBuckets), NumBuckets};
348 }
349
350public:
351 unsigned getNumEntries() const { return NumEntries; }
352
353 void setNumEntries(unsigned Num) {
354 // NumEntries is hardcoded to be 31 bits wide.
355 assert(Num < (1U << 31) && "Cannot support more than 1<<31 entries");
356 NumEntries = Num;
357 }
358
359 const BucketT *getBuckets() const {
360 return Small ? getInlineBuckets() : storage.Large.Buckets;
361 }
362
363 BucketT *getBuckets() {
364 return const_cast<BucketT *>(
365 const_cast<const SmallDenseMapStorage *>(this)->getBuckets());
366 }
367
368 const UsedT *getUsed() const {
369 return Small ? getInlineUsed() : storage.Large.Used;
370 }
371
373 return const_cast<UsedT *>(
374 const_cast<const SmallDenseMapStorage *>(this)->getUsed());
375 }
376
377 unsigned getNumBuckets() const {
378 return Small ? InlineBuckets : storage.Large.NumBuckets;
379 }
380
382 if (Small)
383 return {getInlineBuckets(), getInlineUsed(), InlineBuckets};
384 return {storage.Large.Buckets, storage.Large.Used,
385 storage.Large.NumBuckets};
386 }
387
389 unsigned TmpNumEntries = RHS.NumEntries;
390 RHS.NumEntries = NumEntries;
391 NumEntries = TmpNumEntries;
392
393 if (Small && RHS.Small) {
394 // Both inline: swap the live bucket contents slot by slot, then the used
395 // words. Buckets are raw storage, so a value may only move in one
396 // direction when exactly one side is occupied.
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);
402 if (L && R) {
403 // Both occupied: exchange through a temporary.
404 alignas(BucketT) char Tmp[sizeof(BucketT)];
405 BucketT *T = reinterpret_cast<BucketT *>(Tmp);
406 relocateBucket(T, &LB[I]);
407 relocateBucket(&LB[I], &RB[I]);
408 relocateBucket(&RB[I], T);
409 } else if (L) {
410 relocateBucket(&RB[I], &LB[I]);
411 } else if (R) {
412 relocateBucket(&LB[I], &RB[I]);
413 }
414 }
415 for (unsigned W = 0; W != InlineUsedWords; ++W)
416 std::swap(LU[W], RU[W]);
417 return;
418 }
419 if (!Small && !RHS.Small) {
420 std::swap(storage.Large, RHS.storage.Large);
421 return;
422 }
423
424 SmallDenseMapStorage &SmallSide = Small ? *this : RHS;
425 SmallDenseMapStorage &LargeSide = Small ? RHS : *this;
426
427 // Stash the large rep, then move the small side's inline contents into the
428 // large side (which becomes inline), and finally install the rep on the
429 // small side (which becomes large).
430 LargeRep TmpRep = LargeSide.storage.Large;
431 LargeSide.Small = true;
432 {
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)
437 if (used(SU, I))
438 relocateBucket(&LB[I], &SB[I]);
439 for (unsigned W = 0; W != InlineUsedWords; ++W)
440 LU[W] = SU[W];
441 }
442 SmallSide.Small = false;
443 SmallSide.storage.Large = TmpRep;
444 }
445
446 void grow(unsigned MinNumBuckets, BucketHasher Hasher) {
447 unsigned NewNumBuckets = roundUpNumBuckets(MinNumBuckets);
448 // remove_if asks for the count it already has: rehash in place.
449 if (Small && NewNumBuckets <= InlineBuckets) {
450 InlineRep Old = storage.Inline;
451 clearUsed(getInlineUsed(), InlineBuckets);
452 rehashRelocatable(getInlineBuckets(), getInlineUsed(), InlineBuckets,
453 Old.Buckets, Old.Used, InlineBuckets, sizeof(BucketT),
454 Hasher);
455 return;
456 }
457 void *Storage = growRelocatable(
458 getBuckets(), getUsed(), getNumBuckets(), NewNumBuckets,
459 sizeof(BucketT), allocAlign<BucketT>(), Hasher, /*FreeOld=*/!Small);
460 setLarge(Storage, NewNumBuckets);
461 }
462
464 if (Small)
465 return;
466
467 deallocate_buffer(storage.Large.Buckets,
468 allocBytes<BucketT>(storage.Large.NumBuckets),
470 }
471
472 bool allocateBuckets(unsigned Num) {
473 if (Num <= InlineBuckets) {
474 Small = true;
475 return true;
476 }
478 Num);
479 return true;
480 }
481
482 static unsigned roundUpNumBuckets(unsigned MinNumBuckets) {
483 if (MinNumBuckets <= InlineBuckets)
484 return InlineBuckets;
485 return std::max(64u, MinNumBuckets);
486 }
487
488 // Plan how to shrink the bucket table. Return:
489 // - {false, 0} to reuse the existing bucket table
490 // - {true, N} to reallocate a bucket table with N entries
491 std::pair<bool, unsigned> planShrinkAndClear() const {
492 unsigned NewNumBuckets = 0;
493 if (NumEntries) {
494 NewNumBuckets = 1u << (Log2_32_Ceil(NumEntries) + 1);
495 if (NewNumBuckets > InlineBuckets)
496 NewNumBuckets = std::max(64u, NewNumBuckets);
497 }
498 bool Reuse = Small ? NewNumBuckets <= InlineBuckets
499 : NewNumBuckets == storage.Large.NumBuckets;
500 if (Reuse)
501 return {false, 0}; // Reuse.
502 return {true, NewNumBuckets}; // Reallocate.
503 }
504
506 if (Other.Small)
507 return false;
508
509 Small = false;
510 NumEntries = Other.NumEntries;
511 storage.Large = Other.storage.Large;
512 return true;
513 }
514};
515
516} // namespace densemap::detail
517
518template <typename KeyT, typename ValueT,
519 typename KeyInfoT = DenseMapInfo<KeyT>,
521 bool IsConst = false>
522class DenseMapIterator : DebugEpochBase::HandleBase {
523 friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true>;
524 friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, false>;
525
526 using UsedT = llvm::densemap::detail::UsedT;
527
528public:
530 using value_type = std::conditional_t<IsConst, const Bucket, Bucket>;
533 using iterator_category = std::forward_iterator_tag;
534
535private:
536 using BucketItTy =
537 std::conditional_t<shouldReverseIterate<KeyT>(),
538 std::reverse_iterator<pointer>, pointer>;
539
540 BucketItTy Ptr = {};
541 BucketItTy End = {};
542 // The non-reversed bucket base and the parallel used array. They map a
543 // bucket back to its index so AdvancePastEmptyBuckets can consult the bits.
544 pointer Buckets = {};
545 const UsedT *Used = {};
546
547 DenseMapIterator(BucketItTy Pos, BucketItTy E, pointer BucketsBase,
548 const UsedT *U, const DebugEpochBase &Epoch)
549 : DebugEpochBase::HandleBase(&Epoch), Ptr(Pos), End(E),
550 Buckets(BucketsBase), Used(U) {
551 assert(isHandleInSync() && "invalid construction!");
552 }
553
554public:
555 DenseMapIterator() = default;
556
557 static DenseMapIterator makeBegin(pointer Buckets, const UsedT *Used,
558 unsigned NumBuckets, bool IsEmpty,
559 const DebugEpochBase &Epoch) {
560 // When the map is empty, avoid the overhead of advancing/retreating past
561 // empty buckets.
562 if (IsEmpty)
563 return makeEnd(Buckets, Used, NumBuckets, Epoch);
564 auto R = maybeReverse(llvm::make_range(Buckets, Buckets + NumBuckets));
565 DenseMapIterator Iter(R.begin(), R.end(), Buckets, Used, Epoch);
566 Iter.AdvancePastEmptyBuckets();
567 return Iter;
568 }
569
570 static DenseMapIterator makeEnd(pointer Buckets, const UsedT *Used,
571 unsigned NumBuckets,
572 const DebugEpochBase &Epoch) {
573 auto R = maybeReverse(llvm::make_range(Buckets, Buckets + NumBuckets));
574 return DenseMapIterator(R.end(), R.end(), Buckets, Used, Epoch);
575 }
576
577 static DenseMapIterator makeIterator(pointer P, pointer Buckets,
578 const UsedT *Used, unsigned NumBuckets,
579 const DebugEpochBase &Epoch) {
580 auto R = maybeReverse(llvm::make_range(Buckets, Buckets + NumBuckets));
581 constexpr int Offset = shouldReverseIterate<KeyT>() ? 1 : 0;
582 return DenseMapIterator(BucketItTy(P + Offset), R.end(), Buckets, Used,
583 Epoch);
584 }
585
586 // Converting ctor from non-const iterators to const iterators. SFINAE'd out
587 // for const iterator destinations so it doesn't end up as a user defined copy
588 // constructor.
589 template <bool IsConstSrc,
590 typename = std::enable_if_t<!IsConstSrc && IsConst>>
592 const DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, IsConstSrc> &I)
593 : DebugEpochBase::HandleBase(I), Ptr(I.Ptr), End(I.End),
594 Buckets(I.Buckets), Used(I.Used) {}
595
596 [[nodiscard]] reference operator*() const {
597 assert(isHandleInSync() && "invalid iterator access!");
598 assert(Ptr != End && "dereferencing end() iterator");
599 return *Ptr;
600 }
601 [[nodiscard]] pointer operator->() const { return &operator*(); }
602
603 [[nodiscard]] friend bool operator==(const DenseMapIterator &LHS,
604 const DenseMapIterator &RHS) {
605 assert(LHS.isComparableWith(RHS) && "incomparable iterators!");
606 return LHS.Ptr == RHS.Ptr;
607 }
608
609 [[nodiscard]] friend bool operator!=(const DenseMapIterator &LHS,
610 const DenseMapIterator &RHS) {
611 return !(LHS == RHS);
612 }
613
614 inline DenseMapIterator &operator++() { // Preincrement
615 assert(isHandleInSync() && "invalid iterator access!");
616 assert(Ptr != End && "incrementing end() iterator");
617 ++Ptr;
618 AdvancePastEmptyBuckets();
619 return *this;
620 }
621 DenseMapIterator operator++(int) { // Postincrement
622 assert(isHandleInSync() && "invalid iterator access!");
623 DenseMapIterator tmp = *this;
624 ++*this;
625 return tmp;
626 }
627
628private:
629 void AdvancePastEmptyBuckets() {
630 if constexpr (shouldReverseIterate<KeyT>()) {
631 while (Ptr != End && !llvm::densemap::detail::used(Used, &*Ptr - Buckets))
632 ++Ptr;
633 } else {
634 // Forward iteration skips empty buckets a used-word (32 buckets) at a
635 // time: scan from the current index for the next set occupancy bit.
636 const size_t N = End - Buckets;
637 size_t I = Ptr - Buckets;
638 if (I >= N) {
639 Ptr = End;
640 return;
641 }
642 const size_t NW = llvm::densemap::detail::usedWords(N);
643 size_t W = I >> 5;
644 UsedT Bits = Used[W] & (~UsedT(0) << (I & 31));
645 while (Bits == 0) {
646 if (++W == NW) {
647 Ptr = End;
648 return;
649 }
650 Bits = Used[W];
651 }
652 Ptr = Buckets + ((W << 5) + llvm::countr_zero(Bits));
653 }
654 }
655
656 static auto maybeReverse(iterator_range<pointer> Range) {
657 if constexpr (shouldReverseIterate<KeyT>())
658 return reverse(Range);
659 else
660 return Range;
661 }
662};
663
664template <typename StorageT, typename KeyT, typename ValueT, typename KeyInfoT,
665 typename BucketT>
667 template <typename T>
668 using const_arg_type_t = typename const_pointer_or_const_ref<T>::type;
669
670 using UsedT = llvm::densemap::detail::UsedT;
671
672public:
674 using key_type = KeyT;
675 using mapped_type = ValueT;
676 using value_type = BucketT;
677
681
682 [[nodiscard]] inline iterator begin() {
683 return iterator::makeBegin(getBuckets(), getUsed(), getNumBuckets(),
684 empty(), *this);
685 }
686 [[nodiscard]] inline iterator end() {
687 return iterator::makeEnd(getBuckets(), getUsed(), getNumBuckets(), *this);
688 }
689 [[nodiscard]] inline const_iterator begin() const {
690 return const_iterator::makeBegin(getBuckets(), getUsed(), getNumBuckets(),
691 empty(), *this);
692 }
693 [[nodiscard]] inline const_iterator end() const {
694 return const_iterator::makeEnd(getBuckets(), getUsed(), getNumBuckets(),
695 *this);
696 }
697
698 // Return an iterator to iterate over keys in the map.
699 [[nodiscard]] inline auto keys() {
700 return map_range(*this, [](const BucketT &P) { return P.getFirst(); });
701 }
702
703 // Return an iterator to iterate over values in the map.
704 [[nodiscard]] inline auto values() {
705 return map_range(*this, [](const BucketT &P) { return P.getSecond(); });
706 }
707
708 [[nodiscard]] inline auto keys() const {
709 return map_range(*this, [](const BucketT &P) { return P.getFirst(); });
710 }
711
712 [[nodiscard]] inline auto values() const {
713 return map_range(*this, [](const BucketT &P) { return P.getSecond(); });
714 }
715
716 [[nodiscard]] bool empty() const { return getNumEntries() == 0; }
717 [[nodiscard]] unsigned size() const { return getNumEntries(); }
718
719 /// Grow the DenseMap so that it can contain at least \p NumEntries items
720 /// before resizing again.
721 void reserve(size_type NumEntries) {
722 auto NumBuckets = getMinBucketToReserveForEntries(NumEntries);
724 if (NumBuckets > getNumBuckets())
725 grow(NumBuckets);
726 }
727
728 void clear() {
730 if (getNumEntries() == 0)
731 return;
732
733 // If the capacity of the array is huge, and the # elements used is small,
734 // shrink the array.
735 if (getNumEntries() * 4 < getNumBuckets() && getNumBuckets() > 64) {
737 return;
738 }
739
740 destroyAll();
741 llvm::densemap::detail::clearUsed(getUsed(), getNumBuckets());
742 setNumEntries(0);
743 }
744
746 auto [Reallocate, NewNumBuckets] = Storage.planShrinkAndClear();
747 destroyAll();
748 if (!Reallocate) {
749 initEmpty(Storage);
750 return;
751 }
752 Storage.deallocateBuckets();
753 initWithExactBucketCount(Storage, NewNumBuckets);
754 }
755
756 /// Return true if the specified key is in the map, false otherwise.
757 [[nodiscard]] bool contains(const_arg_type_t<KeyT> Val) const {
758 return doFind(Val) != nullptr;
759 }
760
761 /// Return 1 if the specified key is in the map, 0 otherwise.
762 [[nodiscard]] size_type count(const_arg_type_t<KeyT> Val) const {
763 return contains(Val) ? 1 : 0;
764 }
765
766 [[nodiscard]] iterator find(const_arg_type_t<KeyT> Val) {
767 return find_as(Val);
768 }
769 [[nodiscard]] const_iterator find(const_arg_type_t<KeyT> Val) const {
770 return find_as(Val);
771 }
772
773 /// Alternate version of find() which allows a different, and possibly
774 /// less expensive, key type.
775 /// The DenseMapInfo is responsible for supplying methods
776 /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key
777 /// type used.
778 template <class LookupKeyT>
779 [[nodiscard]] iterator find_as(const LookupKeyT &Val) {
780 if (BucketT *Bucket = doFind(Val))
781 return makeIterator(Bucket);
782 return end();
783 }
784 template <class LookupKeyT>
785 [[nodiscard]] const_iterator find_as(const LookupKeyT &Val) const {
786 if (const BucketT *Bucket = doFind(Val))
787 return makeConstIterator(Bucket);
788 return end();
789 }
790
791 /// Return the entry for the specified key, or a default constructed value if
792 /// no such entry exists.
793 [[nodiscard]] ValueT lookup(const_arg_type_t<KeyT> Val) const {
794 if (const BucketT *Bucket = doFind(Val))
795 return Bucket->getSecond();
796 return ValueT();
797 }
798
799 // Return the entry with the specified key, or \p Default. This variant is
800 // useful, because `lookup` cannot be used with non-default-constructible
801 // values.
802 template <typename U = std::remove_cv_t<ValueT>>
803 [[nodiscard]] ValueT lookup_or(const_arg_type_t<KeyT> Val,
804 U &&Default) const {
805 if (const BucketT *Bucket = doFind(Val))
806 return Bucket->getSecond();
807 return Default;
808 }
809
810 /// Return the entry for the specified key, or abort if no such entry exists.
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");
814 return Iter->second;
815 }
816
817 /// Return the entry for the specified key, or abort if no such entry exists.
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");
821 return Iter->second;
822 }
823
824 // Inserts key,value pair into the map if the key isn't already in the map.
825 // If the key is already in the map, it returns false and doesn't update the
826 // value.
827 std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) {
828 return try_emplace_impl(KV.first, KV.second);
829 }
830
831 // Inserts key,value pair into the map if the key isn't already in the map.
832 // If the key is already in the map, it returns false and doesn't update the
833 // value.
834 std::pair<iterator, bool> insert(std::pair<KeyT, ValueT> &&KV) {
835 return try_emplace_impl(std::move(KV.first), std::move(KV.second));
836 }
837
838 template <
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);
843 }
844
845 template <
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));
850 }
851
852 // Inserts key,value pair into the map if the key isn't already in the map.
853 // The value is constructed in-place if the key is not in the map, otherwise
854 // it is not moved.
855 template <typename... Ts>
856 std::pair<iterator, bool> try_emplace(KeyT &&Key, Ts &&...Args) {
857 return try_emplace_impl(std::move(Key), std::forward<Ts>(Args)...);
858 }
859
860 // Inserts key,value pair into the map if the key isn't already in the map.
861 // The value is constructed in-place if the key is not in the map, otherwise
862 // it is not moved.
863 template <typename... Ts>
864 std::pair<iterator, bool> try_emplace(const KeyT &Key, Ts &&...Args) {
865 return try_emplace_impl(Key, std::forward<Ts>(Args)...);
866 }
867
868 /// Alternate version of insert() which allows a different, and possibly
869 /// less expensive, key type.
870 /// The DenseMapInfo is responsible for supplying methods
871 /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key
872 /// type used.
873 template <typename LookupKeyT>
874 std::pair<iterator, bool> insert_as(std::pair<KeyT, ValueT> &&KV,
875 const LookupKeyT &Val) {
876 BucketT *TheBucket;
877 if (LookupBucketFor(Val, TheBucket))
878 return {makeIterator(TheBucket), false}; // Already in map.
879
880 // Otherwise, insert the new element.
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};
885 }
886
887 /// Range insertion of pairs.
888 template <typename InputIt> void insert(InputIt I, InputIt E) {
889 for (; I != E; ++I)
890 insert(*I);
891 }
892
893 /// Inserts a range of 'std::pair<KeyT, ValueT>' values into the map.
894 template <typename Range> void insert_range(Range &&R) {
895 insert(adl_begin(R), adl_end(R));
896 }
897
898 template <typename V>
899 std::pair<iterator, bool> insert_or_assign(const KeyT &Key, V &&Val) {
900 auto Ret = try_emplace(Key, std::forward<V>(Val));
901 if (!Ret.second)
902 Ret.first->second = std::forward<V>(Val);
903 return Ret;
904 }
905
906 template <typename V>
907 std::pair<iterator, bool> insert_or_assign(KeyT &&Key, V &&Val) {
908 auto Ret = try_emplace(std::move(Key), std::forward<V>(Val));
909 if (!Ret.second)
910 Ret.first->second = std::forward<V>(Val);
911 return Ret;
912 }
913
914 template <typename... Ts>
915 std::pair<iterator, bool> emplace_or_assign(const KeyT &Key, Ts &&...Args) {
916 auto Ret = try_emplace(Key, std::forward<Ts>(Args)...);
917 if (!Ret.second)
918 Ret.first->second = ValueT(std::forward<Ts>(Args)...);
919 return Ret;
920 }
921
922 template <typename... Ts>
923 std::pair<iterator, bool> emplace_or_assign(KeyT &&Key, Ts &&...Args) {
924 auto Ret = try_emplace(std::move(Key), std::forward<Ts>(Args)...);
925 if (!Ret.second)
926 Ret.first->second = ValueT(std::forward<Ts>(Args)...);
927 return Ret;
928 }
929
930 bool erase(const KeyT &Val) {
931 BucketT *TheBucket = doFind(Val);
932 if (!TheBucket)
933 return false; // not in map.
934
935 eraseFromFilledBucket(TheBucket);
936 return true;
937 }
938 void erase(iterator I) { eraseFromFilledBucket(&*I); }
939
940 /// Remove entries that match the given predicate. \p Pred is invoked
941 /// with a reference to each live bucket and must not access the map being
942 /// modified. This is the safe replacement for erase-while-iterating.
943 ///
944 /// Returns whether anything was removed. If so, all iterators and references
945 /// into the map are invalidated.
946 template <typename Predicate> bool remove_if(Predicate Pred) {
947 UsedT *U = getUsed();
948 unsigned NumBuckets = getNumBuckets();
949 BucketT *B = getBuckets();
950 bool Removed = false;
951 for (unsigned I = 0; I != NumBuckets; ++I) {
953 continue;
954 if (Pred(B[I])) {
955 B[I].getSecond().~ValueT();
956 B[I].getFirst().~KeyT();
958 decrementNumEntries();
959 Removed = true;
960 }
961 }
962 if (Removed) {
964 grow(NumBuckets);
965 }
966 return Removed;
967 }
968
969 ValueT &operator[](const KeyT &Key) {
970 return lookupOrInsertIntoBucket(Key).first->second;
971 }
972
973 ValueT &operator[](KeyT &&Key) {
974 return lookupOrInsertIntoBucket(std::move(Key)).first->second;
975 }
976
979 RHS.incrementEpoch();
980 Storage.swap(RHS.Storage);
981 }
982
984
985 /// Create a DenseMap with an optional \p NumElementsToReserve to guarantee
986 /// that this number of elements can be inserted in the map without grow().
987 explicit DenseMapBase(unsigned NumElementsToReserve) {
988 initWithExactBucketCount(
989 Storage, getMinBucketToReserveForEntries(NumElementsToReserve));
990 }
991
992 DenseMapBase(const DenseMapBase &other) : DenseMapBase() { copyFrom(other); }
993
995
996 template <typename InputIt>
997 DenseMapBase(const InputIt &I, const InputIt &E)
998 : DenseMapBase(std::distance(I, E)) {
999 insert(I, E);
1000 }
1001
1002 template <typename RangeT>
1005
1006 DenseMapBase(std::initializer_list<value_type> Vals)
1007 : DenseMapBase(Vals.begin(), Vals.end()) {}
1008
1010 destroyAll();
1011 Storage.deallocateBuckets();
1012 }
1013
1015 if (&other != this)
1016 copyFrom(other);
1017 return *this;
1018 }
1019
1021 destroyAll();
1022 Storage.deallocateBuckets();
1023 initWithExactBucketCount(Storage, 0);
1024 swap(other);
1025 return *this;
1026 }
1027
1028 /// Return the approximate size (in bytes) of the actual map.
1029 /// This is just the raw memory used by DenseMap.
1030 /// If entries are pointers to objects, the size of the referenced objects
1031 /// is not included.
1032 [[nodiscard]] size_t getMemorySize() const {
1033 return llvm::densemap::detail::allocBytes<BucketT>(getNumBuckets());
1034 }
1035
1036private:
1037 StorageT Storage;
1038
1040
1041 static void initEmpty(StorageT &S) {
1042 S.setNumEntries(0);
1043
1044 assert((S.getNumBuckets() & (S.getNumBuckets() - 1)) == 0 &&
1045 "# initial buckets must be a power of two!");
1046 if (S.getNumBuckets())
1047 llvm::densemap::detail::clearUsed(S.getUsed(), S.getNumBuckets());
1048 }
1049
1050 static void initWithExactBucketCount(StorageT &S, unsigned NewNumBuckets) {
1051 if (S.allocateBuckets(NewNumBuckets))
1052 initEmpty(S);
1053 else
1054 S.setNumEntries(0);
1055 }
1056
1057 void destroyAll() {
1058 // No need to iterate through the buckets if the bucket is trivially
1059 // destructible.
1060 if constexpr (std::is_trivially_destructible_v<BucketT>)
1061 return;
1062
1063 if (getNumBuckets() == 0) // Nothing to do.
1064 return;
1065
1066 BucketT *B = getBuckets();
1067 const UsedT *U = getUsed();
1068 const unsigned E = getNumBuckets();
1069 llvm::densemap::detail::forEachUsed(U, E, [&](unsigned I) {
1070 B[I].getSecond().~ValueT();
1071 B[I].getFirst().~KeyT();
1072 });
1073 }
1074
1075 /// Returns the number of buckets to allocate to ensure that the DenseMap can
1076 /// accommodate \p NumEntries without need to grow().
1077 static unsigned getMinBucketToReserveForEntries(unsigned NumEntries) {
1078 // Ensure that "NumEntries * 4 < NumBuckets * 3"
1079 if (NumEntries == 0)
1080 return 0;
1081 // +1 is required because of the strict inequality.
1082 // For example, if NumEntries is 48, we need to return 128.
1083 return NextPowerOf2(NumEntries * 4 / 3 + 1);
1084 }
1085
1086 // Move key/value from Src to Dst.
1087 static LLVM_ATTRIBUTE_NOINLINE void moveFrom(StorageT &Dst, StorageT &Src) {
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;
1096 llvm::densemap::detail::forEachUsed(SrcU, E, [&](unsigned I) {
1097 // Find the first empty slot on this key's probe chain; there is no equal
1098 // key in the destination, so nothing to compare against.
1099 unsigned BucketNo = KeyInfoT::getHashValue(SrcB[I].getFirst()) & Mask;
1100 while (llvm::densemap::detail::used(U, BucketNo))
1101 BucketNo = (BucketNo + 1) & Mask;
1102 llvm::densemap::detail::relocateBucket(B + BucketNo, &SrcB[I]);
1104 });
1105 Dst.setNumEntries(Src.getNumEntries());
1106 Src.deallocateBuckets();
1107 }
1108
1109 LLVM_ATTRIBUTE_NOINLINE void copyFrom(const DenseMapBase &other) {
1110 destroyAll();
1111 Storage.deallocateBuckets();
1112 setNumEntries(0);
1113 if (!Storage.allocateBuckets(other.getNumBuckets())) {
1114 // The bucket list is empty. No work to do.
1115 return;
1116 }
1117
1118 assert(&other != this);
1119 assert(getNumBuckets() == other.getNumBuckets());
1120
1121 setNumEntries(other.getNumEntries());
1122
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,
1129 llvm::densemap::detail::usedWords(NumBuckets) * sizeof(UsedT));
1131 memcpy(reinterpret_cast<void *>(Buckets), OtherBuckets,
1132 NumBuckets * sizeof(BucketT));
1133 } else {
1134 llvm::densemap::detail::forEachUsed(U, NumBuckets, [&](unsigned I) {
1135 ::new (&Buckets[I].getFirst()) KeyT(OtherBuckets[I].getFirst());
1136 ::new (&Buckets[I].getSecond()) ValueT(OtherBuckets[I].getSecond());
1137 });
1138 }
1139 }
1140
1141 /// Erase the entry at \p TheBucket and close the resulting hole via Knuth
1142 /// TAOCP 6.4 Algorithm R.
1143 LLVM_ATTRIBUTE_NOINLINE void eraseFromFilledBucket(BucketT *TheBucket) {
1145 TheBucket->getSecond().~ValueT();
1146 TheBucket->getFirst().~KeyT();
1147 decrementNumEntries();
1148
1149 BucketT *BucketsPtr = getBuckets();
1150 UsedT *U = getUsed();
1151 const unsigned Mask = getNumBuckets() - 1;
1152 unsigned I = TheBucket - BucketsPtr;
1153 unsigned J = I;
1154 while (true) {
1155 J = (J + 1) & Mask;
1156 BucketT &BJ = BucketsPtr[J];
1158 break;
1159 auto Ideal = KeyInfoT::getHashValue(BJ.getFirst());
1160 // If the hole (I) lies on the linear-probe chain from the home bucket
1161 // (Ideal) to J, shift J into the hole and make J the new hole.
1162 if (((I - Ideal) & Mask) < ((J - Ideal) & Mask)) {
1163 llvm::densemap::detail::relocateBucket(&BucketsPtr[I], &BJ);
1164 I = J;
1165 }
1166 }
1168 }
1169
1170 template <typename KeyArgT, typename... Ts>
1171 std::pair<BucketT *, bool> lookupOrInsertIntoBucket(KeyArgT &&Key,
1172 Ts &&...Args) {
1173 BucketT *TheBucket = nullptr;
1174 if (LookupBucketFor(Key, TheBucket))
1175 return {TheBucket, false}; // Already in the map.
1176
1177 // Otherwise, insert the new element.
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};
1182 }
1183
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};
1189 }
1190
1191 iterator makeIterator(BucketT *TheBucket) {
1192 return iterator::makeIterator(TheBucket, getBuckets(), getUsed(),
1193 getNumBuckets(), *this);
1194 }
1195
1196 const_iterator makeConstIterator(const BucketT *TheBucket) const {
1197 return const_iterator::makeIterator(TheBucket, getBuckets(), getUsed(),
1198 getNumBuckets(), *this);
1199 }
1200
1201 unsigned getNumEntries() const { return Storage.getNumEntries(); }
1202
1203 void setNumEntries(unsigned Num) { Storage.setNumEntries(Num); }
1204
1205 void incrementNumEntries() { setNumEntries(getNumEntries() + 1); }
1206
1207 void decrementNumEntries() { setNumEntries(getNumEntries() - 1); }
1208
1209 const BucketT *getBuckets() const { return Storage.getBuckets(); }
1210
1211 BucketT *getBuckets() { return Storage.getBuckets(); }
1212
1213 Rep getRep() const { return Storage.getRep(); }
1214
1215 const UsedT *getUsed() const { return Storage.getUsed(); }
1216
1217 UsedT *getUsed() { return Storage.getUsed(); }
1218
1219 unsigned getNumBuckets() const { return Storage.getNumBuckets(); }
1220
1221 LLVM_ATTRIBUTE_NOINLINE void grow(unsigned MinNumBuckets) {
1222 assert((MinNumBuckets == 0 || isPowerOf2_32(MinNumBuckets)) &&
1223 "bucket count must be zero or a power of two");
1225 Storage.grow(MinNumBuckets,
1227 } else {
1228 unsigned NumBuckets = StorageT::roundUpNumBuckets(MinNumBuckets);
1229 StorageT Tmp;
1230 initWithExactBucketCount(Tmp, NumBuckets);
1231 moveFrom(Tmp, Storage);
1232 if (Storage.maybeMoveFast(std::move(Tmp)))
1233 return;
1234 initWithExactBucketCount(Storage, NumBuckets);
1235 moveFrom(Storage, Tmp);
1236 }
1237 }
1238
1239 template <typename LookupKeyT>
1240 BucketT *findBucketForInsertion(const LookupKeyT &Lookup,
1241 BucketT *TheBucket) {
1243
1244 // Grow the table if the load factor would exceed 3/4 after insertion.
1245 // Linear probing with gap-closing deletion (Knuth Algorithm R) keeps
1246 // every chain compact and bounded by the table's empty-bucket count,
1247 // so no tombstone-driven resize is needed.
1248 unsigned NewNumEntries = getNumEntries() + 1;
1249 unsigned NumBuckets = getNumBuckets();
1250 if (LLVM_UNLIKELY(NewNumEntries * 4 >= NumBuckets * 3)) {
1251 grow(NumBuckets * 2);
1252 LookupBucketFor(Lookup, TheBucket);
1253 }
1254 assert(TheBucket);
1255
1256 // Mark used. The caller will placement-construct the raw key/value.
1257 llvm::densemap::detail::setUsed(getUsed(), TheBucket - getBuckets());
1258
1259 // Only update the state after we've grown our bucket space appropriately
1260 // so that when growing buckets we have self-consistent entry count.
1261 incrementNumEntries();
1262 return TheBucket;
1263 }
1264
1265 template <typename LookupKeyT>
1266 const BucketT *doFind(const LookupKeyT &Val) const {
1267 if (empty())
1268 return nullptr;
1269 auto [BucketsPtr, U, NumBuckets] = getRep();
1270
1271 const unsigned Mask = NumBuckets - 1;
1272 unsigned BucketNo = KeyInfoT::getHashValue(Val) & Mask;
1273 while (true) {
1274 // An empty bucket terminates the probe: the key isn't in the map.
1275 if (LLVM_LIKELY(!llvm::densemap::detail::used(U, BucketNo)))
1276 return nullptr;
1277 const BucketT *Bucket = BucketsPtr + BucketNo;
1278 if (LLVM_LIKELY(KeyInfoT::isEqual(Val, Bucket->getFirst())))
1279 return Bucket;
1280
1281 // Hash collision: continue linear probing.
1282 BucketNo = (BucketNo + 1) & Mask;
1283 }
1284 }
1285
1286 template <typename LookupKeyT> BucketT *doFind(const LookupKeyT &Val) {
1287 return const_cast<BucketT *>(
1288 static_cast<const DenseMapBase *>(this)->doFind(Val));
1289 }
1290
1291 /// Lookup the appropriate bucket for Val, returning it in FoundBucket. If the
1292 /// bucket contains the key and a value, this returns true, otherwise it
1293 /// returns a bucket with an empty marker and returns false.
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;
1299 return false;
1300 }
1301 // getRep() yields const pointers; this object is non-const, so recovering
1302 // a mutable bucket pointer is safe (mirrors the non-const getBuckets()).
1303 BucketT *BucketsPtr = const_cast<BucketT *>(CBuckets);
1304
1305 const unsigned Mask = NumBuckets - 1;
1306 unsigned BucketNo = KeyInfoT::getHashValue(Val) & Mask;
1307 while (true) {
1308 BucketT *ThisBucket = BucketsPtr + BucketNo;
1309 // If we found an empty bucket, the key doesn't exist in the set.
1310 // Return it as the insertion point.
1311 if (LLVM_LIKELY(!llvm::densemap::detail::used(U, BucketNo))) {
1312 FoundBucket = ThisBucket;
1313 return false;
1314 }
1315
1316 // Found Val's bucket? If so, return it.
1317 if (LLVM_LIKELY(KeyInfoT::isEqual(Val, ThisBucket->getFirst()))) {
1318 FoundBucket = ThisBucket;
1319 return true;
1320 }
1321
1322 // Hash collision: continue linear probing.
1323 BucketNo = (BucketNo + 1) & Mask;
1324 }
1325 }
1326};
1327
1328/// Equality comparison for DenseMap.
1329///
1330/// Iterates over elements of LHS confirming that each (key, value) pair in LHS
1331/// is also in RHS, and that no additional pairs are in RHS.
1332/// Equivalent to N calls to RHS.find and N value comparisons. Amortized
1333/// complexity is linear, worst case is O(N^2) (if every hash collides).
1334template <typename Storage1T, typename Storage2T, typename KeyT,
1335 typename ValueT, typename KeyInfoT, typename BucketT>
1336[[nodiscard]] bool operator==(
1339 if (LHS.size() != RHS.size())
1340 return false;
1341
1342 for (auto &KV : LHS) {
1343 auto I = RHS.find(KV.first);
1344 if (I == RHS.end() || I->second != KV.second)
1345 return false;
1346 }
1347
1348 return true;
1349}
1350
1351/// Inequality comparison for DenseMap.
1352///
1353/// Equivalent to !(LHS == RHS). See operator== for performance notes.
1354template <typename Storage1T, typename Storage2T, typename KeyT,
1355 typename ValueT, typename KeyInfoT, typename BucketT>
1361
1362template <typename KeyT, typename ValueT,
1363 typename KeyInfoT = DenseMapInfo<KeyT>,
1365class DenseMap : public DenseMapBase<densemap::detail::DenseMapStorage<BucketT>,
1366 KeyT, ValueT, KeyInfoT, BucketT> {
1368 ValueT, KeyInfoT, BucketT>;
1369
1370public:
1371 using BaseT::BaseT;
1372};
1373
1374template <typename KeyT, typename ValueT, unsigned InlineBuckets = 4,
1375 typename KeyInfoT = DenseMapInfo<KeyT>,
1378 : public DenseMapBase<
1379 densemap::detail::SmallDenseMapStorage<BucketT, InlineBuckets>, KeyT,
1380 ValueT, KeyInfoT, BucketT> {
1381 using BaseT = DenseMapBase<
1383 ValueT, KeyInfoT, BucketT>;
1384
1385public:
1386 using BaseT::BaseT;
1387};
1388
1389template <typename KeyT, typename ValueT, typename KeyInfoT>
1390[[nodiscard]] inline size_t
1392 return X.getMemorySize();
1393}
1394
1395} // end namespace llvm
1396
1397#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:348
#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:368
#define LLVM_ABI
Definition Compiler.h:211
#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:358
#define LLVM_LIKELY(EXPR)
Definition Compiler.h:347
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:757
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:762
bool empty() const
Definition DenseMap.h:716
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:766
std::pair< iterator, bool > emplace_or_assign(const KeyT &Key, Ts &&...Args)
Definition DenseMap.h:915
auto keys() const
Definition DenseMap.h:708
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT, true > const_iterator
Definition DenseMap.h:679
void insert_range(Range &&R)
Inserts a range of 'std::pair<KeyT, ValueT>' values into the map.
Definition DenseMap.h:894
void insert(InputIt I, InputIt E)
Range insertion of pairs.
Definition DenseMap.h:888
std::pair< iterator, bool > try_emplace(const KeyT &Key, Ts &&...Args)
Definition DenseMap.h:864
std::pair< iterator, bool > insert_or_assign(const KeyT &Key, V &&Val)
Definition DenseMap.h:899
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:811
void erase(iterator I)
Definition DenseMap.h:938
void reserve(size_type NumEntries)
Grow the DenseMap so that it can contain at least NumEntries items before resizing again.
Definition DenseMap.h:721
ValueT lookup_or(const_arg_type_t< KeyT > Val, U &&Default) const
Definition DenseMap.h:803
std::pair< iterator, bool > insert(BucketT &&KV)
Definition DenseMap.h:848
const_iterator find(const_arg_type_t< KeyT > Val) const
Definition DenseMap.h:769
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:874
iterator end()
Definition DenseMap.h:686
std::pair< iterator, bool > insert(const BucketT &KV)
Definition DenseMap.h:841
ValueT & operator[](const KeyT &Key)
Definition DenseMap.h:969
DenseMapBase(const InputIt &I, const InputIt &E)
Definition DenseMap.h:997
unsigned size() const
Definition DenseMap.h:717
std::pair< iterator, bool > emplace_or_assign(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:923
const_iterator begin() const
Definition DenseMap.h:689
DenseMapBase(unsigned NumElementsToReserve)
Create a DenseMap with an optional NumElementsToReserve to guarantee that this number of elements can...
Definition DenseMap.h:987
std::pair< iterator, bool > insert(std::pair< KeyT, ValueT > &&KV)
Definition DenseMap.h:834
bool erase(const KeyT &Val)
Definition DenseMap.h:930
DenseMapBase(llvm::from_range_t, const RangeT &Range)
Definition DenseMap.h:1003
const_iterator find_as(const LookupKeyT &Val) const
Definition DenseMap.h:785
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT > iterator
Definition DenseMap.h:678
unsigned size_type
Definition DenseMap.h:673
DenseMapBase(const DenseMapBase &other)
Definition DenseMap.h:992
std::pair< iterator, bool > insert_or_assign(KeyT &&Key, V &&Val)
Definition DenseMap.h:907
DenseMapBase & operator=(const DenseMapBase &other)
Definition DenseMap.h:1014
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:793
iterator find_as(const LookupKeyT &Val)
Alternate version of find() which allows a different, and possibly less expensive,...
Definition DenseMap.h:779
const_iterator end() const
Definition DenseMap.h:693
void swap(DenseMapBase &RHS)
Definition DenseMap.h:977
bool remove_if(Predicate Pred)
Remove entries that match the given predicate.
Definition DenseMap.h:946
DenseMapBase(std::initializer_list< value_type > Vals)
Definition DenseMap.h:1006
iterator begin()
Definition DenseMap.h:682
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:818
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:827
size_t getMemorySize() const
Return the approximate size (in bytes) of the actual map.
Definition DenseMap.h:1032
DenseMapBase(DenseMapBase &&other)
Definition DenseMap.h:994
DenseMapBase & operator=(DenseMapBase &&other)
Definition DenseMap.h:1020
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:856
auto values() const
Definition DenseMap.h:712
void shrink_and_clear()
Definition DenseMap.h:745
ValueT & operator[](KeyT &&Key)
Definition DenseMap.h:973
std::conditional_t< IsConst, const Bucket, Bucket > value_type
Definition DenseMap.h:530
friend bool operator!=(const DenseMapIterator &LHS, const DenseMapIterator &RHS)
Definition DenseMap.h:609
value_type * pointer
Definition DenseMap.h:531
DenseMapIterator & operator++()
Definition DenseMap.h:614
pointer operator->() const
Definition DenseMap.h:601
reference operator*() const
Definition DenseMap.h:596
DenseMapIterator operator++(int)
Definition DenseMap.h:621
DenseMapIterator(const DenseMapIterator< KeyT, ValueT, KeyInfoT, Bucket, IsConstSrc > &I)
Definition DenseMap.h:591
static DenseMapIterator makeIterator(pointer P, pointer Buckets, const UsedT *Used, unsigned NumBuckets, const DebugEpochBase &Epoch)
Definition DenseMap.h:577
ptrdiff_t difference_type
Definition DenseMap.h:529
friend bool operator==(const DenseMapIterator &LHS, const DenseMapIterator &RHS)
Definition DenseMap.h:603
std::forward_iterator_tag iterator_category
Definition DenseMap.h:533
static DenseMapIterator makeBegin(pointer Buckets, const UsedT *Used, unsigned NumBuckets, bool IsEmpty, const DebugEpochBase &Epoch)
Definition DenseMap.h:557
value_type & reference
Definition DenseMap.h:532
static DenseMapIterator makeEnd(pointer Buckets, const UsedT *Used, unsigned NumBuckets, const DebugEpochBase &Epoch)
Definition DenseMap.h:570
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:381
std::pair< bool, unsigned > planShrinkAndClear() const
Definition DenseMap.h:491
void grow(unsigned MinNumBuckets, BucketHasher Hasher)
Definition DenseMap.h:446
void swap(SmallDenseMapStorage &RHS)
Definition DenseMap.h:388
bool maybeMoveFast(SmallDenseMapStorage &&Other)
Definition DenseMap.h:505
static unsigned roundUpNumBuckets(unsigned MinNumBuckets)
Definition DenseMap.h:482
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
@ End
Run the machine verifier once, at the end of the pipeline.
Definition CodeGen.h:267
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