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