[llvm] [ADT] Move DenseMapIterator above DenseMapBase (NFC) (PR #227208)

Kazu Hirata via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 29 00:31:40 PDT 2026


https://github.com/kazutakahirata created https://github.com/llvm/llvm-project/pull/227208

This patch moves the definition of DenseMapIterator right above
DenseMapBase so that all classes in DenseMap.h are defined in the
bottom-up order without forward declarations:

- DenseMapStorage
- SmallDenseMapStorage
- DenseMapIterator
- DenseMapBase
- DenseMap
- SmallDenseMap

Assisted-by: Antigravity


>From 3317d471ecb35c8cca65dd612c8cf83147fc8ff8 Mon Sep 17 00:00:00 2001
From: Kazu Hirata <kazu at google.com>
Date: Mon, 28 Sep 2026 11:12:29 -0700
Subject: [PATCH] [ADT] Move DenseMapIterator above DenseMapBase (NFC)

This patch moves the definition of DenseMapIterator right above
DenseMapBase so that all classes in DenseMap.h are defined in the
bottom-up order without forward declarations:

- DenseMapStorage
- SmallDenseMapStorage
- DenseMapIterator
- DenseMapBase
- DenseMap
- SmallDenseMap

Assisted-by: Antigravity
---
 llvm/include/llvm/ADT/DenseMap.h | 286 +++++++++++++++----------------
 1 file changed, 141 insertions(+), 145 deletions(-)

diff --git a/llvm/include/llvm/ADT/DenseMap.h b/llvm/include/llvm/ADT/DenseMap.h
index 756f9e93a04ef..1757f8ee3438c 100644
--- a/llvm/include/llvm/ADT/DenseMap.h
+++ b/llvm/include/llvm/ADT/DenseMap.h
@@ -539,7 +539,147 @@ template <typename KeyT, typename ValueT,
           typename KeyInfoT = DenseMapInfo<KeyT>,
           typename Bucket = llvm::detail::DenseMapPair<KeyT, ValueT>,
           bool IsConst = false>
-class DenseMapIterator;
+class DenseMapIterator : DebugEpochBase::HandleBase {
+  friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true>;
+  friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, false>;
+
+  using UsedT = llvm::densemap::detail::UsedT;
+
+public:
+  using difference_type = ptrdiff_t;
+  using value_type = std::conditional_t<IsConst, const Bucket, Bucket>;
+  using pointer = value_type *;
+  using reference = value_type &;
+  using iterator_category = std::forward_iterator_tag;
+
+private:
+  using BucketItTy =
+      std::conditional_t<shouldReverseIterate<KeyT>(),
+                         std::reverse_iterator<pointer>, pointer>;
+
+  BucketItTy Ptr = {};
+  BucketItTy End = {};
+  // The non-reversed bucket base and the parallel used array.  They map a
+  // bucket back to its index so AdvancePastEmptyBuckets can consult the bits.
+  pointer Buckets = {};
+  const UsedT *Used = {};
+
+  DenseMapIterator(BucketItTy Pos, BucketItTy E, pointer BucketsBase,
+                   const UsedT *U, const DebugEpochBase &Epoch)
+      : DebugEpochBase::HandleBase(&Epoch), Ptr(Pos), End(E),
+        Buckets(BucketsBase), Used(U) {
+    assert(isHandleInSync() && "invalid construction!");
+  }
+
+public:
+  DenseMapIterator() = default;
+
+  static DenseMapIterator makeBegin(pointer Buckets, const UsedT *Used,
+                                    unsigned NumBuckets, bool IsEmpty,
+                                    const DebugEpochBase &Epoch) {
+    // When the map is empty, avoid the overhead of advancing/retreating past
+    // empty buckets.
+    if (IsEmpty)
+      return makeEnd(Buckets, Used, NumBuckets, Epoch);
+    auto R = maybeReverse(llvm::make_range(Buckets, Buckets + NumBuckets));
+    DenseMapIterator Iter(R.begin(), R.end(), Buckets, Used, Epoch);
+    Iter.AdvancePastEmptyBuckets();
+    return Iter;
+  }
+
+  static DenseMapIterator makeEnd(pointer Buckets, const UsedT *Used,
+                                  unsigned NumBuckets,
+                                  const DebugEpochBase &Epoch) {
+    auto R = maybeReverse(llvm::make_range(Buckets, Buckets + NumBuckets));
+    return DenseMapIterator(R.end(), R.end(), Buckets, Used, Epoch);
+  }
+
+  static DenseMapIterator makeIterator(pointer P, pointer Buckets,
+                                       const UsedT *Used, unsigned NumBuckets,
+                                       const DebugEpochBase &Epoch) {
+    auto R = maybeReverse(llvm::make_range(Buckets, Buckets + NumBuckets));
+    constexpr int Offset = shouldReverseIterate<KeyT>() ? 1 : 0;
+    return DenseMapIterator(BucketItTy(P + Offset), R.end(), Buckets, Used,
+                            Epoch);
+  }
+
+  // Converting ctor from non-const iterators to const iterators. SFINAE'd out
+  // for const iterator destinations so it doesn't end up as a user defined copy
+  // constructor.
+  template <bool IsConstSrc,
+            typename = std::enable_if_t<!IsConstSrc && IsConst>>
+  DenseMapIterator(
+      const DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, IsConstSrc> &I)
+      : DebugEpochBase::HandleBase(I), Ptr(I.Ptr), End(I.End),
+        Buckets(I.Buckets), Used(I.Used) {}
+
+  [[nodiscard]] reference operator*() const {
+    assert(isHandleInSync() && "invalid iterator access!");
+    assert(Ptr != End && "dereferencing end() iterator");
+    return *Ptr;
+  }
+  [[nodiscard]] pointer operator->() const { return &operator*(); }
+
+  [[nodiscard]] friend bool operator==(const DenseMapIterator &LHS,
+                                       const DenseMapIterator &RHS) {
+    assert(LHS.isComparableWith(RHS) && "incomparable iterators!");
+    return LHS.Ptr == RHS.Ptr;
+  }
+
+  [[nodiscard]] friend bool operator!=(const DenseMapIterator &LHS,
+                                       const DenseMapIterator &RHS) {
+    return !(LHS == RHS);
+  }
+
+  inline DenseMapIterator &operator++() { // Preincrement
+    assert(isHandleInSync() && "invalid iterator access!");
+    assert(Ptr != End && "incrementing end() iterator");
+    ++Ptr;
+    AdvancePastEmptyBuckets();
+    return *this;
+  }
+  DenseMapIterator operator++(int) { // Postincrement
+    assert(isHandleInSync() && "invalid iterator access!");
+    DenseMapIterator tmp = *this;
+    ++*this;
+    return tmp;
+  }
+
+private:
+  void AdvancePastEmptyBuckets() {
+    if constexpr (shouldReverseIterate<KeyT>()) {
+      while (Ptr != End && !llvm::densemap::detail::used(Used, &*Ptr - Buckets))
+        ++Ptr;
+    } else {
+      // Forward iteration skips empty buckets a used-word (32 buckets) at a
+      // time: scan from the current index for the next set occupancy bit.
+      const size_t N = End - Buckets;
+      size_t I = Ptr - Buckets;
+      if (I >= N) {
+        Ptr = End;
+        return;
+      }
+      const size_t NW = llvm::densemap::detail::usedWords(N);
+      size_t W = I >> 5;
+      UsedT Bits = Used[W] & (~UsedT(0) << (I & 31));
+      while (Bits == 0) {
+        if (++W == NW) {
+          Ptr = End;
+          return;
+        }
+        Bits = Used[W];
+      }
+      Ptr = Buckets + ((W << 5) + llvm::countr_zero(Bits));
+    }
+  }
+
+  static auto maybeReverse(iterator_range<pointer> Range) {
+    if constexpr (shouldReverseIterate<KeyT>())
+      return reverse(Range);
+    else
+      return Range;
+  }
+};
 
 template <typename StorageT, typename KeyT, typename ValueT, typename KeyInfoT,
           typename BucketT>
@@ -1331,150 +1471,6 @@ class SmallDenseMap
   using BaseT::BaseT;
 };
 
-template <typename KeyT, typename ValueT, typename KeyInfoT, typename Bucket,
-          bool IsConst>
-class DenseMapIterator : DebugEpochBase::HandleBase {
-  friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true>;
-  friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, false>;
-
-  using UsedT = llvm::densemap::detail::UsedT;
-
-public:
-  using difference_type = ptrdiff_t;
-  using value_type = std::conditional_t<IsConst, const Bucket, Bucket>;
-  using pointer = value_type *;
-  using reference = value_type &;
-  using iterator_category = std::forward_iterator_tag;
-
-private:
-  using BucketItTy =
-      std::conditional_t<shouldReverseIterate<KeyT>(),
-                         std::reverse_iterator<pointer>, pointer>;
-
-  BucketItTy Ptr = {};
-  BucketItTy End = {};
-  // The non-reversed bucket base and the parallel used array.  They map a
-  // bucket back to its index so AdvancePastEmptyBuckets can consult the bits.
-  pointer Buckets = {};
-  const UsedT *Used = {};
-
-  DenseMapIterator(BucketItTy Pos, BucketItTy E, pointer BucketsBase,
-                   const UsedT *U, const DebugEpochBase &Epoch)
-      : DebugEpochBase::HandleBase(&Epoch), Ptr(Pos), End(E),
-        Buckets(BucketsBase), Used(U) {
-    assert(isHandleInSync() && "invalid construction!");
-  }
-
-public:
-  DenseMapIterator() = default;
-
-  static DenseMapIterator makeBegin(pointer Buckets, const UsedT *Used,
-                                    unsigned NumBuckets, bool IsEmpty,
-                                    const DebugEpochBase &Epoch) {
-    // When the map is empty, avoid the overhead of advancing/retreating past
-    // empty buckets.
-    if (IsEmpty)
-      return makeEnd(Buckets, Used, NumBuckets, Epoch);
-    auto R = maybeReverse(llvm::make_range(Buckets, Buckets + NumBuckets));
-    DenseMapIterator Iter(R.begin(), R.end(), Buckets, Used, Epoch);
-    Iter.AdvancePastEmptyBuckets();
-    return Iter;
-  }
-
-  static DenseMapIterator makeEnd(pointer Buckets, const UsedT *Used,
-                                  unsigned NumBuckets,
-                                  const DebugEpochBase &Epoch) {
-    auto R = maybeReverse(llvm::make_range(Buckets, Buckets + NumBuckets));
-    return DenseMapIterator(R.end(), R.end(), Buckets, Used, Epoch);
-  }
-
-  static DenseMapIterator makeIterator(pointer P, pointer Buckets,
-                                       const UsedT *Used, unsigned NumBuckets,
-                                       const DebugEpochBase &Epoch) {
-    auto R = maybeReverse(llvm::make_range(Buckets, Buckets + NumBuckets));
-    constexpr int Offset = shouldReverseIterate<KeyT>() ? 1 : 0;
-    return DenseMapIterator(BucketItTy(P + Offset), R.end(), Buckets, Used,
-                            Epoch);
-  }
-
-  // Converting ctor from non-const iterators to const iterators. SFINAE'd out
-  // for const iterator destinations so it doesn't end up as a user defined copy
-  // constructor.
-  template <bool IsConstSrc,
-            typename = std::enable_if_t<!IsConstSrc && IsConst>>
-  DenseMapIterator(
-      const DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, IsConstSrc> &I)
-      : DebugEpochBase::HandleBase(I), Ptr(I.Ptr), End(I.End),
-        Buckets(I.Buckets), Used(I.Used) {}
-
-  [[nodiscard]] reference operator*() const {
-    assert(isHandleInSync() && "invalid iterator access!");
-    assert(Ptr != End && "dereferencing end() iterator");
-    return *Ptr;
-  }
-  [[nodiscard]] pointer operator->() const { return &operator*(); }
-
-  [[nodiscard]] friend bool operator==(const DenseMapIterator &LHS,
-                                       const DenseMapIterator &RHS) {
-    assert(LHS.isComparableWith(RHS) && "incomparable iterators!");
-    return LHS.Ptr == RHS.Ptr;
-  }
-
-  [[nodiscard]] friend bool operator!=(const DenseMapIterator &LHS,
-                                       const DenseMapIterator &RHS) {
-    return !(LHS == RHS);
-  }
-
-  inline DenseMapIterator &operator++() { // Preincrement
-    assert(isHandleInSync() && "invalid iterator access!");
-    assert(Ptr != End && "incrementing end() iterator");
-    ++Ptr;
-    AdvancePastEmptyBuckets();
-    return *this;
-  }
-  DenseMapIterator operator++(int) { // Postincrement
-    assert(isHandleInSync() && "invalid iterator access!");
-    DenseMapIterator tmp = *this;
-    ++*this;
-    return tmp;
-  }
-
-private:
-  void AdvancePastEmptyBuckets() {
-    if constexpr (shouldReverseIterate<KeyT>()) {
-      while (Ptr != End && !llvm::densemap::detail::used(Used, &*Ptr - Buckets))
-        ++Ptr;
-    } else {
-      // Forward iteration skips empty buckets a used-word (32 buckets) at a
-      // time: scan from the current index for the next set occupancy bit.
-      const size_t N = End - Buckets;
-      size_t I = Ptr - Buckets;
-      if (I >= N) {
-        Ptr = End;
-        return;
-      }
-      const size_t NW = llvm::densemap::detail::usedWords(N);
-      size_t W = I >> 5;
-      UsedT Bits = Used[W] & (~UsedT(0) << (I & 31));
-      while (Bits == 0) {
-        if (++W == NW) {
-          Ptr = End;
-          return;
-        }
-        Bits = Used[W];
-      }
-      Ptr = Buckets + ((W << 5) + llvm::countr_zero(Bits));
-    }
-  }
-
-  static auto maybeReverse(iterator_range<pointer> Range) {
-    if constexpr (shouldReverseIterate<KeyT>())
-      return reverse(Range);
-    else
-      return Range;
-  }
-};
-
 template <typename KeyT, typename ValueT, typename KeyInfoT>
 [[nodiscard]] inline size_t
 capacity_in_bytes(const DenseMap<KeyT, ValueT, KeyInfoT> &X) {



More information about the llvm-commits mailing list