[llvm] [ADT] Add begin and end to EytzingerTableSpan and EytzingerTable (NFC) (PR #210478)

Kazu Hirata via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 17 19:55:23 PDT 2026


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

This patch adds iterator and const_iterator type aliases as well as
begin() and end() methods to EytzingerTableSpan and EytzingerTable.

I'm going to be using these as part of the SecNameTable in the
Eytzinger layout.

RFC:
https://discourse.llvm.org/t/rfc-faster-sample-profile-loading/90957/8

Assisted-by: Antigravity


>From 23175686cb141ef3e655d78c7ffb576c2049e9a7 Mon Sep 17 00:00:00 2001
From: Kazu Hirata <kazu at google.com>
Date: Fri, 17 Jul 2026 19:47:59 -0700
Subject: [PATCH] [ADT] Add begin and end to EytzingerTableSpan and
 EytzingerTable (NFC)

This patch adds iterator and const_iterator type aliases as well as
begin() and end() methods to EytzingerTableSpan and EytzingerTable.

I'm going to be using these as part of the SecNameTable in the
Eytzinger layout.

RFC:
https://discourse.llvm.org/t/rfc-faster-sample-profile-loading/90957/8

Assisted-by: Antigravity
---
 llvm/include/llvm/ADT/Eytzinger.h    | 13 ++++++++
 llvm/unittests/ADT/EytzingerTest.cpp | 46 ++++++++++++++++++++++++++++
 2 files changed, 59 insertions(+)

diff --git a/llvm/include/llvm/ADT/Eytzinger.h b/llvm/include/llvm/ADT/Eytzinger.h
index e3813331a59a7..685de6cc35e11 100644
--- a/llvm/include/llvm/ADT/Eytzinger.h
+++ b/llvm/include/llvm/ADT/Eytzinger.h
@@ -29,10 +29,15 @@ namespace llvm {
 /// Eytzinger (breadth-first) order.
 template <typename T> class EytzingerTableSpan {
 public:
+  using iterator = const T *;
+  using const_iterator = const T *;
+
   EytzingerTableSpan() = default;
   EytzingerTableSpan(const T *Data, size_t NumEntries)
       : Data(Data), NumEntries(NumEntries) {}
 
+  [[nodiscard]] iterator begin() const { return Data; }
+  [[nodiscard]] iterator end() const { return Data + NumEntries; }
   [[nodiscard]] const T *data() const { return Data; }
   [[nodiscard]] bool empty() const { return !Data || NumEntries == 0; }
   [[nodiscard]] size_t size() const { return NumEntries; }
@@ -121,6 +126,9 @@ template <typename T> class EytzingerTable {
   explicit EytzingerTable(std::vector<T> Buffer) : Storage(std::move(Buffer)) {}
 
 public:
+  using iterator = typename std::vector<T>::const_iterator;
+  using const_iterator = typename std::vector<T>::const_iterator;
+
   EytzingerTable() = default;
 
   /// Construct an Eytzinger search tree from a vector of keys by sorting,
@@ -161,6 +169,11 @@ template <typename T> class EytzingerTable {
 
   [[nodiscard]] bool isSorted() const { return asSpan().isSorted(); }
 
+  [[nodiscard]] iterator begin() { return Storage.begin(); }
+  [[nodiscard]] const_iterator begin() const { return Storage.begin(); }
+  [[nodiscard]] iterator end() { return Storage.end(); }
+  [[nodiscard]] const_iterator end() const { return Storage.end(); }
+
   [[nodiscard]] const T *data() const { return Storage.data(); }
   [[nodiscard]] size_t size() const { return Storage.size(); }
   [[nodiscard]] bool empty() const { return Storage.empty(); }
diff --git a/llvm/unittests/ADT/EytzingerTest.cpp b/llvm/unittests/ADT/EytzingerTest.cpp
index e887d7cd279f2..17cd06b6a1443 100644
--- a/llvm/unittests/ADT/EytzingerTest.cpp
+++ b/llvm/unittests/ADT/EytzingerTest.cpp
@@ -20,6 +20,8 @@ TEST(EytzingerTest, EmptyTable) {
   EXPECT_TRUE(Empty.empty());
   EXPECT_EQ(Empty.size(), 0u);
   EXPECT_EQ(Empty.data(), nullptr);
+  EXPECT_EQ(Empty.begin(), Empty.end());
+  EXPECT_EQ(Empty.begin(), nullptr);
   EXPECT_TRUE(Empty.isSorted());
   EXPECT_EQ(Empty.findIndex(42), std::nullopt);
   EXPECT_FALSE(Empty.contains(42));
@@ -28,6 +30,7 @@ TEST(EytzingerTest, EmptyTable) {
   EytzingerTableSpan<int> NullSpan(nullptr, 0);
   EXPECT_TRUE(NullSpan.empty());
   EXPECT_EQ(NullSpan.size(), 0u);
+  EXPECT_EQ(NullSpan.begin(), NullSpan.end());
   EXPECT_TRUE(NullSpan.isSorted());
   EXPECT_EQ(NullSpan.findIndex(42), std::nullopt);
   EXPECT_FALSE(NullSpan.contains(42));
@@ -250,12 +253,15 @@ TEST(EytzingerTest, EytzingerTableEmptyAndSingle) {
   auto EmptyTable = EytzingerTable<int>::create(std::vector<int>{});
   EXPECT_TRUE(EmptyTable.empty());
   EXPECT_EQ(EmptyTable.size(), 0u);
+  EXPECT_EQ(EmptyTable.begin(), EmptyTable.end());
   EXPECT_TRUE(EmptyTable.isSorted());
   EXPECT_FALSE(EmptyTable.contains(42));
 
   auto SingleTable = EytzingerTable<int>::create(std::vector<int>{42, 42});
   EXPECT_FALSE(SingleTable.empty());
   EXPECT_EQ(SingleTable.size(), 1u);
+  EXPECT_NE(SingleTable.begin(), SingleTable.end());
+  EXPECT_EQ(*SingleTable.begin(), 42);
   EXPECT_TRUE(SingleTable.isSorted());
   EXPECT_EQ(SingleTable[0], 42);
   EXPECT_TRUE(SingleTable.contains(42));
@@ -297,4 +303,44 @@ TEST(EytzingerTest, EytzingerTableHeterogeneousCreate) {
   EXPECT_FALSE(Table.contains(uint64_t(999ULL)));
 }
 
+TEST(EytzingerTest, EytzingerTableSpanBeginEnd) {
+  const int Data[] = {40, 20, 60, 10, 30, 50, 70};
+  EytzingerTableSpan<int> Span(Data, 7);
+
+  EXPECT_EQ(Span.begin(), Data);
+  EXPECT_EQ(Span.end(), Data + 7);
+  EXPECT_EQ(std::distance(Span.begin(), Span.end()), 7);
+
+  std::vector<int> Traversed(Span.begin(), Span.end());
+  std::vector<int> Expected = {40, 20, 60, 10, 30, 50, 70};
+  EXPECT_EQ(Traversed, Expected);
+
+  // Range-based for loop verification.
+  std::vector<int> RangeTraversed;
+  for (const int &Val : Span)
+    RangeTraversed.push_back(Val);
+  EXPECT_EQ(RangeTraversed, Expected);
+}
+
+TEST(EytzingerTest, EytzingerTableBeginEnd) {
+  std::vector<int> Unsorted = {70, 20, 40, 10, 60, 30, 50};
+  auto Table = EytzingerTable<int>::create(std::move(Unsorted));
+
+  EXPECT_EQ(std::distance(Table.begin(), Table.end()), 7);
+
+  std::vector<int> Traversed(Table.begin(), Table.end());
+  std::vector<int> Expected = {40, 20, 60, 10, 30, 50, 70};
+  EXPECT_EQ(Traversed, Expected);
+
+  // Range-based for loop verification on both non-const and const tables.
+  std::vector<int> RangeTraversed;
+  for (const int &Val : Table)
+    RangeTraversed.push_back(Val);
+  EXPECT_EQ(RangeTraversed, Expected);
+
+  const auto &ConstTable = Table;
+  std::vector<int> ConstTraversed(ConstTable.begin(), ConstTable.end());
+  EXPECT_EQ(ConstTraversed, Expected);
+}
+
 } // namespace



More information about the llvm-commits mailing list