LLVM 22.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//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_ADT_DENSEMAP_H
15#define LLVM_ADT_DENSEMAP_H
16
17#include "llvm/ADT/ADL.h"
20#include "llvm/ADT/STLExtras.h"
28#include <algorithm>
29#include <cassert>
30#include <cstddef>
31#include <cstring>
32#include <initializer_list>
33#include <iterator>
34#include <new>
35#include <type_traits>
36#include <utility>
37
38namespace llvm {
39
40namespace detail {
41
42// We extend a pair to allow users to override the bucket type with their own
43// implementation without requiring two members.
44template <typename KeyT, typename ValueT>
45struct DenseMapPair : std::pair<KeyT, ValueT> {
46 using std::pair<KeyT, ValueT>::pair;
47
48 KeyT &getFirst() { return std::pair<KeyT, ValueT>::first; }
49 const KeyT &getFirst() const { return std::pair<KeyT, ValueT>::first; }
50 ValueT &getSecond() { return std::pair<KeyT, ValueT>::second; }
51 const ValueT &getSecond() const { return std::pair<KeyT, ValueT>::second; }
52};
53
54} // end namespace detail
55
56template <typename KeyT, typename ValueT,
57 typename KeyInfoT = DenseMapInfo<KeyT>,
59 bool IsConst = false>
60class DenseMapIterator;
61
62template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
63 typename BucketT>
65 template <typename T>
66 using const_arg_type_t = typename const_pointer_or_const_ref<T>::type;
67
68public:
70 using key_type = KeyT;
71 using mapped_type = ValueT;
72 using value_type = BucketT;
73
77
78 [[nodiscard]] inline iterator begin() {
79 return iterator::makeBegin(buckets(), empty(), *this);
80 }
81 [[nodiscard]] inline iterator end() {
82 return iterator::makeEnd(buckets(), *this);
83 }
84 [[nodiscard]] inline const_iterator begin() const {
85 return const_iterator::makeBegin(buckets(), empty(), *this);
86 }
87 [[nodiscard]] inline const_iterator end() const {
88 return const_iterator::makeEnd(buckets(), *this);
89 }
90
91 // Return an iterator to iterate over keys in the map.
92 [[nodiscard]] inline auto keys() {
93 return map_range(*this, [](const BucketT &P) { return P.getFirst(); });
94 }
95
96 // Return an iterator to iterate over values in the map.
97 [[nodiscard]] inline auto values() {
98 return map_range(*this, [](const BucketT &P) { return P.getSecond(); });
99 }
100
101 [[nodiscard]] inline auto keys() const {
102 return map_range(*this, [](const BucketT &P) { return P.getFirst(); });
103 }
104
105 [[nodiscard]] inline auto values() const {
106 return map_range(*this, [](const BucketT &P) { return P.getSecond(); });
107 }
108
109 [[nodiscard]] bool empty() const { return getNumEntries() == 0; }
110 [[nodiscard]] unsigned size() const { return getNumEntries(); }
111
112 /// Grow the densemap so that it can contain at least \p NumEntries items
113 /// before resizing again.
114 void reserve(size_type NumEntries) {
115 auto NumBuckets = getMinBucketToReserveForEntries(NumEntries);
117 if (NumBuckets > getNumBuckets())
118 grow(NumBuckets);
119 }
120
121 void clear() {
123 if (getNumEntries() == 0 && getNumTombstones() == 0)
124 return;
125
126 // If the capacity of the array is huge, and the # elements used is small,
127 // shrink the array.
128 if (getNumEntries() * 4 < getNumBuckets() && getNumBuckets() > 64) {
130 return;
131 }
132
133 const KeyT EmptyKey = KeyInfoT::getEmptyKey();
134 if constexpr (std::is_trivially_destructible_v<ValueT>) {
135 // Use a simpler loop when values don't need destruction.
136 for (BucketT &B : buckets())
137 B.getFirst() = EmptyKey;
138 } else {
139 const KeyT TombstoneKey = KeyInfoT::getTombstoneKey();
140 unsigned NumEntries = getNumEntries();
141 for (BucketT &B : buckets()) {
142 if (!KeyInfoT::isEqual(B.getFirst(), EmptyKey)) {
143 if (!KeyInfoT::isEqual(B.getFirst(), TombstoneKey)) {
144 B.getSecond().~ValueT();
145 --NumEntries;
146 }
147 B.getFirst() = EmptyKey;
148 }
149 }
150 assert(NumEntries == 0 && "Node count imbalance!");
151 (void)NumEntries;
152 }
153 setNumEntries(0);
154 setNumTombstones(0);
155 }
156
158 auto [Reallocate, NewNumBuckets] = derived().planShrinkAndClear();
159 destroyAll();
160 if (!Reallocate) {
161 initEmpty();
162 return;
163 }
164 derived().deallocateBuckets();
165 derived().init(NewNumBuckets);
166 }
167
168 /// Return true if the specified key is in the map, false otherwise.
169 [[nodiscard]] bool contains(const_arg_type_t<KeyT> Val) const {
170 return doFind(Val) != nullptr;
171 }
172
173 /// Return 1 if the specified key is in the map, 0 otherwise.
174 [[nodiscard]] size_type count(const_arg_type_t<KeyT> Val) const {
175 return contains(Val) ? 1 : 0;
176 }
177
178 [[nodiscard]] iterator find(const_arg_type_t<KeyT> Val) {
179 return find_as(Val);
180 }
181 [[nodiscard]] const_iterator find(const_arg_type_t<KeyT> Val) const {
182 return find_as(Val);
183 }
184
185 /// Alternate version of find() which allows a different, and possibly
186 /// less expensive, key type.
187 /// The DenseMapInfo is responsible for supplying methods
188 /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key
189 /// type used.
190 template <class LookupKeyT>
191 [[nodiscard]] iterator find_as(const LookupKeyT &Val) {
192 if (BucketT *Bucket = doFind(Val))
193 return makeIterator(Bucket);
194 return end();
195 }
196 template <class LookupKeyT>
197 [[nodiscard]] const_iterator find_as(const LookupKeyT &Val) const {
198 if (const BucketT *Bucket = doFind(Val))
199 return makeConstIterator(Bucket);
200 return end();
201 }
202
203 /// lookup - Return the entry for the specified key, or a default
204 /// constructed value if no such entry exists.
205 [[nodiscard]] ValueT lookup(const_arg_type_t<KeyT> Val) const {
206 if (const BucketT *Bucket = doFind(Val))
207 return Bucket->getSecond();
208 return ValueT();
209 }
210
211 // Return the entry with the specified key, or \p Default. This variant is
212 // useful, because `lookup` cannot be used with non-default-constructible
213 // values.
214 template <typename U = std::remove_cv_t<ValueT>>
215 [[nodiscard]] ValueT lookup_or(const_arg_type_t<KeyT> Val,
216 U &&Default) const {
217 if (const BucketT *Bucket = doFind(Val))
218 return Bucket->getSecond();
219 return Default;
220 }
221
222 /// at - Return the entry for the specified key, or abort if no such
223 /// entry exists.
224 [[nodiscard]] const ValueT &at(const_arg_type_t<KeyT> Val) const {
225 auto Iter = this->find(std::move(Val));
226 assert(Iter != this->end() && "DenseMap::at failed due to a missing key");
227 return Iter->second;
228 }
229
230 // Inserts key,value pair into the map if the key isn't already in the map.
231 // If the key is already in the map, it returns false and doesn't update the
232 // value.
233 std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) {
234 return try_emplace_impl(KV.first, KV.second);
235 }
236
237 // Inserts key,value pair into the map if the key isn't already in the map.
238 // If the key is already in the map, it returns false and doesn't update the
239 // value.
240 std::pair<iterator, bool> insert(std::pair<KeyT, ValueT> &&KV) {
241 return try_emplace_impl(std::move(KV.first), std::move(KV.second));
242 }
243
244 // Inserts key,value pair into the map if the key isn't already in the map.
245 // The value is constructed in-place if the key is not in the map, otherwise
246 // it is not moved.
247 template <typename... Ts>
248 std::pair<iterator, bool> try_emplace(KeyT &&Key, Ts &&...Args) {
249 return try_emplace_impl(std::move(Key), std::forward<Ts>(Args)...);
250 }
251
252 // Inserts key,value pair into the map if the key isn't already in the map.
253 // The value is constructed in-place if the key is not in the map, otherwise
254 // it is not moved.
255 template <typename... Ts>
256 std::pair<iterator, bool> try_emplace(const KeyT &Key, Ts &&...Args) {
257 return try_emplace_impl(Key, std::forward<Ts>(Args)...);
258 }
259
260 /// Alternate version of insert() which allows a different, and possibly
261 /// less expensive, key type.
262 /// The DenseMapInfo is responsible for supplying methods
263 /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key
264 /// type used.
265 template <typename LookupKeyT>
266 std::pair<iterator, bool> insert_as(std::pair<KeyT, ValueT> &&KV,
267 const LookupKeyT &Val) {
268 BucketT *TheBucket;
269 if (LookupBucketFor(Val, TheBucket))
270 return {makeIterator(TheBucket), false}; // Already in map.
271
272 // Otherwise, insert the new element.
273 TheBucket = findBucketForInsertion(Val, TheBucket);
274 TheBucket->getFirst() = std::move(KV.first);
275 ::new (&TheBucket->getSecond()) ValueT(std::move(KV.second));
276 return {makeIterator(TheBucket), true};
277 }
278
279 /// insert - Range insertion of pairs.
280 template <typename InputIt> void insert(InputIt I, InputIt E) {
281 for (; I != E; ++I)
282 insert(*I);
283 }
284
285 /// Inserts range of 'std::pair<KeyT, ValueT>' values into the map.
286 template <typename Range> void insert_range(Range &&R) {
287 insert(adl_begin(R), adl_end(R));
288 }
289
290 template <typename V>
291 std::pair<iterator, bool> insert_or_assign(const KeyT &Key, V &&Val) {
292 auto Ret = try_emplace(Key, std::forward<V>(Val));
293 if (!Ret.second)
294 Ret.first->second = std::forward<V>(Val);
295 return Ret;
296 }
297
298 template <typename V>
299 std::pair<iterator, bool> insert_or_assign(KeyT &&Key, V &&Val) {
300 auto Ret = try_emplace(std::move(Key), std::forward<V>(Val));
301 if (!Ret.second)
302 Ret.first->second = std::forward<V>(Val);
303 return Ret;
304 }
305
306 template <typename... Ts>
307 std::pair<iterator, bool> emplace_or_assign(const KeyT &Key, Ts &&...Args) {
308 auto Ret = try_emplace(Key, std::forward<Ts>(Args)...);
309 if (!Ret.second)
310 Ret.first->second = ValueT(std::forward<Ts>(Args)...);
311 return Ret;
312 }
313
314 template <typename... Ts>
315 std::pair<iterator, bool> emplace_or_assign(KeyT &&Key, Ts &&...Args) {
316 auto Ret = try_emplace(std::move(Key), std::forward<Ts>(Args)...);
317 if (!Ret.second)
318 Ret.first->second = ValueT(std::forward<Ts>(Args)...);
319 return Ret;
320 }
321
322 bool erase(const KeyT &Val) {
323 BucketT *TheBucket = doFind(Val);
324 if (!TheBucket)
325 return false; // not in map.
326
327 TheBucket->getSecond().~ValueT();
328 TheBucket->getFirst() = KeyInfoT::getTombstoneKey();
329 decrementNumEntries();
330 incrementNumTombstones();
331 return true;
332 }
334 BucketT *TheBucket = &*I;
335 TheBucket->getSecond().~ValueT();
336 TheBucket->getFirst() = KeyInfoT::getTombstoneKey();
337 decrementNumEntries();
338 incrementNumTombstones();
339 }
340
341 ValueT &operator[](const KeyT &Key) {
342 return lookupOrInsertIntoBucket(Key).first->second;
343 }
344
345 ValueT &operator[](KeyT &&Key) {
346 return lookupOrInsertIntoBucket(std::move(Key)).first->second;
347 }
348
349 /// isPointerIntoBucketsArray - Return true if the specified pointer points
350 /// somewhere into the DenseMap's array of buckets (i.e. either to a key or
351 /// value in the DenseMap).
352 [[nodiscard]] bool isPointerIntoBucketsArray(const void *Ptr) const {
353 return Ptr >= getBuckets() && Ptr < getBucketsEnd();
354 }
355
356 /// getPointerIntoBucketsArray() - Return an opaque pointer into the buckets
357 /// array. In conjunction with the previous method, this can be used to
358 /// determine whether an insertion caused the DenseMap to reallocate.
359 [[nodiscard]] const void *getPointerIntoBucketsArray() const {
360 return getBuckets();
361 }
362
363 void swap(DerivedT &RHS) {
364 this->incrementEpoch();
365 RHS.incrementEpoch();
366 derived().swapImpl(RHS);
367 }
368
369protected:
370 DenseMapBase() = default;
371
372 void destroyAll() {
373 // No need to iterate through the buckets if both KeyT and ValueT are
374 // trivially destructible.
375 if constexpr (std::is_trivially_destructible_v<KeyT> &&
376 std::is_trivially_destructible_v<ValueT>)
377 return;
378
379 if (getNumBuckets() == 0) // Nothing to do.
380 return;
381
382 const KeyT EmptyKey = KeyInfoT::getEmptyKey();
383 const KeyT TombstoneKey = KeyInfoT::getTombstoneKey();
384 for (BucketT &B : buckets()) {
385 if (!KeyInfoT::isEqual(B.getFirst(), EmptyKey) &&
386 !KeyInfoT::isEqual(B.getFirst(), TombstoneKey))
387 B.getSecond().~ValueT();
388 B.getFirst().~KeyT();
389 }
390 }
391
392 void initEmpty() {
393 static_assert(std::is_base_of_v<DenseMapBase, DerivedT>,
394 "Must pass the derived type to this template!");
395 setNumEntries(0);
396 setNumTombstones(0);
397
398 assert((getNumBuckets() & (getNumBuckets() - 1)) == 0 &&
399 "# initial buckets must be a power of two!");
400 const KeyT EmptyKey = KeyInfoT::getEmptyKey();
401 for (BucketT &B : buckets())
402 ::new (&B.getFirst()) KeyT(EmptyKey);
403 }
404
405 /// Returns the number of buckets to allocate to ensure that the DenseMap can
406 /// accommodate \p NumEntries without need to grow().
407 unsigned getMinBucketToReserveForEntries(unsigned NumEntries) {
408 // Ensure that "NumEntries * 4 < NumBuckets * 3"
409 if (NumEntries == 0)
410 return 0;
411 // +1 is required because of the strict inequality.
412 // For example, if NumEntries is 48, we need to return 128.
413 return NextPowerOf2(NumEntries * 4 / 3 + 1);
414 }
415
417 // Insert all the old elements.
418 const KeyT EmptyKey = KeyInfoT::getEmptyKey();
419 const KeyT TombstoneKey = KeyInfoT::getTombstoneKey();
420 for (BucketT &B : OldBuckets) {
421 if (!KeyInfoT::isEqual(B.getFirst(), EmptyKey) &&
422 !KeyInfoT::isEqual(B.getFirst(), TombstoneKey)) {
423 // Insert the key/value into the new table.
424 BucketT *DestBucket;
425 bool FoundVal = LookupBucketFor(B.getFirst(), DestBucket);
426 (void)FoundVal; // silence warning.
427 assert(!FoundVal && "Key already in new map?");
428 DestBucket->getFirst() = std::move(B.getFirst());
429 ::new (&DestBucket->getSecond()) ValueT(std::move(B.getSecond()));
430 incrementNumEntries();
431
432 // Free the value.
433 B.getSecond().~ValueT();
434 }
435 B.getFirst().~KeyT();
436 }
437 }
438
440 initEmpty();
441 moveFromImpl(OldBuckets);
442 }
443
444 // Move key/value from Other to *this. Other will be in a zombie state.
445 void moveFrom(DerivedT &Other) { moveFromImpl(Other.buckets()); }
446
447 void copyFrom(const DerivedT &other) {
448 this->destroyAll();
449 derived().deallocateBuckets();
450 setNumEntries(0);
451 setNumTombstones(0);
452 if (!derived().allocateBuckets(other.getNumBuckets())) {
453 // The bucket list is empty. No work to do.
454 return;
455 }
456
457 assert(&other != this);
458 assert(getNumBuckets() == other.getNumBuckets());
459
460 setNumEntries(other.getNumEntries());
461 setNumTombstones(other.getNumTombstones());
462
463 BucketT *Buckets = getBuckets();
464 const BucketT *OtherBuckets = other.getBuckets();
465 const size_t NumBuckets = getNumBuckets();
466 if constexpr (std::is_trivially_copyable_v<KeyT> &&
467 std::is_trivially_copyable_v<ValueT>) {
468 memcpy(reinterpret_cast<void *>(Buckets), OtherBuckets,
469 NumBuckets * sizeof(BucketT));
470 } else {
471 const KeyT EmptyKey = KeyInfoT::getEmptyKey();
472 const KeyT TombstoneKey = KeyInfoT::getTombstoneKey();
473 for (size_t I = 0; I < NumBuckets; ++I) {
474 ::new (&Buckets[I].getFirst()) KeyT(OtherBuckets[I].getFirst());
475 if (!KeyInfoT::isEqual(Buckets[I].getFirst(), EmptyKey) &&
476 !KeyInfoT::isEqual(Buckets[I].getFirst(), TombstoneKey))
477 ::new (&Buckets[I].getSecond()) ValueT(OtherBuckets[I].getSecond());
478 }
479 }
480 }
481
482private:
483 DerivedT &derived() { return *static_cast<DerivedT *>(this); }
484 const DerivedT &derived() const {
485 return *static_cast<const DerivedT *>(this);
486 }
487
488 template <typename KeyArgT, typename... Ts>
489 std::pair<BucketT *, bool> lookupOrInsertIntoBucket(KeyArgT &&Key,
490 Ts &&...Args) {
491 BucketT *TheBucket = nullptr;
492 if (LookupBucketFor(Key, TheBucket))
493 return {TheBucket, false}; // Already in the map.
494
495 // Otherwise, insert the new element.
496 TheBucket = findBucketForInsertion(Key, TheBucket);
497 TheBucket->getFirst() = std::forward<KeyArgT>(Key);
498 ::new (&TheBucket->getSecond()) ValueT(std::forward<Ts>(Args)...);
499 return {TheBucket, true};
500 }
501
502 template <typename KeyArgT, typename... Ts>
503 std::pair<iterator, bool> try_emplace_impl(KeyArgT &&Key, Ts &&...Args) {
504 auto [Bucket, Inserted] = lookupOrInsertIntoBucket(
505 std::forward<KeyArgT>(Key), std::forward<Ts>(Args)...);
506 return {makeIterator(Bucket), Inserted};
507 }
508
509 iterator makeIterator(BucketT *TheBucket) {
510 return iterator::makeIterator(TheBucket, buckets(), *this);
511 }
512
513 const_iterator makeConstIterator(const BucketT *TheBucket) const {
514 return const_iterator::makeIterator(TheBucket, buckets(), *this);
515 }
516
517 unsigned getNumEntries() const { return derived().getNumEntries(); }
518
519 void setNumEntries(unsigned Num) { derived().setNumEntries(Num); }
520
521 void incrementNumEntries() { setNumEntries(getNumEntries() + 1); }
522
523 void decrementNumEntries() { setNumEntries(getNumEntries() - 1); }
524
525 unsigned getNumTombstones() const { return derived().getNumTombstones(); }
526
527 void setNumTombstones(unsigned Num) { derived().setNumTombstones(Num); }
528
529 void incrementNumTombstones() { setNumTombstones(getNumTombstones() + 1); }
530
531 void decrementNumTombstones() { setNumTombstones(getNumTombstones() - 1); }
532
533 const BucketT *getBuckets() const { return derived().getBuckets(); }
534
535 BucketT *getBuckets() { return derived().getBuckets(); }
536
537 unsigned getNumBuckets() const { return derived().getNumBuckets(); }
538
539 BucketT *getBucketsEnd() { return getBuckets() + getNumBuckets(); }
540
541 const BucketT *getBucketsEnd() const {
542 return getBuckets() + getNumBuckets();
543 }
544
545 iterator_range<BucketT *> buckets() {
546 return llvm::make_range(getBuckets(), getBucketsEnd());
547 }
548
549 iterator_range<const BucketT *> buckets() const {
550 return llvm::make_range(getBuckets(), getBucketsEnd());
551 }
552
553 void grow(unsigned AtLeast) { derived().grow(AtLeast); }
554
555 template <typename LookupKeyT>
556 BucketT *findBucketForInsertion(const LookupKeyT &Lookup,
557 BucketT *TheBucket) {
559
560 // If the load of the hash table is more than 3/4, or if fewer than 1/8 of
561 // the buckets are empty (meaning that many are filled with tombstones),
562 // grow the table.
563 //
564 // The later case is tricky. For example, if we had one empty bucket with
565 // tons of tombstones, failing lookups (e.g. for insertion) would have to
566 // probe almost the entire table until it found the empty bucket. If the
567 // table completely filled with tombstones, no lookup would ever succeed,
568 // causing infinite loops in lookup.
569 unsigned NewNumEntries = getNumEntries() + 1;
570 unsigned NumBuckets = getNumBuckets();
571 if (LLVM_UNLIKELY(NewNumEntries * 4 >= NumBuckets * 3)) {
572 this->grow(NumBuckets * 2);
573 LookupBucketFor(Lookup, TheBucket);
574 } else if (LLVM_UNLIKELY(NumBuckets -
575 (NewNumEntries + getNumTombstones()) <=
576 NumBuckets / 8)) {
577 this->grow(NumBuckets);
578 LookupBucketFor(Lookup, TheBucket);
579 }
580 assert(TheBucket);
581
582 // Only update the state after we've grown our bucket space appropriately
583 // so that when growing buckets we have self-consistent entry count.
584 incrementNumEntries();
585
586 // If we are writing over a tombstone, remember this.
587 const KeyT EmptyKey = KeyInfoT::getEmptyKey();
588 if (!KeyInfoT::isEqual(TheBucket->getFirst(), EmptyKey))
589 decrementNumTombstones();
590
591 return TheBucket;
592 }
593
594 template <typename LookupKeyT>
595 const BucketT *doFind(const LookupKeyT &Val) const {
596 const BucketT *BucketsPtr = getBuckets();
597 const unsigned NumBuckets = getNumBuckets();
598 if (NumBuckets == 0)
599 return nullptr;
600
601 const KeyT EmptyKey = KeyInfoT::getEmptyKey();
602 unsigned BucketNo = KeyInfoT::getHashValue(Val) & (NumBuckets - 1);
603 unsigned ProbeAmt = 1;
604 while (true) {
605 const BucketT *Bucket = BucketsPtr + BucketNo;
606 if (LLVM_LIKELY(KeyInfoT::isEqual(Val, Bucket->getFirst())))
607 return Bucket;
608 if (LLVM_LIKELY(KeyInfoT::isEqual(Bucket->getFirst(), EmptyKey)))
609 return nullptr;
610
611 // Otherwise, it's a hash collision or a tombstone, continue quadratic
612 // probing.
613 BucketNo += ProbeAmt++;
614 BucketNo &= NumBuckets - 1;
615 }
616 }
617
618 template <typename LookupKeyT> BucketT *doFind(const LookupKeyT &Val) {
619 return const_cast<BucketT *>(
620 static_cast<const DenseMapBase *>(this)->doFind(Val));
621 }
622
623 /// LookupBucketFor - Lookup the appropriate bucket for Val, returning it in
624 /// FoundBucket. If the bucket contains the key and a value, this returns
625 /// true, otherwise it returns a bucket with an empty marker or tombstone and
626 /// returns false.
627 template <typename LookupKeyT>
628 bool LookupBucketFor(const LookupKeyT &Val, BucketT *&FoundBucket) {
629 BucketT *BucketsPtr = getBuckets();
630 const unsigned NumBuckets = getNumBuckets();
631
632 if (NumBuckets == 0) {
633 FoundBucket = nullptr;
634 return false;
635 }
636
637 // FoundTombstone - Keep track of whether we find a tombstone while probing.
638 BucketT *FoundTombstone = nullptr;
639 const KeyT EmptyKey = KeyInfoT::getEmptyKey();
640 const KeyT TombstoneKey = KeyInfoT::getTombstoneKey();
641 assert(!KeyInfoT::isEqual(Val, EmptyKey) &&
642 !KeyInfoT::isEqual(Val, TombstoneKey) &&
643 "Empty/Tombstone value shouldn't be inserted into map!");
644
645 unsigned BucketNo = KeyInfoT::getHashValue(Val) & (NumBuckets - 1);
646 unsigned ProbeAmt = 1;
647 while (true) {
648 BucketT *ThisBucket = BucketsPtr + BucketNo;
649 // Found Val's bucket? If so, return it.
650 if (LLVM_LIKELY(KeyInfoT::isEqual(Val, ThisBucket->getFirst()))) {
651 FoundBucket = ThisBucket;
652 return true;
653 }
654
655 // If we found an empty bucket, the key doesn't exist in the set.
656 // Insert it and return the default value.
657 if (LLVM_LIKELY(KeyInfoT::isEqual(ThisBucket->getFirst(), EmptyKey))) {
658 // If we've already seen a tombstone while probing, fill it in instead
659 // of the empty bucket we eventually probed to.
660 FoundBucket = FoundTombstone ? FoundTombstone : ThisBucket;
661 return false;
662 }
663
664 // If this is a tombstone, remember it. If Val ends up not in the map, we
665 // prefer to return it than something that would require more probing.
666 if (KeyInfoT::isEqual(ThisBucket->getFirst(), TombstoneKey) &&
667 !FoundTombstone)
668 FoundTombstone = ThisBucket; // Remember the first tombstone found.
669
670 // Otherwise, it's a hash collision or a tombstone, continue quadratic
671 // probing.
672 BucketNo += ProbeAmt++;
673 BucketNo &= (NumBuckets - 1);
674 }
675 }
676
677public:
678 /// Return the approximate size (in bytes) of the actual map.
679 /// This is just the raw memory used by DenseMap.
680 /// If entries are pointers to objects, the size of the referenced objects
681 /// are not included.
682 [[nodiscard]] size_t getMemorySize() const {
683 return getNumBuckets() * sizeof(BucketT);
684 }
685};
686
687/// Equality comparison for DenseMap.
688///
689/// Iterates over elements of LHS confirming that each (key, value) pair in LHS
690/// is also in RHS, and that no additional pairs are in RHS.
691/// Equivalent to N calls to RHS.find and N value comparisons. Amortized
692/// complexity is linear, worst case is O(N^2) (if every hash collides).
693template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
694 typename BucketT>
695[[nodiscard]] bool
698 if (LHS.size() != RHS.size())
699 return false;
700
701 for (auto &KV : LHS) {
702 auto I = RHS.find(KV.first);
703 if (I == RHS.end() || I->second != KV.second)
704 return false;
705 }
706
707 return true;
708}
709
710/// Inequality comparison for DenseMap.
711///
712/// Equivalent to !(LHS == RHS). See operator== for performance notes.
713template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
714 typename BucketT>
715[[nodiscard]] bool
720
721template <typename KeyT, typename ValueT,
722 typename KeyInfoT = DenseMapInfo<KeyT>,
724class DenseMap : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>,
725 KeyT, ValueT, KeyInfoT, BucketT> {
726 friend class DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT>;
727
728 // Lift some types from the dependent base class into this class for
729 // simplicity of referring to them.
731
732 BucketT *Buckets;
733 unsigned NumEntries;
734 unsigned NumTombstones;
735 unsigned NumBuckets;
736
737public:
738 /// Create a DenseMap with an optional \p NumElementsToReserve to guarantee
739 /// that this number of elements can be inserted in the map without grow().
740 explicit DenseMap(unsigned NumElementsToReserve = 0) {
741 init(NumElementsToReserve);
742 }
743
744 DenseMap(const DenseMap &other) : BaseT() {
745 init(0);
746 this->copyFrom(other);
747 }
748
749 DenseMap(DenseMap &&other) : BaseT() {
750 init(0);
751 this->swap(other);
752 }
753
754 template <typename InputIt> DenseMap(const InputIt &I, const InputIt &E) {
755 init(std::distance(I, E));
756 this->insert(I, E);
757 }
758
759 template <typename RangeT>
762
763 DenseMap(std::initializer_list<typename BaseT::value_type> Vals)
764 : DenseMap(Vals.begin(), Vals.end()) {}
765
767 this->destroyAll();
768 deallocateBuckets();
769 }
770
771private:
772 void swapImpl(DenseMap &RHS) {
773 std::swap(Buckets, RHS.Buckets);
774 std::swap(NumEntries, RHS.NumEntries);
775 std::swap(NumTombstones, RHS.NumTombstones);
776 std::swap(NumBuckets, RHS.NumBuckets);
777 }
778
779public:
780 DenseMap &operator=(const DenseMap &other) {
781 if (&other != this)
782 this->copyFrom(other);
783 return *this;
784 }
785
787 this->destroyAll();
788 deallocateBuckets();
789 init(0);
790 this->swap(other);
791 return *this;
792 }
793
794private:
795 unsigned getNumEntries() const { return NumEntries; }
796
797 void setNumEntries(unsigned Num) { NumEntries = Num; }
798
799 unsigned getNumTombstones() const { return NumTombstones; }
800
801 void setNumTombstones(unsigned Num) { NumTombstones = Num; }
802
803 BucketT *getBuckets() const { return Buckets; }
804
805 unsigned getNumBuckets() const { return NumBuckets; }
806
807 void deallocateBuckets() {
808 deallocate_buffer(Buckets, sizeof(BucketT) * NumBuckets, alignof(BucketT));
809 }
810
811 bool allocateBuckets(unsigned Num) {
812 NumBuckets = Num;
813 if (NumBuckets == 0) {
814 Buckets = nullptr;
815 return false;
816 }
817
818 Buckets = static_cast<BucketT *>(
819 allocate_buffer(sizeof(BucketT) * NumBuckets, alignof(BucketT)));
820 return true;
821 }
822
823 void init(unsigned InitNumEntries) {
824 auto InitBuckets = BaseT::getMinBucketToReserveForEntries(InitNumEntries);
825 if (allocateBuckets(InitBuckets)) {
826 this->BaseT::initEmpty();
827 } else {
828 NumEntries = 0;
829 NumTombstones = 0;
830 }
831 }
832
833 void grow(unsigned AtLeast) {
834 unsigned OldNumBuckets = NumBuckets;
835 BucketT *OldBuckets = Buckets;
836
837 allocateBuckets(std::max<unsigned>(
838 64, static_cast<unsigned>(NextPowerOf2(AtLeast - 1))));
839 assert(Buckets);
840 if (!OldBuckets) {
841 this->BaseT::initEmpty();
842 return;
843 }
844
845 this->moveFromOldBuckets(
846 llvm::make_range(OldBuckets, OldBuckets + OldNumBuckets));
847
848 // Free the old table.
849 deallocate_buffer(OldBuckets, sizeof(BucketT) * OldNumBuckets,
850 alignof(BucketT));
851 }
852
853 // Plan how to shrink the bucket table. Return:
854 // - {false, 0} to reuse the existing bucket table
855 // - {true, N} to reallocate a bucket table with N entries
856 std::pair<bool, unsigned> planShrinkAndClear() const {
857 unsigned NewNumBuckets = 0;
858 if (NumEntries)
859 NewNumBuckets = std::max(64u, 1u << (Log2_32_Ceil(NumEntries) + 1));
860 if (NewNumBuckets == NumBuckets)
861 return {false, 0}; // Reuse.
862 return {true, NewNumBuckets}; // Reallocate.
863 }
864};
865
866template <typename KeyT, typename ValueT, unsigned InlineBuckets = 4,
867 typename KeyInfoT = DenseMapInfo<KeyT>,
869class SmallDenseMap
870 : public DenseMapBase<
871 SmallDenseMap<KeyT, ValueT, InlineBuckets, KeyInfoT, BucketT>, KeyT,
872 ValueT, KeyInfoT, BucketT> {
873 friend class DenseMapBase<SmallDenseMap, 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
879 static_assert(isPowerOf2_64(InlineBuckets),
880 "InlineBuckets must be a power of 2.");
881
882 unsigned Small : 1;
883 unsigned NumEntries : 31;
884 unsigned NumTombstones;
885
886 struct LargeRep {
887 BucketT *Buckets;
888 unsigned NumBuckets;
890 return llvm::make_range(Buckets, Buckets + NumBuckets);
891 }
892 };
893
894 /// A "union" of an inline bucket array and the struct representing
895 /// a large bucket. This union will be discriminated by the 'Small' bit.
896 AlignedCharArrayUnion<BucketT[InlineBuckets], LargeRep> storage;
897
898 struct ExactBucketCount {};
899 SmallDenseMap(unsigned NumBuckets, ExactBucketCount) {
900 allocateBuckets(NumBuckets);
901 this->BaseT::initEmpty();
902 }
903
904public:
905 explicit SmallDenseMap(unsigned NumElementsToReserve = 0) {
906 init(NumElementsToReserve);
907 }
908
909 SmallDenseMap(const SmallDenseMap &other) : BaseT() {
910 init(0);
911 this->copyFrom(other);
912 }
913
914 SmallDenseMap(SmallDenseMap &&other) : BaseT() {
915 init(0);
916 this->swap(other);
917 }
918
919 template <typename InputIt>
920 SmallDenseMap(const InputIt &I, const InputIt &E) {
921 init(std::distance(I, E));
922 this->insert(I, E);
923 }
924
925 template <typename RangeT>
927 : SmallDenseMap(adl_begin(Range), adl_end(Range)) {}
928
929 SmallDenseMap(std::initializer_list<typename BaseT::value_type> Vals)
930 : SmallDenseMap(Vals.begin(), Vals.end()) {}
931
933 this->destroyAll();
934 deallocateBuckets();
935 }
936
937private:
938 void swapImpl(SmallDenseMap &RHS) {
939 unsigned TmpNumEntries = RHS.NumEntries;
940 RHS.NumEntries = NumEntries;
941 NumEntries = TmpNumEntries;
942 std::swap(NumTombstones, RHS.NumTombstones);
943
944 const KeyT EmptyKey = KeyInfoT::getEmptyKey();
945 const KeyT TombstoneKey = KeyInfoT::getTombstoneKey();
946 if (Small && RHS.Small) {
947 // If we're swapping inline bucket arrays, we have to cope with some of
948 // the tricky bits of DenseMap's storage system: the buckets are not
949 // fully initialized. Thus we swap every key, but we may have
950 // a one-directional move of the value.
951 for (unsigned i = 0, e = InlineBuckets; i != e; ++i) {
952 BucketT *LHSB = &getInlineBuckets()[i],
953 *RHSB = &RHS.getInlineBuckets()[i];
954 bool hasLHSValue = (!KeyInfoT::isEqual(LHSB->getFirst(), EmptyKey) &&
955 !KeyInfoT::isEqual(LHSB->getFirst(), TombstoneKey));
956 bool hasRHSValue = (!KeyInfoT::isEqual(RHSB->getFirst(), EmptyKey) &&
957 !KeyInfoT::isEqual(RHSB->getFirst(), TombstoneKey));
958 if (hasLHSValue && hasRHSValue) {
959 // Swap together if we can...
960 std::swap(*LHSB, *RHSB);
961 continue;
962 }
963 // Swap separately and handle any asymmetry.
964 std::swap(LHSB->getFirst(), RHSB->getFirst());
965 if (hasLHSValue) {
966 ::new (&RHSB->getSecond()) ValueT(std::move(LHSB->getSecond()));
967 LHSB->getSecond().~ValueT();
968 } else if (hasRHSValue) {
969 ::new (&LHSB->getSecond()) ValueT(std::move(RHSB->getSecond()));
970 RHSB->getSecond().~ValueT();
971 }
972 }
973 return;
974 }
975 if (!Small && !RHS.Small) {
976 std::swap(*getLargeRep(), *RHS.getLargeRep());
977 return;
978 }
979
980 SmallDenseMap &SmallSide = Small ? *this : RHS;
981 SmallDenseMap &LargeSide = Small ? RHS : *this;
982
983 // First stash the large side's rep and move the small side across.
984 LargeRep TmpRep = std::move(*LargeSide.getLargeRep());
985 LargeSide.getLargeRep()->~LargeRep();
986 LargeSide.Small = true;
987 // This is similar to the standard move-from-old-buckets, but the bucket
988 // count hasn't actually rotated in this case. So we have to carefully
989 // move construct the keys and values into their new locations, but there
990 // is no need to re-hash things.
991 for (unsigned i = 0, e = InlineBuckets; i != e; ++i) {
992 BucketT *NewB = &LargeSide.getInlineBuckets()[i],
993 *OldB = &SmallSide.getInlineBuckets()[i];
994 ::new (&NewB->getFirst()) KeyT(std::move(OldB->getFirst()));
995 OldB->getFirst().~KeyT();
996 if (!KeyInfoT::isEqual(NewB->getFirst(), EmptyKey) &&
997 !KeyInfoT::isEqual(NewB->getFirst(), TombstoneKey)) {
998 ::new (&NewB->getSecond()) ValueT(std::move(OldB->getSecond()));
999 OldB->getSecond().~ValueT();
1000 }
1001 }
1002
1003 // The hard part of moving the small buckets across is done, just move
1004 // the TmpRep into its new home.
1005 SmallSide.Small = false;
1006 new (SmallSide.getLargeRep()) LargeRep(std::move(TmpRep));
1007 }
1008
1009public:
1010 SmallDenseMap &operator=(const SmallDenseMap &other) {
1011 if (&other != this)
1012 this->copyFrom(other);
1013 return *this;
1014 }
1015
1016 SmallDenseMap &operator=(SmallDenseMap &&other) {
1017 this->destroyAll();
1018 deallocateBuckets();
1019 init(0);
1020 this->swap(other);
1021 return *this;
1022 }
1023
1024private:
1025 unsigned getNumEntries() const { return NumEntries; }
1026
1027 void setNumEntries(unsigned Num) {
1028 // NumEntries is hardcoded to be 31 bits wide.
1029 assert(Num < (1U << 31) && "Cannot support more than 1<<31 entries");
1030 NumEntries = Num;
1031 }
1032
1033 unsigned getNumTombstones() const { return NumTombstones; }
1034
1035 void setNumTombstones(unsigned Num) { NumTombstones = Num; }
1036
1037 const BucketT *getInlineBuckets() const {
1038 assert(Small);
1039 // Note that this cast does not violate aliasing rules as we assert that
1040 // the memory's dynamic type is the small, inline bucket buffer, and the
1041 // 'storage' is a POD containing a char buffer.
1042 return reinterpret_cast<const BucketT *>(&storage);
1043 }
1044
1045 BucketT *getInlineBuckets() {
1046 return const_cast<BucketT *>(
1047 const_cast<const SmallDenseMap *>(this)->getInlineBuckets());
1048 }
1049
1050 const LargeRep *getLargeRep() const {
1051 assert(!Small);
1052 // Note, same rule about aliasing as with getInlineBuckets.
1053 return reinterpret_cast<const LargeRep *>(&storage);
1054 }
1055
1056 LargeRep *getLargeRep() {
1057 return const_cast<LargeRep *>(
1058 const_cast<const SmallDenseMap *>(this)->getLargeRep());
1059 }
1060
1061 const BucketT *getBuckets() const {
1062 return Small ? getInlineBuckets() : getLargeRep()->Buckets;
1063 }
1064
1065 BucketT *getBuckets() {
1066 return const_cast<BucketT *>(
1067 const_cast<const SmallDenseMap *>(this)->getBuckets());
1068 }
1069
1070 unsigned getNumBuckets() const {
1071 return Small ? InlineBuckets : getLargeRep()->NumBuckets;
1072 }
1073
1074 iterator_range<BucketT *> inlineBuckets() {
1075 BucketT *Begin = getInlineBuckets();
1076 return llvm::make_range(Begin, Begin + InlineBuckets);
1077 }
1078
1079 void deallocateBuckets() {
1080 // Fast path to deallocateBuckets in case getLargeRep()->NumBuckets == 0,
1081 // just like destroyAll. This path is used to destruct zombie instances
1082 // after moves.
1083 if (Small || getLargeRep()->NumBuckets == 0)
1084 return;
1085
1086 deallocate_buffer(getLargeRep()->Buckets,
1087 sizeof(BucketT) * getLargeRep()->NumBuckets,
1088 alignof(BucketT));
1089 getLargeRep()->~LargeRep();
1090 }
1091
1092 bool allocateBuckets(unsigned Num) {
1093 if (Num <= InlineBuckets) {
1094 Small = true;
1095 } else {
1096 Small = false;
1097 BucketT *NewBuckets = static_cast<BucketT *>(
1098 allocate_buffer(sizeof(BucketT) * Num, alignof(BucketT)));
1099 new (getLargeRep()) LargeRep{NewBuckets, Num};
1100 }
1101 return true;
1102 }
1103
1104 void init(unsigned InitNumEntries) {
1105 auto InitBuckets = BaseT::getMinBucketToReserveForEntries(InitNumEntries);
1106 allocateBuckets(InitBuckets);
1107 this->BaseT::initEmpty();
1108 }
1109
1110 void grow(unsigned AtLeast) {
1111 if (AtLeast > InlineBuckets)
1112 AtLeast = std::max<unsigned>(64, NextPowerOf2(AtLeast - 1));
1113
1114 SmallDenseMap Tmp(AtLeast, ExactBucketCount{});
1115 Tmp.moveFrom(*this);
1116
1117 if (Tmp.Small) {
1118 // Use moveFrom in those rare cases where we stay in the small mode. This
1119 // can happen when we have many tombstones.
1120 this->BaseT::initEmpty();
1121 this->moveFrom(Tmp);
1122 Tmp.Small = false;
1123 Tmp.getLargeRep()->NumBuckets = 0;
1124 } else {
1125 deallocateBuckets();
1126 Small = false;
1127 NumTombstones = 0;
1128 *getLargeRep() = std::move(*Tmp.getLargeRep());
1129 Tmp.getLargeRep()->NumBuckets = 0;
1130 }
1131 }
1132
1133 // Plan how to shrink the bucket table. Return:
1134 // - {false, 0} to reuse the existing bucket table
1135 // - {true, N} to reallocate a bucket table with N entries
1136 std::pair<bool, unsigned> planShrinkAndClear() const {
1137 unsigned NewNumBuckets = 0;
1138 if (!this->empty()) {
1139 NewNumBuckets = 1u << (Log2_32_Ceil(this->size()) + 1);
1140 if (NewNumBuckets > InlineBuckets)
1141 NewNumBuckets = std::max(64u, NewNumBuckets);
1142 }
1143 bool Reuse = Small ? NewNumBuckets <= InlineBuckets
1144 : NewNumBuckets == getLargeRep()->NumBuckets;
1145 if (Reuse)
1146 return {false, 0}; // Reuse.
1147 return {true, NewNumBuckets}; // Reallocate.
1148 }
1149};
1150
1151template <typename KeyT, typename ValueT, typename KeyInfoT, typename Bucket,
1152 bool IsConst>
1153class DenseMapIterator : DebugEpochBase::HandleBase {
1154 friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true>;
1155 friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, false>;
1156
1157public:
1159 using value_type = std::conditional_t<IsConst, const Bucket, Bucket>;
1162 using iterator_category = std::forward_iterator_tag;
1163
1164private:
1165 using BucketItTy =
1166 std::conditional_t<shouldReverseIterate<KeyT>(),
1167 std::reverse_iterator<pointer>, pointer>;
1168
1169 BucketItTy Ptr = {};
1170 BucketItTy End = {};
1171
1172 DenseMapIterator(BucketItTy Pos, BucketItTy E, const DebugEpochBase &Epoch)
1173 : DebugEpochBase::HandleBase(&Epoch), Ptr(Pos), End(E) {
1174 assert(isHandleInSync() && "invalid construction!");
1175 }
1176
1177public:
1178 DenseMapIterator() = default;
1179
1180 static DenseMapIterator makeBegin(iterator_range<pointer> Buckets,
1181 bool IsEmpty, const DebugEpochBase &Epoch) {
1182 // When the map is empty, avoid the overhead of advancing/retreating past
1183 // empty buckets.
1184 if (IsEmpty)
1185 return makeEnd(Buckets, Epoch);
1186 auto R = maybeReverse(Buckets);
1187 DenseMapIterator Iter(R.begin(), R.end(), Epoch);
1188 Iter.AdvancePastEmptyBuckets();
1189 return Iter;
1190 }
1191
1192 static DenseMapIterator makeEnd(iterator_range<pointer> Buckets,
1193 const DebugEpochBase &Epoch) {
1194 auto R = maybeReverse(Buckets);
1195 return DenseMapIterator(R.end(), R.end(), Epoch);
1196 }
1197
1198 static DenseMapIterator makeIterator(pointer P,
1200 const DebugEpochBase &Epoch) {
1201 auto R = maybeReverse(Buckets);
1202 constexpr int Offset = shouldReverseIterate<KeyT>() ? 1 : 0;
1203 return DenseMapIterator(BucketItTy(P + Offset), R.end(), Epoch);
1204 }
1205
1206 // Converting ctor from non-const iterators to const iterators. SFINAE'd out
1207 // for const iterator destinations so it doesn't end up as a user defined copy
1208 // constructor.
1209 template <bool IsConstSrc,
1210 typename = std::enable_if_t<!IsConstSrc && IsConst>>
1212 const DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, IsConstSrc> &I)
1213 : DebugEpochBase::HandleBase(I), Ptr(I.Ptr), End(I.End) {}
1214
1215 [[nodiscard]] reference operator*() const {
1216 assert(isHandleInSync() && "invalid iterator access!");
1217 assert(Ptr != End && "dereferencing end() iterator");
1218 return *Ptr;
1219 }
1220 [[nodiscard]] pointer operator->() const { return &operator*(); }
1221
1222 [[nodiscard]] friend bool operator==(const DenseMapIterator &LHS,
1223 const DenseMapIterator &RHS) {
1224 assert((!LHS.getEpochAddress() || LHS.isHandleInSync()) &&
1225 "handle not in sync!");
1226 assert((!RHS.getEpochAddress() || RHS.isHandleInSync()) &&
1227 "handle not in sync!");
1228 assert(LHS.getEpochAddress() == RHS.getEpochAddress() &&
1229 "comparing incomparable iterators!");
1230 return LHS.Ptr == RHS.Ptr;
1231 }
1232
1233 [[nodiscard]] friend bool operator!=(const DenseMapIterator &LHS,
1234 const DenseMapIterator &RHS) {
1235 return !(LHS == RHS);
1236 }
1237
1238 inline DenseMapIterator &operator++() { // Preincrement
1239 assert(isHandleInSync() && "invalid iterator access!");
1240 assert(Ptr != End && "incrementing end() iterator");
1241 ++Ptr;
1242 AdvancePastEmptyBuckets();
1243 return *this;
1244 }
1245 DenseMapIterator operator++(int) { // Postincrement
1246 assert(isHandleInSync() && "invalid iterator access!");
1247 DenseMapIterator tmp = *this;
1248 ++*this;
1249 return tmp;
1250 }
1251
1252private:
1253 void AdvancePastEmptyBuckets() {
1254 assert(Ptr <= End);
1255 const KeyT Empty = KeyInfoT::getEmptyKey();
1256 const KeyT Tombstone = KeyInfoT::getTombstoneKey();
1257
1258 while (Ptr != End && (KeyInfoT::isEqual(Ptr->getFirst(), Empty) ||
1259 KeyInfoT::isEqual(Ptr->getFirst(), Tombstone)))
1260 ++Ptr;
1261 }
1262
1263 static auto maybeReverse(iterator_range<pointer> Range) {
1264 if constexpr (shouldReverseIterate<KeyT>())
1265 return reverse(Range);
1266 else
1267 return Range;
1268 }
1269};
1270
1271template <typename KeyT, typename ValueT, typename KeyInfoT>
1272[[nodiscard]] inline size_t
1274 return X.getMemorySize();
1275}
1276
1277} // end namespace llvm
1278
1279#endif // LLVM_ADT_DENSEMAP_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
aarch64 promote const
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_UNLIKELY(EXPR)
Definition Compiler.h:336
#define LLVM_LIKELY(EXPR)
Definition Compiler.h:335
This file defines DenseMapInfo traits for DenseMap.
This file defines the DebugEpochBase and DebugEpochBase::HandleBase classes.
#define I(x, y, z)
Definition MD5.cpp:57
This file defines counterparts of C library allocation functions defined in the namespace 'std'.
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
#define P(N)
if(PassOpts->AAPipeline)
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 TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
LocallyHashedType DenseMapInfo< LocallyHashedType >::Empty
LocallyHashedType DenseMapInfo< LocallyHashedType >::Tombstone
static int Lookup(ArrayRef< TableEntry > Table, unsigned Opcode)
Value * RHS
Value * LHS
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
Definition DenseMap.h:205
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:178
void copyFrom(const DerivedT &other)
Definition DenseMap.h:447
unsigned size_type
Definition DenseMap.h:69
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:248
std::pair< iterator, bool > insert(std::pair< KeyT, ValueT > &&KV)
Definition DenseMap.h:240
bool erase(const KeyT &Val)
Definition DenseMap.h:322
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT > iterator
Definition DenseMap.h:74
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:266
void moveFromImpl(iterator_range< BucketT * > OldBuckets)
Definition DenseMap.h:416
void moveFrom(DerivedT &Other)
Definition DenseMap.h:445
DenseMapBase()=default
const_iterator find_as(const LookupKeyT &Val) const
Definition DenseMap.h:197
const_iterator end() const
Definition DenseMap.h:87
void moveFromOldBuckets(iterator_range< BucketT * > OldBuckets)
Definition DenseMap.h:439
iterator find_as(const LookupKeyT &Val)
Alternate version of find() which allows a different, and possibly less expensive,...
Definition DenseMap.h:191
unsigned size() const
Definition DenseMap.h:110
const_iterator find(const_arg_type_t< KeyT > Val) const
Definition DenseMap.h:181
bool empty() const
Definition DenseMap.h:109
std::pair< iterator, bool > emplace_or_assign(const KeyT &Key, Ts &&...Args)
Definition DenseMap.h:307
void insert(InputIt I, InputIt E)
insert - Range insertion of pairs.
Definition DenseMap.h:280
iterator begin()
Definition DenseMap.h:78
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:174
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT, true > const_iterator
Definition DenseMap.h:75
iterator end()
Definition DenseMap.h:81
const ValueT & at(const_arg_type_t< KeyT > Val) const
at - Return the entry for the specified key, or abort if no such entry exists.
Definition DenseMap.h:224
bool isPointerIntoBucketsArray(const void *Ptr) const
isPointerIntoBucketsArray - Return true if the specified pointer points somewhere into the DenseMap's...
Definition DenseMap.h:352
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
Definition DenseMap.h:169
std::pair< iterator, bool > try_emplace(const KeyT &Key, Ts &&...Args)
Definition DenseMap.h:256
const_iterator begin() const
Definition DenseMap.h:84
std::pair< iterator, bool > emplace_or_assign(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:315
void insert_range(Range &&R)
Inserts range of 'std::pair<KeyT, ValueT>' values into the map.
Definition DenseMap.h:286
const void * getPointerIntoBucketsArray() const
getPointerIntoBucketsArray() - Return an opaque pointer into the buckets array.
Definition DenseMap.h:359
std::pair< iterator, bool > insert_or_assign(KeyT &&Key, V &&Val)
Definition DenseMap.h:299
ValueT lookup_or(const_arg_type_t< KeyT > Val, U &&Default) const
Definition DenseMap.h:215
unsigned getMinBucketToReserveForEntries(unsigned NumEntries)
Returns the number of buckets to allocate to ensure that the DenseMap can accommodate NumEntries with...
Definition DenseMap.h:407
void swap(DerivedT &RHS)
Definition DenseMap.h:363
ValueT & operator[](const KeyT &Key)
Definition DenseMap.h:341
BucketT value_type
Definition DenseMap.h:72
auto keys() const
Definition DenseMap.h:101
void shrink_and_clear()
Definition DenseMap.h:157
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:233
void erase(iterator I)
Definition DenseMap.h:333
std::pair< iterator, bool > insert_or_assign(const KeyT &Key, V &&Val)
Definition DenseMap.h:291
void reserve(size_type NumEntries)
Grow the densemap so that it can contain at least NumEntries items before resizing again.
Definition DenseMap.h:114
ValueT & operator[](KeyT &&Key)
Definition DenseMap.h:345
auto values() const
Definition DenseMap.h:105
size_t getMemorySize() const
Return the approximate size (in bytes) of the actual map.
Definition DenseMap.h:682
std::conditional_t< IsConst, const BucketT, BucketT > value_type
Definition DenseMap.h:1159
static DenseMapIterator makeIterator(pointer P, iterator_range< pointer > Buckets, const DebugEpochBase &Epoch)
Definition DenseMap.h:1198
friend bool operator!=(const DenseMapIterator &LHS, const DenseMapIterator &RHS)
Definition DenseMap.h:1233
DenseMapIterator & operator++()
Definition DenseMap.h:1238
pointer operator->() const
Definition DenseMap.h:1220
reference operator*() const
Definition DenseMap.h:1215
static DenseMapIterator makeBegin(iterator_range< pointer > Buckets, bool IsEmpty, const DebugEpochBase &Epoch)
Definition DenseMap.h:1180
DenseMapIterator operator++(int)
Definition DenseMap.h:1245
DenseMapIterator(const DenseMapIterator< KeyT, ValueT, KeyInfoT, Bucket, IsConstSrc > &I)
Definition DenseMap.h:1211
friend bool operator==(const DenseMapIterator &LHS, const DenseMapIterator &RHS)
Definition DenseMap.h:1222
static DenseMapIterator makeEnd(iterator_range< pointer > Buckets, const DebugEpochBase &Epoch)
Definition DenseMap.h:1192
DenseMap(std::initializer_list< typename BaseT::value_type > Vals)
Definition DenseMap.h:763
DenseMap(unsigned NumElementsToReserve=0)
Create a DenseMap with an optional NumElementsToReserve to guarantee that this number of elements can...
Definition DenseMap.h:740
DenseMap & operator=(DenseMap &&other)
Definition DenseMap.h:786
DenseMap(llvm::from_range_t, const RangeT &Range)
Definition DenseMap.h:760
DenseMap(const DenseMap &other)
Definition DenseMap.h:744
DenseMap(const InputIt &I, const InputIt &E)
Definition DenseMap.h:754
DenseMap(DenseMap &&other)
Definition DenseMap.h:749
DenseMap & operator=(const DenseMap &other)
Definition DenseMap.h:780
SmallDenseMap(const InputIt &I, const InputIt &E)
Definition DenseMap.h:920
SmallDenseMap & operator=(SmallDenseMap &&other)
Definition DenseMap.h:1016
SmallDenseMap(unsigned NumElementsToReserve=0)
Definition DenseMap.h:905
SmallDenseMap(std::initializer_list< typename BaseT::value_type > Vals)
Definition DenseMap.h:929
SmallDenseMap(SmallDenseMap &&other)
Definition DenseMap.h:914
SmallDenseMap(const SmallDenseMap &other)
Definition DenseMap.h:909
SmallDenseMap(llvm::from_range_t, const RangeT &Range)
Definition DenseMap.h:926
A range adaptor for a pair of iterators.
constexpr char IsConst[]
Key for Kernel::Arg::Metadata::mIsConst.
A self-contained host- and target-independent arbitrary-precision floating-point software implementat...
Definition ADL.h:123
constexpr double e
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:477
bool isEqual(const GCNRPTracker::LiveRegSet &S1, const GCNRPTracker::LiveRegSet &S2)
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:844
bool operator!=(uint64_t V1, const APInt &V2)
Definition APInt.h:2114
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)
Definition STLExtras.h:364
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
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
iterator_range(Container &&) -> iterator_range< llvm::detail::IterOfRange< Container > >
@ Other
Any other memory.
Definition ModRef.h:68
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1867
@ Default
The result values are 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:867
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:869
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:51
const KeyT & getFirst() const
Definition DenseMap.h:49