Skip to content

Commit 627f801

Browse files
[ADT] Rename NumNonEmpty to NumEntries in SmallPtrSet (NFC) (#153757)
Without this patch, we use NumNonEmpty, which keeps track of the number of valid entries plus tombstones even though we have a separate variable to keep track of the number of tombstones. This patch simplifies the metadata. Specifically, it changes the name and semantics of the variable to NumEntries to keep track of the number of valid entries. The difference in semantics requires some code changes aside from mechanical replacements: - size() just returns NumEntries. - erase_imp() and remove_if() need to decrement NumEntries in the large mode. - insert_imp_big() increments NumEntries for successful insertions, regardless of whether a tombstone is being replaced with a valid entry. It also computes the number of non-tombstone empty slots as: CurArraySize - NumEntries - NumTombstones - Grow() no longer needs NumNonEmpty -= NumTombstones. Overall, the resulting code should look more intuitive and more consistent with DenseMapSet.
1 parent 638bd11 commit 627f801

File tree

2 files changed

+43
-42
lines changed

2 files changed

+43
-42
lines changed

llvm/include/llvm/ADT/SmallPtrSet.h

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,10 @@ class SmallPtrSetImplBase : public DebugEpochBase {
6262
/// CurArraySize - The allocated size of CurArray, always a power of two.
6363
unsigned CurArraySize;
6464

65-
/// Number of elements in CurArray that contain a value or are a tombstone.
65+
/// Number of elements in CurArray that contain a value.
6666
/// If small, all these elements are at the beginning of CurArray and the rest
6767
/// is uninitialized.
68-
unsigned NumNonEmpty;
68+
unsigned NumEntries;
6969
/// Number of tombstones in CurArray.
7070
unsigned NumTombstones;
7171
/// Whether the set is in small representation.
@@ -79,7 +79,7 @@ class SmallPtrSetImplBase : public DebugEpochBase {
7979
SmallPtrSetImplBase &&that);
8080

8181
explicit SmallPtrSetImplBase(const void **SmallStorage, unsigned SmallSize)
82-
: CurArray(SmallStorage), CurArraySize(SmallSize), NumNonEmpty(0),
82+
: CurArray(SmallStorage), CurArraySize(SmallSize), NumEntries(0),
8383
NumTombstones(0), IsSmall(true) {
8484
assert(llvm::has_single_bit(SmallSize) &&
8585
"Initial size must be a power of two!");
@@ -96,7 +96,7 @@ class SmallPtrSetImplBase : public DebugEpochBase {
9696
SmallPtrSetImplBase &operator=(const SmallPtrSetImplBase &) = delete;
9797

9898
[[nodiscard]] bool empty() const { return size() == 0; }
99-
size_type size() const { return NumNonEmpty - NumTombstones; }
99+
size_type size() const { return NumEntries; }
100100
size_type capacity() const { return CurArraySize; }
101101

102102
void clear() {
@@ -110,25 +110,25 @@ class SmallPtrSetImplBase : public DebugEpochBase {
110110
memset(CurArray, -1, CurArraySize * sizeof(void *));
111111
}
112112

113-
NumNonEmpty = 0;
113+
NumEntries = 0;
114114
NumTombstones = 0;
115115
}
116116

117-
void reserve(size_type NumEntries) {
117+
void reserve(size_type NewNumEntries) {
118118
incrementEpoch();
119119
// Do nothing if we're given zero as a reservation size.
120-
if (NumEntries == 0)
120+
if (NewNumEntries == 0)
121121
return;
122-
// No need to expand if we're small and NumEntries will fit in the space.
123-
if (isSmall() && NumEntries <= CurArraySize)
122+
// No need to expand if we're small and NewNumEntries will fit in the space.
123+
if (isSmall() && NewNumEntries <= CurArraySize)
124124
return;
125125
// insert_imp_big will reallocate if stores is more than 75% full, on the
126126
// /final/ insertion.
127-
if (!isSmall() && ((NumEntries - 1) * 4) < (CurArraySize * 3))
127+
if (!isSmall() && ((NewNumEntries - 1) * 4) < (CurArraySize * 3))
128128
return;
129129
// We must Grow -- find the size where we'd be 75% full, then round up to
130130
// the next power of two.
131-
size_type NewSize = NumEntries + (NumEntries / 3);
131+
size_type NewSize = NewNumEntries + (NewNumEntries / 3);
132132
NewSize = llvm::bit_ceil(NewSize);
133133
// Like insert_imp_big, always allocate at least 128 elements.
134134
NewSize = std::max(128u, NewSize);
@@ -145,15 +145,15 @@ class SmallPtrSetImplBase : public DebugEpochBase {
145145
}
146146

147147
const void **EndPointer() const {
148-
return isSmall() ? CurArray + NumNonEmpty : CurArray + CurArraySize;
148+
return isSmall() ? CurArray + NumEntries : CurArray + CurArraySize;
149149
}
150150

151151
iterator_range<const void **> small_buckets() {
152-
return make_range(CurArray, CurArray + NumNonEmpty);
152+
return make_range(CurArray, CurArray + NumEntries);
153153
}
154154

155155
iterator_range<const void *const *> small_buckets() const {
156-
return {CurArray, CurArray + NumNonEmpty};
156+
return {CurArray, CurArray + NumEntries};
157157
}
158158

159159
iterator_range<const void **> buckets() {
@@ -172,10 +172,10 @@ class SmallPtrSetImplBase : public DebugEpochBase {
172172
}
173173

174174
// Nope, there isn't. If we stay small, just 'pushback' now.
175-
if (NumNonEmpty < CurArraySize) {
176-
CurArray[NumNonEmpty++] = Ptr;
175+
if (NumEntries < CurArraySize) {
176+
CurArray[NumEntries++] = Ptr;
177177
incrementEpoch();
178-
return std::make_pair(CurArray + (NumNonEmpty - 1), true);
178+
return std::make_pair(CurArray + (NumEntries - 1), true);
179179
}
180180
// Otherwise, hit the big set case, which will call grow.
181181
}
@@ -190,7 +190,7 @@ class SmallPtrSetImplBase : public DebugEpochBase {
190190
if (isSmall()) {
191191
for (const void *&Bucket : small_buckets()) {
192192
if (Bucket == Ptr) {
193-
Bucket = CurArray[--NumNonEmpty];
193+
Bucket = CurArray[--NumEntries];
194194
incrementEpoch();
195195
return true;
196196
}
@@ -204,6 +204,7 @@ class SmallPtrSetImplBase : public DebugEpochBase {
204204

205205
*const_cast<const void **>(Bucket) = getTombstoneMarker();
206206
NumTombstones++;
207+
--NumEntries;
207208
// Treat this consistently from an API perspective, even if we don't
208209
// actually invalidate iterators here.
209210
incrementEpoch();
@@ -430,12 +431,12 @@ class SmallPtrSetImpl : public SmallPtrSetImplBase {
430431
bool remove_if(UnaryPredicate P) {
431432
bool Removed = false;
432433
if (isSmall()) {
433-
const void **APtr = CurArray, **E = CurArray + NumNonEmpty;
434+
const void **APtr = CurArray, **E = CurArray + NumEntries;
434435
while (APtr != E) {
435436
PtrType Ptr = PtrTraits::getFromVoidPointer(const_cast<void *>(*APtr));
436437
if (P(Ptr)) {
437438
*APtr = *--E;
438-
--NumNonEmpty;
439+
--NumEntries;
439440
incrementEpoch();
440441
Removed = true;
441442
} else {
@@ -452,6 +453,7 @@ class SmallPtrSetImpl : public SmallPtrSetImplBase {
452453
if (P(Ptr)) {
453454
Bucket = getTombstoneMarker();
454455
++NumTombstones;
456+
--NumEntries;
455457
incrementEpoch();
456458
Removed = true;
457459
}

llvm/lib/Support/SmallPtrSet.cpp

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ void SmallPtrSetImplBase::shrink_and_clear() {
2828
// Reduce the number of buckets.
2929
unsigned Size = size();
3030
CurArraySize = Size > 16 ? 1 << (Log2_32_Ceil(Size) + 1) : 32;
31-
NumNonEmpty = NumTombstones = 0;
31+
NumEntries = NumTombstones = 0;
3232

3333
// Install the new array. Clear all the buckets to empty.
3434
CurArray = (const void**)safe_malloc(sizeof(void*) * CurArraySize);
@@ -41,7 +41,8 @@ SmallPtrSetImplBase::insert_imp_big(const void *Ptr) {
4141
if (LLVM_UNLIKELY(size() * 4 >= CurArraySize * 3)) {
4242
// If more than 3/4 of the array is full, grow.
4343
Grow(CurArraySize < 64 ? 128 : CurArraySize * 2);
44-
} else if (LLVM_UNLIKELY(CurArraySize - NumNonEmpty < CurArraySize / 8)) {
44+
} else if (LLVM_UNLIKELY(CurArraySize - NumEntries - NumTombstones <
45+
CurArraySize / 8)) {
4546
// If fewer of 1/8 of the array is empty (meaning that many are filled with
4647
// tombstones), rehash.
4748
Grow(CurArraySize);
@@ -55,8 +56,7 @@ SmallPtrSetImplBase::insert_imp_big(const void *Ptr) {
5556
// Otherwise, insert it!
5657
if (*Bucket == getTombstoneMarker())
5758
--NumTombstones;
58-
else
59-
++NumNonEmpty; // Track density.
59+
++NumEntries;
6060
*Bucket = Ptr;
6161
incrementEpoch();
6262
return std::make_pair(Bucket, true);
@@ -130,7 +130,6 @@ void SmallPtrSetImplBase::Grow(unsigned NewSize) {
130130

131131
if (!WasSmall)
132132
free(OldBuckets.begin());
133-
NumNonEmpty -= NumTombstones;
134133
NumTombstones = 0;
135134
IsSmall = false;
136135
}
@@ -193,7 +192,7 @@ void SmallPtrSetImplBase::copyHelper(const SmallPtrSetImplBase &RHS) {
193192
// Copy over the contents from the other set
194193
std::copy(RHS.CurArray, RHS.EndPointer(), CurArray);
195194

196-
NumNonEmpty = RHS.NumNonEmpty;
195+
NumEntries = RHS.NumEntries;
197196
NumTombstones = RHS.NumTombstones;
198197
}
199198

@@ -215,21 +214,21 @@ void SmallPtrSetImplBase::moveHelper(const void **SmallStorage,
215214
if (RHS.isSmall()) {
216215
// Copy a small RHS rather than moving.
217216
CurArray = SmallStorage;
218-
std::copy(RHS.CurArray, RHS.CurArray + RHS.NumNonEmpty, CurArray);
217+
std::copy(RHS.CurArray, RHS.CurArray + RHS.NumEntries, CurArray);
219218
} else {
220219
CurArray = RHS.CurArray;
221220
RHS.CurArray = RHSSmallStorage;
222221
}
223222

224223
// Copy the rest of the trivial members.
225224
CurArraySize = RHS.CurArraySize;
226-
NumNonEmpty = RHS.NumNonEmpty;
225+
NumEntries = RHS.NumEntries;
227226
NumTombstones = RHS.NumTombstones;
228227
IsSmall = RHS.IsSmall;
229228

230229
// Make the RHS small and empty.
231230
RHS.CurArraySize = SmallSize;
232-
RHS.NumNonEmpty = 0;
231+
RHS.NumEntries = 0;
233232
RHS.NumTombstones = 0;
234233
RHS.IsSmall = true;
235234
}
@@ -243,7 +242,7 @@ void SmallPtrSetImplBase::swap(const void **SmallStorage,
243242
if (!this->isSmall() && !RHS.isSmall()) {
244243
std::swap(this->CurArray, RHS.CurArray);
245244
std::swap(this->CurArraySize, RHS.CurArraySize);
246-
std::swap(this->NumNonEmpty, RHS.NumNonEmpty);
245+
std::swap(this->NumEntries, RHS.NumEntries);
247246
std::swap(this->NumTombstones, RHS.NumTombstones);
248247
return;
249248
}
@@ -253,9 +252,9 @@ void SmallPtrSetImplBase::swap(const void **SmallStorage,
253252
// If only RHS is small, copy the small elements into LHS and move the pointer
254253
// from LHS to RHS.
255254
if (!this->isSmall() && RHS.isSmall()) {
256-
std::copy(RHS.CurArray, RHS.CurArray + RHS.NumNonEmpty, SmallStorage);
255+
std::copy(RHS.CurArray, RHS.CurArray + RHS.NumEntries, SmallStorage);
257256
std::swap(RHS.CurArraySize, this->CurArraySize);
258-
std::swap(this->NumNonEmpty, RHS.NumNonEmpty);
257+
std::swap(this->NumEntries, RHS.NumEntries);
259258
std::swap(this->NumTombstones, RHS.NumTombstones);
260259
RHS.CurArray = this->CurArray;
261260
RHS.IsSmall = false;
@@ -267,10 +266,10 @@ void SmallPtrSetImplBase::swap(const void **SmallStorage,
267266
// If only LHS is small, copy the small elements into RHS and move the pointer
268267
// from RHS to LHS.
269268
if (this->isSmall() && !RHS.isSmall()) {
270-
std::copy(this->CurArray, this->CurArray + this->NumNonEmpty,
269+
std::copy(this->CurArray, this->CurArray + this->NumEntries,
271270
RHSSmallStorage);
272271
std::swap(RHS.CurArraySize, this->CurArraySize);
273-
std::swap(RHS.NumNonEmpty, this->NumNonEmpty);
272+
std::swap(RHS.NumEntries, this->NumEntries);
274273
std::swap(RHS.NumTombstones, this->NumTombstones);
275274
this->CurArray = RHS.CurArray;
276275
this->IsSmall = false;
@@ -281,16 +280,16 @@ void SmallPtrSetImplBase::swap(const void **SmallStorage,
281280

282281
// Both a small, just swap the small elements.
283282
assert(this->isSmall() && RHS.isSmall());
284-
unsigned MinNonEmpty = std::min(this->NumNonEmpty, RHS.NumNonEmpty);
285-
std::swap_ranges(this->CurArray, this->CurArray + MinNonEmpty, RHS.CurArray);
286-
if (this->NumNonEmpty > MinNonEmpty) {
287-
std::copy(this->CurArray + MinNonEmpty, this->CurArray + this->NumNonEmpty,
288-
RHS.CurArray + MinNonEmpty);
283+
unsigned MinEntries = std::min(this->NumEntries, RHS.NumEntries);
284+
std::swap_ranges(this->CurArray, this->CurArray + MinEntries, RHS.CurArray);
285+
if (this->NumEntries > MinEntries) {
286+
std::copy(this->CurArray + MinEntries, this->CurArray + this->NumEntries,
287+
RHS.CurArray + MinEntries);
289288
} else {
290-
std::copy(RHS.CurArray + MinNonEmpty, RHS.CurArray + RHS.NumNonEmpty,
291-
this->CurArray + MinNonEmpty);
289+
std::copy(RHS.CurArray + MinEntries, RHS.CurArray + RHS.NumEntries,
290+
this->CurArray + MinEntries);
292291
}
293292
assert(this->CurArraySize == RHS.CurArraySize);
294-
std::swap(this->NumNonEmpty, RHS.NumNonEmpty);
293+
std::swap(this->NumEntries, RHS.NumEntries);
295294
std::swap(this->NumTombstones, RHS.NumTombstones);
296295
}

0 commit comments

Comments
 (0)