[llvm] [CycleInfo] Drop GraphTraits and df_iterator. NFC (PR #209847)

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 15 18:50:45 PDT 2026


https://github.com/MaskRay updated https://github.com/llvm/llvm-project/pull/209847

>From e2d5783f57eff289a947f09173e024cc7d7be66d Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Wed, 15 Jul 2026 10:58:21 -0700
Subject: [PATCH 1/2] [CycleInfo] Drop GraphTraits and df_iterator. NFC

depth_first uses SmallPtrSet visited-set, which is pure overhead on a
tree. Replace them with explicit child-stack walks and delete the unused
GraphTraits specializations to prevent misuse.
---
 llvm/include/llvm/ADT/GenericCycleImpl.h     | 46 ++++++++++++--------
 llvm/include/llvm/ADT/GenericCycleInfo.h     | 44 -------------------
 llvm/lib/Transforms/Utils/FixIrreducible.cpp |  7 ++-
 3 files changed, 35 insertions(+), 62 deletions(-)

diff --git a/llvm/include/llvm/ADT/GenericCycleImpl.h b/llvm/include/llvm/ADT/GenericCycleImpl.h
index 8196912a23cd3..9f83efc2aa946 100644
--- a/llvm/include/llvm/ADT/GenericCycleImpl.h
+++ b/llvm/include/llvm/ADT/GenericCycleImpl.h
@@ -485,8 +485,13 @@ void GenericCycleInfoCompute<ContextT>::run(FunctionT *F) {
 /// \brief Recompute depth values of \p SubTree and all descendants.
 template <typename ContextT>
 void GenericCycleInfoCompute<ContextT>::updateDepth(CycleT *SubTree) {
-  for (CycleT *Cycle : depth_first(SubTree))
+  SmallVector<CycleT *, 8> Worklist = {SubTree};
+  while (!Worklist.empty()) {
+    CycleT *Cycle = Worklist.pop_back_val();
     Cycle->Depth = Cycle->ParentCycle ? Cycle->ParentCycle->Depth + 1 : 1;
+    for (CycleT *Child : Cycle->children())
+      Worklist.push_back(Child);
+  }
 }
 
 /// \brief Compute a DFS of basic blocks starting at the function entry.
@@ -634,21 +639,23 @@ void GenericCycleInfo<ContextT>::verifyCycleNest(bool VerifyFull) const {
 #ifndef NDEBUG
   DenseSet<BlockT *> CycleHeaders;
 
-  for (CycleT *TopCycle : toplevel_cycles()) {
-    for (CycleT *Cycle : depth_first(TopCycle)) {
-      BlockT *Header = Cycle->getHeader();
-      assert(CycleHeaders.insert(Header).second);
-      if (VerifyFull)
-        verifyCycle(*Cycle);
-      else
-        verifyCycleNest(*Cycle);
-      // Check the block map entries for blocks contained in this cycle.
-      for (BlockT *BB : getBlocks(*Cycle)) {
-        CycleT *CycleInBlockMap = getCycle(BB);
-        assert(CycleInBlockMap != nullptr);
-        assert(Cycle->contains(CycleInBlockMap));
-      }
+  SmallVector<CycleT *, 8> Worklist(toplevel_begin(), toplevel_end());
+  while (!Worklist.empty()) {
+    CycleT *Cycle = Worklist.pop_back_val();
+    BlockT *Header = Cycle->getHeader();
+    assert(CycleHeaders.insert(Header).second);
+    if (VerifyFull)
+      verifyCycle(*Cycle);
+    else
+      verifyCycleNest(*Cycle);
+    // Check the block map entries for blocks contained in this cycle.
+    for (BlockT *BB : getBlocks(*Cycle)) {
+      CycleT *CycleInBlockMap = getCycle(BB);
+      assert(CycleInBlockMap != nullptr);
+      assert(Cycle->contains(CycleInBlockMap));
     }
+    for (CycleT *Child : Cycle->children())
+      Worklist.push_back(Child);
   }
 #endif
 }
@@ -661,12 +668,17 @@ template <typename ContextT> void GenericCycleInfo<ContextT>::verify() const {
 /// \brief Print the cycle info.
 template <typename ContextT>
 void GenericCycleInfo<ContextT>::print(raw_ostream &Out) const {
-  for (const auto *TLC : toplevel_cycles()) {
-    for (const CycleT *Cycle : depth_first(TLC)) {
+  SmallVector<const CycleT *, 8> Stack;
+  for (const CycleT *TLC : toplevel_cycles()) {
+    Stack.push_back(TLC);
+    while (!Stack.empty()) {
+      const CycleT *Cycle = Stack.pop_back_val();
       for (unsigned I = 0; I < Cycle->Depth; ++I)
         Out << "    ";
 
       Out << print(Cycle) << '\n';
+      for (const auto &Child : reverse(Cycle->Children))
+        Stack.push_back(Child.get());
     }
   }
 }
diff --git a/llvm/include/llvm/ADT/GenericCycleInfo.h b/llvm/include/llvm/ADT/GenericCycleInfo.h
index e67f9f0939fd9..448f2fa2db127 100644
--- a/llvm/include/llvm/ADT/GenericCycleInfo.h
+++ b/llvm/include/llvm/ADT/GenericCycleInfo.h
@@ -351,50 +351,6 @@ template <typename ContextT> class GenericCycleInfo {
   //@}
 };
 
-/// \brief GraphTraits for iterating over a sub-tree of the CycleT tree.
-template <typename CycleRefT, typename ChildIteratorT> struct CycleGraphTraits {
-  using NodeRef = CycleRefT;
-
-  using nodes_iterator = ChildIteratorT;
-  using ChildIteratorType = nodes_iterator;
-
-  static NodeRef getEntryNode(NodeRef Graph) { return Graph; }
-
-  static ChildIteratorType child_begin(NodeRef Ref) {
-    return Ref->child_begin();
-  }
-  static ChildIteratorType child_end(NodeRef Ref) { return Ref->child_end(); }
-
-  // Not implemented:
-  // static nodes_iterator nodes_begin(GraphType *G)
-  // static nodes_iterator nodes_end  (GraphType *G)
-  //    nodes_iterator/begin/end - Allow iteration over all nodes in the graph
-
-  // typedef EdgeRef           - Type of Edge token in the graph, which should
-  //                             be cheap to copy.
-  // typedef ChildEdgeIteratorType - Type used to iterate over children edges in
-  //                             graph, dereference to a EdgeRef.
-
-  // static ChildEdgeIteratorType child_edge_begin(NodeRef)
-  // static ChildEdgeIteratorType child_edge_end(NodeRef)
-  //     Return iterators that point to the beginning and ending of the
-  //     edge list for the given callgraph node.
-  //
-  // static NodeRef edge_dest(EdgeRef)
-  //     Return the destination node of an edge.
-  // static unsigned       size       (GraphType *G)
-  //    Return total number of nodes in the graph
-};
-
-template <typename BlockT>
-struct GraphTraits<const GenericCycle<BlockT> *>
-    : CycleGraphTraits<const GenericCycle<BlockT> *,
-                       typename GenericCycle<BlockT>::const_child_iterator> {};
-template <typename BlockT>
-struct GraphTraits<GenericCycle<BlockT> *>
-    : CycleGraphTraits<GenericCycle<BlockT> *,
-                       typename GenericCycle<BlockT>::const_child_iterator> {};
-
 } // namespace llvm
 
 #endif // LLVM_ADT_GENERICCYCLEINFO_H
diff --git a/llvm/lib/Transforms/Utils/FixIrreducible.cpp b/llvm/lib/Transforms/Utils/FixIrreducible.cpp
index 087515122bada..9ef0eedcad887 100644
--- a/llvm/lib/Transforms/Utils/FixIrreducible.cpp
+++ b/llvm/lib/Transforms/Utils/FixIrreducible.cpp
@@ -429,9 +429,14 @@ static bool FixIrreducibleImpl(Function &F, CycleInfo &CI, DominatorTree &DT,
                     << F.getName() << "\n");
 
   bool Changed = false;
+  SmallVector<Cycle *, 8> Worklist;
   for (Cycle *TopCycle : CI.toplevel_cycles()) {
-    for (Cycle *C : depth_first(TopCycle)) {
+    Worklist.push_back(TopCycle);
+    while (!Worklist.empty()) {
+      Cycle *C = Worklist.pop_back_val();
       Changed |= fixIrreducible(*C, CI, DT, LI);
+      SmallVector<Cycle *, 4> Children(C->child_begin(), C->child_end());
+      Worklist.append(Children.rbegin(), Children.rend());
     }
   }
 

>From d7d5fd4867c1ce258580d4475746ab6e5eeb7da1 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Wed, 15 Jul 2026 18:50:34 -0700
Subject: [PATCH 2/2] update iterator type; use reverse(children)

---
 llvm/include/llvm/ADT/GenericCycleInfo.h     | 8 ++++++--
 llvm/lib/Transforms/Utils/FixIrreducible.cpp | 3 +--
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/llvm/include/llvm/ADT/GenericCycleInfo.h b/llvm/include/llvm/ADT/GenericCycleInfo.h
index 448f2fa2db127..96b5fb1f4e66a 100644
--- a/llvm/include/llvm/ADT/GenericCycleInfo.h
+++ b/llvm/include/llvm/ADT/GenericCycleInfo.h
@@ -130,9 +130,13 @@ template <typename ContextT> class GenericCycle {
   using const_child_iterator_base =
       typename std::vector<std::unique_ptr<GenericCycle>>::const_iterator;
   struct const_child_iterator
-      : iterator_adaptor_base<const_child_iterator, const_child_iterator_base> {
+      : iterator_adaptor_base<const_child_iterator, const_child_iterator_base,
+                              std::random_access_iterator_tag, GenericCycle *,
+                              std::ptrdiff_t, GenericCycle *, GenericCycle *> {
     using Base =
-        iterator_adaptor_base<const_child_iterator, const_child_iterator_base>;
+        iterator_adaptor_base<const_child_iterator, const_child_iterator_base,
+                              std::random_access_iterator_tag, GenericCycle *,
+                              std::ptrdiff_t, GenericCycle *, GenericCycle *>;
 
     const_child_iterator() = default;
     explicit const_child_iterator(const_child_iterator_base I) : Base(I) {}
diff --git a/llvm/lib/Transforms/Utils/FixIrreducible.cpp b/llvm/lib/Transforms/Utils/FixIrreducible.cpp
index 9ef0eedcad887..81feb34eb953d 100644
--- a/llvm/lib/Transforms/Utils/FixIrreducible.cpp
+++ b/llvm/lib/Transforms/Utils/FixIrreducible.cpp
@@ -435,8 +435,7 @@ static bool FixIrreducibleImpl(Function &F, CycleInfo &CI, DominatorTree &DT,
     while (!Worklist.empty()) {
       Cycle *C = Worklist.pop_back_val();
       Changed |= fixIrreducible(*C, CI, DT, LI);
-      SmallVector<Cycle *, 4> Children(C->child_begin(), C->child_end());
-      Worklist.append(Children.rbegin(), Children.rend());
+      llvm::append_range(Worklist, reverse(C->children()));
     }
   }
 



More information about the llvm-commits mailing list