@@ -154,6 +154,17 @@ class DenseMapBase : public DebugEpochBase {
154154 setNumTombstones (0 );
155155 }
156156
157+ void shrink_and_clear () {
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+
157168 // / Return true if the specified key is in the map, false otherwise.
158169 [[nodiscard]] bool contains (const_arg_type_t <KeyT> Val) const {
159170 return doFind (Val) != nullptr ;
@@ -529,8 +540,6 @@ class DenseMapBase : public DebugEpochBase {
529540
530541 void grow (unsigned AtLeast) { derived ().grow (AtLeast); }
531542
532- void shrink_and_clear () { derived ().shrink_and_clear (); }
533-
534543 template <typename LookupKeyT>
535544 BucketT *findBucketForInsertion (const LookupKeyT &Lookup,
536545 BucketT *TheBucket) {
@@ -770,25 +779,6 @@ class DenseMap : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>,
770779 return *this ;
771780 }
772781
773- void shrink_and_clear () {
774- unsigned OldNumBuckets = NumBuckets;
775- unsigned OldNumEntries = NumEntries;
776- this ->destroyAll ();
777-
778- // Reduce the number of buckets.
779- unsigned NewNumBuckets = 0 ;
780- if (OldNumEntries)
781- NewNumBuckets = std::max (64 , 1 << (Log2_32_Ceil (OldNumEntries) + 1 ));
782- if (NewNumBuckets == NumBuckets) {
783- this ->BaseT ::initEmpty ();
784- return ;
785- }
786-
787- deallocate_buffer (Buckets, sizeof (BucketT) * OldNumBuckets,
788- alignof (BucketT));
789- init (NewNumBuckets);
790- }
791-
792782private:
793783 unsigned getNumEntries () const { return NumEntries; }
794784
@@ -847,6 +837,18 @@ class DenseMap : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>,
847837 deallocate_buffer (OldBuckets, sizeof (BucketT) * OldNumBuckets,
848838 alignof (BucketT));
849839 }
840+
841+ // Plan how to shrink the bucket table. Return:
842+ // - {false, 0} to reuse the existing bucket table
843+ // - {true, N} to reallocate a bucket table with N entries
844+ std::pair<bool , unsigned > planShrinkAndClear () const {
845+ unsigned NewNumBuckets = 0 ;
846+ if (NumEntries)
847+ NewNumBuckets = std::max (64u , 1u << (Log2_32_Ceil (NumEntries) + 1 ));
848+ if (NewNumBuckets == NumBuckets)
849+ return {false , 0 }; // Reuse.
850+ return {true , NewNumBuckets}; // Reallocate.
851+ }
850852};
851853
852854template <typename KeyT, typename ValueT, unsigned InlineBuckets = 4 ,
@@ -999,27 +1001,6 @@ class SmallDenseMap
9991001 return *this ;
10001002 }
10011003
1002- void shrink_and_clear () {
1003- unsigned OldSize = this ->size ();
1004- this ->destroyAll ();
1005-
1006- // Reduce the number of buckets.
1007- unsigned NewNumBuckets = 0 ;
1008- if (OldSize) {
1009- NewNumBuckets = 1 << (Log2_32_Ceil (OldSize) + 1 );
1010- if (NewNumBuckets > InlineBuckets && NewNumBuckets < 64u )
1011- NewNumBuckets = 64 ;
1012- }
1013- if ((Small && NewNumBuckets <= InlineBuckets) ||
1014- (!Small && NewNumBuckets == getLargeRep ()->NumBuckets )) {
1015- this ->BaseT ::initEmpty ();
1016- return ;
1017- }
1018-
1019- deallocateBuckets ();
1020- init (NewNumBuckets);
1021- }
1022-
10231004private:
10241005 unsigned getNumEntries () const { return NumEntries; }
10251006
@@ -1148,6 +1129,23 @@ class SmallDenseMap
11481129 deallocate_buffer (OldRep.Buckets , sizeof (BucketT) * OldRep.NumBuckets ,
11491130 alignof (BucketT));
11501131 }
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+ }
11511149};
11521150
11531151template <typename KeyT, typename ValueT, typename KeyInfoT, typename Bucket,
0 commit comments