[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