Skip to content

Commit f502bab

Browse files
[ADT] Overhaul the DenseMapIterator creation logic (NFC) (#156221)
Without this patch, it's overly complicated to create iterators in DenseMap. - We must specify whether to advance a newly created iterator, which is needed in begin(). - We call shouldReverseIterate outside and inside DenseMapIterator. This patch cleans up all this by creating factory methods: - DenseMapIterator::makeBegin - DenseMapIterator::makeEnd - DenseMapIterator::makeIterator With these: - makeBegin knows that we need to advance the iterator to the first valid bucket. - Callers outside DenseMapIterator do not reference shouldReverseIterate at all. Now, it's a lot simpler to call helper functions DenseMapBase::{makeIterator,makeConstIterator}. We just have to pass the Bucket pointer: makeIterator(Bucket); and they take care of the rest, including passing *this as Epoch.
1 parent df95dfc commit f502bab

File tree

1 file changed

+49
-57
lines changed

1 file changed

+49
-57
lines changed

llvm/include/llvm/ADT/DenseMap.h

Lines changed: 49 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -76,26 +76,14 @@ class DenseMapBase : public DebugEpochBase {
7676
DenseMapIterator<KeyT, ValueT, KeyInfoT, BucketT, true>;
7777

7878
inline iterator begin() {
79-
// When the map is empty, avoid the overhead of advancing/retreating past
80-
// empty buckets.
81-
if (empty())
82-
return end();
83-
if (shouldReverseIterate<KeyT>())
84-
return makeIterator(getBucketsEnd() - 1, getBuckets(), *this);
85-
return makeIterator(getBuckets(), getBucketsEnd(), *this);
86-
}
87-
inline iterator end() {
88-
return makeIterator(getBucketsEnd(), getBucketsEnd(), *this, true);
79+
return iterator::makeBegin(buckets(), empty(), *this);
8980
}
81+
inline iterator end() { return iterator::makeEnd(buckets(), *this); }
9082
inline const_iterator begin() const {
91-
if (empty())
92-
return end();
93-
if (shouldReverseIterate<KeyT>())
94-
return makeConstIterator(getBucketsEnd() - 1, getBuckets(), *this);
95-
return makeConstIterator(getBuckets(), getBucketsEnd(), *this);
83+
return const_iterator::makeBegin(buckets(), empty(), *this);
9684
}
9785
inline const_iterator end() const {
98-
return makeConstIterator(getBucketsEnd(), getBucketsEnd(), *this, true);
86+
return const_iterator::makeEnd(buckets(), *this);
9987
}
10088

10189
// Return an iterator to iterate over keys in the map.
@@ -184,17 +172,13 @@ class DenseMapBase : public DebugEpochBase {
184172
/// type used.
185173
template <class LookupKeyT> iterator find_as(const LookupKeyT &Val) {
186174
if (BucketT *Bucket = doFind(Val))
187-
return makeIterator(
188-
Bucket, shouldReverseIterate<KeyT>() ? getBuckets() : getBucketsEnd(),
189-
*this, true);
175+
return makeIterator(Bucket);
190176
return end();
191177
}
192178
template <class LookupKeyT>
193179
const_iterator find_as(const LookupKeyT &Val) const {
194180
if (const BucketT *Bucket = doFind(Val))
195-
return makeConstIterator(
196-
Bucket, shouldReverseIterate<KeyT>() ? getBuckets() : getBucketsEnd(),
197-
*this, true);
181+
return makeConstIterator(Bucket);
198182
return end();
199183
}
200184

@@ -264,13 +248,13 @@ class DenseMapBase : public DebugEpochBase {
264248
const LookupKeyT &Val) {
265249
BucketT *TheBucket;
266250
if (LookupBucketFor(Val, TheBucket))
267-
return {makeInsertIterator(TheBucket), false}; // Already in map.
251+
return {makeIterator(TheBucket), false}; // Already in map.
268252

269253
// Otherwise, insert the new element.
270254
TheBucket = findBucketForInsertion(Val, TheBucket);
271255
TheBucket->getFirst() = std::move(KV.first);
272256
::new (&TheBucket->getSecond()) ValueT(std::move(KV.second));
273-
return {makeInsertIterator(TheBucket), true};
257+
return {makeIterator(TheBucket), true};
274258
}
275259

276260
/// insert - Range insertion of pairs.
@@ -482,33 +466,15 @@ class DenseMapBase : public DebugEpochBase {
482466
std::pair<iterator, bool> try_emplace_impl(KeyArgT &&Key, Ts &&...Args) {
483467
auto [Bucket, Inserted] = lookupOrInsertIntoBucket(
484468
std::forward<KeyArgT>(Key), std::forward<Ts>(Args)...);
485-
return {makeInsertIterator(Bucket), Inserted};
469+
return {makeIterator(Bucket), Inserted};
486470
}
487471

488-
iterator makeIterator(BucketT *P, BucketT *E, DebugEpochBase &Epoch,
489-
bool NoAdvance = false) {
490-
if (shouldReverseIterate<KeyT>()) {
491-
BucketT *B = P == getBucketsEnd() ? getBuckets() : P + 1;
492-
return iterator(B, E, Epoch, NoAdvance);
493-
}
494-
return iterator(P, E, Epoch, NoAdvance);
472+
iterator makeIterator(BucketT *TheBucket) {
473+
return iterator::makeIterator(TheBucket, buckets(), *this);
495474
}
496475

497-
const_iterator makeConstIterator(const BucketT *P, const BucketT *E,
498-
const DebugEpochBase &Epoch,
499-
const bool NoAdvance = false) const {
500-
if (shouldReverseIterate<KeyT>()) {
501-
const BucketT *B = P == getBucketsEnd() ? getBuckets() : P + 1;
502-
return const_iterator(B, E, Epoch, NoAdvance);
503-
}
504-
return const_iterator(P, E, Epoch, NoAdvance);
505-
}
506-
507-
iterator makeInsertIterator(BucketT *TheBucket) {
508-
return makeIterator(TheBucket,
509-
shouldReverseIterate<KeyT>() ? getBuckets()
510-
: getBucketsEnd(),
511-
*this, true);
476+
const_iterator makeConstIterator(const BucketT *TheBucket) const {
477+
return const_iterator::makeIterator(TheBucket, buckets(), *this);
512478
}
513479

514480
unsigned getNumEntries() const {
@@ -555,6 +521,10 @@ class DenseMapBase : public DebugEpochBase {
555521
return llvm::make_range(getBuckets(), getBucketsEnd());
556522
}
557523

524+
iterator_range<const BucketT *> buckets() const {
525+
return llvm::make_range(getBuckets(), getBucketsEnd());
526+
}
527+
558528
void grow(unsigned AtLeast) { static_cast<DerivedT *>(this)->grow(AtLeast); }
559529

560530
void shrink_and_clear() { static_cast<DerivedT *>(this)->shrink_and_clear(); }
@@ -1217,21 +1187,43 @@ class DenseMapIterator : DebugEpochBase::HandleBase {
12171187
pointer Ptr = nullptr;
12181188
pointer End = nullptr;
12191189

1220-
public:
1221-
DenseMapIterator() = default;
1222-
1223-
DenseMapIterator(pointer Pos, pointer E, const DebugEpochBase &Epoch,
1224-
bool NoAdvance = false)
1190+
DenseMapIterator(pointer Pos, pointer E, const DebugEpochBase &Epoch)
12251191
: DebugEpochBase::HandleBase(&Epoch), Ptr(Pos), End(E) {
12261192
assert(isHandleInSync() && "invalid construction!");
1193+
}
12271194

1228-
if (NoAdvance)
1229-
return;
1195+
public:
1196+
DenseMapIterator() = default;
1197+
1198+
static DenseMapIterator makeBegin(iterator_range<pointer> Buckets,
1199+
bool IsEmpty, const DebugEpochBase &Epoch) {
1200+
// When the map is empty, avoid the overhead of advancing/retreating past
1201+
// empty buckets.
1202+
if (IsEmpty)
1203+
return makeEnd(Buckets, Epoch);
12301204
if (shouldReverseIterate<KeyT>()) {
1231-
RetreatPastEmptyBuckets();
1232-
return;
1205+
DenseMapIterator Iter(Buckets.end(), Buckets.begin(), Epoch);
1206+
Iter.RetreatPastEmptyBuckets();
1207+
return Iter;
12331208
}
1234-
AdvancePastEmptyBuckets();
1209+
DenseMapIterator Iter(Buckets.begin(), Buckets.end(), Epoch);
1210+
Iter.AdvancePastEmptyBuckets();
1211+
return Iter;
1212+
}
1213+
1214+
static DenseMapIterator makeEnd(iterator_range<pointer> Buckets,
1215+
const DebugEpochBase &Epoch) {
1216+
if (shouldReverseIterate<KeyT>())
1217+
return DenseMapIterator(Buckets.begin(), Buckets.begin(), Epoch);
1218+
return DenseMapIterator(Buckets.end(), Buckets.end(), Epoch);
1219+
}
1220+
1221+
static DenseMapIterator makeIterator(pointer P,
1222+
iterator_range<pointer> Buckets,
1223+
const DebugEpochBase &Epoch) {
1224+
if (shouldReverseIterate<KeyT>())
1225+
return DenseMapIterator(P + 1, Buckets.begin(), Epoch);
1226+
return DenseMapIterator(P, Buckets.end(), Epoch);
12351227
}
12361228

12371229
// Converting ctor from non-const iterators to const iterators. SFINAE'd out

0 commit comments

Comments
 (0)