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