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
99
100// Number of used words backing N buckets where N is zero or a power of two.
101constexpr size_t usedWords(size_t N) {
102 assert((N == 0 || isPowerOf2_64(N)) &&
103 "bucket count must be zero or a power of two");
104 return (N + 31) / 32;
105}
106
107inline bool used(const UsedT *U, size_t I) {
108 return (U[I >> 5] >> (I & 31)) & 1;
109}
110inline void setUsed(UsedT *U, size_t I) { U[I >> 5] |= UsedT(1) << (I & 31); }
111inline void unsetUsed(UsedT *U, size_t I) {
112 U[I >> 5] &= ~(UsedT(1) << (I & 31));
113}
114
115// Invoke Func(I) for each occupied bucket index I in [0, N). Set always_inline;
116// otherwise, for a heavy caller such as moveFrom's rehash, the inliner can
117// leave it out of line and the per-element call dwarfs the work.
118template <typename Fn>
120 Fn Func) {
121 const unsigned NW = usedWords(N);
122 for (unsigned W = 0; W != NW; ++W) {
123 UsedT Bits = U[W];
124 while (Bits) {
125 Func((W << 5) + llvm::countr_zero(Bits));
126 Bits &= Bits - 1;
127 }
128 }
129}
130
131// Buckets and the used array share one allocation: the bucket array first, then
132// the used words. NumBuckets is a power of two >= 4, so the bucket region size
133// is a multiple of sizeof(UsedT) and the trailing used words are aligned.
134template <typename BucketT> constexpr size_t allocAlign() {
135 return std::max(alignof(BucketT), alignof(UsedT));
136}
137template <typename BucketT> size_t allocBytes(unsigned Num) {
138 return sizeof(BucketT) * static_cast<size_t>(Num) +
139 usedWords(Num) * sizeof(UsedT);
140}
141
142} // namespace densemap::detail
143
144// Befriended below so DenseMapBase can expose its bucket-relocation callback
145// erase to ValueHandleBase, the only caller that caches bucket pointers.
146class ValueHandleBase;
147
148template <typename KeyT, typename ValueT,
149 typename KeyInfoT = DenseMapInfo<KeyT>,
151 bool IsConst = false>
152class DenseMapIterator;
153
154template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
155 typename BucketT>
157 template <typename T>
158 using const_arg_type_t = typename const_pointer_or_const_ref<T>::type;
159
160 using UsedT = llvm::densemap::detail::UsedT;
161
162public:
164 using key_type = KeyT;
165 using mapped_type = ValueT;
166 using value_type = BucketT;
167
171
172 [[nodiscard]] inline iterator begin() {
173 return iterator::makeBegin(getBuckets(), getUsed(), getNumBuckets(),
174 empty(), *this);
175 }
176 [[nodiscard]] inline iterator end() {
177 return iterator::makeEnd(getBuckets(), getUsed(), getNumBuckets(), *this);
178 }
179 [[nodiscard]] inline const_iterator begin() const {
180 return const_iterator::makeBegin(getBuckets(), getUsed(), getNumBuckets(),
181 empty(), *this);
182 }
183 [[nodiscard]] inline const_iterator end() const {
184 return const_iterator::makeEnd(getBuckets(), getUsed(), getNumBuckets(),
185 *this);
186 }
187
188 // Return an iterator to iterate over keys in the map.
189 [[nodiscard]] inline auto keys() {
190 return map_range(*this, [](const BucketT &P) { return P.getFirst(); });
191 }
192
193 // Return an iterator to iterate over values in the map.
194 [[nodiscard]] inline auto values() {
195 return map_range(*this, [](const BucketT &P) { return P.getSecond(); });
196 }
197
198 [[nodiscard]] inline auto keys() const {
199 return map_range(*this, [](const BucketT &P) { return P.getFirst(); });
200 }
201
202 [[nodiscard]] inline auto values() const {
203 return map_range(*this, [](const BucketT &P) { return P.getSecond(); });
204 }
205
206 [[nodiscard]] bool empty() const { return getNumEntries() == 0; }
207 [[nodiscard]] unsigned size() const { return getNumEntries(); }
208
209 /// Grow the densemap so that it can contain at least \p NumEntries items
210 /// before resizing again.
211 void reserve(size_type NumEntries) {
212 auto NumBuckets = getMinBucketToReserveForEntries(NumEntries);
214 if (NumBuckets > getNumBuckets())
215 grow(NumBuckets);
216 }
217
218 void clear() {
220 if (getNumEntries() == 0)
221 return;
222
223 // If the capacity of the array is huge, and the # elements used is small,
224 // shrink the array.
225 if (getNumEntries() * 4 < getNumBuckets() && getNumBuckets() > 64) {
227 return;
228 }
229
230 destroyAll();
231 std::memset(getUsed(), 0,
232 llvm::densemap::detail::usedWords(getNumBuckets()) *
233 sizeof(UsedT));
234 setNumEntries(0);
235 }
236
238 auto [Reallocate, NewNumBuckets] = derived().planShrinkAndClear();
239 destroyAll();
240 if (!Reallocate) {
241 initEmpty();
242 return;
243 }
244 derived().deallocateBuckets();
245 initWithExactBucketCount(NewNumBuckets);
246 }
247
248 /// Return true if the specified key is in the map, false otherwise.
249 [[nodiscard]] bool contains(const_arg_type_t<KeyT> Val) const {
250 return doFind(Val) != nullptr;
251 }
252
253 /// Return 1 if the specified key is in the map, 0 otherwise.
254 [[nodiscard]] size_type count(const_arg_type_t<KeyT> Val) const {
255 return contains(Val) ? 1 : 0;
256 }
257
258 [[nodiscard]] iterator find(const_arg_type_t<KeyT> Val) {
259 return find_as(Val);
260 }
261 [[nodiscard]] const_iterator find(const_arg_type_t<KeyT> Val) const {
262 return find_as(Val);
263 }
264
265 /// Alternate version of find() which allows a different, and possibly
266 /// less expensive, key type.
267 /// The DenseMapInfo is responsible for supplying methods
268 /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key
269 /// type used.
270 template <class LookupKeyT>
271 [[nodiscard]] iterator find_as(const LookupKeyT &Val) {
272 if (BucketT *Bucket = doFind(Val))
273 return makeIterator(Bucket);
274 return end();
275 }
276 template <class LookupKeyT>
277 [[nodiscard]] const_iterator find_as(const LookupKeyT &Val) const {
278 if (const BucketT *Bucket = doFind(Val))
279 return makeConstIterator(Bucket);
280 return end();
281 }
282
283 /// Return the entry for the specified key, or a default constructed value if
284 /// no such entry exists.
285 [[nodiscard]] ValueT lookup(const_arg_type_t<KeyT> Val) const {
286 if (const BucketT *Bucket = doFind(Val))
287 return Bucket->getSecond();
288 return ValueT();
289 }
290
291 // Return the entry with the specified key, or \p Default. This variant is
292 // useful, because `lookup` cannot be used with non-default-constructible
293 // values.
294 template <typename U = std::remove_cv_t<ValueT>>
295 [[nodiscard]] ValueT lookup_or(const_arg_type_t<KeyT> Val,
296 U &&Default) const {
297 if (const BucketT *Bucket = doFind(Val))
298 return Bucket->getSecond();
299 return Default;
300 }
301
302 /// Return the entry for the specified key, or abort if no such entry exists.
303 [[nodiscard]] ValueT &at(const_arg_type_t<KeyT> Val) {
304 auto Iter = this->find(std::move(Val));
305 assert(Iter != this->end() && "DenseMap::at failed due to a missing key");
306 return Iter->second;
307 }
308
309 /// Return the entry for the specified key, or abort if no such entry exists.
310 [[nodiscard]] const ValueT &at(const_arg_type_t<KeyT> Val) const {
311 auto Iter = this->find(std::move(Val));
312 assert(Iter != this->end() && "DenseMap::at failed due to a missing key");
313 return Iter->second;
314 }
315
316 // Inserts key,value pair into the map if the key isn't already in the map.
317 // If the key is already in the map, it returns false and doesn't update the
318 // value.
319 std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) {
320 return try_emplace_impl(KV.first, KV.second);
321 }
322
323 // Inserts key,value pair into the map if the key isn't already in the map.
324 // If the key is already in the map, it returns false and doesn't update the
325 // value.
326 std::pair<iterator, bool> insert(std::pair<KeyT, ValueT> &&KV) {
327 return try_emplace_impl(std::move(KV.first), std::move(KV.second));
328 }
329
330 template <
331 typename B = BucketT,
332 typename = std::enable_if_t<!std::is_same_v<B, std::pair<KeyT, ValueT>>>>
333 std::pair<iterator, bool> insert(const BucketT &KV) {
334 return try_emplace_impl(KV.first, KV.second);
335 }
336
337 template <
338 typename B = BucketT,
339 typename = std::enable_if_t<!std::is_same_v<B, std::pair<KeyT, ValueT>>>>
340 std::pair<iterator, bool> insert(BucketT &&KV) {
341 return try_emplace_impl(std::move(KV.first), std::move(KV.second));
342 }
343
344 // Inserts key,value pair into the map if the key isn't already in the map.
345 // The value is constructed in-place if the key is not in the map, otherwise
346 // it is not moved.
347 template <typename... Ts>
348 std::pair<iterator, bool> try_emplace(KeyT &&Key, Ts &&...Args) {
349 return try_emplace_impl(std::move(Key), std::forward<Ts>(Args)...);
350 }
351
352 // Inserts key,value pair into the map if the key isn't already in the map.
353 // The value is constructed in-place if the key is not in the map, otherwise
354 // it is not moved.
355 template <typename... Ts>
356 std::pair<iterator, bool> try_emplace(const KeyT &Key, Ts &&...Args) {
357 return try_emplace_impl(Key, std::forward<Ts>(Args)...);
358 }
359
360 /// Alternate version of insert() which allows a different, and possibly
361 /// less expensive, key type.
362 /// The DenseMapInfo is responsible for supplying methods
363 /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key
364 /// type used.
365 template <typename LookupKeyT>
366 std::pair<iterator, bool> insert_as(std::pair<KeyT, ValueT> &&KV,
367 const LookupKeyT &Val) {
368 BucketT *TheBucket;
369 if (LookupBucketFor(Val, TheBucket))
370 return {makeIterator(TheBucket), false}; // Already in map.
371
372 // Otherwise, insert the new element.
373 TheBucket = findBucketForInsertion(Val, TheBucket);
374 ::new (&TheBucket->getFirst()) KeyT(std::move(KV.first));
375 ::new (&TheBucket->getSecond()) ValueT(std::move(KV.second));
376 return {makeIterator(TheBucket), true};
377 }
378
379 /// Range insertion of pairs.
380 template <typename InputIt> void insert(InputIt I, InputIt E) {
381 for (; I != E; ++I)
382 insert(*I);
383 }
384
385 /// Inserts range of 'std::pair<KeyT, ValueT>' values into the map.
386 template <typename Range> void insert_range(Range &&R) {
387 insert(adl_begin(R), adl_end(R));
388 }
389
390 template <typename V>
391 std::pair<iterator, bool> insert_or_assign(const KeyT &Key, V &&Val) {
392 auto Ret = try_emplace(Key, std::forward<V>(Val));
393 if (!Ret.second)
394 Ret.first->second = std::forward<V>(Val);
395 return Ret;
396 }
397
398 template <typename V>
399 std::pair<iterator, bool> insert_or_assign(KeyT &&Key, V &&Val) {
400 auto Ret = try_emplace(std::move(Key), std::forward<V>(Val));
401 if (!Ret.second)
402 Ret.first->second = std::forward<V>(Val);
403 return Ret;
404 }
405
406 template <typename... Ts>
407 std::pair<iterator, bool> emplace_or_assign(const KeyT &Key, Ts &&...Args) {
408 auto Ret = try_emplace(Key, std::forward<Ts>(Args)...);
409 if (!Ret.second)
410 Ret.first->second = ValueT(std::forward<Ts>(Args)...);
411 return Ret;
412 }
413
414 template <typename... Ts>
415 std::pair<iterator, bool> emplace_or_assign(KeyT &&Key, Ts &&...Args) {
416 auto Ret = try_emplace(std::move(Key), std::forward<Ts>(Args)...);
417 if (!Ret.second)
418 Ret.first->second = ValueT(std::forward<Ts>(Args)...);
419 return Ret;
420 }
421
422 void eraseFromFilledBucket(BucketT *TheBucket) {
423 eraseFromFilledBucket(TheBucket, [](BucketT &) {});
424 }
425
426 bool erase(const KeyT &Val) {
427 BucketT *TheBucket = doFind(Val);
428 if (!TheBucket)
429 return false; // not in map.
430
431 eraseFromFilledBucket(TheBucket);
432 return true;
433 }
435
436 /// Remove entries that match the given predicate. \p Pred is invoked
437 /// with a reference to each live bucket and must not access the map being
438 /// modified. This is the safe replacement for erase-while-iterating.
439 ///
440 /// Returns whether anything was removed. If so, all iterators and references
441 /// into the map are invalidated.
442 template <typename Predicate> bool remove_if(Predicate Pred) {
443 UsedT *U = getUsed();
444 unsigned NumBuckets = getNumBuckets();
445 BucketT *B = getBuckets();
446 bool Removed = false;
447 for (unsigned I = 0; I != NumBuckets; ++I) {
449 continue;
450 if (Pred(B[I])) {
451 B[I].getSecond().~ValueT();
452 B[I].getFirst().~KeyT();
454 decrementNumEntries();
455 Removed = true;
456 }
457 }
458 if (Removed) {
460 this->grow(NumBuckets);
461 }
462 return Removed;
463 }
464
465 ValueT &operator[](const KeyT &Key) {
466 return lookupOrInsertIntoBucket(Key).first->second;
467 }
468
469 ValueT &operator[](KeyT &&Key) {
470 return lookupOrInsertIntoBucket(std::move(Key)).first->second;
471 }
472
473 /// Return true if the specified pointer points somewhere into the DenseMap's
474 /// array of buckets (i.e. either to a key or value in the DenseMap).
475 [[nodiscard]] bool isPointerIntoBucketsArray(const void *Ptr) const {
476 return Ptr >= getBuckets() && Ptr < getBucketsEnd();
477 }
478
479 /// getPointerIntoBucketsArray() - Return an opaque pointer into the buckets
480 /// array. In conjunction with the previous method, this can be used to
481 /// determine whether an insertion caused the DenseMap to reallocate.
482 [[nodiscard]] const void *getPointerIntoBucketsArray() const {
483 return getBuckets();
484 }
485
486 void swap(DerivedT &RHS) {
487 this->incrementEpoch();
488 RHS.incrementEpoch();
489 derived().swapImpl(RHS);
490 }
491
492protected:
493 DenseMapBase() = default;
494
496
497 // A snapshot of the three fields the hot lookup paths need. Fetching them
498 // together lets SmallDenseMap test its Small discriminator once rather than
499 // once per accessor; for plain DenseMap it is three member loads either way.
500 struct Rep {
501 const BucketT *Buckets;
502 const UsedT *Used;
503 unsigned NumBuckets;
504 };
505
506 void initWithExactBucketCount(unsigned NewNumBuckets) {
507 if (derived().allocateBuckets(NewNumBuckets))
508 initEmpty();
509 else
510 setNumEntries(0);
511 }
512
513 void destroyAll() {
514 // No need to iterate through the buckets if the bucket is trivially
515 // destructible.
516 if constexpr (std::is_trivially_destructible_v<BucketT>)
517 return;
518
519 if (getNumBuckets() == 0) // Nothing to do.
520 return;
521
522 BucketT *B = getBuckets();
523 const UsedT *U = getUsed();
524 const unsigned E = getNumBuckets();
525 llvm::densemap::detail::forEachUsed(U, E, [&](unsigned I) {
526 B[I].getSecond().~ValueT();
527 B[I].getFirst().~KeyT();
528 });
529 }
530
531 void initEmpty() {
532 static_assert(std::is_base_of_v<DenseMapBase, DerivedT>,
533 "Must pass the derived type to this template!");
534 setNumEntries(0);
535
536 assert((getNumBuckets() & (getNumBuckets() - 1)) == 0 &&
537 "# initial buckets must be a power of two!");
538 if (getNumBuckets()) {
539 std::memset(getUsed(), 0,
540 llvm::densemap::detail::usedWords(getNumBuckets()) *
541 sizeof(UsedT));
542 }
543 }
544
545 /// Returns the number of buckets to allocate to ensure that the DenseMap can
546 /// accommodate \p NumEntries without need to grow().
547 unsigned getMinBucketToReserveForEntries(unsigned NumEntries) {
548 // Ensure that "NumEntries * 4 < NumBuckets * 3"
549 if (NumEntries == 0)
550 return 0;
551 // +1 is required because of the strict inequality.
552 // For example, if NumEntries is 48, we need to return 128.
553 return NextPowerOf2(NumEntries * 4 / 3 + 1);
554 }
555
556 // Move key/value from Other to *this.
557 // Other is left in a valid but empty state.
559 assert(getNumEntries() == 0 && "moveFrom requires an empty destination");
560 BucketT *OtherB = Other.getBuckets();
561 UsedT *OtherU = Other.getUsed();
562 const unsigned E = Other.getNumBuckets();
563 UsedT *U = getUsed();
564 BucketT *B = getBuckets();
565 const unsigned Mask = getNumBuckets() - 1;
566 llvm::densemap::detail::forEachUsed(OtherU, E, [&](unsigned I) {
567 // Find the first empty slot on this key's probe chain; there is no equal
568 // key in the destination, so nothing to compare against.
569 unsigned BucketNo = KeyInfoT::getHashValue(OtherB[I].getFirst()) & Mask;
570 while (llvm::densemap::detail::used(U, BucketNo))
571 BucketNo = (BucketNo + 1) & Mask;
572 BucketT *DestBucket = B + BucketNo;
573 ::new (&DestBucket->getFirst()) KeyT(std::move(OtherB[I].getFirst()));
574 ::new (&DestBucket->getSecond()) ValueT(std::move(OtherB[I].getSecond()));
576
577 // Free the moved-out key/value.
578 OtherB[I].getSecond().~ValueT();
579 OtherB[I].getFirst().~KeyT();
580 });
581 setNumEntries(Other.getNumEntries());
582 Other.derived().kill();
583 }
584
585 LLVM_ATTRIBUTE_NOINLINE void copyFrom(const DerivedT &other) {
586 this->destroyAll();
587 derived().deallocateBuckets();
588 setNumEntries(0);
589 if (!derived().allocateBuckets(other.getNumBuckets())) {
590 // The bucket list is empty. No work to do.
591 return;
592 }
593
594 assert(&other != this);
595 assert(getNumBuckets() == other.getNumBuckets());
596
597 setNumEntries(other.getNumEntries());
598
599 BucketT *Buckets = getBuckets();
600 const BucketT *OtherBuckets = other.getBuckets();
601 const unsigned NumBuckets = getNumBuckets();
602 UsedT *U = getUsed();
603 const UsedT *OtherU = other.getUsed();
604 std::memcpy(U, OtherU,
605 llvm::densemap::detail::usedWords(NumBuckets) * sizeof(UsedT));
607 memcpy(reinterpret_cast<void *>(Buckets), OtherBuckets,
608 NumBuckets * sizeof(BucketT));
609 } else {
610 llvm::densemap::detail::forEachUsed(U, NumBuckets, [&](unsigned I) {
611 ::new (&Buckets[I].getFirst()) KeyT(OtherBuckets[I].getFirst());
612 ::new (&Buckets[I].getSecond()) ValueT(OtherBuckets[I].getSecond());
613 });
614 }
615 }
616
617private:
618 // ValueHandleBase caches pointers into the bucket array, so it needs the
619 // callback erase below to fix them up as entries shift. It is the only
620 // intended caller; do not add new ones.
621 friend class ValueHandleBase;
622
623 /// Erase the entry at \p TheBucket and close the resulting hole via Knuth
624 /// TAOCP 6.4 Algorithm R. For callers that cache pointers into the bucket
625 /// array, call \p OnMoved per shifted bucket.
626 template <typename OnMovedT>
627 LLVM_ATTRIBUTE_NOINLINE void eraseFromFilledBucket(BucketT *TheBucket,
628 OnMovedT &&OnMoved) {
630 TheBucket->getSecond().~ValueT();
631 TheBucket->getFirst().~KeyT();
632 decrementNumEntries();
633
634 BucketT *BucketsPtr = getBuckets();
635 UsedT *U = getUsed();
636 const unsigned Mask = getNumBuckets() - 1;
637 unsigned I = TheBucket - BucketsPtr;
638 unsigned J = I;
639 while (true) {
640 J = (J + 1) & Mask;
641 BucketT &BJ = BucketsPtr[J];
643 break;
644 auto Ideal = KeyInfoT::getHashValue(BJ.getFirst());
645 // If the hole (I) lies on the linear-probe chain from the home bucket
646 // (Ideal) to J, shift J into the hole and make J the new hole.
647 if (((I - Ideal) & Mask) < ((J - Ideal) & Mask)) {
648 BucketT &BI = BucketsPtr[I];
649 ::new (&BI.getFirst()) KeyT(std::move(BJ.getFirst()));
650 ::new (&BI.getSecond()) ValueT(std::move(BJ.getSecond()));
651 BJ.getSecond().~ValueT();
652 BJ.getFirst().~KeyT();
653 OnMoved(BI);
654 I = J;
655 }
656 }
657 llvm::densemap::detail::unsetUsed(U, I);
658 }
659
660 /// Erase \p Val and close the resulting hole by potentially shifting other
661 /// entries into it. For callers that cache pointers into the bucket array,
662 /// call \p OnMoved per shifted bucket.
663 template <typename OnMovedT> bool erase(const KeyT &Val, OnMovedT &&OnMoved) {
664 BucketT *TheBucket = doFind(Val);
665 if (!TheBucket)
666 return false;
667 eraseFromFilledBucket(TheBucket, std::forward<OnMovedT>(OnMoved));
668 return true;
669 }
670
671 DerivedT &derived() { return *static_cast<DerivedT *>(this); }
672 const DerivedT &derived() const {
673 return *static_cast<const DerivedT *>(this);
674 }
675
676 template <typename KeyArgT, typename... Ts>
677 std::pair<BucketT *, bool> lookupOrInsertIntoBucket(KeyArgT &&Key,
678 Ts &&...Args) {
679 BucketT *TheBucket = nullptr;
680 if (LookupBucketFor(Key, TheBucket))
681 return {TheBucket, false}; // Already in the map.
682
683 // Otherwise, insert the new element.
684 TheBucket = findBucketForInsertion(Key, TheBucket);
685 ::new (&TheBucket->getFirst()) KeyT(std::forward<KeyArgT>(Key));
686 ::new (&TheBucket->getSecond()) ValueT(std::forward<Ts>(Args)...);
687 return {TheBucket, true};
688 }
689
690 template <typename KeyArgT, typename... Ts>
691 std::pair<iterator, bool> try_emplace_impl(KeyArgT &&Key, Ts &&...Args) {
692 auto [Bucket, Inserted] = lookupOrInsertIntoBucket(
693 std::forward<KeyArgT>(Key), std::forward<Ts>(Args)...);
694 return {makeIterator(Bucket), Inserted};
695 }
696
697 iterator makeIterator(BucketT *TheBucket) {
698 return iterator::makeIterator(TheBucket, getBuckets(), getUsed(),
699 getNumBuckets(), *this);
700 }
701
702 const_iterator makeConstIterator(const BucketT *TheBucket) const {
703 return const_iterator::makeIterator(TheBucket, getBuckets(), getUsed(),
704 getNumBuckets(), *this);
705 }
706
707 unsigned getNumEntries() const { return derived().getNumEntries(); }
708
709 void setNumEntries(unsigned Num) { derived().setNumEntries(Num); }
710
711 void incrementNumEntries() { setNumEntries(getNumEntries() + 1); }
712
713 void decrementNumEntries() { setNumEntries(getNumEntries() - 1); }
714
715 const BucketT *getBuckets() const { return derived().getBuckets(); }
716
717 BucketT *getBuckets() { return derived().getBuckets(); }
718
719 Rep getRep() const { return derived().getRep(); }
720
721 const UsedT *getUsed() const { return derived().getUsed(); }
722
723 UsedT *getUsed() { return derived().getUsed(); }
724
725 unsigned getNumBuckets() const { return derived().getNumBuckets(); }
726
727 BucketT *getBucketsEnd() { return getBuckets() + getNumBuckets(); }
728
729 const BucketT *getBucketsEnd() const {
730 return getBuckets() + getNumBuckets();
731 }
732
733 LLVM_ATTRIBUTE_NOINLINE void grow(unsigned MinNumBuckets) {
734 unsigned NumBuckets = DerivedT::roundUpNumBuckets(MinNumBuckets);
735 DerivedT Tmp(NumBuckets, ExactBucketCount{});
736 Tmp.moveFrom(derived());
737 if (derived().maybeMoveFast(std::move(Tmp)))
738 return;
739 initWithExactBucketCount(NumBuckets);
740 moveFrom(Tmp);
741 }
742
743 template <typename LookupKeyT>
744 BucketT *findBucketForInsertion(const LookupKeyT &Lookup,
745 BucketT *TheBucket) {
747
748 // Grow the table if the load factor would exceed 3/4 after insertion.
749 // Linear probing with gap-closing deletion (Knuth Algorithm R) keeps
750 // every chain compact and bounded by the table's empty-bucket count,
751 // so no tombstone-driven resize is needed.
752 unsigned NewNumEntries = getNumEntries() + 1;
753 unsigned NumBuckets = getNumBuckets();
754 if (LLVM_UNLIKELY(NewNumEntries * 4 >= NumBuckets * 3)) {
755 this->grow(NumBuckets * 2);
756 LookupBucketFor(Lookup, TheBucket);
757 }
758 assert(TheBucket);
759
760 // Mark used. The caller will placement-construct the raw key/value.
761 llvm::densemap::detail::setUsed(getUsed(), TheBucket - getBuckets());
762
763 // Only update the state after we've grown our bucket space appropriately
764 // so that when growing buckets we have self-consistent entry count.
765 incrementNumEntries();
766 return TheBucket;
767 }
768
769 template <typename LookupKeyT>
770 const BucketT *doFind(const LookupKeyT &Val) const {
771 if (empty())
772 return nullptr;
773 auto [BucketsPtr, U, NumBuckets] = getRep();
774
775 const unsigned Mask = NumBuckets - 1;
776 unsigned BucketNo = KeyInfoT::getHashValue(Val) & Mask;
777 while (true) {
778 // An empty bucket terminates the probe: the key isn't in the map.
779 if (LLVM_LIKELY(!llvm::densemap::detail::used(U, BucketNo)))
780 return nullptr;
781 const BucketT *Bucket = BucketsPtr + BucketNo;
782 if (LLVM_LIKELY(KeyInfoT::isEqual(Val, Bucket->getFirst())))
783 return Bucket;
784
785 // Hash collision: continue linear probing.
786 BucketNo = (BucketNo + 1) & Mask;
787 }
788 }
789
790 template <typename LookupKeyT> BucketT *doFind(const LookupKeyT &Val) {
791 return const_cast<BucketT *>(
792 static_cast<const DenseMapBase *>(this)->doFind(Val));
793 }
794
795 /// Lookup the appropriate bucket for Val, returning it in FoundBucket. If the
796 /// bucket contains the key and a value, this returns true, otherwise it
797 /// returns a bucket with an empty marker and returns false.
798 template <typename LookupKeyT>
799 bool LookupBucketFor(const LookupKeyT &Val, BucketT *&FoundBucket) {
800 auto [CBuckets, U, NumBuckets] = getRep();
801 if (NumBuckets == 0) {
802 FoundBucket = nullptr;
803 return false;
804 }
805 // getRep() yields const pointers; this object is non-const, so recovering
806 // a mutable bucket pointer is safe (mirrors the non-const getBuckets()).
807 BucketT *BucketsPtr = const_cast<BucketT *>(CBuckets);
808
809 const unsigned Mask = NumBuckets - 1;
810 unsigned BucketNo = KeyInfoT::getHashValue(Val) & Mask;
811 while (true) {
812 BucketT *ThisBucket = BucketsPtr + BucketNo;
813 // If we found an empty bucket, the key doesn't exist in the set.
814 // Return it as the insertion point.
815 if (LLVM_LIKELY(!llvm::densemap::detail::used(U, BucketNo))) {
816 FoundBucket = ThisBucket;
817 return false;
818 }
819
820 // Found Val's bucket? If so, return it.
821 if (LLVM_LIKELY(KeyInfoT::isEqual(Val, ThisBucket->getFirst()))) {
822 FoundBucket = ThisBucket;
823 return true;
824 }
825
826 // Hash collision: continue linear probing.
827 BucketNo = (BucketNo + 1) & Mask;
828 }
829 }
830
831public:
832 /// Return the approximate size (in bytes) of the actual map.
833 /// This is just the raw memory used by DenseMap.
834 /// If entries are pointers to objects, the size of the referenced objects
835 /// are not included.
836 [[nodiscard]] size_t getMemorySize() const {
837 return llvm::densemap::detail::allocBytes<BucketT>(getNumBuckets());
838 }
839};
840
841/// Equality comparison for DenseMap.
842///
843/// Iterates over elements of LHS confirming that each (key, value) pair in LHS
844/// is also in RHS, and that no additional pairs are in RHS.
845/// Equivalent to N calls to RHS.find and N value comparisons. Amortized
846/// complexity is linear, worst case is O(N^2) (if every hash collides).
847template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
848 typename BucketT>
849[[nodiscard]] bool
852 if (LHS.size() != RHS.size())
853 return false;
854
855 for (auto &KV : LHS) {
856 auto I = RHS.find(KV.first);
857 if (I == RHS.end() || I->second != KV.second)
858 return false;
859 }
860
861 return true;
862}
863
864/// Inequality comparison for DenseMap.
865///
866/// Equivalent to !(LHS == RHS). See operator== for performance notes.
867template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
868 typename BucketT>
869[[nodiscard]] bool
874
875template <typename KeyT, typename ValueT,
876 typename KeyInfoT = DenseMapInfo<KeyT>,
878class DenseMap : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>,
879 KeyT, ValueT, KeyInfoT, BucketT> {
880 friend class DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT>;
881
882 // Lift some types from the dependent base class into this class for
883 // simplicity of referring to them.
885 using UsedT = llvm::densemap::detail::UsedT;
886
887 BucketT *Buckets = nullptr;
888 UsedT *Used = nullptr;
889 unsigned NumEntries = 0;
890 unsigned NumBuckets = 0;
891
892 explicit DenseMap(unsigned NumBuckets, typename BaseT::ExactBucketCount) {
893 this->initWithExactBucketCount(NumBuckets);
894 }
895
896public:
897 /// Create a DenseMap with an optional \p NumElementsToReserve to guarantee
898 /// that this number of elements can be inserted in the map without grow().
899 explicit DenseMap(unsigned NumElementsToReserve = 0)
900 : DenseMap(BaseT::getMinBucketToReserveForEntries(NumElementsToReserve),
901 typename BaseT::ExactBucketCount{}) {}
902
903 DenseMap(const DenseMap &other) : DenseMap() { this->copyFrom(other); }
904
905 DenseMap(DenseMap &&other) : DenseMap() { this->swap(other); }
906
907 template <typename InputIt>
908 DenseMap(const InputIt &I, const InputIt &E) : DenseMap(std::distance(I, E)) {
909 this->insert(I, E);
910 }
911
912 template <typename RangeT>
914 : DenseMap(adl_begin(Range), adl_end(Range)) {}
915
916 DenseMap(std::initializer_list<typename BaseT::value_type> Vals)
917 : DenseMap(Vals.begin(), Vals.end()) {}
918
920 this->destroyAll();
921 deallocateBuckets();
922 }
923
924 DenseMap &operator=(const DenseMap &other) {
925 if (&other != this)
926 this->copyFrom(other);
927 return *this;
928 }
929
930 DenseMap &operator=(DenseMap &&other) {
931 this->destroyAll();
932 deallocateBuckets();
933 this->initWithExactBucketCount(0);
934 this->swap(other);
935 return *this;
936 }
937
938private:
939 void swapImpl(DenseMap &RHS) {
940 std::swap(Buckets, RHS.Buckets);
941 std::swap(Used, RHS.Used);
942 std::swap(NumEntries, RHS.NumEntries);
943 std::swap(NumBuckets, RHS.NumBuckets);
944 }
945
946 unsigned getNumEntries() const { return NumEntries; }
947
948 void setNumEntries(unsigned Num) { NumEntries = Num; }
949
950 BucketT *getBuckets() const { return Buckets; }
951
952 typename BaseT::Rep getRep() const { return {Buckets, Used, NumBuckets}; }
953
954 UsedT *getUsed() const { return Used; }
955
956 unsigned getNumBuckets() const { return NumBuckets; }
957
958 void deallocateBuckets() {
959 if (NumBuckets == 0)
960 return;
961 deallocate_buffer(Buckets,
964 Buckets = nullptr;
965 Used = nullptr;
966 NumBuckets = 0;
967 }
968
969 bool allocateBuckets(unsigned Num) {
970 NumBuckets = Num;
971 if (NumBuckets == 0) {
972 Buckets = nullptr;
973 Used = nullptr;
974 return false;
975 }
976
977 auto *Storage = static_cast<char *>(
980 Buckets = reinterpret_cast<BucketT *>(Storage);
981 // NumBuckets is a power of two >= 4 (getMinBucketToReserveForEntries(1) is
982 // 4), so the used array trailing the buckets is aligned.
983 assert(sizeof(BucketT) * NumBuckets % alignof(UsedT) == 0 &&
984 "used array would be misaligned");
985 Used = reinterpret_cast<UsedT *>(Storage + sizeof(BucketT) * NumBuckets);
986 return true;
987 }
988
989 // Put the zombie instance in a known good state after a move.
990 // deallocateBuckets() already resets to the empty state.
991 void kill() { deallocateBuckets(); }
992
993 static unsigned roundUpNumBuckets(unsigned MinNumBuckets) {
994 return std::max(64u,
995 static_cast<unsigned>(NextPowerOf2(MinNumBuckets - 1)));
996 }
997
998 bool maybeMoveFast(DenseMap &&Other) {
999 swapImpl(Other);
1000 return true;
1001 }
1002
1003 // Plan how to shrink the bucket table. Return:
1004 // - {false, 0} to reuse the existing bucket table
1005 // - {true, N} to reallocate a bucket table with N entries
1006 std::pair<bool, unsigned> planShrinkAndClear() const {
1007 unsigned NewNumBuckets = 0;
1008 if (NumEntries)
1009 NewNumBuckets = std::max(64u, 1u << (Log2_32_Ceil(NumEntries) + 1));
1010 if (NewNumBuckets == NumBuckets)
1011 return {false, 0}; // Reuse.
1012 return {true, NewNumBuckets}; // Reallocate.
1013 }
1014};
1015
1016template <typename KeyT, typename ValueT, unsigned InlineBuckets = 4,
1017 typename KeyInfoT = DenseMapInfo<KeyT>,
1019class SmallDenseMap
1020 : public DenseMapBase<
1021 SmallDenseMap<KeyT, ValueT, InlineBuckets, KeyInfoT, BucketT>, KeyT,
1022 ValueT, KeyInfoT, BucketT> {
1023 friend class DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT, BucketT>;
1024
1025 // Lift some types from the dependent base class into this class for
1026 // simplicity of referring to them.
1028 using UsedT = llvm::densemap::detail::UsedT;
1029
1030 static_assert(isPowerOf2_64(InlineBuckets),
1031 "InlineBuckets must be a power of 2.");
1032
1033 // Number of used words backing the inline buckets (>= 1).
1034 static constexpr unsigned InlineUsedWords =
1035 llvm::densemap::detail::usedWords(InlineBuckets);
1036
1037 unsigned Small : 1;
1038 unsigned NumEntries : 31;
1039
1040 // Inline storage: the bucket array followed by the parallel used words.
1041 struct InlineRep {
1042 alignas(BucketT) char Buckets[sizeof(BucketT) * InlineBuckets];
1043 UsedT Used[InlineUsedWords];
1044 };
1045 struct LargeRep {
1046 BucketT *Buckets;
1047 UsedT *Used;
1048 unsigned NumBuckets;
1049 };
1050
1051 // Discriminated by the Small bit.
1052 union {
1053 InlineRep Inline;
1054 LargeRep Large;
1055 } storage;
1056
1057 SmallDenseMap(unsigned NumBuckets, typename BaseT::ExactBucketCount) {
1058 this->initWithExactBucketCount(NumBuckets);
1059 }
1060
1061public:
1062 explicit SmallDenseMap(unsigned NumElementsToReserve = 0)
1063 : SmallDenseMap(
1064 BaseT::getMinBucketToReserveForEntries(NumElementsToReserve),
1065 typename BaseT::ExactBucketCount{}) {}
1066
1067 SmallDenseMap(const SmallDenseMap &other) : SmallDenseMap() {
1068 this->copyFrom(other);
1069 }
1070
1071 SmallDenseMap(SmallDenseMap &&other) : SmallDenseMap() { this->swap(other); }
1072
1073 template <typename InputIt>
1074 SmallDenseMap(const InputIt &I, const InputIt &E)
1075 : SmallDenseMap(std::distance(I, E)) {
1076 this->insert(I, E);
1077 }
1078
1079 template <typename RangeT>
1081 : SmallDenseMap(adl_begin(Range), adl_end(Range)) {}
1082
1083 SmallDenseMap(std::initializer_list<typename BaseT::value_type> Vals)
1084 : SmallDenseMap(Vals.begin(), Vals.end()) {}
1085
1087 this->destroyAll();
1088 deallocateBuckets();
1089 }
1090
1091 SmallDenseMap &operator=(const SmallDenseMap &other) {
1092 if (&other != this)
1093 this->copyFrom(other);
1094 return *this;
1095 }
1096
1097 SmallDenseMap &operator=(SmallDenseMap &&other) {
1098 this->destroyAll();
1099 deallocateBuckets();
1100 this->initWithExactBucketCount(0);
1101 this->swap(other);
1102 return *this;
1103 }
1104
1105private:
1106 // Move-construct *Dst from *Src, then destroy *Src. Dst is raw storage.
1107 static void relocateBucket(BucketT *Dst, BucketT *Src) {
1108 ::new (&Dst->getFirst()) KeyT(std::move(Src->getFirst()));
1109 ::new (&Dst->getSecond()) ValueT(std::move(Src->getSecond()));
1110 Src->getSecond().~ValueT();
1111 Src->getFirst().~KeyT();
1112 }
1113
1114 void swapImpl(SmallDenseMap &RHS) {
1115 unsigned TmpNumEntries = RHS.NumEntries;
1116 RHS.NumEntries = NumEntries;
1117 NumEntries = TmpNumEntries;
1118
1119 if (Small && RHS.Small) {
1120 // Both inline: swap the live bucket contents slot by slot, then the used
1121 // used words. Buckets are raw storage, so a value may only move in one
1122 // direction when exactly one side is occupied.
1123 UsedT *LU = getInlineUsed(), *RU = RHS.getInlineUsed();
1124 BucketT *LB = getInlineBuckets(), *RB = RHS.getInlineBuckets();
1125 for (unsigned I = 0; I != InlineBuckets; ++I) {
1126 bool L = llvm::densemap::detail::used(LU, I);
1127 bool R = llvm::densemap::detail::used(RU, I);
1128 if (L && R) {
1129 // Both occupied: exchange through a temporary.
1130 alignas(BucketT) char Tmp[sizeof(BucketT)];
1131 BucketT *T = reinterpret_cast<BucketT *>(Tmp);
1132 relocateBucket(T, &LB[I]);
1133 relocateBucket(&LB[I], &RB[I]);
1134 relocateBucket(&RB[I], T);
1135 } else if (L) {
1136 relocateBucket(&RB[I], &LB[I]);
1137 } else if (R) {
1138 relocateBucket(&LB[I], &RB[I]);
1139 }
1140 }
1141 for (unsigned W = 0; W != InlineUsedWords; ++W)
1142 std::swap(LU[W], RU[W]);
1143 return;
1144 }
1145 if (!Small && !RHS.Small) {
1146 std::swap(storage.Large, RHS.storage.Large);
1147 return;
1148 }
1149
1150 SmallDenseMap &SmallSide = Small ? *this : RHS;
1151 SmallDenseMap &LargeSide = Small ? RHS : *this;
1152
1153 // Stash the large rep, then move the small side's inline contents into the
1154 // large side (which becomes inline), and finally install the rep on the
1155 // small side (which becomes large).
1156 LargeRep TmpRep = LargeSide.storage.Large;
1157 LargeSide.Small = true;
1158 {
1159 UsedT *SU = SmallSide.getInlineUsed(), *LU = LargeSide.getInlineUsed();
1160 BucketT *SB = SmallSide.getInlineBuckets(),
1161 *LB = LargeSide.getInlineBuckets();
1162 for (unsigned I = 0; I != InlineBuckets; ++I)
1164 relocateBucket(&LB[I], &SB[I]);
1165 for (unsigned W = 0; W != InlineUsedWords; ++W)
1166 LU[W] = SU[W];
1167 }
1168 SmallSide.Small = false;
1169 SmallSide.storage.Large = TmpRep;
1170 }
1171
1172 unsigned getNumEntries() const { return NumEntries; }
1173
1174 void setNumEntries(unsigned Num) {
1175 // NumEntries is hardcoded to be 31 bits wide.
1176 assert(Num < (1U << 31) && "Cannot support more than 1<<31 entries");
1177 NumEntries = Num;
1178 }
1179
1180 const BucketT *getInlineBuckets() const {
1181 assert(Small);
1182 // Note that this cast does not violate aliasing rules as we assert that
1183 // the memory's dynamic type is the small, inline bucket buffer, and the
1184 // 'storage' is a POD containing a char buffer.
1185 return reinterpret_cast<const BucketT *>(storage.Inline.Buckets);
1186 }
1187
1188 BucketT *getInlineBuckets() {
1189 assert(Small);
1190 return reinterpret_cast<BucketT *>(storage.Inline.Buckets);
1191 }
1192
1193 const UsedT *getInlineUsed() const {
1194 assert(Small);
1195 return storage.Inline.Used;
1196 }
1197
1198 UsedT *getInlineUsed() {
1199 assert(Small);
1200 return storage.Inline.Used;
1201 }
1202
1203 const BucketT *getBuckets() const {
1204 return Small ? getInlineBuckets() : storage.Large.Buckets;
1205 }
1206
1207 typename BaseT::Rep getRep() const {
1208 if (Small)
1209 return {getInlineBuckets(), getInlineUsed(), InlineBuckets};
1210 return {storage.Large.Buckets, storage.Large.Used,
1211 storage.Large.NumBuckets};
1212 }
1213
1214 BucketT *getBuckets() {
1215 return const_cast<BucketT *>(
1216 const_cast<const SmallDenseMap *>(this)->getBuckets());
1217 }
1218
1219 const UsedT *getUsed() const {
1220 return Small ? getInlineUsed() : storage.Large.Used;
1221 }
1222
1223 UsedT *getUsed() {
1224 return const_cast<UsedT *>(
1225 const_cast<const SmallDenseMap *>(this)->getUsed());
1226 }
1227
1228 unsigned getNumBuckets() const {
1229 return Small ? InlineBuckets : storage.Large.NumBuckets;
1230 }
1231
1232 void deallocateBuckets() {
1233 // Fast path in case storage.Large.NumBuckets == 0, just like destroyAll.
1234 // This path is used to destruct zombie instances after moves.
1235 if (Small || storage.Large.NumBuckets == 0)
1236 return;
1237
1239 storage.Large.Buckets,
1240 llvm::densemap::detail::allocBytes<BucketT>(storage.Large.NumBuckets),
1242 storage.Large.NumBuckets = 0;
1243 }
1244
1245 bool allocateBuckets(unsigned Num) {
1246 if (Num <= InlineBuckets) {
1247 Small = true;
1248 return true;
1249 }
1250 Small = false;
1251 auto *S = static_cast<char *>(
1254 storage.Large.Buckets = reinterpret_cast<BucketT *>(S);
1255 storage.Large.Used = reinterpret_cast<UsedT *>(S + sizeof(BucketT) * Num);
1256 storage.Large.NumBuckets = Num;
1257 return true;
1258 }
1259
1260 // Put the zombie instance in a known good state after a move.
1261 void kill() {
1262 deallocateBuckets();
1263 Small = false;
1264 storage.Large = LargeRep{nullptr, nullptr, 0};
1265 }
1266
1267 static unsigned roundUpNumBuckets(unsigned MinNumBuckets) {
1268 if (MinNumBuckets <= InlineBuckets)
1269 return InlineBuckets;
1270 return std::max(64u,
1271 static_cast<unsigned>(NextPowerOf2(MinNumBuckets - 1)));
1272 }
1273
1274 bool maybeMoveFast(SmallDenseMap &&Other) {
1275 if (Other.Small)
1276 return false;
1277
1278 Small = false;
1279 NumEntries = Other.NumEntries;
1280 storage.Large = Other.storage.Large;
1281 Other.storage.Large.NumBuckets = 0;
1282 return true;
1283 }
1284
1285 // Plan how to shrink the bucket table. Return:
1286 // - {false, 0} to reuse the existing bucket table
1287 // - {true, N} to reallocate a bucket table with N entries
1288 std::pair<bool, unsigned> planShrinkAndClear() const {
1289 unsigned NewNumBuckets = 0;
1290 if (!this->empty()) {
1291 NewNumBuckets = 1u << (Log2_32_Ceil(this->size()) + 1);
1292 if (NewNumBuckets > InlineBuckets)
1293 NewNumBuckets = std::max(64u, NewNumBuckets);
1294 }
1295 bool Reuse = Small ? NewNumBuckets <= InlineBuckets
1296 : NewNumBuckets == storage.Large.NumBuckets;
1297 if (Reuse)
1298 return {false, 0}; // Reuse.
1299 return {true, NewNumBuckets}; // Reallocate.
1300 }
1301};
1302
1303template <typename KeyT, typename ValueT, typename KeyInfoT, typename Bucket,
1304 bool IsConst>
1305class DenseMapIterator : DebugEpochBase::HandleBase {
1306 friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true>;
1307 friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, false>;
1308
1309 using UsedT = llvm::densemap::detail::UsedT;
1310
1311public:
1313 using value_type = std::conditional_t<IsConst, const Bucket, Bucket>;
1316 using iterator_category = std::forward_iterator_tag;
1317
1318private:
1319 using BucketItTy =
1320 std::conditional_t<shouldReverseIterate<KeyT>(),
1321 std::reverse_iterator<pointer>, pointer>;
1322
1323 BucketItTy Ptr = {};
1324 BucketItTy End = {};
1325 // The non-reversed bucket base and the parallel used array. They map a
1326 // bucket back to its index so AdvancePastEmptyBuckets can consult the bits.
1327 pointer Buckets = {};
1328 const UsedT *Used = {};
1329
1330 DenseMapIterator(BucketItTy Pos, BucketItTy E, pointer BucketsBase,
1331 const UsedT *U, const DebugEpochBase &Epoch)
1332 : DebugEpochBase::HandleBase(&Epoch), Ptr(Pos), End(E),
1333 Buckets(BucketsBase), Used(U) {
1334 assert(isHandleInSync() && "invalid construction!");
1335 }
1336
1337public:
1338 DenseMapIterator() = default;
1339
1340 static DenseMapIterator makeBegin(pointer Buckets, const UsedT *Used,
1341 unsigned NumBuckets, bool IsEmpty,
1342 const DebugEpochBase &Epoch) {
1343 // When the map is empty, avoid the overhead of advancing/retreating past
1344 // empty buckets.
1345 if (IsEmpty)
1346 return makeEnd(Buckets, Used, NumBuckets, Epoch);
1347 auto R = maybeReverse(llvm::make_range(Buckets, Buckets + NumBuckets));
1348 DenseMapIterator Iter(R.begin(), R.end(), Buckets, Used, Epoch);
1349 Iter.AdvancePastEmptyBuckets();
1350 return Iter;
1351 }
1352
1353 static DenseMapIterator makeEnd(pointer Buckets, const UsedT *Used,
1354 unsigned NumBuckets,
1355 const DebugEpochBase &Epoch) {
1356 auto R = maybeReverse(llvm::make_range(Buckets, Buckets + NumBuckets));
1357 return DenseMapIterator(R.end(), R.end(), Buckets, Used, Epoch);
1358 }
1359
1360 static DenseMapIterator makeIterator(pointer P, pointer Buckets,
1361 const UsedT *Used, unsigned NumBuckets,
1362 const DebugEpochBase &Epoch) {
1363 auto R = maybeReverse(llvm::make_range(Buckets, Buckets + NumBuckets));
1364 constexpr int Offset = shouldReverseIterate<KeyT>() ? 1 : 0;
1365 return DenseMapIterator(BucketItTy(P + Offset), R.end(), Buckets, Used,
1366 Epoch);
1367 }
1368
1369 // Converting ctor from non-const iterators to const iterators. SFINAE'd out
1370 // for const iterator destinations so it doesn't end up as a user defined copy
1371 // constructor.
1372 template <bool IsConstSrc,
1373 typename = std::enable_if_t<!IsConstSrc && IsConst>>
1375 const DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, IsConstSrc> &I)
1376 : DebugEpochBase::HandleBase(I), Ptr(I.Ptr), End(I.End),
1377 Buckets(I.Buckets), Used(I.Used) {}
1378
1379 [[nodiscard]] reference operator*() const {
1380 assert(isHandleInSync() && "invalid iterator access!");
1381 assert(Ptr != End && "dereferencing end() iterator");
1382 return *Ptr;
1383 }
1384 [[nodiscard]] pointer operator->() const { return &operator*(); }
1385
1386 [[nodiscard]] friend bool operator==(const DenseMapIterator &LHS,
1387 const DenseMapIterator &RHS) {
1388 assert(LHS.isComparableWith(RHS) && "incomparable iterators!");
1389 return LHS.Ptr == RHS.Ptr;
1390 }
1391
1392 [[nodiscard]] friend bool operator!=(const DenseMapIterator &LHS,
1393 const DenseMapIterator &RHS) {
1394 return !(LHS == RHS);
1395 }
1396
1397 inline DenseMapIterator &operator++() { // Preincrement
1398 assert(isHandleInSync() && "invalid iterator access!");
1399 assert(Ptr != End && "incrementing end() iterator");
1400 ++Ptr;
1401 AdvancePastEmptyBuckets();
1402 return *this;
1403 }
1404 DenseMapIterator operator++(int) { // Postincrement
1405 assert(isHandleInSync() && "invalid iterator access!");
1406 DenseMapIterator tmp = *this;
1407 ++*this;
1408 return tmp;
1409 }
1410
1411private:
1412 void AdvancePastEmptyBuckets() {
1413 if constexpr (shouldReverseIterate<KeyT>()) {
1414 while (Ptr != End && !llvm::densemap::detail::used(Used, &*Ptr - Buckets))
1415 ++Ptr;
1416 } else {
1417 // Forward iteration skips empty buckets a used-word (32 buckets) at a
1418 // time: scan from the current index for the next set occupancy bit.
1419 const size_t N = End - Buckets;
1420 size_t I = Ptr - Buckets;
1421 if (I >= N) {
1422 Ptr = End;
1423 return;
1424 }
1425 const size_t NW = llvm::densemap::detail::usedWords(N);
1426 size_t W = I >> 5;
1427 UsedT Bits = Used[W] & (~UsedT(0) << (I & 31));
1428 while (Bits == 0) {
1429 if (++W == NW) {
1430 Ptr = End;
1431 return;
1432 }
1433 Bits = Used[W];
1434 }
1435 Ptr = Buckets + ((W << 5) + llvm::countr_zero(Bits));
1436 }
1437 }
1438
1439 static auto maybeReverse(iterator_range<pointer> Range) {
1440 if constexpr (shouldReverseIterate<KeyT>())
1441 return reverse(Range);
1442 else
1443 return Range;
1444 }
1445};
1446
1447template <typename KeyT, typename ValueT, typename KeyInfoT>
1448[[nodiscard]] inline size_t
1450 return X.getMemorySize();
1451}
1452
1453} // end namespace llvm
1454
1455#endif // LLVM_ADT_DENSEMAP_H
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
aarch64 promote const
#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:344
#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:364
#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:354
#define LLVM_LIKELY(EXPR)
Definition Compiler.h:343
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'.
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 unsigned getMinBucketToReserveForEntries(unsigned NumEntries)
Returns the number of buckets to allocate to ensure that the DenseMap can accommodate NumEntries with...
Definition StringMap.cpp:21
static int Lookup(ArrayRef< TableEntry > Table, unsigned Opcode)
Value * RHS
Value * LHS
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:303
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:285
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:258
unsigned size_type
Definition DenseMap.h:163
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:348
std::pair< iterator, bool > insert(std::pair< KeyT, ValueT > &&KV)
Definition DenseMap.h:326
bool erase(const KeyT &Val)
Definition DenseMap.h:426
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT > iterator
Definition DenseMap.h:168
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:366
DenseMapBase()=default
const_iterator find_as(const LookupKeyT &Val) const
Definition DenseMap.h:277
const_iterator end() const
Definition DenseMap.h:183
iterator find_as(const LookupKeyT &Val)
Alternate version of find() which allows a different, and possibly less expensive,...
Definition DenseMap.h:271
unsigned size() const
Definition DenseMap.h:207
const_iterator find(const_arg_type_t< KeyT > Val) const
Definition DenseMap.h:261
bool empty() const
Definition DenseMap.h:206
std::pair< iterator, bool > emplace_or_assign(const KeyT &Key, Ts &&...Args)
Definition DenseMap.h:407
void insert(InputIt I, InputIt E)
Range insertion of pairs.
Definition DenseMap.h:380
iterator begin()
Definition DenseMap.h:172
LLVM_ATTRIBUTE_NOINLINE void copyFrom(const DerivedT &other)
Definition DenseMap.h:585
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:254
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT, true > const_iterator
Definition DenseMap.h:169
bool remove_if(Predicate Pred)
Remove entries that match the given predicate.
Definition DenseMap.h:442
LLVM_ATTRIBUTE_NOINLINE void moveFrom(DerivedT &Other)
Definition DenseMap.h:558
iterator end()
Definition DenseMap.h:176
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:310
bool isPointerIntoBucketsArray(const void *Ptr) const
Return true if the specified pointer points somewhere into the DenseMap's array of buckets (i....
Definition DenseMap.h:475
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
Definition DenseMap.h:249
std::pair< iterator, bool > try_emplace(const KeyT &Key, Ts &&...Args)
Definition DenseMap.h:356
std::pair< iterator, bool > insert(const BucketT &KV)
Definition DenseMap.h:333
const_iterator begin() const
Definition DenseMap.h:179
std::pair< iterator, bool > emplace_or_assign(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:415
void insert_range(Range &&R)
Inserts range of 'std::pair<KeyT, ValueT>' values into the map.
Definition DenseMap.h:386
const void * getPointerIntoBucketsArray() const
getPointerIntoBucketsArray() - Return an opaque pointer into the buckets array.
Definition DenseMap.h:482
std::pair< iterator, bool > insert_or_assign(KeyT &&Key, V &&Val)
Definition DenseMap.h:399
ValueT lookup_or(const_arg_type_t< KeyT > Val, U &&Default) const
Definition DenseMap.h:295
unsigned getMinBucketToReserveForEntries(unsigned NumEntries)
Returns the number of buckets to allocate to ensure that the DenseMap can accommodate NumEntries with...
Definition DenseMap.h:547
void swap(DerivedT &RHS)
Definition DenseMap.h:486
ValueT & operator[](const KeyT &Key)
Definition DenseMap.h:465
auto keys() const
Definition DenseMap.h:198
void initWithExactBucketCount(unsigned NewNumBuckets)
Definition DenseMap.h:506
void eraseFromFilledBucket(BucketT *TheBucket)
Definition DenseMap.h:422
void shrink_and_clear()
Definition DenseMap.h:237
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:319
std::pair< iterator, bool > insert(BucketT &&KV)
Definition DenseMap.h:340
void erase(iterator I)
Definition DenseMap.h:434
std::pair< iterator, bool > insert_or_assign(const KeyT &Key, V &&Val)
Definition DenseMap.h:391
void reserve(size_type NumEntries)
Grow the densemap so that it can contain at least NumEntries items before resizing again.
Definition DenseMap.h:211
ValueT & operator[](KeyT &&Key)
Definition DenseMap.h:469
auto values() const
Definition DenseMap.h:202
size_t getMemorySize() const
Return the approximate size (in bytes) of the actual map.
Definition DenseMap.h:836
std::conditional_t< IsConst, const BucketT, BucketT > value_type
Definition DenseMap.h:1313
friend bool operator!=(const DenseMapIterator &LHS, const DenseMapIterator &RHS)
Definition DenseMap.h:1392
DenseMapIterator & operator++()
Definition DenseMap.h:1397
pointer operator->() const
Definition DenseMap.h:1384
reference operator*() const
Definition DenseMap.h:1379
DenseMapIterator operator++(int)
Definition DenseMap.h:1404
DenseMapIterator(const DenseMapIterator< KeyT, ValueT, KeyInfoT, Bucket, IsConstSrc > &I)
Definition DenseMap.h:1374
static DenseMapIterator makeIterator(pointer P, pointer Buckets, const UsedT *Used, unsigned NumBuckets, const DebugEpochBase &Epoch)
Definition DenseMap.h:1360
friend bool operator==(const DenseMapIterator &LHS, const DenseMapIterator &RHS)
Definition DenseMap.h:1386
static DenseMapIterator makeBegin(pointer Buckets, const UsedT *Used, unsigned NumBuckets, bool IsEmpty, const DebugEpochBase &Epoch)
Definition DenseMap.h:1340
static DenseMapIterator makeEnd(pointer Buckets, const UsedT *Used, unsigned NumBuckets, const DebugEpochBase &Epoch)
Definition DenseMap.h:1353
DenseMap(std::initializer_list< typename BaseT::value_type > Vals)
Definition DenseMap.h:916
DenseMap(unsigned NumElementsToReserve=0)
Create a DenseMap with an optional NumElementsToReserve to guarantee that this number of elements can...
Definition DenseMap.h:899
DenseMap & operator=(DenseMap &&other)
Definition DenseMap.h:930
DenseMap(llvm::from_range_t, const RangeT &Range)
Definition DenseMap.h:913
DenseMap(const DenseMap &other)
Definition DenseMap.h:903
DenseMap(const InputIt &I, const InputIt &E)
Definition DenseMap.h:908
DenseMap(DenseMap &&other)
Definition DenseMap.h:905
DenseMap & operator=(const DenseMap &other)
Definition DenseMap.h:924
SmallDenseMap(const InputIt &I, const InputIt &E)
Definition DenseMap.h:1074
SmallDenseMap & operator=(SmallDenseMap &&other)
Definition DenseMap.h:1097
SmallDenseMap & operator=(const SmallDenseMap &other)
Definition DenseMap.h:1091
SmallDenseMap(unsigned NumElementsToReserve=0)
Definition DenseMap.h:1062
SmallDenseMap(std::initializer_list< typename BaseT::value_type > Vals)
Definition DenseMap.h:1083
SmallDenseMap(SmallDenseMap &&other)
Definition DenseMap.h:1071
SmallDenseMap(const SmallDenseMap &other)
Definition DenseMap.h:1067
SmallDenseMap(llvm::from_range_t, const RangeT &Range)
Definition DenseMap.h:1080
This is the common base class of value handles.
Definition ValueHandle.h:30
LLVM Value Representation.
Definition Value.h:75
constexpr char IsConst[]
Key for Kernel::Arg::Metadata::mIsConst.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
void setUsed(UsedT *U, size_t I)
Definition DenseMap.h:110
constexpr size_t usedWords(size_t N)
Definition DenseMap.h:101
LLVM_ATTRIBUTE_ALWAYS_INLINE void forEachUsed(const UsedT *U, unsigned N, Fn Func)
Definition DenseMap.h:119
constexpr size_t allocAlign()
Definition DenseMap.h:134
size_t allocBytes(unsigned Num)
Definition DenseMap.h:137
bool used(const UsedT *U, size_t I)
Definition DenseMap.h:107
void unsetUsed(UsedT *U, size_t I)
Definition DenseMap.h:111
constexpr bool isRelocatableBucket
Definition DenseMap.h:94
A self-contained host- and target-independent arbitrary-precision floating-point software implementat...
Definition ADL.h:123
bool empty() const
Definition BasicBlock.h:101
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
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition STLExtras.h:1685
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 shouldReverseIterate()
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
@ 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
@ Default
The result value is uniform if and only if all operands are uniform.
Definition Uniformity.h:20
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
const BucketT * Buckets
Definition DenseMap.h:501
const UsedT * Used
Definition DenseMap.h:502
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