[llvm] 15776b5 - [CycleInfo] Remove GenericCycle::TopLevelCycle. NFC (#209677)

via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 15 00:50:55 PDT 2026


Author: Fangrui Song
Date: 2026-07-15T07:50:51Z
New Revision: 15776b5cddd4bfd8ff06f2aac6e9eea09cf0112c

URL: https://github.com/llvm/llvm-project/commit/15776b5cddd4bfd8ff06f2aac6e9eea09cf0112c
DIFF: https://github.com/llvm/llvm-project/commit/15776b5cddd4bfd8ff06f2aac6e9eea09cf0112c.diff

LOG: [CycleInfo] Remove GenericCycle::TopLevelCycle. NFC (#209677)

moveTopLevelCycleToNewParent maintains TopLevelCycle eagerly, rewriting
the whole re-parented subtree with depth_first. When discovery nests k
cycles one by one this is quadratic, and the df_iterator walk plus its
visited set dominate construction on deep nests (~78% of time on a
1500-deep nest).

Walk ParentCycle links in getTopLevelParentCycle instead and delete the
member. The walk is valid during construction too: parent links are
always current, and discovery queries blocks whose innermost cycle sits
at the top of the forest being merged, so the walk is short.

Aided by Claude Fable 5

Added: 
    

Modified: 
    llvm/include/llvm/ADT/GenericCycleImpl.h
    llvm/include/llvm/ADT/GenericCycleInfo.h

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/ADT/GenericCycleImpl.h b/llvm/include/llvm/ADT/GenericCycleImpl.h
index dfeb479d764e5..1710141d39cad 100644
--- a/llvm/include/llvm/ADT/GenericCycleImpl.h
+++ b/llvm/include/llvm/ADT/GenericCycleImpl.h
@@ -227,11 +227,6 @@ void GenericCycle<ContextT>::verifyCycleNest() const {
   if (ParentCycle) {
     assert(is_contained(ParentCycle->children(), this) &&
            "Cycle is not a subcycle of its parent!");
-    assert(ParentCycle->TopLevelCycle == TopLevelCycle &&
-           "Top level cycle of parent cycle must be the same");
-  } else {
-    assert(TopLevelCycle == this &&
-           "Cycle without parent must be top-level cycle");
   }
 #endif
 }
@@ -293,7 +288,9 @@ template <typename ContextT>
 auto GenericCycleInfo<ContextT>::getTopLevelParentCycle(
     const BlockT *Block) const -> CycleT * {
   CycleT *Cycle = getCycle(Block);
-  return Cycle ? Cycle->TopLevelCycle : nullptr;
+  while (Cycle && Cycle->ParentCycle)
+    Cycle = Cycle->ParentCycle;
+  return Cycle;
 }
 
 template <typename ContextT>
@@ -311,9 +308,6 @@ void GenericCycleInfo<ContextT>::moveTopLevelCycleToNewParent(CycleT *NewParent,
   *Pos = std::move(CurrentContainer.back());
   CurrentContainer.pop_back();
   Child->ParentCycle = NewParent;
-  Child->TopLevelCycle = NewParent;
-  for (CycleT *Cycle : depth_first(Child))
-    Cycle->TopLevelCycle = NewParent;
   // This only relinks the cycle tree and does NOT touch BlockLayout, so it
   // leaves every cycle's [IdxBegin, IdxEnd) range stale, i.e. BlockLayout is
   // left invalid. The caller must call layoutBlocks() before any

diff  --git a/llvm/include/llvm/ADT/GenericCycleInfo.h b/llvm/include/llvm/ADT/GenericCycleInfo.h
index c3093d4cf83e5..5a414d502225c 100644
--- a/llvm/include/llvm/ADT/GenericCycleInfo.h
+++ b/llvm/include/llvm/ADT/GenericCycleInfo.h
@@ -54,10 +54,6 @@ template <typename ContextT> class GenericCycle {
   /// at the root.
   GenericCycle *ParentCycle = nullptr;
 
-  /// The top-level cycle this cycle is part of. Points to itself if this is
-  /// a top-level cycle.
-  GenericCycle *TopLevelCycle;
-
   /// The entry block(s) of the cycle. The header is the only entry if
   /// this is a loop. Is empty for the root "cycle", to avoid
   /// unnecessary memory use.
@@ -108,7 +104,7 @@ template <typename ContextT> class GenericCycle {
   GenericCycle &operator=(GenericCycle &&Rhs) = delete;
 
 public:
-  GenericCycle() : TopLevelCycle(this) {}
+  GenericCycle() = default;
 
   /// \brief Whether the cycle is a natural loop.
   bool isReducible() const { return Entries.size() == 1; }


        


More information about the llvm-commits mailing list