LLVM 23.0.0git
DenseMap.h
Go to the documentation of this file.
1//===- llvm/ADT/DenseMap.h - Dense probed hash table ------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file defines the DenseMap class.
11///
12//===----------------------------------------------------------------------===//
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
56// Befriended below so DenseMapBase can expose its bucket-relocation callback
57// erase to ValueHandleBase, the only caller that caches bucket pointers.
58class ValueHandleBase;
59
60template <typename KeyT, typename ValueT,
61 typename KeyInfoT = DenseMapInfo<KeyT>,
63 bool IsConst = false>
64class DenseMapIterator;
65
66template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
67 typename BucketT>
69 template <typename T>
70 using const_arg_type_t = typename const_pointer_or_const_ref<T>::type;
71
72public:
74 using key_type = KeyT;
75 using mapped_type = ValueT;
76 using value_type = BucketT;
77
81
82 [[nodiscard]] inline iterator begin() {
83 return iterator::makeBegin(buckets(), empty(), *this);
84 }
85 [[nodiscard]] inline iterator end() {
86 return iterator::makeEnd(buckets(), *this);
87 }
88 [[nodiscard]] inline const_iterator begin() const {
89 return const_iterator::makeBegin(buckets(), empty(), *this);
90 }
91 [[nodiscard]] inline const_iterator end() const {
92 return const_iterator::makeEnd(buckets(), *this);
93 }
94
95 // Return an iterator to iterate over keys in the map.
96 [[nodiscard]] inline auto keys() {
97 return map_range(*this, [](const BucketT &P) { return P.getFirst(); });
98 }
99
100 // Return an iterator to iterate over values in the map.
101 [[nodiscard]] inline auto values() {
102 return map_range(*this, [](const BucketT &P) { return P.getSecond(); });
103 }
104
105 [[nodiscard]] inline auto keys() const {
106 return map_range(*this, [](const BucketT &P) { return P.getFirst(); });
107 }
108
109 [[nodiscard]] inline auto values() const {
110 return map_range(*this, [](const BucketT &P) { return P.getSecond(); });
111 }
112
113 [[nodiscard]] bool empty() const { return getNumEntries() == 0; }
114 [[nodiscard]] unsigned size() const { return getNumEntries(); }
115
116 /// Grow the densemap so that it can contain at least \p NumEntries items
117 /// before resizing again.
118 void reserve(size_type NumEntries) {
119 auto NumBuckets = getMinBucketToReserveForEntries(NumEntries);
121 if (NumBuckets > getNumBuckets())
122 grow(NumBuckets);
123 }
124
125 void clear() {
127 if (getNumEntries() == 0)
128 return;
129
130 // If the capacity of the array is huge, and the # elements used is small,
131 // shrink the array.
132 if (getNumEntries() * 4 < getNumBuckets() && getNumBuckets() > 64) {
134 return;
135 }
136
137 const KeyT EmptyKey = KeyInfoT::getEmptyKey();
138 if constexpr (std::is_trivially_destructible_v<ValueT>) {
139 // Use a simpler loop when values don't need destruction.
140 for (BucketT &B : buckets())
141 B.getFirst() = EmptyKey;
142 } else {
143 unsigned NumEntries = getNumEntries();
144 for (BucketT &B : buckets()) {
145 if (!KeyInfoT::isEqual(B.getFirst(), EmptyKey)) {
146 B.getSecond().~ValueT();
147 --NumEntries;
148 B.getFirst() = EmptyKey;
149 }
150 }
151 assert(NumEntries == 0 && "Node count imbalance!");
152 (void)NumEntries;
153 }
154 setNumEntries(0);
155 }
156
158 auto [Reallocate, NewNumBuckets] = derived().planShrinkAndClear();
159 destroyAll();
160 if (!Reallocate) {
161 initEmpty();
162 return;
163 }
164 derived().deallocateBuckets();
165 initWithExactBucketCount(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 /// Return the entry for the specified key, or a default constructed value if
204 /// 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 /// Return the entry for the specified key, or abort if no such entry exists.
223 [[nodiscard]] ValueT &at(const_arg_type_t<KeyT> Val) {
224 auto Iter = this->find(std::move(Val));
225 assert(Iter != this->end() && "DenseMap::at failed due to a missing key");
226 return Iter->second;
227 }
228
229 /// Return the entry for the specified key, or abort if no such entry exists.
230 [[nodiscard]] const ValueT &at(const_arg_type_t<KeyT> Val) const {
231 auto Iter = this->find(std::move(Val));
232 assert(Iter != this->end() && "DenseMap::at failed due to a missing key");
233 return Iter->second;
234 }
235
236 // Inserts key,value pair into the map if the key isn't already in the map.
237 // If the key is already in the map, it returns false and doesn't update the
238 // value.
239 std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) {
240 return try_emplace_impl(KV.first, KV.second);
241 }
242
243 // Inserts key,value pair into the map if the key isn't already in the map.
244 // If the key is already in the map, it returns false and doesn't update the
245 // value.
246 std::pair<iterator, bool> insert(std::pair<KeyT, ValueT> &&KV) {
247 return try_emplace_impl(std::move(KV.first), std::move(KV.second));
248 }
249
250 // Inserts key,value pair into the map if the key isn't already in the map.
251 // The value is constructed in-place if the key is not in the map, otherwise
252 // it is not moved.
253 template <typename... Ts>
254 std::pair<iterator, bool> try_emplace(KeyT &&Key, Ts &&...Args) {
255 return try_emplace_impl(std::move(Key), std::forward<Ts>(Args)...);
256 }
257
258 // Inserts key,value pair into the map if the key isn't already in the map.
259 // The value is constructed in-place if the key is not in the map, otherwise
260 // it is not moved.
261 template <typename... Ts>
262 std::pair<iterator, bool> try_emplace(const KeyT &Key, Ts &&...Args) {
263 return try_emplace_impl(Key, std::forward<Ts>(Args)...);
264 }
265
266 /// Alternate version of insert() which allows a different, and possibly
267 /// less expensive, key type.
268 /// The DenseMapInfo is responsible for supplying methods
269 /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key
270 /// type used.
271 template <typename LookupKeyT>
272 std::pair<iterator, bool> insert_as(std::pair<KeyT, ValueT> &&KV,
273 const LookupKeyT &Val) {
274 BucketT *TheBucket;
275 if (LookupBucketFor(Val, TheBucket))
276 return {makeIterator(TheBucket), false}; // Already in map.
277
278 // Otherwise, insert the new element.
279 TheBucket = findBucketForInsertion(Val, TheBucket);
280 TheBucket->getFirst() = std::move(KV.first);
281 ::new (&TheBucket->getSecond()) ValueT(std::move(KV.second));
282 return {makeIterator(TheBucket), true};
283 }
284
285 /// Range insertion of pairs.
286 template <typename InputIt> void insert(InputIt I, InputIt E) {
287 for (; I != E; ++I)
288 insert(*I);
289 }
290
291 /// Inserts range of 'std::pair<KeyT, ValueT>' values into the map.
292 template <typename Range> void insert_range(Range &&R) {
293 insert(adl_begin(R), adl_end(R));
294 }
295
296 template <typename V>
297 std::pair<iterator, bool> insert_or_assign(const KeyT &Key, V &&Val) {
298 auto Ret = try_emplace(Key, std::forward<V>(Val));
299 if (!Ret.second)
300 Ret.first->second = std::forward<V>(Val);
301 return Ret;
302 }
303
304 template <typename V>
305 std::pair<iterator, bool> insert_or_assign(KeyT &&Key, V &&Val) {
306 auto Ret = try_emplace(std::move(Key), std::forward<V>(Val));
307 if (!Ret.second)
308 Ret.first->second = std::forward<V>(Val);
309 return Ret;
310 }
311
312 template <typename... Ts>
313 std::pair<iterator, bool> emplace_or_assign(const KeyT &Key, Ts &&...Args) {
314 auto Ret = try_emplace(Key, std::forward<Ts>(Args)...);
315 if (!Ret.second)
316 Ret.first->second = ValueT(std::forward<Ts>(Args)...);
317 return Ret;
318 }
319
320 template <typename... Ts>
321 std::pair<iterator, bool> emplace_or_assign(KeyT &&Key, Ts &&...Args) {
322 auto Ret = try_emplace(std::move(Key), std::forward<Ts>(Args)...);
323 if (!Ret.second)
324 Ret.first->second = ValueT(std::forward<Ts>(Args)...);
325 return Ret;
326 }
327
328 void eraseFromFilledBucket(BucketT *TheBucket) {
329 eraseFromFilledBucket(TheBucket, [](BucketT &) {});
330 }
331
332 bool erase(const KeyT &Val) {
333 BucketT *TheBucket = doFind(Val);
334 if (!TheBucket)
335 return false; // not in map.
336
337 eraseFromFilledBucket(TheBucket);
338 return true;
339 }
341
342 /// Remove entries that match the given predicate. \p Pred is invoked
343 /// with a reference to each live bucket and must not access the map being
344 /// modified. This is the safe replacement for erase-while-iterating.
345 ///
346 /// Returns whether anything was removed. If so, all iterators and references
347 /// into the map are invalidated.
348 template <typename Predicate> bool remove_if(Predicate Pred) {
349 const KeyT EmptyKey = KeyInfoT::getEmptyKey();
350 unsigned NumBuckets = getNumBuckets();
351 bool Removed = false;
352 for (BucketT &B : buckets()) {
353 if (KeyInfoT::isEqual(B.getFirst(), EmptyKey))
354 continue;
355 if (Pred(B)) {
356 B.getSecond().~ValueT();
357 B.getFirst() = EmptyKey;
358 decrementNumEntries();
359 Removed = true;
360 }
361 }
362 if (Removed) {
364 this->grow(NumBuckets);
365 }
366 return Removed;
367 }
368
369 ValueT &operator[](const KeyT &Key) {
370 return lookupOrInsertIntoBucket(Key).first->second;
371 }
372
373 ValueT &operator[](KeyT &&Key) {
374 return lookupOrInsertIntoBucket(std::move(Key)).first->second;
375 }
376
377 /// Return true if the specified pointer points somewhere into the DenseMap's
378 /// array of buckets (i.e. either to a key or value in the DenseMap).
379 [[nodiscard]] bool isPointerIntoBucketsArray(const void *Ptr) const {
380 return Ptr >= getBuckets() && Ptr < getBucketsEnd();
381 }
382
383 /// getPointerIntoBucketsArray() - Return an opaque pointer into the buckets
384 /// array. In conjunction with the previous method, this can be used to
385 /// determine whether an insertion caused the DenseMap to reallocate.
386 [[nodiscard]] const void *getPointerIntoBucketsArray() const {
387 return getBuckets();
388 }
389
390 void swap(DerivedT &RHS) {
391 this->incrementEpoch();
392 RHS.incrementEpoch();
393 derived().swapImpl(RHS);
394 }
395
396protected:
397 DenseMapBase() = default;
398
400
401 void initWithExactBucketCount(unsigned NewNumBuckets) {
402 if (derived().allocateBuckets(NewNumBuckets))
403 initEmpty();
404 else
405 setNumEntries(0);
406 }
407
408 void destroyAll() {
409 // No need to iterate through the buckets if both KeyT and ValueT are
410 // trivially destructible.
411 if constexpr (std::is_trivially_destructible_v<KeyT> &&
412 std::is_trivially_destructible_v<ValueT>)
413 return;
414
415 if (getNumBuckets() == 0) // Nothing to do.
416 return;
417
418 const KeyT EmptyKey = KeyInfoT::getEmptyKey();
419 for (BucketT &B : buckets()) {
420 if (!KeyInfoT::isEqual(B.getFirst(), EmptyKey))
421 B.getSecond().~ValueT();
422 B.getFirst().~KeyT();
423 }
424 }
425
426 void initEmpty() {
427 static_assert(std::is_base_of_v<DenseMapBase, DerivedT>,
428 "Must pass the derived type to this template!");
429 setNumEntries(0);
430
431 assert((getNumBuckets() & (getNumBuckets() - 1)) == 0 &&
432 "# initial buckets must be a power of two!");
433 const KeyT EmptyKey = KeyInfoT::getEmptyKey();
434 for (BucketT &B : buckets())
435 ::new (&B.getFirst()) KeyT(EmptyKey);
436 }
437
438 /// Returns the number of buckets to allocate to ensure that the DenseMap can
439 /// accommodate \p NumEntries without need to grow().
440 unsigned getMinBucketToReserveForEntries(unsigned NumEntries) {
441 // Ensure that "NumEntries * 4 < NumBuckets * 3"
442 if (NumEntries == 0)
443 return 0;
444 // +1 is required because of the strict inequality.
445 // For example, if NumEntries is 48, we need to return 128.
446 return NextPowerOf2(NumEntries * 4 / 3 + 1);
447 }
448
449 // Move key/value from Other to *this.
450 // Other is left in a valid but empty state.
451 void moveFrom(DerivedT &Other) {
452 // Insert all the old elements.
453 const KeyT EmptyKey = KeyInfoT::getEmptyKey();
454 for (BucketT &B : Other.buckets()) {
455 if (!KeyInfoT::isEqual(B.getFirst(), EmptyKey)) {
456 // Insert the key/value into the new table.
457 BucketT *DestBucket;
458 bool FoundVal = LookupBucketFor(B.getFirst(), DestBucket);
459 (void)FoundVal; // silence warning.
460 assert(!FoundVal && "Key already in new map?");
461 DestBucket->getFirst() = std::move(B.getFirst());
462 ::new (&DestBucket->getSecond()) ValueT(std::move(B.getSecond()));
463 incrementNumEntries();
464
465 // Free the value.
466 B.getSecond().~ValueT();
467 }
468 B.getFirst().~KeyT();
469 }
470 Other.derived().kill();
471 }
472
473 void copyFrom(const DerivedT &other) {
474 this->destroyAll();
475 derived().deallocateBuckets();
476 setNumEntries(0);
477 if (!derived().allocateBuckets(other.getNumBuckets())) {
478 // The bucket list is empty. No work to do.
479 return;
480 }
481
482 assert(&other != this);
483 assert(getNumBuckets() == other.getNumBuckets());
484
485 setNumEntries(other.getNumEntries());
486
487 BucketT *Buckets = getBuckets();
488 const BucketT *OtherBuckets = other.getBuckets();
489 const size_t NumBuckets = getNumBuckets();
490 if constexpr (std::is_trivially_copyable_v<KeyT> &&
491 std::is_trivially_copyable_v<ValueT>) {
492 memcpy(reinterpret_cast<void *>(Buckets), OtherBuckets,
493 NumBuckets * sizeof(BucketT));
494 } else {
495 const KeyT EmptyKey = KeyInfoT::getEmptyKey();
496 for (size_t I = 0; I < NumBuckets; ++I) {
497 ::new (&Buckets[I].getFirst()) KeyT(OtherBuckets[I].getFirst());
498 if (!KeyInfoT::isEqual(Buckets[I].getFirst(), EmptyKey))
499 ::new (&Buckets[I].getSecond()) ValueT(OtherBuckets[I].getSecond());
500 }
501 }
502 }
503
504private:
505 // ValueHandleBase caches pointers into the bucket array, so it needs the
506 // callback erase below to fix them up as entries shift. It is the only
507 // intended caller; do not add new ones.
508 friend class ValueHandleBase;
509
510 /// Erase the entry at \p TheBucket and close the resulting hole via Knuth
511 /// TAOCP 6.4 Algorithm R. For callers that cache pointers into the bucket
512 /// array, call \p OnMoved per shifted bucket.
513 template <typename OnMovedT>
514 void eraseFromFilledBucket(BucketT *TheBucket, OnMovedT &&OnMoved) {
516 TheBucket->getSecond().~ValueT();
517 decrementNumEntries();
518
519 BucketT *BucketsPtr = getBuckets();
520 const unsigned NumBuckets = getNumBuckets();
521 const unsigned Mask = NumBuckets - 1;
522 const KeyT EmptyKey = KeyInfoT::getEmptyKey();
523 unsigned I = static_cast<unsigned>(TheBucket - BucketsPtr);
524 unsigned J = I;
525 while (true) {
526 J = (J + 1) & Mask;
527 BucketT &BJ = BucketsPtr[J];
528 if (KeyInfoT::isEqual(BJ.getFirst(), EmptyKey))
529 break;
530 auto Ideal = KeyInfoT::getHashValue(BJ.getFirst());
531 // If the hole (I) lies on the linear-probe chain from the home bucket
532 // (Ideal) to J, shift J into the hole and make J the new hole.
533 if (((I - Ideal) & Mask) < ((J - Ideal) & Mask)) {
534 BucketT &BI = BucketsPtr[I];
535 BI.getFirst() = std::move(BJ.getFirst());
536 ::new (&BI.getSecond()) ValueT(std::move(BJ.getSecond()));
537 BJ.getSecond().~ValueT();
538 OnMoved(BI);
539 I = J;
540 }
541 }
542 BucketsPtr[I].getFirst() = EmptyKey;
543 }
544
545 /// Erase \p Val and close the resulting hole by potentially shifting other
546 /// entries into it. For callers that cache pointers into the bucket array,
547 /// call \p OnMoved per shifted bucket.
548 template <typename OnMovedT> bool erase(const KeyT &Val, OnMovedT &&OnMoved) {
549 BucketT *TheBucket = doFind(Val);
550 if (!TheBucket)
551 return false;
552 eraseFromFilledBucket(TheBucket, std::forward<OnMovedT>(OnMoved));
553 return true;
554 }
555
556 DerivedT &derived() { return *static_cast<DerivedT *>(this); }
557 const DerivedT &derived() const {
558 return *static_cast<const DerivedT *>(this);
559 }
560
561 template <typename KeyArgT, typename... Ts>
562 std::pair<BucketT *, bool> lookupOrInsertIntoBucket(KeyArgT &&Key,
563 Ts &&...Args) {
564 BucketT *TheBucket = nullptr;
565 if (LookupBucketFor(Key, TheBucket))
566 return {TheBucket, false}; // Already in the map.
567
568 // Otherwise, insert the new element.
569 TheBucket = findBucketForInsertion(Key, TheBucket);
570 TheBucket->getFirst() = std::forward<KeyArgT>(Key);
571 ::new (&TheBucket->getSecond()) ValueT(std::forward<Ts>(Args)...);
572 return {TheBucket, true};
573 }
574
575 template <typename KeyArgT, typename... Ts>
576 std::pair<iterator, bool> try_emplace_impl(KeyArgT &&Key, Ts &&...Args) {
577 auto [Bucket, Inserted] = lookupOrInsertIntoBucket(
578 std::forward<KeyArgT>(Key), std::forward<Ts>(Args)...);
579 return {makeIterator(Bucket), Inserted};
580 }
581
582 iterator makeIterator(BucketT *TheBucket) {
583 return iterator::makeIterator(TheBucket, buckets(), *this);
584 }
585
586 const_iterator makeConstIterator(const BucketT *TheBucket) const {
587 return const_iterator::makeIterator(TheBucket, buckets(), *this);
588 }
589
590 unsigned getNumEntries() const { return derived().getNumEntries(); }
591
592 void setNumEntries(unsigned Num) { derived().setNumEntries(Num); }
593
594 void incrementNumEntries() { setNumEntries(getNumEntries() + 1); }
595
596 void decrementNumEntries() { setNumEntries(getNumEntries() - 1); }
597
598 const BucketT *getBuckets() const { return derived().getBuckets(); }
599
600 BucketT *getBuckets() { return derived().getBuckets(); }
601
602 unsigned getNumBuckets() const { return derived().getNumBuckets(); }
603
604 BucketT *getBucketsEnd() { return getBuckets() + getNumBuckets(); }
605
606 const BucketT *getBucketsEnd() const {
607 return getBuckets() + getNumBuckets();
608 }
609
610 iterator_range<BucketT *> buckets() {
611 return llvm::make_range(getBuckets(), getBucketsEnd());
612 }
613
614 iterator_range<const BucketT *> buckets() const {
615 return llvm::make_range(getBuckets(), getBucketsEnd());
616 }
617
618 void grow(unsigned MinNumBuckets) {
619 unsigned NumBuckets = DerivedT::roundUpNumBuckets(MinNumBuckets);
620 DerivedT Tmp(NumBuckets, ExactBucketCount{});
621 Tmp.moveFrom(derived());
622 if (derived().maybeMoveFast(std::move(Tmp)))
623 return;
624 initWithExactBucketCount(NumBuckets);
625 moveFrom(Tmp);
626 }
627
628 template <typename LookupKeyT>
629 BucketT *findBucketForInsertion(const LookupKeyT &Lookup,
630 BucketT *TheBucket) {
632
633 // Grow the table if the load factor would exceed 3/4 after insertion.
634 // Linear probing with gap-closing deletion (Knuth Algorithm R) keeps
635 // every chain compact and bounded by the table's empty-bucket count,
636 // so no tombstone-driven resize is needed.
637 unsigned NewNumEntries = getNumEntries() + 1;
638 unsigned NumBuckets = getNumBuckets();
639 if (LLVM_UNLIKELY(NewNumEntries * 4 >= NumBuckets * 3)) {
640 this->grow(NumBuckets * 2);
641 LookupBucketFor(Lookup, TheBucket);
642 }
643 assert(TheBucket);
644
645 // Only update the state after we've grown our bucket space appropriately
646 // so that when growing buckets we have self-consistent entry count.
647 incrementNumEntries();
648 return TheBucket;
649 }
650
651 template <typename LookupKeyT>
652 const BucketT *doFind(const LookupKeyT &Val) const {
653 const BucketT *BucketsPtr = getBuckets();
654 const unsigned NumBuckets = getNumBuckets();
655 if (NumBuckets == 0)
656 return nullptr;
657
658 const KeyT EmptyKey = KeyInfoT::getEmptyKey();
659 unsigned BucketNo = KeyInfoT::getHashValue(Val) & (NumBuckets - 1);
660 while (true) {
661 const BucketT *Bucket = BucketsPtr + BucketNo;
662 if (LLVM_LIKELY(KeyInfoT::isEqual(Val, Bucket->getFirst())))
663 return Bucket;
664 if (LLVM_LIKELY(KeyInfoT::isEqual(Bucket->getFirst(), EmptyKey)))
665 return nullptr;
666
667 // Hash collision: continue linear probing.
668 BucketNo = (BucketNo + 1) & (NumBuckets - 1);
669 }
670 }
671
672 template <typename LookupKeyT> BucketT *doFind(const LookupKeyT &Val) {
673 return const_cast<BucketT *>(
674 static_cast<const DenseMapBase *>(this)->doFind(Val));
675 }
676
677 /// Lookup the appropriate bucket for Val, returning it in FoundBucket. If the
678 /// bucket contains the key and a value, this returns true, otherwise it
679 /// returns a bucket with an empty marker and returns false.
680 template <typename LookupKeyT>
681 bool LookupBucketFor(const LookupKeyT &Val, BucketT *&FoundBucket) {
682 BucketT *BucketsPtr = getBuckets();
683 const unsigned NumBuckets = getNumBuckets();
684
685 if (NumBuckets == 0) {
686 FoundBucket = nullptr;
687 return false;
688 }
689
690 const KeyT EmptyKey = KeyInfoT::getEmptyKey();
691 assert(!KeyInfoT::isEqual(Val, EmptyKey) &&
692 "Empty value shouldn't be inserted into map!");
693
694 unsigned BucketNo = KeyInfoT::getHashValue(Val) & (NumBuckets - 1);
695 while (true) {
696 BucketT *ThisBucket = BucketsPtr + BucketNo;
697 // Found Val's bucket? If so, return it.
698 if (LLVM_LIKELY(KeyInfoT::isEqual(Val, ThisBucket->getFirst()))) {
699 FoundBucket = ThisBucket;
700 return true;
701 }
702
703 // If we found an empty bucket, the key doesn't exist in the set.
704 // Return it as the insertion point.
705 if (LLVM_LIKELY(KeyInfoT::isEqual(ThisBucket->getFirst(), EmptyKey))) {
706 FoundBucket = ThisBucket;
707 return false;
708 }
709
710 // Hash collision: continue linear probing.
711 BucketNo = (BucketNo + 1) & (NumBuckets - 1);
712 }
713 }
714
715public:
716 /// Return the approximate size (in bytes) of the actual map.
717 /// This is just the raw memory used by DenseMap.
718 /// If entries are pointers to objects, the size of the referenced objects
719 /// are not included.
720 [[nodiscard]] size_t getMemorySize() const {
721 return getNumBuckets() * sizeof(BucketT);
722 }
723};
724
725/// Equality comparison for DenseMap.
726///
727/// Iterates over elements of LHS confirming that each (key, value) pair in LHS
728/// is also in RHS, and that no additional pairs are in RHS.
729/// Equivalent to N calls to RHS.find and N value comparisons. Amortized
730/// complexity is linear, worst case is O(N^2) (if every hash collides).
731template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
732 typename BucketT>
733[[nodiscard]] bool
736 if (LHS.size() != RHS.size())
737 return false;
738
739 for (auto &KV : LHS) {
740 auto I = RHS.find(KV.first);
741 if (I == RHS.end() || I->second != KV.second)
742 return false;
743 }
744
745 return true;
746}
747
748/// Inequality comparison for DenseMap.
749///
750/// Equivalent to !(LHS == RHS). See operator== for performance notes.
751template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
752 typename BucketT>
753[[nodiscard]] bool
758
759template <typename KeyT, typename ValueT,
760 typename KeyInfoT = DenseMapInfo<KeyT>,
762class DenseMap : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>,
763 KeyT, ValueT, KeyInfoT, BucketT> {
764 friend class DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT>;
765
766 // Lift some types from the dependent base class into this class for
767 // simplicity of referring to them.
769
770 BucketT *Buckets = nullptr;
771 unsigned NumEntries = 0;
772 unsigned NumBuckets = 0;
773
774 explicit DenseMap(unsigned NumBuckets, typename BaseT::ExactBucketCount) {
775 this->initWithExactBucketCount(NumBuckets);
776 }
777
778public:
779 /// Create a DenseMap with an optional \p NumElementsToReserve to guarantee
780 /// that this number of elements can be inserted in the map without grow().
781 explicit DenseMap(unsigned NumElementsToReserve = 0)
782 : DenseMap(BaseT::getMinBucketToReserveForEntries(NumElementsToReserve),
783 typename BaseT::ExactBucketCount{}) {}
784
785 DenseMap(const DenseMap &other) : DenseMap() { this->copyFrom(other); }
786
787 DenseMap(DenseMap &&other) : DenseMap() { this->swap(other); }
788
789 template <typename InputIt>
790 DenseMap(const InputIt &I, const InputIt &E) : DenseMap(std::distance(I, E)) {
791 this->insert(I, E);
792 }
793
794 template <typename RangeT>
796 : DenseMap(adl_begin(Range), adl_end(Range)) {}
797
798 DenseMap(std::initializer_list<typename BaseT::value_type> Vals)
799 : DenseMap(Vals.begin(), Vals.end()) {}
800
802 this->destroyAll();
803 deallocateBuckets();
804 }
805
806 DenseMap &operator=(const DenseMap &other) {
807 if (&other != this)
808 this->copyFrom(other);
809 return *this;
810 }
811
812 DenseMap &operator=(DenseMap &&other) {
813 this->destroyAll();
814 deallocateBuckets();
816 this->swap(other);
817 return *this;
818 }
819
820private:
821 void swapImpl(DenseMap &RHS) {
822 std::swap(Buckets, RHS.Buckets);
823 std::swap(NumEntries, RHS.NumEntries);
824 std::swap(NumBuckets, RHS.NumBuckets);
825 }
826
827 unsigned getNumEntries() const { return NumEntries; }
828
829 void setNumEntries(unsigned Num) { NumEntries = Num; }
830
831 BucketT *getBuckets() const { return Buckets; }
832
833 unsigned getNumBuckets() const { return NumBuckets; }
834
835 void deallocateBuckets() {
836 deallocate_buffer(Buckets, sizeof(BucketT) * NumBuckets, alignof(BucketT));
837 }
838
839 bool allocateBuckets(unsigned Num) {
840 NumBuckets = Num;
841 if (NumBuckets == 0) {
842 Buckets = nullptr;
843 return false;
844 }
845
846 Buckets = static_cast<BucketT *>(
847 allocate_buffer(sizeof(BucketT) * NumBuckets, alignof(BucketT)));
848 return true;
849 }
850
851 // Put the zombie instance in a known good state after a move.
852 void kill() {
853 deallocateBuckets();
854 Buckets = nullptr;
855 NumBuckets = 0;
856 }
857
858 static unsigned roundUpNumBuckets(unsigned MinNumBuckets) {
859 return std::max(64u,
860 static_cast<unsigned>(NextPowerOf2(MinNumBuckets - 1)));
861 }
862
863 bool maybeMoveFast(DenseMap &&Other) {
864 swapImpl(Other);
865 return true;
866 }
867
868 // Plan how to shrink the bucket table. Return:
869 // - {false, 0} to reuse the existing bucket table
870 // - {true, N} to reallocate a bucket table with N entries
871 std::pair<bool, unsigned> planShrinkAndClear() const {
872 unsigned NewNumBuckets = 0;
873 if (NumEntries)
874 NewNumBuckets = std::max(64u, 1u << (Log2_32_Ceil(NumEntries) + 1));
875 if (NewNumBuckets == NumBuckets)
876 return {false, 0}; // Reuse.
877 return {true, NewNumBuckets}; // Reallocate.
878 }
879};
880
881template <typename KeyT, typename ValueT, unsigned InlineBuckets = 4,
882 typename KeyInfoT = DenseMapInfo<KeyT>,
884class SmallDenseMap
885 : public DenseMapBase<
886 SmallDenseMap<KeyT, ValueT, InlineBuckets, KeyInfoT, BucketT>, KeyT,
887 ValueT, KeyInfoT, BucketT> {
888 friend class DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT, BucketT>;
889
890 // Lift some types from the dependent base class into this class for
891 // simplicity of referring to them.
893
894 static_assert(isPowerOf2_64(InlineBuckets),
895 "InlineBuckets must be a power of 2.");
896
897 unsigned Small : 1;
898 unsigned NumEntries : 31;
899
900 struct LargeRep {
901 BucketT *Buckets;
902 unsigned NumBuckets;
904 return llvm::make_range(Buckets, Buckets + NumBuckets);
905 }
906 };
907
908 /// A "union" of an inline bucket array and the struct representing
909 /// a large bucket. This union will be discriminated by the 'Small' bit.
910 AlignedCharArrayUnion<BucketT[InlineBuckets], LargeRep> storage;
911
912 SmallDenseMap(unsigned NumBuckets, typename BaseT::ExactBucketCount) {
913 this->initWithExactBucketCount(NumBuckets);
914 }
915
916public:
917 explicit SmallDenseMap(unsigned NumElementsToReserve = 0)
918 : SmallDenseMap(
919 BaseT::getMinBucketToReserveForEntries(NumElementsToReserve),
920 typename BaseT::ExactBucketCount{}) {}
921
922 SmallDenseMap(const SmallDenseMap &other) : SmallDenseMap() {
923 this->copyFrom(other);
924 }
925
926 SmallDenseMap(SmallDenseMap &&other) : SmallDenseMap() { this->swap(other); }
927
928 template <typename InputIt>
929 SmallDenseMap(const InputIt &I, const InputIt &E)
930 : SmallDenseMap(std::distance(I, E)) {
931 this->insert(I, E);
932 }
933
934 template <typename RangeT>
936 : SmallDenseMap(adl_begin(Range), adl_end(Range)) {}
937
938 SmallDenseMap(std::initializer_list<typename BaseT::value_type> Vals)
939 : SmallDenseMap(Vals.begin(), Vals.end()) {}
940
942 this->destroyAll();
943 deallocateBuckets();
944 }
945
946 SmallDenseMap &operator=(const SmallDenseMap &other) {
947 if (&other != this)
948 this->copyFrom(other);
949 return *this;
950 }
951
952 SmallDenseMap &operator=(SmallDenseMap &&other) {
953 this->destroyAll();
954 deallocateBuckets();
956 this->swap(other);
957 return *this;
958 }
959
960private:
961 void swapImpl(SmallDenseMap &RHS) {
962 unsigned TmpNumEntries = RHS.NumEntries;
963 RHS.NumEntries = NumEntries;
964 NumEntries = TmpNumEntries;
965
966 const KeyT EmptyKey = KeyInfoT::getEmptyKey();
967 if (Small && RHS.Small) {
968 // If we're swapping inline bucket arrays, we have to cope with some of
969 // the tricky bits of DenseMap's storage system: the buckets are not
970 // fully initialized. Thus we swap every key, but we may have
971 // a one-directional move of the value.
972 for (unsigned i = 0, e = InlineBuckets; i != e; ++i) {
973 BucketT *LHSB = &getInlineBuckets()[i],
974 *RHSB = &RHS.getInlineBuckets()[i];
975 bool hasLHSValue = !KeyInfoT::isEqual(LHSB->getFirst(), EmptyKey);
976 bool hasRHSValue = !KeyInfoT::isEqual(RHSB->getFirst(), EmptyKey);
977 if (hasLHSValue && hasRHSValue) {
978 // Swap together if we can...
979 std::swap(*LHSB, *RHSB);
980 continue;
981 }
982 // Swap separately and handle any asymmetry.
983 std::swap(LHSB->getFirst(), RHSB->getFirst());
984 if (hasLHSValue) {
985 ::new (&RHSB->getSecond()) ValueT(std::move(LHSB->getSecond()));
986 LHSB->getSecond().~ValueT();
987 } else if (hasRHSValue) {
988 ::new (&LHSB->getSecond()) ValueT(std::move(RHSB->getSecond()));
989 RHSB->getSecond().~ValueT();
990 }
991 }
992 return;
993 }
994 if (!Small && !RHS.Small) {
995 std::swap(*getLargeRep(), *RHS.getLargeRep());
996 return;
997 }
998
999 SmallDenseMap &SmallSide = Small ? *this : RHS;
1000 SmallDenseMap &LargeSide = Small ? RHS : *this;
1001
1002 // First stash the large side's rep and move the small side across.
1003 LargeRep TmpRep = std::move(*LargeSide.getLargeRep());
1004 LargeSide.getLargeRep()->~LargeRep();
1005 LargeSide.Small = true;
1006 // This is similar to the standard move-from-old-buckets, but the bucket
1007 // count hasn't actually rotated in this case. So we have to carefully
1008 // move construct the keys and values into their new locations, but there
1009 // is no need to re-hash things.
1010 for (unsigned i = 0, e = InlineBuckets; i != e; ++i) {
1011 BucketT *NewB = &LargeSide.getInlineBuckets()[i],
1012 *OldB = &SmallSide.getInlineBuckets()[i];
1013 ::new (&NewB->getFirst()) KeyT(std::move(OldB->getFirst()));
1014 OldB->getFirst().~KeyT();
1015 if (!KeyInfoT::isEqual(NewB->getFirst(), EmptyKey)) {
1016 ::new (&NewB->getSecond()) ValueT(std::move(OldB->getSecond()));
1017 OldB->getSecond().~ValueT();
1018 }
1019 }
1020
1021 // The hard part of moving the small buckets across is done, just move
1022 // the TmpRep into its new home.
1023 SmallSide.Small = false;
1024 new (SmallSide.getLargeRep()) LargeRep(std::move(TmpRep));
1025 }
1026
1027 unsigned getNumEntries() const { return NumEntries; }
1028
1029 void setNumEntries(unsigned Num) {
1030 // NumEntries is hardcoded to be 31 bits wide.
1031 assert(Num < (1U << 31) && "Cannot support more than 1<<31 entries");
1032 NumEntries = Num;
1033 }
1034
1035 const BucketT *getInlineBuckets() const {
1036 assert(Small);
1037 // Note that this cast does not violate aliasing rules as we assert that
1038 // the memory's dynamic type is the small, inline bucket buffer, and the
1039 // 'storage' is a POD containing a char buffer.
1040 return reinterpret_cast<const BucketT *>(&storage);
1041 }
1042
1043 BucketT *getInlineBuckets() {
1044 return const_cast<BucketT *>(
1045 const_cast<const SmallDenseMap *>(this)->getInlineBuckets());
1046 }
1047
1048 const LargeRep *getLargeRep() const {
1049 assert(!Small);
1050 // Note, same rule about aliasing as with getInlineBuckets.
1051 return reinterpret_cast<const LargeRep *>(&storage);
1052 }
1053
1054 LargeRep *getLargeRep() {
1055 return const_cast<LargeRep *>(
1056 const_cast<const SmallDenseMap *>(this)->getLargeRep());
1057 }
1058
1059 const BucketT *getBuckets() const {
1060 return Small ? getInlineBuckets() : getLargeRep()->Buckets;
1061 }
1062
1063 BucketT *getBuckets() {
1064 return const_cast<BucketT *>(
1065 const_cast<const SmallDenseMap *>(this)->getBuckets());
1066 }
1067
1068 unsigned getNumBuckets() const {
1069 return Small ? InlineBuckets : getLargeRep()->NumBuckets;
1070 }
1071
1072 iterator_range<BucketT *> inlineBuckets() {
1073 BucketT *Begin = getInlineBuckets();
1074 return llvm::make_range(Begin, Begin + InlineBuckets);
1075 }
1076
1077 void deallocateBuckets() {
1078 // Fast path to deallocateBuckets in case getLargeRep()->NumBuckets == 0,
1079 // just like destroyAll. This path is used to destruct zombie instances
1080 // after moves.
1081 if (Small || getLargeRep()->NumBuckets == 0)
1082 return;
1083
1084 deallocate_buffer(getLargeRep()->Buckets,
1085 sizeof(BucketT) * getLargeRep()->NumBuckets,
1086 alignof(BucketT));
1087 getLargeRep()->~LargeRep();
1088 }
1089
1090 bool allocateBuckets(unsigned Num) {
1091 if (Num <= InlineBuckets) {
1092 Small = true;
1093 } else {
1094 Small = false;
1095 BucketT *NewBuckets = static_cast<BucketT *>(
1096 allocate_buffer(sizeof(BucketT) * Num, alignof(BucketT)));
1097 new (getLargeRep()) LargeRep{NewBuckets, Num};
1098 }
1099 return true;
1100 }
1101
1102 // Put the zombie instance in a known good state after a move.
1103 void kill() {
1104 deallocateBuckets();
1105 Small = false;
1106 new (getLargeRep()) LargeRep{nullptr, 0};
1107 }
1108
1109 static unsigned roundUpNumBuckets(unsigned MinNumBuckets) {
1110 if (MinNumBuckets <= InlineBuckets)
1111 return MinNumBuckets;
1112 return std::max(64u,
1113 static_cast<unsigned>(NextPowerOf2(MinNumBuckets - 1)));
1114 }
1115
1116 bool maybeMoveFast(SmallDenseMap &&Other) {
1117 if (Other.Small)
1118 return false;
1119
1120 Small = false;
1121 NumEntries = Other.NumEntries;
1122 *getLargeRep() = std::move(*Other.getLargeRep());
1123 Other.getLargeRep()->NumBuckets = 0;
1124 return true;
1125 }
1126
1127 // Plan how to shrink the bucket table. Return:
1128 // - {false, 0} to reuse the existing bucket table
1129 // - {true, N} to reallocate a bucket table with N entries
1130 std::pair<bool, unsigned> planShrinkAndClear() const {
1131 unsigned NewNumBuckets = 0;
1132 if (!this->empty()) {
1133 NewNumBuckets = 1u << (Log2_32_Ceil(this->size()) + 1);
1134 if (NewNumBuckets > InlineBuckets)
1135 NewNumBuckets = std::max(64u, NewNumBuckets);
1136 }
1137 bool Reuse = Small ? NewNumBuckets <= InlineBuckets
1138 : NewNumBuckets == getLargeRep()->NumBuckets;
1139 if (Reuse)
1140 return {false, 0}; // Reuse.
1141 return {true, NewNumBuckets}; // Reallocate.
1142 }
1143};
1144
1145template <typename KeyT, typename ValueT, typename KeyInfoT, typename Bucket,
1146 bool IsConst>
1147class DenseMapIterator : DebugEpochBase::HandleBase {
1148 friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true>;
1149 friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, false>;
1150
1151public:
1153 using value_type = std::conditional_t<IsConst, const Bucket, Bucket>;
1156 using iterator_category = std::forward_iterator_tag;
1157
1158private:
1159 using BucketItTy =
1160 std::conditional_t<shouldReverseIterate<KeyT>(),
1161 std::reverse_iterator<pointer>, pointer>;
1162
1163 BucketItTy Ptr = {};
1164 BucketItTy End = {};
1165
1166 DenseMapIterator(BucketItTy Pos, BucketItTy E, const DebugEpochBase &Epoch)
1167 : DebugEpochBase::HandleBase(&Epoch), Ptr(Pos), End(E) {
1168 assert(isHandleInSync() && "invalid construction!");
1169 }
1170
1171public:
1172 DenseMapIterator() = default;
1173
1174 static DenseMapIterator makeBegin(iterator_range<pointer> Buckets,
1175 bool IsEmpty, const DebugEpochBase &Epoch) {
1176 // When the map is empty, avoid the overhead of advancing/retreating past
1177 // empty buckets.
1178 if (IsEmpty)
1179 return makeEnd(Buckets, Epoch);
1180 auto R = maybeReverse(Buckets);
1181 DenseMapIterator Iter(R.begin(), R.end(), Epoch);
1182 Iter.AdvancePastEmptyBuckets();
1183 return Iter;
1184 }
1185
1186 static DenseMapIterator makeEnd(iterator_range<pointer> Buckets,
1187 const DebugEpochBase &Epoch) {
1188 auto R = maybeReverse(Buckets);
1189 return DenseMapIterator(R.end(), R.end(), Epoch);
1190 }
1191
1192 static DenseMapIterator makeIterator(pointer P,
1194 const DebugEpochBase &Epoch) {
1195 auto R = maybeReverse(Buckets);
1196 constexpr int Offset = shouldReverseIterate<KeyT>() ? 1 : 0;
1197 return DenseMapIterator(BucketItTy(P + Offset), R.end(), Epoch);
1198 }
1199
1200 // Converting ctor from non-const iterators to const iterators. SFINAE'd out
1201 // for const iterator destinations so it doesn't end up as a user defined copy
1202 // constructor.
1203 template <bool IsConstSrc,
1204 typename = std::enable_if_t<!IsConstSrc && IsConst>>
1206 const DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, IsConstSrc> &I)
1207 : DebugEpochBase::HandleBase(I), Ptr(I.Ptr), End(I.End) {}
1208
1209 [[nodiscard]] reference operator*() const {
1210 assert(isHandleInSync() && "invalid iterator access!");
1211 assert(Ptr != End && "dereferencing end() iterator");
1212 return *Ptr;
1213 }
1214 [[nodiscard]] pointer operator->() const { return &operator*(); }
1215
1216 [[nodiscard]] friend bool operator==(const DenseMapIterator &LHS,
1217 const DenseMapIterator &RHS) {
1218 assert((!LHS.getEpochAddress() || LHS.isHandleInSync()) &&
1219 "handle not in sync!");
1220 assert((!RHS.getEpochAddress() || RHS.isHandleInSync()) &&
1221 "handle not in sync!");
1222 assert(LHS.getEpochAddress() == RHS.getEpochAddress() &&
1223 "comparing incomparable iterators!");
1224 return LHS.Ptr == RHS.Ptr;
1225 }
1226
1227 [[nodiscard]] friend bool operator!=(const DenseMapIterator &LHS,
1228 const DenseMapIterator &RHS) {
1229 return !(LHS == RHS);
1230 }
1231
1232 inline DenseMapIterator &operator++() { // Preincrement
1233 assert(isHandleInSync() && "invalid iterator access!");
1234 assert(Ptr != End && "incrementing end() iterator");
1235 ++Ptr;
1236 AdvancePastEmptyBuckets();
1237 return *this;
1238 }
1239 DenseMapIterator operator++(int) { // Postincrement
1240 assert(isHandleInSync() && "invalid iterator access!");
1241 DenseMapIterator tmp = *this;
1242 ++*this;
1243 return tmp;
1244 }
1245
1246private:
1247 void AdvancePastEmptyBuckets() {
1248 assert(Ptr <= End);
1249 const KeyT Empty = KeyInfoT::getEmptyKey();
1250
1251 while (Ptr != End && KeyInfoT::isEqual(Ptr->getFirst(), Empty))
1252 ++Ptr;
1253 }
1254
1255 static auto maybeReverse(iterator_range<pointer> Range) {
1256 if constexpr (shouldReverseIterate<KeyT>())
1257 return reverse(Range);
1258 else
1259 return Range;
1260 }
1261};
1262
1263template <typename KeyT, typename ValueT, typename KeyInfoT>
1264[[nodiscard]] inline size_t
1266 return X.getMemorySize();
1267}
1268
1269} // end namespace llvm
1270
1271#endif // LLVM_ADT_DENSEMAP_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
aarch64 promote const
static bool isEqual(const Function &Caller, const Function &Callee)
#define X(NUM, ENUM, NAME)
Definition ELF.h:853
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_UNLIKELY(EXPR)
Definition Compiler.h:336
#define LLVM_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.
LocallyHashedType DenseMapInfo< LocallyHashedType >::Empty
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:223
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:205
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:178
void copyFrom(const DerivedT &other)
Definition DenseMap.h:473
unsigned size_type
Definition DenseMap.h:73
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:254
std::pair< iterator, bool > insert(std::pair< KeyT, ValueT > &&KV)
Definition DenseMap.h:246
bool erase(const KeyT &Val)
Definition DenseMap.h:332
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT > iterator
Definition DenseMap.h:78
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:272
void moveFrom(DerivedT &Other)
Definition DenseMap.h:451
DenseMapBase()=default
const_iterator find_as(const LookupKeyT &Val) const
Definition DenseMap.h:197
const_iterator end() const
Definition DenseMap.h:91
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:114
const_iterator find(const_arg_type_t< KeyT > Val) const
Definition DenseMap.h:181
bool empty() const
Definition DenseMap.h:113
std::pair< iterator, bool > emplace_or_assign(const KeyT &Key, Ts &&...Args)
Definition DenseMap.h:313
void insert(InputIt I, InputIt E)
Range insertion of pairs.
Definition DenseMap.h:286
iterator begin()
Definition DenseMap.h:82
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:79
bool remove_if(Predicate Pred)
Remove entries that match the given predicate.
Definition DenseMap.h:348
iterator end()
Definition DenseMap.h:85
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:230
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:379
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:262
const_iterator begin() const
Definition DenseMap.h:88
std::pair< iterator, bool > emplace_or_assign(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:321
void insert_range(Range &&R)
Inserts range of 'std::pair<KeyT, ValueT>' values into the map.
Definition DenseMap.h:292
const void * getPointerIntoBucketsArray() const
getPointerIntoBucketsArray() - Return an opaque pointer into the buckets array.
Definition DenseMap.h:386
std::pair< iterator, bool > insert_or_assign(KeyT &&Key, V &&Val)
Definition DenseMap.h:305
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:440
void swap(DerivedT &RHS)
Definition DenseMap.h:390
ValueT & operator[](const KeyT &Key)
Definition DenseMap.h:369
BucketT value_type
Definition DenseMap.h:76
auto keys() const
Definition DenseMap.h:105
void initWithExactBucketCount(unsigned NewNumBuckets)
Definition DenseMap.h:401
void eraseFromFilledBucket(BucketT *TheBucket)
Definition DenseMap.h:328
void shrink_and_clear()
Definition DenseMap.h:157
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:239
void erase(iterator I)
Definition DenseMap.h:340
std::pair< iterator, bool > insert_or_assign(const KeyT &Key, V &&Val)
Definition DenseMap.h:297
void reserve(size_type NumEntries)
Grow the densemap so that it can contain at least NumEntries items before resizing again.
Definition DenseMap.h:118
ValueT & operator[](KeyT &&Key)
Definition DenseMap.h:373
auto values() const
Definition DenseMap.h:109
size_t getMemorySize() const
Return the approximate size (in bytes) of the actual map.
Definition DenseMap.h:720
std::conditional_t< IsConst, const BucketT, BucketT > value_type
Definition DenseMap.h:1153
static DenseMapIterator makeIterator(pointer P, iterator_range< pointer > Buckets, const DebugEpochBase &Epoch)
Definition DenseMap.h:1192
friend bool operator!=(const DenseMapIterator &LHS, const DenseMapIterator &RHS)
Definition DenseMap.h:1227
DenseMapIterator & operator++()
Definition DenseMap.h:1232
pointer operator->() const
Definition DenseMap.h:1214
reference operator*() const
Definition DenseMap.h:1209
static DenseMapIterator makeBegin(iterator_range< pointer > Buckets, bool IsEmpty, const DebugEpochBase &Epoch)
Definition DenseMap.h:1174
DenseMapIterator operator++(int)
Definition DenseMap.h:1239
DenseMapIterator(const DenseMapIterator< KeyT, ValueT, KeyInfoT, Bucket, IsConstSrc > &I)
Definition DenseMap.h:1205
friend bool operator==(const DenseMapIterator &LHS, const DenseMapIterator &RHS)
Definition DenseMap.h:1216
static DenseMapIterator makeEnd(iterator_range< pointer > Buckets, const DebugEpochBase &Epoch)
Definition DenseMap.h:1186
DenseMap(std::initializer_list< typename BaseT::value_type > Vals)
Definition DenseMap.h:798
DenseMap(unsigned NumElementsToReserve=0)
Create a DenseMap with an optional NumElementsToReserve to guarantee that this number of elements can...
Definition DenseMap.h:781
DenseMap & operator=(DenseMap &&other)
Definition DenseMap.h:812
DenseMap(llvm::from_range_t, const RangeT &Range)
Definition DenseMap.h:795
DenseMap(const DenseMap &other)
Definition DenseMap.h:785
DenseMap(const InputIt &I, const InputIt &E)
Definition DenseMap.h:790
DenseMap(DenseMap &&other)
Definition DenseMap.h:787
DenseMap & operator=(const DenseMap &other)
Definition DenseMap.h:806
SmallDenseMap(const InputIt &I, const InputIt &E)
Definition DenseMap.h:929
SmallDenseMap & operator=(SmallDenseMap &&other)
Definition DenseMap.h:952
SmallDenseMap & operator=(const SmallDenseMap &other)
Definition DenseMap.h:946
SmallDenseMap(unsigned NumElementsToReserve=0)
Definition DenseMap.h:917
SmallDenseMap(std::initializer_list< typename BaseT::value_type > Vals)
Definition DenseMap.h:938
SmallDenseMap(SmallDenseMap &&other)
Definition DenseMap.h:926
SmallDenseMap(const SmallDenseMap &other)
Definition DenseMap.h:922
SmallDenseMap(llvm::from_range_t, const RangeT &Range)
Definition DenseMap.h:935
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
bool empty() const
Definition BasicBlock.h:101
This is an optimization pass for GlobalISel generic memory operations.
unsigned Log2_32_Ceil(uint32_t Value)
Return the ceil log base 2 of the specified value, 32 if the value is zero.
Definition MathExtras.h:344
@ Offset
Definition DWP.cpp:558
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition STLExtras.h:1668
constexpr auto adl_begin(RangeT &&range) -> decltype(adl_detail::begin_impl(std::forward< RangeT >(range)))
Returns the begin iterator to range using std::begin and function found through Argument-Dependent Lo...
Definition ADL.h:78
BitVector::size_type capacity_in_bytes(const BitVector &X)
Definition BitVector.h:845
bool operator!=(uint64_t V1, const APInt &V2)
Definition APInt.h:2142
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:284
constexpr auto adl_end(RangeT &&range) -> decltype(adl_detail::end_impl(std::forward< RangeT >(range)))
Returns the end iterator to range using std::end and functions found through Argument-Dependent Looku...
Definition ADL.h:86
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
auto map_range(ContainerTy &&C, FuncTy F)
Return a range that applies F to the elements of C.
Definition STLExtras.h:365
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:1916
@ Default
The result value is uniform if and only if all operands are uniform.
Definition Uniformity.h:20
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
Definition MathExtras.h:373
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:861
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:863
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