[llvm] [CycleInfo] Move cycle accessors to GenericCycleInfo. NFC (PR #209990)
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 16 09:52:37 PDT 2026
https://github.com/MaskRay updated https://github.com/llvm/llvm-project/pull/209990
>From cdf0b8dac07d03639c1bf36ce83acb16dda9b141 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Thu, 16 Jul 2026 00:35:47 -0700
Subject: [PATCH] [CycleInfo] Move cycle accessors to GenericCycleInfo. NFC
Move member functions off GenericCycle onto GenericCycleInfo.
GenericCycle now holds only data and the child-iterator type, and all
cycle queries go through GenericCycleInfo. This prepares replacing the
GenericCycle pointer with an opaque handle.
Aided by Claude Opus 4.8
Pull Request: https://github.com/llvm/llvm-project/pull/209990
---
llvm/include/llvm/ADT/GenericCycleImpl.h | 58 +++++-----
llvm/include/llvm/ADT/GenericCycleInfo.h | 104 ++++++------------
llvm/include/llvm/ADT/GenericUniformityImpl.h | 83 +++++++-------
.../llvm/IR/GenericConvergenceVerifierImpl.h | 4 +-
llvm/lib/CodeGen/MachineCycleAnalysis.cpp | 2 +-
llvm/lib/CodeGen/MachineSink.cpp | 11 +-
.../AMDGPUGlobalISelDivergenceLowering.cpp | 7 +-
llvm/lib/Target/AMDGPU/SIInstrInfo.cpp | 4 +-
llvm/lib/Target/AMDGPU/SILowerSGPRSpills.cpp | 6 +-
.../Transforms/IPO/AttributorAttributes.cpp | 2 +-
llvm/lib/Transforms/Utils/FixIrreducible.cpp | 16 +--
11 files changed, 134 insertions(+), 163 deletions(-)
diff --git a/llvm/include/llvm/ADT/GenericCycleImpl.h b/llvm/include/llvm/ADT/GenericCycleImpl.h
index 043b7f48501b8..779a6eb813401 100644
--- a/llvm/include/llvm/ADT/GenericCycleImpl.h
+++ b/llvm/include/llvm/ADT/GenericCycleImpl.h
@@ -84,7 +84,7 @@ auto GenericCycleInfo<ContextT>::getCyclePreheader(const CycleT &C) const
if (!Predecessor)
return nullptr;
- assert(C.isReducible() && "Cycle Predecessor must be in a reducible cycle!");
+ assert(isReducible(C) && "Cycle Predecessor must be in a reducible cycle!");
if (succ_size(Predecessor) != 1)
return nullptr;
@@ -99,13 +99,13 @@ auto GenericCycleInfo<ContextT>::getCyclePreheader(const CycleT &C) const
template <typename ContextT>
auto GenericCycleInfo<ContextT>::getCyclePredecessor(const CycleT &C) const
-> BlockT * {
- if (!C.isReducible())
+ if (!isReducible(C))
return nullptr;
BlockT *Out = nullptr;
// Loop over the predecessors of the header node...
- BlockT *Header = C.getHeader();
+ BlockT *Header = getHeader(C);
for (const auto Pred : predecessors(Header)) {
if (!contains(C, Pred)) {
if (Out && Out != Pred)
@@ -120,7 +120,7 @@ auto GenericCycleInfo<ContextT>::getCyclePredecessor(const CycleT &C) const
template <typename ContextT>
void GenericCycleInfo<ContextT>::verifyCycle(const CycleT &C) const {
#ifndef NDEBUG
- assert(C.getNumBlocks() != 0 && "Cycle cannot be empty.");
+ assert(getNumBlocks(C) != 0 && "Cycle cannot be empty.");
DenseSet<BlockT *> Blocks;
for (BlockT *BB : getBlocks(C)) {
assert(Blocks.insert(BB).second); // duplicates in block list?
@@ -128,7 +128,7 @@ void GenericCycleInfo<ContextT>::verifyCycle(const CycleT &C) const {
assert(!C.Entries.empty() && "Cycle must have one or more entries.");
DenseSet<BlockT *> Entries;
- for (BlockT *Entry : C.entries()) {
+ for (BlockT *Entry : getEntries(C)) {
assert(Entries.insert(Entry).second); // duplicate entry?
assert(contains(C, Entry));
}
@@ -143,7 +143,7 @@ void GenericCycleInfo<ContextT>::verifyCycle(const CycleT &C) const {
SmallPtrSet<BlockT *, 8> VisitedBBs;
// Check the individual blocks.
- for (BlockT *BB : depth_first_ext(C.getHeader(), VisitSet)) {
+ for (BlockT *BB : depth_first_ext(getHeader(C), VisitSet)) {
assert(llvm::any_of(llvm::children<BlockT *>(BB),
[&](BlockT *B) { return contains(C, B); }) &&
"Cycle block has no in-cycle successors!");
@@ -168,13 +168,13 @@ void GenericCycleInfo<ContextT>::verifyCycle(const CycleT &C) const {
assert(!OutsideCyclePreds.contains(CB) &&
"Non-entry block reachable from outside!");
}
- assert(BB != &C.getHeader()->getParent()->front() &&
+ assert(BB != &getHeader(C)->getParent()->front() &&
"Cycle contains function entry block!");
VisitedBBs.insert(BB);
}
- if (VisitedBBs.size() != C.getNumBlocks()) {
+ if (VisitedBBs.size() != getNumBlocks(C)) {
dbgs() << "The following blocks are unreachable in the cycle:\n ";
ListSeparator LS;
for (auto *BB : Blocks) {
@@ -195,7 +195,7 @@ template <typename ContextT>
void GenericCycleInfo<ContextT>::verifyCycleNest(const CycleT &C) const {
#ifndef NDEBUG
// Check the subcycles.
- for (CycleT *Child : C.children()) {
+ for (CycleT *Child : children(C)) {
// Each block in each subcycle should be contained within this cycle.
for (BlockT *BB : getBlocks(*Child)) {
assert(contains(C, BB) &&
@@ -206,7 +206,7 @@ void GenericCycleInfo<ContextT>::verifyCycleNest(const CycleT &C) const {
// Check the parent cycle pointer.
if (C.ParentCycle) {
- assert(is_contained(C.ParentCycle->children(), &C) &&
+ assert(is_contained(children(*C.ParentCycle), &C) &&
"Cycle is not a subcycle of its parent!");
}
#endif
@@ -316,7 +316,7 @@ void GenericCycleInfo<ContextT>::addBlockToCycle(BlockT *Block, CycleT *Cycle) {
addToBlockMap(Block, Cycle);
// Cycle and its ancestors gain the new block: extend each one's slice and
// invalidate its exit-block cache in a single walk up the tree.
- for (CycleT *C = Cycle; C; C = C->getParentCycle()) {
+ for (CycleT *C = Cycle; C; C = getParentCycle(*C)) {
++C->IdxEnd;
if (!ExitBlocksCaches.empty())
ExitBlocksCaches[getCycleIndex(*C)].clear();
@@ -442,7 +442,7 @@ void GenericCycleInfoCompute<ContextT>::run(FunctionT *F) {
}
}
if (IsEntry) {
- assert(!NewCycle->isEntry(Block));
+ assert(!Info.isEntry(*NewCycle, Block));
LLVM_DEBUG(errs() << "append as entry\n");
NewCycle->appendEntry(Block);
} else {
@@ -462,18 +462,18 @@ void GenericCycleInfoCompute<ContextT>::run(FunctionT *F) {
LLVM_DEBUG(errs() << " block " << Info.Context.print(Block) << ": ");
if (BlockParent != NewCycle) {
- LLVM_DEBUG(errs()
- << "discovered child cycle "
- << Info.Context.print(BlockParent->getHeader()) << "\n");
+ LLVM_DEBUG(errs() << "discovered child cycle "
+ << Info.Context.print(Info.getHeader(*BlockParent))
+ << "\n");
// Make BlockParent the child of NewCycle.
moveTopLevelCycleToNewParent(NewCycle, BlockParent);
- for (auto *ChildEntry : BlockParent->entries())
+ for (auto *ChildEntry : Info.getEntries(*BlockParent))
ProcessPredecessors(ChildEntry);
} else {
- LLVM_DEBUG(errs()
- << "known child cycle "
- << Info.Context.print(BlockParent->getHeader()) << "\n");
+ LLVM_DEBUG(errs() << "known child cycle "
+ << Info.Context.print(Info.getHeader(*BlockParent))
+ << "\n");
}
} else {
Info.addToBlockMap(Block, NewCycle);
@@ -601,17 +601,17 @@ auto GenericCycleInfo<ContextT>::getSmallestCommonCycle(CycleT *A,
// If cycles A and B have different depth replace them with parent cycle
// until they have the same depth.
- while (A->getDepth() > B->getDepth())
- A = A->getParentCycle();
- while (B->getDepth() > A->getDepth())
- B = B->getParentCycle();
+ while (getDepth(*A) > getDepth(*B))
+ A = getParentCycle(*A);
+ while (getDepth(*B) > getDepth(*A))
+ B = getParentCycle(*B);
// Cycles A and B are at same depth but may be disjoint, replace them with
// parent cycles until we find cycle that contains both or we run out of
// parent cycles.
while (A != B) {
- A = A->getParentCycle();
- B = B->getParentCycle();
+ A = getParentCycle(*A);
+ B = getParentCycle(*B);
}
return A;
@@ -638,7 +638,7 @@ void GenericCycleInfo<ContextT>::verifyCycleNest(bool VerifyFull) const {
DenseSet<BlockT *> CycleHeaders;
for (const CycleT &Cycle : cycles()) {
- BlockT *Header = Cycle.getHeader();
+ BlockT *Header = getHeader(Cycle);
assert(CycleHeaders.insert(Header).second);
if (VerifyFull)
verifyCycle(Cycle);
@@ -648,7 +648,7 @@ void GenericCycleInfo<ContextT>::verifyCycleNest(bool VerifyFull) const {
for (BlockT *BB : getBlocks(Cycle)) {
CycleT *CycleInBlockMap = getCycle(BB);
assert(CycleInBlockMap != nullptr);
- assert(Cycle.contains(CycleInBlockMap));
+ assert(contains(Cycle, *CycleInBlockMap));
}
}
#endif
@@ -675,10 +675,10 @@ template <typename ContextT>
Printable GenericCycleInfo<ContextT>::print(const CycleT *Cycle) const {
return Printable([this, Cycle](raw_ostream &Out) {
Out << "depth=" << Cycle->Depth << ": entries("
- << Cycle->printEntries(Context) << ')';
+ << printEntries(*Cycle, Context) << ')';
for (auto *Block : getBlocks(*Cycle)) {
- if (Cycle->isEntry(Block))
+ if (isEntry(*Cycle, Block))
continue;
Out << ' ' << Context.print(Block);
diff --git a/llvm/include/llvm/ADT/GenericCycleInfo.h b/llvm/include/llvm/ADT/GenericCycleInfo.h
index 07995faffefc5..8b706f5986307 100644
--- a/llvm/include/llvm/ADT/GenericCycleInfo.h
+++ b/llvm/include/llvm/ADT/GenericCycleInfo.h
@@ -92,39 +92,6 @@ template <typename ContextT> class GenericCycle {
public:
GenericCycle() = default;
- /// \brief Whether the cycle is a natural loop.
- bool isReducible() const { return Entries.size() == 1; }
-
- BlockT *getHeader() const { return Entries[0]; }
-
- const SmallVectorImpl<BlockT *> & getEntries() const {
- return Entries;
- }
-
- /// \brief Return whether \p Block is an entry block of the cycle.
- bool isEntry(const BlockT *Block) const {
- return is_contained(Entries, Block);
- }
-
- /// \brief Replace all entries with \p Block as single entry.
- /// \p Block must be contained in the cycle.
- void setSingleEntry(BlockT *Block) {
- Entries.clear();
- Entries.push_back(Block);
- }
-
- /// \brief Returns true iff this cycle contains \p C. O(1). Non-strict, i.e.
- /// returns true if C is the same cycle.
- bool contains(const GenericCycle *C) const {
- return C && IdxBegin <= C->IdxBegin && C->IdxEnd <= IdxEnd;
- }
-
- const GenericCycle *getParentCycle() const { return ParentCycle; }
- GenericCycle *getParentCycle() { return ParentCycle; }
- unsigned getDepth() const { return Depth; }
-
- size_t getNumBlocks() const { return IdxEnd - IdxBegin; }
-
/// Iteration over child cycles: the first child (if any) immediately
/// follows this cycle in the preorder array, and each next sibling follows
/// the previous child's subtree.
@@ -147,41 +114,7 @@ template <typename ContextT> class GenericCycle {
return C == Other.C;
}
};
-
- const_child_iterator child_begin() const {
- return const_child_iterator{this + 1};
- }
- const_child_iterator child_end() const {
- return const_child_iterator{this + 1 + NumDescendants};
- }
- iterator_range<const_child_iterator> children() const {
- return llvm::make_range(child_begin(), child_end());
- }
//@}
-
- /// Iteration over entry blocks.
- //@{
- using const_entry_iterator =
- typename SmallVectorImpl<BlockT *>::const_iterator;
- const_entry_iterator entry_begin() const { return Entries.begin(); }
- const_entry_iterator entry_end() const { return Entries.end(); }
- size_t getNumEntries() const { return Entries.size(); }
- iterator_range<const_entry_iterator> entries() const {
- return llvm::make_range(entry_begin(), entry_end());
- }
- using const_reverse_entry_iterator =
- typename SmallVectorImpl<BlockT *>::const_reverse_iterator;
- const_reverse_entry_iterator entry_rbegin() const { return Entries.rbegin(); }
- const_reverse_entry_iterator entry_rend() const { return Entries.rend(); }
- //@}
-
- Printable printEntries(const ContextT &Ctx) const {
- return Printable([this, &Ctx](raw_ostream &Out) {
- ListSeparator LS(" ");
- for (auto *Entry : Entries)
- Out << LS << Ctx.print(Entry);
- });
- }
};
/// \brief Cycle information for a function.
@@ -249,9 +182,42 @@ template <typename ContextT> class GenericCycleInfo {
return Number < BlockMap.size() ? BlockMap[Number] : nullptr;
}
+ BlockT *getHeader(const CycleT &C) const { return C.Entries[0]; }
+ bool isReducible(const CycleT &C) const { return C.Entries.size() == 1; }
+ CycleT *getParentCycle(const CycleT &C) const { return C.ParentCycle; }
+ unsigned getDepth(const CycleT &C) const { return C.Depth; }
+ size_t getNumBlocks(const CycleT &C) const { return C.IdxEnd - C.IdxBegin; }
+
+ ArrayRef<BlockT *> getEntries(const CycleT &C) const { return C.Entries; }
+ bool isEntry(const CycleT &C, const BlockT *Block) const {
+ return is_contained(C.Entries, Block);
+ }
+ void setSingleEntry(CycleT &C, BlockT *Block) {
+ C.Entries.clear();
+ C.Entries.push_back(Block);
+ }
+ /// Returns true iff \p Outer contains \p Inner. O(1). Non-strict.
+ bool contains(const CycleT &Outer, const CycleT &Inner) const {
+ return Outer.IdxBegin <= Inner.IdxBegin && Inner.IdxEnd <= Outer.IdxEnd;
+ }
+ iterator_range<typename CycleT::const_child_iterator>
+ children(const CycleT &C) const {
+ return llvm::make_range(
+ typename CycleT::const_child_iterator{&C + 1},
+ typename CycleT::const_child_iterator{&C + 1 + C.NumDescendants});
+ }
+ Printable printEntries(const CycleT &C, const ContextT &Ctx) const {
+ return Printable([&C, &Ctx](raw_ostream &Out) {
+ ListSeparator LS(" ");
+ for (auto *Entry : C.Entries)
+ Out << LS << Ctx.print(Entry);
+ });
+ }
+
/// \brief Return whether \p Block is contained in \p C. O(1).
bool contains(const CycleT &C, const BlockT *Block) const {
- return C.contains(getCycle(Block));
+ const CycleT *Inner = getCycle(Block);
+ return Inner && contains(C, *Inner);
}
/// \brief Return the blocks of \p C, including those of nested cycles.
@@ -267,7 +233,7 @@ template <typename ContextT> class GenericCycleInfo {
/// if it is not contained in any cycle.
unsigned getCycleDepth(const BlockT *Block) const {
CycleT *Cycle = getCycle(Block);
- return Cycle ? Cycle->getDepth() : 0;
+ return Cycle ? getDepth(*Cycle) : 0;
}
CycleT *getTopLevelParentCycle(const BlockT *Block) const {
diff --git a/llvm/include/llvm/ADT/GenericUniformityImpl.h b/llvm/include/llvm/ADT/GenericUniformityImpl.h
index 630476daf2cd6..528fe11d8579e 100644
--- a/llvm/include/llvm/ADT/GenericUniformityImpl.h
+++ b/llvm/include/llvm/ADT/GenericUniformityImpl.h
@@ -641,18 +641,19 @@ template <typename ContextT> class DivergencePropagator {
// Locate the largest ancestor cycle that is not reducible and does not
// contain a reducible ancestor. This is done with a lambda that is defined
// and invoked in the same statement.
- const CycleT *IrreducibleAncestor = [](const CycleT *C) -> const CycleT * {
+ const CycleT *IrreducibleAncestor =
+ [this](const CycleT *C) -> const CycleT * {
if (!C)
return nullptr;
- if (C->isReducible())
+ if (CI.isReducible(*C))
return nullptr;
- while (const CycleT *P = C->getParentCycle()) {
- if (P->isReducible())
+ while (const CycleT *P = CI.getParentCycle(*C)) {
+ if (CI.isReducible(*P))
return C;
C = P;
}
- assert(!C->getParentCycle());
- assert(!C->isReducible());
+ assert(!CI.getParentCycle(*C));
+ assert(!CI.isReducible(*C));
return C;
}(DivTermCycle);
@@ -740,15 +741,15 @@ template <typename ContextT> class DivergencePropagator {
// A cycle has exit divergence if the label of an exit block does
// not match the label of its header.
for (const auto *Cycle = CI.getCycle(&DivTermBlock); Cycle;
- Cycle = Cycle->getParentCycle()) {
- if (Cycle->isReducible()) {
+ Cycle = CI.getParentCycle(*Cycle)) {
+ if (CI.isReducible(*Cycle)) {
// The exit divergence of a reducible cycle is recorded while
// propagating labels.
continue;
}
SmallVector<BlockT *> Exits;
CI.getExitBlocks(*Cycle, Exits);
- auto *Header = Cycle->getHeader();
+ auto *Header = CI.getHeader(*Cycle);
auto *HeaderLabel = BlockLabels[Header];
for (const auto *Exit : Exits) {
if (BlockLabels[Exit] != HeaderLabel) {
@@ -906,17 +907,17 @@ void GenericUniformityAnalysisImpl<ContextT>::propagateCycleExitDivergence(
auto *OuterDivCycle = DivCycle;
auto *ExitLevelCycle = CI.getCycle(&DivExit);
const unsigned CycleExitDepth =
- ExitLevelCycle ? ExitLevelCycle->getDepth() : 0;
+ ExitLevelCycle ? CI.getDepth(*ExitLevelCycle) : 0;
// Find outer-most cycle that does not contain \p DivExit
- while (DivCycle && DivCycle->getDepth() > CycleExitDepth) {
+ while (DivCycle && CI.getDepth(*DivCycle) > CycleExitDepth) {
LLVM_DEBUG(dbgs() << " Found exiting cycle: "
- << Context.print(DivCycle->getHeader()) << "\n");
+ << Context.print(CI.getHeader(*DivCycle)) << "\n");
OuterDivCycle = DivCycle;
- DivCycle = DivCycle->getParentCycle();
+ DivCycle = CI.getParentCycle(*DivCycle);
}
LLVM_DEBUG(dbgs() << "\tOuter-most exiting cycle: "
- << Context.print(OuterDivCycle->getHeader()) << "\n");
+ << Context.print(CI.getHeader(*OuterDivCycle)) << "\n");
if (!DivergentExitCycles.insert(OuterDivCycle).second)
return;
@@ -924,7 +925,7 @@ void GenericUniformityAnalysisImpl<ContextT>::propagateCycleExitDivergence(
// Exit divergence does not matter if the cycle itself is assumed to
// be divergent.
for (const auto *C : AssumedDivergent) {
- if (C->contains(OuterDivCycle))
+ if (CI.contains(*C, *OuterDivCycle))
return;
}
@@ -969,10 +970,11 @@ void GenericUniformityAnalysisImpl<ContextT>::taintAndPushPhiNodes(
/// Add \p Candidate to \p Cycles if it is not already contained in \p Cycles.
///
/// \return true iff \p Candidate was added to \p Cycles.
-template <typename CycleT>
-bool insertIfNotContained(SmallVector<CycleT *> &Cycles, CycleT *Candidate) {
+template <typename CycleInfoT, typename CycleT>
+bool insertIfNotContained(const CycleInfoT &CI, SmallVector<CycleT *> &Cycles,
+ CycleT *Candidate) {
if (llvm::any_of(Cycles,
- [Candidate](CycleT *C) { return C->contains(Candidate); }))
+ [&](CycleT *C) { return CI.contains(*C, *Candidate); }))
return false;
Cycles.push_back(Candidate);
return true;
@@ -994,20 +996,20 @@ const CycleT *getExtDivCycle(const CycleInfoT &CI, const CycleT *Cycle,
return nullptr;
const auto *OriginalCycle = Cycle;
- const auto *Parent = Cycle->getParentCycle();
+ const auto *Parent = CI.getParentCycle(*Cycle);
while (Parent && !CI.contains(*Parent, DivTermBlock)) {
Cycle = Parent;
- Parent = Cycle->getParentCycle();
+ Parent = CI.getParentCycle(*Cycle);
}
// If the original cycle is not the outermost cycle, then the outermost cycle
// is irreducible. If the outermost cycle were reducible, then external
// diverged paths would not reach the original inner cycle.
(void)OriginalCycle;
- assert(Cycle == OriginalCycle || !Cycle->isReducible());
+ assert(Cycle == OriginalCycle || !CI.isReducible(*Cycle));
- if (Cycle->isReducible()) {
- assert(Cycle->getHeader() == JoinBlock);
+ if (CI.isReducible(*Cycle)) {
+ assert(CI.getHeader(*Cycle) == JoinBlock);
return nullptr;
}
@@ -1034,23 +1036,23 @@ const CycleT *getIntDivCycle(const CycleInfoT &CI, const CycleT *Cycle,
// Find the smallest common cycle, if one exists.
assert(Cycle && CI.contains(*Cycle, JoinBlock));
while (Cycle && !CI.contains(*Cycle, DivTermBlock)) {
- Cycle = Cycle->getParentCycle();
+ Cycle = CI.getParentCycle(*Cycle);
}
- if (!Cycle || Cycle->isReducible())
+ if (!Cycle || CI.isReducible(*Cycle))
return nullptr;
- if (DT.properlyDominates(Cycle->getHeader(), JoinBlock))
+ if (DT.properlyDominates(CI.getHeader(*Cycle), JoinBlock))
return nullptr;
- LLVM_DEBUG(dbgs() << " header " << Context.print(Cycle->getHeader())
+ LLVM_DEBUG(dbgs() << " header " << Context.print(CI.getHeader(*Cycle))
<< " does not dominate join\n");
- const auto *Parent = Cycle->getParentCycle();
- while (Parent && !DT.properlyDominates(Parent->getHeader(), JoinBlock)) {
- LLVM_DEBUG(dbgs() << " header " << Context.print(Parent->getHeader())
+ const auto *Parent = CI.getParentCycle(*Cycle);
+ while (Parent && !DT.properlyDominates(CI.getHeader(*Parent), JoinBlock)) {
+ LLVM_DEBUG(dbgs() << " header " << Context.print(CI.getHeader(*Parent))
<< " does not dominate join\n");
Cycle = Parent;
- Parent = Parent->getParentCycle();
+ Parent = CI.getParentCycle(*Parent);
}
LLVM_DEBUG(dbgs() << " cycle made divergent by internal branch\n");
@@ -1085,7 +1087,7 @@ bool GenericUniformityAnalysisImpl<ContextT>::isTemporalDivergent(
const BlockT *DefBlock = Def.getParent();
for (const CycleT *Cycle = CI.getCycle(DefBlock);
Cycle && !CI.contains(*Cycle, &ObservingBlock);
- Cycle = Cycle->getParentCycle()) {
+ Cycle = CI.getParentCycle(*Cycle)) {
if (DivergentExitCycles.contains(Cycle)) {
return true;
}
@@ -1124,8 +1126,8 @@ void GenericUniformityAnalysisImpl<ContextT>::analyzeControlDivergence(
// Sort by order of decreasing depth. This allows later cycles to be skipped
// because they are already contained in earlier ones.
- llvm::sort(DivCycles, [](const CycleT *A, const CycleT *B) {
- return A->getDepth() > B->getDepth();
+ llvm::sort(DivCycles, [this](const CycleT *A, const CycleT *B) {
+ return CI.getDepth(*A) > CI.getDepth(*B);
});
// Cycles that are assumed divergent due to the diverged entry
@@ -1134,7 +1136,7 @@ void GenericUniformityAnalysisImpl<ContextT>::analyzeControlDivergence(
// cycle are assumed divergent. "Cycle invariant" values may be
// assumed uniform, but that requires further analysis.
for (auto *C : DivCycles) {
- if (!insertIfNotContained(AssumedDivergent, C))
+ if (!insertIfNotContained(CI, AssumedDivergent, C))
continue;
LLVM_DEBUG(dbgs() << "process divergent cycle\n");
for (const BlockT *BB : CI.getBlocks(*C)) {
@@ -1343,10 +1345,11 @@ void llvm::ModifiedPostOrder<ContextT>::computeStackPO(
LLVM_DEBUG(dbgs() << " visiting " << CI.getSSAContext().print(NextBB)
<< "\n");
auto *NestedCycle = CI.getCycle(NextBB);
- if (Cycle != NestedCycle && (!Cycle || Cycle->contains(NestedCycle))) {
+ if (Cycle != NestedCycle &&
+ (!Cycle || (NestedCycle && CI.contains(*Cycle, *NestedCycle)))) {
LLVM_DEBUG(dbgs() << " found a cycle\n");
- while (NestedCycle->getParentCycle() != Cycle)
- NestedCycle = NestedCycle->getParentCycle();
+ while (CI.getParentCycle(*NestedCycle) != Cycle)
+ NestedCycle = CI.getParentCycle(*NestedCycle);
SmallVector<BlockT *, 3> NestedExits;
CI.getExitBlocks(*NestedCycle, NestedExits);
@@ -1404,7 +1407,7 @@ void ModifiedPostOrder<ContextT>::computeCyclePO(
SmallPtrSetImpl<const BlockT *> &Finalized) {
LLVM_DEBUG(dbgs() << "inside computeCyclePO\n");
SmallVector<const BlockT *> Stack;
- auto *CycleHeader = Cycle->getHeader();
+ auto *CycleHeader = CI.getHeader(*Cycle);
LLVM_DEBUG(dbgs() << " noted header: "
<< CI.getSSAContext().print(CycleHeader) << "\n");
@@ -1414,7 +1417,7 @@ void ModifiedPostOrder<ContextT>::computeCyclePO(
// Visit the header last
LLVM_DEBUG(dbgs() << " finishing header: "
<< CI.getSSAContext().print(CycleHeader) << "\n");
- appendBlock(*CycleHeader, Cycle->isReducible());
+ appendBlock(*CycleHeader, CI.isReducible(*Cycle));
// Initialize with immediate successors
for (auto *BB : successors(CycleHeader)) {
diff --git a/llvm/include/llvm/IR/GenericConvergenceVerifierImpl.h b/llvm/include/llvm/IR/GenericConvergenceVerifierImpl.h
index 1dbbee5c2dd72..19b03a0e581ff 100644
--- a/llvm/include/llvm/IR/GenericConvergenceVerifierImpl.h
+++ b/llvm/include/llvm/IR/GenericConvergenceVerifierImpl.h
@@ -170,13 +170,13 @@ void GenericConvergenceVerifier<ContextT>::verify(const DominatorTreeT &DT) {
{Context.print(User), CI.print(BBCycle)});
while (true) {
- auto *Parent = BBCycle->getParentCycle();
+ auto *Parent = CI.getParentCycle(*BBCycle);
if (!Parent || CI.contains(*Parent, DefBB))
break;
BBCycle = Parent;
};
- Check(BBCycle->isReducible() && BB == BBCycle->getHeader(),
+ Check(CI.isReducible(*BBCycle) && BB == CI.getHeader(*BBCycle),
"Cycle heart must dominate all blocks in the cycle.",
{Context.print(User), Context.printAsOperand(BB), CI.print(BBCycle)});
Check(!CycleHearts.count(BBCycle),
diff --git a/llvm/lib/CodeGen/MachineCycleAnalysis.cpp b/llvm/lib/CodeGen/MachineCycleAnalysis.cpp
index ad77b5b59513d..adefedc65ca55 100644
--- a/llvm/lib/CodeGen/MachineCycleAnalysis.cpp
+++ b/llvm/lib/CodeGen/MachineCycleAnalysis.cpp
@@ -151,7 +151,7 @@ bool llvm::isCycleInvariant(const MachineCycleInfo &CI,
} else if (!MO.isDead()) {
// A def that isn't dead can't be moved.
return false;
- } else if (any_of(Cycle.getEntries(),
+ } else if (any_of(CI.getEntries(Cycle),
[&](const MachineBasicBlock *Block) {
return Block->isLiveIn(Reg);
})) {
diff --git a/llvm/lib/CodeGen/MachineSink.cpp b/llvm/lib/CodeGen/MachineSink.cpp
index 768abf7723013..0e2ce14876183 100644
--- a/llvm/lib/CodeGen/MachineSink.cpp
+++ b/llvm/lib/CodeGen/MachineSink.cpp
@@ -1121,7 +1121,7 @@ bool MachineSinking::isLegalToBreakCriticalEdge(MachineInstr &MI,
// Check for backedges of more "complex" cycles.
if (FromCycle == ToCycle && FromCycle &&
- (!FromCycle->isReducible() || FromCycle->getHeader() == ToBB))
+ (!CI->isReducible(*FromCycle) || CI->getHeader(*FromCycle) == ToBB))
return false;
// It's not always legal to break critical edges and sink the computation
@@ -1345,8 +1345,9 @@ bool MachineSinking::isProfitableToSinkTo(Register Reg, MachineInstr &MI,
// impact for this operand. Defination outside of cycle means:
// 1: defination is outside of cycle.
// 2: defination is in this cycle, but it is a PHI in the cycle header.
- if (Cycle != MCycle || (DefMI->isPHI() && Cycle && Cycle->isReducible() &&
- Cycle->getHeader() == DefMI->getParent()))
+ if (Cycle != MCycle ||
+ (DefMI->isPHI() && Cycle && CI->isReducible(*Cycle) &&
+ CI->getHeader(*Cycle) == DefMI->getParent()))
continue;
// The DefMI is defined inside the cycle.
// If sinking this operand makes some register pressure set exceed limit,
@@ -1913,8 +1914,8 @@ bool MachineSinking::SinkInstruction(MachineInstr &MI, bool &SawStore,
// Don't sink instructions into a cycle.
if (!TryBreak && CI->getCycle(SuccToSinkTo) &&
- (!CI->getCycle(SuccToSinkTo)->isReducible() ||
- CI->getCycle(SuccToSinkTo)->getHeader() == SuccToSinkTo)) {
+ (!CI->isReducible(*CI->getCycle(SuccToSinkTo)) ||
+ CI->getHeader(*CI->getCycle(SuccToSinkTo)) == SuccToSinkTo)) {
LLVM_DEBUG(dbgs() << " *** NOTE: cycle header found\n");
TryBreak = true;
}
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUGlobalISelDivergenceLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUGlobalISelDivergenceLowering.cpp
index 0c1622eebf686..538bc72102e3f 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUGlobalISelDivergenceLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUGlobalISelDivergenceLowering.cpp
@@ -236,6 +236,8 @@ bool DivergenceLoweringHelper::lowerTemporalDivergenceI1() {
initializeLaneMaskRegisterAttributes(BoolS1);
MachineSSAUpdater SSAUpdater(*MF);
+ const auto &CInfo = MUI->getCycleInfo();
+
// In case of use outside muliple nested cycles or muliple uses we only need
// to merge lane mask across largest relevant cycle.
SmallDenseMap<Register, std::pair<const MachineCycle *, Register>> LRCCache;
@@ -246,12 +248,11 @@ bool DivergenceLoweringHelper::lowerTemporalDivergenceI1() {
auto [LRCCacheIter, RegNotCached] = LRCCache.try_emplace(Reg);
auto &CycleMergedMask = LRCCacheIter->getSecond();
const MachineCycle *&CachedLRC = CycleMergedMask.first;
- if (RegNotCached || LRC->contains(CachedLRC)) {
+ if (RegNotCached || CInfo.contains(*LRC, *CachedLRC)) {
CachedLRC = LRC;
}
}
- const auto &CInfo = MUI->getCycleInfo();
for (auto &LRCCacheEntry : LRCCache) {
Register Reg = LRCCacheEntry.first;
auto &CycleMergedMask = LRCCacheEntry.getSecond();
@@ -263,7 +264,7 @@ bool DivergenceLoweringHelper::lowerTemporalDivergenceI1() {
MachineBasicBlock *MBB = MRI->getVRegDef(Reg)->getParent();
SSAUpdater.AddAvailableValue(MBB, MergedMask);
- for (auto Entry : Cycle->getEntries()) {
+ for (auto Entry : CInfo.getEntries(*Cycle)) {
for (MachineBasicBlock *Pred : Entry->predecessors()) {
if (!CInfo.contains(*Cycle, Pred)) {
B.setInsertPt(*Pred, Pred->getFirstTerminator());
diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
index 34cf595e8d39b..2395c326dc3fc 100644
--- a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
@@ -235,7 +235,7 @@ bool SIInstrInfo::isSafeToSink(MachineInstr &MI,
MachineCycle *ToCycle = CI->getCycle(SuccToSinkTo);
// Check if there is a FromCycle that contains SgprDef's basic block but
// does not contain SuccToSinkTo and also has divergent exit condition.
- while (FromCycle && !FromCycle->contains(ToCycle)) {
+ while (FromCycle && !(ToCycle && CI->contains(*FromCycle, *ToCycle))) {
SmallVector<MachineBasicBlock *, 1> ExitingBlocks;
CI->getExitingBlocks(*FromCycle, ExitingBlocks);
@@ -245,7 +245,7 @@ bool SIInstrInfo::isSafeToSink(MachineInstr &MI,
return false;
}
- FromCycle = FromCycle->getParentCycle();
+ FromCycle = CI->getParentCycle(*FromCycle);
}
}
}
diff --git a/llvm/lib/Target/AMDGPU/SILowerSGPRSpills.cpp b/llvm/lib/Target/AMDGPU/SILowerSGPRSpills.cpp
index 48a38b1ffd460..cde821bfb8ba8 100644
--- a/llvm/lib/Target/AMDGPU/SILowerSGPRSpills.cpp
+++ b/llvm/lib/Target/AMDGPU/SILowerSGPRSpills.cpp
@@ -305,14 +305,14 @@ bool SILowerSGPRSpills::spillCalleeSavedRegs(
MachineBasicBlock *SILowerSGPRSpills::getCycleDomBB(MachineCycle *C) {
// If the insertion point lands on a cycle entry, move it to a block that
// dominates all entries.
- if (C->isReducible()) {
- if (auto *IDom = MDT->getNode(C->getHeader())->getIDom())
+ if (MCI->isReducible(*C)) {
+ if (auto *IDom = MDT->getNode(MCI->getHeader(*C))->getIDom())
return IDom->getBlock();
llvm_unreachable("Expected cycle to have an IDom.");
return nullptr;
}
- const SmallVectorImpl<MachineBasicBlock *> &Entries = C->getEntries();
+ ArrayRef<MachineBasicBlock *> Entries = MCI->getEntries(*C);
assert(!Entries.empty() && "Expected cycle to have at least one entry.");
MachineBasicBlock *EntryBB = Entries[0];
for (unsigned I = 1; I < Entries.size(); ++I)
diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
index 66a05a077b208..fb70ee86920ca 100644
--- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
+++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
@@ -223,7 +223,7 @@ static bool mayBeInCycle(const CycleInfo *CI, const Instruction *I,
return false;
if (CPtr)
*CPtr = C;
- return !HeaderOnly || BB == C->getHeader();
+ return !HeaderOnly || BB == CI->getHeader(*C);
}
/// Checks if a type could have padding bytes.
diff --git a/llvm/lib/Transforms/Utils/FixIrreducible.cpp b/llvm/lib/Transforms/Utils/FixIrreducible.cpp
index 4fd08a90e86bc..b6bed8413c3fe 100644
--- a/llvm/lib/Transforms/Utils/FixIrreducible.cpp
+++ b/llvm/lib/Transforms/Utils/FixIrreducible.cpp
@@ -225,7 +225,7 @@ static void updateLoopInfo(CycleInfo &CI, LoopInfo &LI, Cycle &C,
// The parent loop is a natural loop L mapped to the cycle header H as long as
// H is not also the header of L. In the latter case, L is destroyed and we
// seek its parent instead.
- BasicBlock *CycleHeader = C.getHeader();
+ BasicBlock *CycleHeader = CI.getHeader(C);
Loop *ParentLoop = LI.getLoopFor(CycleHeader);
if (ParentLoop && ParentLoop->getHeader() == CycleHeader)
ParentLoop = ParentLoop->getParentLoop();
@@ -261,7 +261,7 @@ static void updateLoopInfo(CycleInfo &CI, LoopInfo &LI, Cycle &C,
LLVM_DEBUG(dbgs() << "header for new loop: "
<< NewLoop->getHeader()->getName() << "\n");
- reconnectChildLoops(LI, ParentLoop, NewLoop, C.getHeader());
+ reconnectChildLoops(LI, ParentLoop, NewLoop, CI.getHeader(C));
LLVM_DEBUG(dbgs() << "Verify new loop.\n"; NewLoop->print(dbgs()));
NewLoop->verifyLoop();
@@ -276,7 +276,7 @@ static void updateLoopInfo(CycleInfo &CI, LoopInfo &LI, Cycle &C,
// hierarchy of loops.
static bool fixIrreducible(Cycle &C, CycleInfo &CI, DominatorTree &DT,
LoopInfo *LI) {
- if (C.isReducible())
+ if (CI.isReducible(C))
return false;
LLVM_DEBUG(dbgs() << "Processing cycle:\n" << CI.print(&C) << "\n";);
@@ -285,7 +285,7 @@ static bool fixIrreducible(Cycle &C, CycleInfo &CI, DominatorTree &DT,
SetVector<BasicBlock *> Predecessors;
// Redirect internal edges incident on the header.
- BasicBlock *Header = C.getHeader();
+ BasicBlock *Header = CI.getHeader(C);
for (BasicBlock *P : predecessors(Header)) {
if (CI.contains(C, P))
Predecessors.insert(P);
@@ -329,7 +329,7 @@ static bool fixIrreducible(Cycle &C, CycleInfo &CI, DominatorTree &DT,
// Redirect external incoming edges. This includes the edges on the header.
Predecessors.clear();
- for (BasicBlock *E : C.entries()) {
+ for (BasicBlock *E : CI.getEntries(C)) {
for (BasicBlock *P : predecessors(E)) {
if (!CI.contains(C, P))
Predecessors.insert(P);
@@ -394,7 +394,7 @@ static bool fixIrreducible(Cycle &C, CycleInfo &CI, DominatorTree &DT,
// the new ControlFlowHub, which can be mitigated if the orders match. So we
// reverse the entries when adding them to the hub.
SetVector<BasicBlock *> Entries;
- Entries.insert(C.entry_rbegin(), C.entry_rend());
+ Entries.insert(CI.getEntries(C).rbegin(), CI.getEntries(C).rend());
CHub.finalize(&DTU, GuardBlocks, "irr");
#if defined(EXPENSIVE_CHECKS)
@@ -413,10 +413,10 @@ static bool fixIrreducible(Cycle &C, CycleInfo &CI, DominatorTree &DT,
<< "\n");
CI.addBlockToCycle(G, &C);
}
- C.setSingleEntry(GuardBlocks[0]);
+ CI.setSingleEntry(C, GuardBlocks[0]);
CI.verifyCycle(C);
- if (Cycle *Parent = C.getParentCycle())
+ if (Cycle *Parent = CI.getParentCycle(C))
CI.verifyCycle(*Parent);
LLVM_DEBUG(dbgs() << "Finished one cycle:\n"; CI.print(dbgs()););
More information about the llvm-commits
mailing list