Skip to content

Conversation

kazutakahirata
Copy link
Contributor

SmallPtrSetIterator has two tasks:

  • iterate the buckets in the requested direction
  • skip the empty and tombstone buckets

These tasks are intertwined in the current implementation. This patch
separates them.

A new private iterator type, BucketItTy, now handles the iteration
direction. This is an alias for a raw pointer for forward iteration
and std::reverse_iterator for reverse iteration.

The user-facing iterator now focuses solely on advancing BucketItTy
while skipping invalid (empty or tombstone) buckets. AdvanceIfNotValid
now works transparently for both directions. operator++ on BucketItTy
does the right thing whether it's a raw pointer or a
std::reverse_iterator.

This simplification removes RetreatIfNotValid and the
reverse-iteration logic in operator*() and operator++().

SmallPtrSetIterator has two tasks:

 - iterate the buckets in the requested direction
 - skip the empty and tombstone buckets

These tasks are intertwined in the current implementation. This patch
separates them.

A new private iterator type, BucketItTy, now handles the iteration
direction. This is an alias for a raw pointer for forward iteration
and std::reverse_iterator<pointer> for reverse iteration.

The user-facing iterator now focuses solely on advancing BucketItTy
while skipping invalid (empty or tombstone) buckets. AdvanceIfNotValid
now works transparently for both directions. operator++ on BucketItTy
does the right thing whether it's a raw pointer or a
std::reverse_iterator.

This simplification removes RetreatIfNotValid and the
reverse-iteration logic in operator*() and operator++().
@llvmbot
Copy link
Member

llvmbot commented Sep 25, 2025

@llvm/pr-subscribers-llvm-adt

Author: Kazu Hirata (kazutakahirata)

Changes

SmallPtrSetIterator has two tasks:

  • iterate the buckets in the requested direction
  • skip the empty and tombstone buckets

These tasks are intertwined in the current implementation. This patch
separates them.

A new private iterator type, BucketItTy, now handles the iteration
direction. This is an alias for a raw pointer for forward iteration
and std::reverse_iterator<pointer> for reverse iteration.

The user-facing iterator now focuses solely on advancing BucketItTy
while skipping invalid (empty or tombstone) buckets. AdvanceIfNotValid
now works transparently for both directions. operator++ on BucketItTy
does the right thing whether it's a raw pointer or a
std::reverse_iterator.

This simplification removes RetreatIfNotValid and the
reverse-iteration logic in operator*() and operator++().


Full diff: https://github.com/llvm/llvm-project/pull/160643.diff

1 Files Affected:

  • (modified) llvm/include/llvm/ADT/SmallPtrSet.h (+7-23)
diff --git a/llvm/include/llvm/ADT/SmallPtrSet.h b/llvm/include/llvm/ADT/SmallPtrSet.h
index dca9f7995926d..d5332379fc542 100644
--- a/llvm/include/llvm/ADT/SmallPtrSet.h
+++ b/llvm/include/llvm/ADT/SmallPtrSet.h
@@ -281,16 +281,17 @@ class SmallPtrSetImplBase : public DebugEpochBase {
 /// instances of SmallPtrSetIterator.
 class SmallPtrSetIteratorImpl {
 protected:
-  const void *const *Bucket;
-  const void *const *End;
+  using BucketItTy =
+      std::conditional_t<shouldReverseIterate(),
+                         std::reverse_iterator<const void *const *>,
+                         const void *const *>;
+
+  BucketItTy Bucket;
+  BucketItTy End;
 
 public:
   explicit SmallPtrSetIteratorImpl(const void *const *BP, const void *const *E)
       : Bucket(BP), End(E) {
-    if (shouldReverseIterate()) {
-      RetreatIfNotValid();
-      return;
-    }
     AdvanceIfNotValid();
   }
 
@@ -312,14 +313,6 @@ class SmallPtrSetIteratorImpl {
             *Bucket == SmallPtrSetImplBase::getTombstoneMarker()))
       ++Bucket;
   }
-  void RetreatIfNotValid() {
-    assert(Bucket >= End);
-    while (Bucket != End &&
-           (Bucket[-1] == SmallPtrSetImplBase::getEmptyMarker() ||
-            Bucket[-1] == SmallPtrSetImplBase::getTombstoneMarker())) {
-      --Bucket;
-    }
-  }
 };
 
 /// SmallPtrSetIterator - This implements a const_iterator for SmallPtrSet.
@@ -344,21 +337,12 @@ class LLVM_DEBUGEPOCHBASE_HANDLEBASE_EMPTYBASE SmallPtrSetIterator
 
   const PtrTy operator*() const {
     assert(isHandleInSync() && "invalid iterator access!");
-    if (shouldReverseIterate()) {
-      assert(Bucket > End);
-      return PtrTraits::getFromVoidPointer(const_cast<void *>(Bucket[-1]));
-    }
     assert(Bucket < End);
     return PtrTraits::getFromVoidPointer(const_cast<void *>(*Bucket));
   }
 
   inline SmallPtrSetIterator &operator++() { // Preincrement
     assert(isHandleInSync() && "invalid iterator access!");
-    if (shouldReverseIterate()) {
-      --Bucket;
-      RetreatIfNotValid();
-      return *this;
-    }
     ++Bucket;
     AdvanceIfNotValid();
     return *this;

@kazutakahirata kazutakahirata merged commit fddb8fe into llvm:main Sep 25, 2025
11 checks passed
@kazutakahirata kazutakahirata deleted the cleanup_20250924_ADT_SmallPtrSet_reverse branch September 25, 2025 15:53
mahesh-attarde pushed a commit to mahesh-attarde/llvm-project that referenced this pull request Oct 3, 2025
…lvm#160643)

SmallPtrSetIterator has two tasks:

 - iterate the buckets in the requested direction
 - skip the empty and tombstone buckets

These tasks are intertwined in the current implementation. This patch
separates them.

A new private iterator type, BucketItTy, now handles the iteration
direction. This is an alias for a raw pointer for forward iteration
and std::reverse_iterator<pointer> for reverse iteration.

The user-facing iterator now focuses solely on advancing BucketItTy
while skipping invalid (empty or tombstone) buckets. AdvanceIfNotValid
now works transparently for both directions. operator++ on BucketItTy
does the right thing whether it's a raw pointer or a
std::reverse_iterator.

This simplification removes RetreatIfNotValid and the
reverse-iteration logic in operator*() and operator++().
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants