diff --git a/llvm/include/llvm/ADT/DenseMap.h b/llvm/include/llvm/ADT/DenseMap.h index db59bd595bca7..f559f77cca1fd 100644 --- a/llvm/include/llvm/ADT/DenseMap.h +++ b/llvm/include/llvm/ADT/DenseMap.h @@ -413,11 +413,13 @@ class DenseMapBase : public DebugEpochBase { return NextPowerOf2(NumEntries * 4 / 3 + 1); } - void moveFromImpl(iterator_range OldBuckets) { + // Move key/value from Other to *this. + // Other is left in a valid but empty state. + void moveFrom(DerivedT &Other) { // Insert all the old elements. const KeyT EmptyKey = KeyInfoT::getEmptyKey(); const KeyT TombstoneKey = KeyInfoT::getTombstoneKey(); - for (BucketT &B : OldBuckets) { + for (BucketT &B : Other.buckets()) { if (!KeyInfoT::isEqual(B.getFirst(), EmptyKey) && !KeyInfoT::isEqual(B.getFirst(), TombstoneKey)) { // Insert the key/value into the new table. @@ -434,17 +436,6 @@ class DenseMapBase : public DebugEpochBase { } B.getFirst().~KeyT(); } - } - - void moveFromOldBuckets(iterator_range OldBuckets) { - initEmpty(); - moveFromImpl(OldBuckets); - } - - // Move key/value from Other to *this. - // Other is left in a valid but empty state. - void moveFrom(DerivedT &Other) { - moveFromImpl(Other.buckets()); Other.derived().kill(); } @@ -738,6 +729,11 @@ class DenseMap : public DenseMapBase, unsigned NumTombstones; unsigned NumBuckets; + struct ExactBucketCount {}; + explicit DenseMap(unsigned NumBuckets, ExactBucketCount) { + initWithExactBucketCount(NumBuckets); + } + public: /// Create a DenseMap with an optional \p NumElementsToReserve to guarantee /// that this number of elements can be inserted in the map without grow(). @@ -824,9 +820,8 @@ class DenseMap : public DenseMapBase, return true; } - void init(unsigned InitNumEntries) { - auto InitBuckets = BaseT::getMinBucketToReserveForEntries(InitNumEntries); - if (allocateBuckets(InitBuckets)) { + void initWithExactBucketCount(unsigned NewNumBuckets) { + if (allocateBuckets(NewNumBuckets)) { this->BaseT::initEmpty(); } else { NumEntries = 0; @@ -834,6 +829,11 @@ class DenseMap : public DenseMapBase, } } + void init(unsigned InitNumEntries) { + auto InitBuckets = BaseT::getMinBucketToReserveForEntries(InitNumEntries); + initWithExactBucketCount(InitBuckets); + } + // Put the zombie instance in a known good state after a move. void kill() { deallocateBuckets(); @@ -842,23 +842,10 @@ class DenseMap : public DenseMapBase, } void grow(unsigned AtLeast) { - unsigned OldNumBuckets = NumBuckets; - BucketT *OldBuckets = Buckets; - - allocateBuckets(std::max( - 64, static_cast(NextPowerOf2(AtLeast - 1)))); - assert(Buckets); - if (!OldBuckets) { - this->BaseT::initEmpty(); - return; - } - - this->moveFromOldBuckets( - llvm::make_range(OldBuckets, OldBuckets + OldNumBuckets)); - - // Free the old table. - deallocate_buffer(OldBuckets, sizeof(BucketT) * OldNumBuckets, - alignof(BucketT)); + AtLeast = std::max(64, NextPowerOf2(AtLeast - 1)); + DenseMap Tmp(AtLeast, ExactBucketCount{}); + Tmp.moveFrom(*this); + swapImpl(Tmp); } // Plan how to shrink the bucket table. Return: