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