[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