[llvm] [Analysis] Use CycleInfo for BranchProbabilityInfo (PR #210301)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 17 03:51:25 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-powerpc

Author: Alexis Engelke (aengelke)

<details>
<summary>Changes</summary>

Instead of computing a cycle info (SccInfo) internally in
BranchProbabilityInfo, use CycleInfo and remove the use of LoopInfo.
After recent improvements to CycleInfo, the extra analysis is cheaper
than computing the same information internally.

Replacing LoopInfo with CycleInfo has some impliciation that the
loop/cycle forest can differ if the header of an irreducible loop (which
is ignored by loop info) also happens to be the header of a different
natural loop. (Simple example: S -> A, B; A -> A, B; B -> A, B --
LoopInfo will find {{A}, {B}}; CycleInfo will find {A, {B}}].) In these
cases, the default weights will differ.

---

Patch is 96.56 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/210301.diff


38 Files Affected:

- (modified) llvm/include/llvm/Analysis/BranchProbabilityInfo.h (+4-5) 
- (modified) llvm/include/llvm/Analysis/LazyBranchProbabilityInfo.h (+7-7) 
- (modified) llvm/lib/Analysis/BranchProbabilityInfo.cpp (+56-270) 
- (modified) llvm/lib/Analysis/LazyBranchProbabilityInfo.cpp (+7-7) 
- (modified) llvm/lib/Analysis/ModuleSummaryAnalysis.cpp (+4-1) 
- (modified) llvm/lib/Analysis/OptimizationRemarkEmitter.cpp (+4-1) 
- (modified) llvm/lib/CodeGen/CodeGenPrepare.cpp (+4-1) 
- (modified) llvm/lib/CodeGen/MachineFunctionPass.cpp (+2) 
- (modified) llvm/lib/Transforms/IPO/PartialInlining.cpp (+13-4) 
- (modified) llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp (+4-1) 
- (modified) llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp (+10-3) 
- (modified) llvm/test/CodeGen/AArch64/GlobalISel/gisel-commandline-option.ll (+1) 
- (modified) llvm/test/CodeGen/AArch64/O3-pipeline.ll (+7-2) 
- (modified) llvm/test/CodeGen/AMDGPU/llc-pipeline.ll (+21-8) 
- (modified) llvm/test/CodeGen/ARM/O3-pipeline.ll (+9-5) 
- (modified) llvm/test/CodeGen/LoongArch/annotate-tablejump.ll (+18-18) 
- (modified) llvm/test/CodeGen/LoongArch/opt-pipeline.ll (+5-2) 
- (modified) llvm/test/CodeGen/M68k/pipeline.ll (+5-2) 
- (modified) llvm/test/CodeGen/PowerPC/O3-pipeline.ll (+7-2) 
- (modified) llvm/test/CodeGen/RISCV/GlobalISel/gisel-commandline-option.ll (+1) 
- (modified) llvm/test/CodeGen/RISCV/O3-pipeline.ll (+11-6) 
- (modified) llvm/test/CodeGen/SPIRV/llc-pipeline.ll (+7-3) 
- (modified) llvm/test/CodeGen/WebAssembly/GlobalISel/gisel-commandline-option.ll (+2-1) 
- (modified) llvm/test/CodeGen/X86/opt-pipeline.ll (+5-2) 
- (modified) llvm/test/CodeGen/X86/pr38795.ll (+51-48) 
- (modified) llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll (+2-2) 
- (modified) llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll (+2-2) 
- (modified) llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll (+4-3) 
- (modified) llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll (+2-2) 
- (modified) llvm/test/Transforms/Inline/cgscc-incremental-invalidate.ll (+6-3) 
- (modified) llvm/test/Transforms/PGOProfile/Inputs/irreducible.proftext (+4-4) 
- (modified) llvm/test/Transforms/PGOProfile/Inputs/irreducible_entry.proftext (+3-3) 
- (modified) llvm/unittests/Analysis/BlockFrequencyInfoTest.cpp (+5-1) 
- (modified) llvm/unittests/Analysis/BranchProbabilityInfoTest.cpp (+5-4) 
- (modified) llvm/unittests/Analysis/ProfileSummaryInfoTest.cpp (+5-1) 
- (modified) llvm/unittests/Transforms/IPO/FunctionSpecializationTest.cpp (+3-1) 
- (modified) llvm/unittests/Transforms/Utils/BasicBlockUtilsTest.cpp (+10-4) 
- (modified) llvm/unittests/Transforms/Utils/SizeOptsTest.cpp (+6-2) 


``````````diff
diff --git a/llvm/include/llvm/Analysis/BranchProbabilityInfo.h b/llvm/include/llvm/Analysis/BranchProbabilityInfo.h
index dfc0079724d52..970fd532a1485 100644
--- a/llvm/include/llvm/Analysis/BranchProbabilityInfo.h
+++ b/llvm/include/llvm/Analysis/BranchProbabilityInfo.h
@@ -27,8 +27,7 @@
 namespace llvm {
 
 class Function;
-class Loop;
-class LoopInfo;
+class CycleInfo;
 class raw_ostream;
 class DominatorTree;
 class PostDominatorTree;
@@ -110,11 +109,11 @@ class BranchProbabilityInfo {
 public:
   BranchProbabilityInfo() = default;
 
-  BranchProbabilityInfo(const Function &F, const LoopInfo &LI,
+  BranchProbabilityInfo(const Function &F, const CycleInfo &CI,
                         const TargetLibraryInfo *TLI = nullptr,
                         DominatorTree *DT = nullptr,
                         PostDominatorTree *PDT = nullptr) {
-    calculate(F, LI, TLI, DT, PDT);
+    calculate(F, CI, TLI, DT, PDT);
   }
 
   LLVM_ABI bool invalidate(Function &, const PreservedAnalyses &PA,
@@ -174,7 +173,7 @@ class BranchProbabilityInfo {
     return IsLikely ? LikelyProb : LikelyProb.getCompl();
   }
 
-  LLVM_ABI void calculate(const Function &F, const LoopInfo &LI,
+  LLVM_ABI void calculate(const Function &F, const CycleInfo &CI,
                           const TargetLibraryInfo *TLI, DominatorTree *DT,
                           PostDominatorTree *PDT);
 
diff --git a/llvm/include/llvm/Analysis/LazyBranchProbabilityInfo.h b/llvm/include/llvm/Analysis/LazyBranchProbabilityInfo.h
index 0f8932f784881..6cd4528d05a64 100644
--- a/llvm/include/llvm/Analysis/LazyBranchProbabilityInfo.h
+++ b/llvm/include/llvm/Analysis/LazyBranchProbabilityInfo.h
@@ -20,8 +20,8 @@
 #include "llvm/Pass.h"
 
 namespace llvm {
+class CycleInfo;
 class Function;
-class LoopInfo;
 class TargetLibraryInfo;
 
 /// This is an alternative analysis pass to
@@ -41,7 +41,7 @@ class TargetLibraryInfo;
 ///   LazyBranchProbabilityInfoPass::getLazyBPIAnalysisUsage(AU)
 ///
 /// 3. The computed BPI should be requested with
-///    getAnalysis<LazyBranchProbabilityInfoPass>().getBPI() before LoopInfo
+///    getAnalysis<LazyBranchProbabilityInfoPass>().getBPI() before CycleInfo
 ///    could be invalidated for example by changing the CFG.
 ///
 /// Note that it is expected that we wouldn't need this functionality for the
@@ -54,15 +54,15 @@ class LLVM_ABI LazyBranchProbabilityInfoPass : public FunctionPass {
   /// analysis without paying for the overhead if BPI doesn't end up being used.
   class LazyBranchProbabilityInfo {
   public:
-    LazyBranchProbabilityInfo(const Function *F, const LoopInfo *LI,
+    LazyBranchProbabilityInfo(const Function *F, const CycleInfo *CI,
                               const TargetLibraryInfo *TLI)
-        : F(F), LI(LI), TLI(TLI) {}
+        : F(F), CI(CI), TLI(TLI) {}
 
     /// Retrieve the BPI with the branch probabilities computed.
     BranchProbabilityInfo &getCalculated() {
       if (!Calculated) {
-        assert(F && LI && "call setAnalysis");
-        BPI.calculate(*F, *LI, TLI, nullptr, nullptr);
+        assert(F && CI && "call setAnalysis");
+        BPI.calculate(*F, *CI, TLI, nullptr, nullptr);
         Calculated = true;
       }
       return BPI;
@@ -76,7 +76,7 @@ class LLVM_ABI LazyBranchProbabilityInfoPass : public FunctionPass {
     BranchProbabilityInfo BPI;
     bool Calculated = false;
     const Function *F;
-    const LoopInfo *LI;
+    const CycleInfo *CI;
     const TargetLibraryInfo *TLI;
   };
 
diff --git a/llvm/lib/Analysis/BranchProbabilityInfo.cpp b/llvm/lib/Analysis/BranchProbabilityInfo.cpp
index 1b0a8b8e74f4a..076e7e5e12599 100644
--- a/llvm/lib/Analysis/BranchProbabilityInfo.cpp
+++ b/llvm/lib/Analysis/BranchProbabilityInfo.cpp
@@ -16,7 +16,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/Analysis/ConstantFolding.h"
-#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/CycleAnalysis.h"
 #include "llvm/Analysis/PostDominators.h"
 #include "llvm/Analysis/TargetLibraryInfo.h"
 #include "llvm/IR/Attributes.h"
@@ -61,7 +61,7 @@ static cl::opt<std::string> PrintBranchProbFuncName(
 
 INITIALIZE_PASS_BEGIN(BranchProbabilityInfoWrapperPass, "branch-prob",
                       "Branch Probability Analysis", false, true)
-INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
+INITIALIZE_PASS_DEPENDENCY(CycleInfoWrapperPass)
 INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
 INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
 INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass)
@@ -165,98 +165,23 @@ namespace {
 class BPIConstruction {
 public:
   BPIConstruction(BranchProbabilityInfo &BPI) : BPI(BPI) {}
-  void calculate(const Function &F, const LoopInfo &LI,
+  void calculate(const Function &F, const CycleInfo &CI,
                  const TargetLibraryInfo *TLI, DominatorTree *DT,
                  PostDominatorTree *PDT);
 
 private:
-  // Data structure to track SCCs for handling irreducible loops.
-  class SccInfo {
-    // Enum of types to classify basic blocks in SCC. Basic block belonging to
-    // SCC is 'Inner' until it is either 'Header' or 'Exiting'. Note that a
-    // basic block can be 'Header' and 'Exiting' at the same time.
-    enum SccBlockType {
-      Inner = 0x0,
-      Header = 0x1,
-      Exiting = 0x2,
-    };
-    // Map of basic blocks to SCC IDs they belong to. If basic block doesn't
-    // belong to any SCC it is not in the map.
-    using SccMap = DenseMap<const BasicBlock *, int>;
-    // Each basic block in SCC is attributed with one or several types from
-    // SccBlockType. Map value has uint32_t type (instead of SccBlockType)
-    // since basic block may be for example "Header" and "Exiting" at the same
-    // time and we need to be able to keep more than one value from
-    // SccBlockType.
-    using SccBlockTypeMap = DenseMap<const BasicBlock *, uint32_t>;
-    // Vector containing classification of basic blocks for all  SCCs where i'th
-    // vector element corresponds to SCC with ID equal to i.
-    using SccBlockTypeMaps = std::vector<SccBlockTypeMap>;
-
-    SccMap SccNums;
-    SccBlockTypeMaps SccBlocks;
-
-  public:
-    explicit SccInfo(const Function &F);
-
-    /// If \p BB belongs to some SCC then ID of that SCC is returned, otherwise
-    /// -1 is returned. If \p BB belongs to more than one SCC at the same time
-    /// result is undefined.
-    int getSCCNum(const BasicBlock *BB) const;
-    /// Returns true if \p BB is a 'header' block in SCC with \p SccNum ID,
-    /// false otherwise.
-    bool isSCCHeader(const BasicBlock *BB, int SccNum) const {
-      return getSccBlockType(BB, SccNum) & Header;
-    }
-    /// Returns true if \p BB is an 'exiting' block in SCC with \p SccNum ID,
-    /// false otherwise.
-    bool isSCCExitingBlock(const BasicBlock *BB, int SccNum) const {
-      return getSccBlockType(BB, SccNum) & Exiting;
-    }
-    /// Fills in \p Enters vector with all such blocks that don't belong to
-    /// SCC with \p SccNum ID but there is an edge to a block belonging to the
-    /// SCC.
-    void getSccEnterBlocks(int SccNum,
-                           SmallVectorImpl<BasicBlock *> &Enters) const;
-    /// Fills in \p Exits vector with all such blocks that don't belong to
-    /// SCC with \p SccNum ID but there is an edge from a block belonging to the
-    /// SCC.
-    void getSccExitBlocks(int SccNum,
-                          SmallVectorImpl<BasicBlock *> &Exits) const;
-
-  private:
-    /// Returns \p BB's type according to classification given by SccBlockType
-    /// enum. Please note that \p BB must belong to SSC with \p SccNum ID.
-    uint32_t getSccBlockType(const BasicBlock *BB, int SccNum) const;
-    /// Calculates \p BB's type and stores it in internal data structures for
-    /// future use. Please note that \p BB must belong to SSC with \p SccNum ID.
-    void calculateSccBlockType(const BasicBlock *BB, int SccNum);
-  };
-
-  /// Pair of Loop and SCC ID number. Used to unify handling of normal and
-  /// SCC based loop representations.
-  using LoopData = std::pair<Loop *, int>;
   /// Helper class to keep basic block along with its loop data information.
   class LoopBlock {
   public:
-    explicit LoopBlock(const BasicBlock *BB, const LoopInfo &LI,
-                       const SccInfo &SccI);
+    explicit LoopBlock(const BasicBlock *BB, const CycleInfo &CI) : BB(BB), C(CI.getCycle(BB)) {}
 
     const BasicBlock *getBlock() const { return BB; }
     BasicBlock *getBlock() { return const_cast<BasicBlock *>(BB); }
-    LoopData getLoopData() const { return LD; }
-    Loop *getLoop() const { return LD.first; }
-    int getSccNum() const { return LD.second; }
-
-    bool belongsToLoop() const { return getLoop() || getSccNum() != -1; }
-    bool belongsToSameLoop(const LoopBlock &LB) const {
-      return (LB.getLoop() && getLoop() == LB.getLoop()) ||
-             (LB.getSccNum() != -1 && getSccNum() == LB.getSccNum());
-    }
+    CycleRef getCycle() const { return C; }
 
   private:
     const BasicBlock *const BB = nullptr;
-    LoopData LD = {nullptr, -1};
+    CycleRef C = CycleRef();
   };
 
   // Pair of LoopBlocks representing an edge from first to second block.
@@ -264,7 +189,7 @@ class BPIConstruction {
 
   /// Helper to construct LoopBlock for \p BB.
   LoopBlock getLoopBlock(const BasicBlock *BB) const {
-    return LoopBlock(BB, *LI, *SccI);
+    return LoopBlock(BB, *CI);
   }
 
   /// Returns true if destination block belongs to some loop and source block is
@@ -278,24 +203,18 @@ class BPIConstruction {
   /// Returns true if \p Edge is either enters to or exits from some loop, false
   /// in all other cases.
   bool isLoopEnteringExitingEdge(const LoopEdge &Edge) const;
-  /// Returns true if source and destination blocks belongs to the same loop and
-  /// destination block is loop header.
-  bool isLoopBackEdge(const LoopEdge &Edge) const;
   // Fills in \p Enters vector with all "enter" blocks to a loop \LB belongs to.
   void getLoopEnterBlocks(const LoopBlock &LB,
                           SmallVectorImpl<BasicBlock *> &Enters) const;
-  // Fills in \p Exits vector with all "exit" blocks from a loop \LB belongs to.
-  void getLoopExitBlocks(const LoopBlock &LB,
-                         SmallVectorImpl<BasicBlock *> &Exits) const;
 
   /// Returns estimated weight for \p BB. std::nullopt if \p BB has no estimated
   /// weight.
   std::optional<uint32_t> getEstimatedBlockWeight(const BasicBlock *BB) const;
 
   /// Returns estimated weight to enter \p L. In other words it is weight of
-  /// loop's header block not scaled by trip count. Returns std::nullopt if \p L
+  /// loop's header block not scaled by trip count. Returns std::nullopt if \p C
   /// has no no estimated weight.
-  std::optional<uint32_t> getEstimatedLoopWeight(const LoopData &L) const;
+  std::optional<uint32_t> getEstimatedLoopWeight(CycleRef C) const;
 
   /// Return estimated weight for \p Edge. Returns std::nullopt if estimated
   /// weight is unknown.
@@ -341,133 +260,23 @@ class BPIConstruction {
 
   BranchProbabilityInfo &BPI;
 
-  const LoopInfo *LI = nullptr;
-
-  /// Keeps information about all SCCs in a function.
-  std::unique_ptr<const SccInfo> SccI;
+  const CycleInfo *CI = nullptr;
 
   /// Keeps mapping of a basic block to its estimated weight.
   SmallDenseMap<const BasicBlock *, uint32_t> EstimatedBlockWeight;
 
   /// Keeps mapping of a loop to estimated weight to enter the loop.
-  SmallDenseMap<LoopData, uint32_t> EstimatedLoopWeight;
+  SmallDenseMap<CycleRef, uint32_t> EstimatedLoopWeight;
 };
 
-BPIConstruction::SccInfo::SccInfo(const Function &F) {
-  // Record SCC numbers of blocks in the CFG to identify irreducible loops.
-  // FIXME: We could only calculate this if the CFG is known to be irreducible
-  // (perhaps cache this info in LoopInfo if we can easily calculate it there?).
-  int SccNum = 0;
-  for (scc_iterator<const Function *> It = scc_begin(&F); !It.isAtEnd();
-       ++It, ++SccNum) {
-    // Ignore single-block SCCs since they either aren't loops or LoopInfo will
-    // catch them.
-    const std::vector<const BasicBlock *> &Scc = *It;
-    if (Scc.size() == 1)
-      continue;
-
-    LLVM_DEBUG(dbgs() << "BPI: SCC " << SccNum << ":");
-    for (const auto *BB : Scc) {
-      LLVM_DEBUG(dbgs() << " " << BB->getName());
-      SccNums[BB] = SccNum;
-      calculateSccBlockType(BB, SccNum);
-    }
-    LLVM_DEBUG(dbgs() << "\n");
-  }
-}
-
-int BPIConstruction::SccInfo::getSCCNum(const BasicBlock *BB) const {
-  auto SccIt = SccNums.find(BB);
-  if (SccIt == SccNums.end())
-    return -1;
-  return SccIt->second;
-}
-
-void BPIConstruction::SccInfo::getSccEnterBlocks(
-    int SccNum, SmallVectorImpl<BasicBlock *> &Enters) const {
-
-  for (auto MapIt : SccBlocks[SccNum]) {
-    const auto *BB = MapIt.first;
-    if (isSCCHeader(BB, SccNum))
-      for (const auto *Pred : predecessors(BB))
-        if (getSCCNum(Pred) != SccNum)
-          Enters.push_back(const_cast<BasicBlock *>(BB));
-  }
-}
-
-void BPIConstruction::SccInfo::getSccExitBlocks(
-    int SccNum, SmallVectorImpl<BasicBlock *> &Exits) const {
-  for (auto MapIt : SccBlocks[SccNum]) {
-    const auto *BB = MapIt.first;
-    if (isSCCExitingBlock(BB, SccNum))
-      for (const auto *Succ : successors(BB))
-        if (getSCCNum(Succ) != SccNum)
-          Exits.push_back(const_cast<BasicBlock *>(Succ));
-  }
-}
-
-uint32_t BPIConstruction::SccInfo::getSccBlockType(const BasicBlock *BB,
-                                                   int SccNum) const {
-  assert(getSCCNum(BB) == SccNum);
-
-  assert(SccBlocks.size() > static_cast<unsigned>(SccNum) && "Unknown SCC");
-  const auto &SccBlockTypes = SccBlocks[SccNum];
-
-  auto It = SccBlockTypes.find(BB);
-  if (It != SccBlockTypes.end()) {
-    return It->second;
-  }
-  return Inner;
-}
-
-void BPIConstruction::SccInfo::calculateSccBlockType(const BasicBlock *BB,
-                                                     int SccNum) {
-  assert(getSCCNum(BB) == SccNum);
-  uint32_t BlockType = Inner;
-
-  if (llvm::any_of(predecessors(BB), [&](const BasicBlock *Pred) {
-        // Consider any block that is an entry point to the SCC as
-        // a header.
-        return getSCCNum(Pred) != SccNum;
-      }))
-    BlockType |= Header;
-
-  if (llvm::any_of(successors(BB), [&](const BasicBlock *Succ) {
-        return getSCCNum(Succ) != SccNum;
-      }))
-    BlockType |= Exiting;
-
-  // Lazily compute the set of headers for a given SCC and cache the results
-  // in the SccHeaderMap.
-  if (SccBlocks.size() <= static_cast<unsigned>(SccNum))
-    SccBlocks.resize(SccNum + 1);
-  auto &SccBlockTypes = SccBlocks[SccNum];
-
-  if (BlockType != Inner) {
-    bool IsInserted;
-    std::tie(std::ignore, IsInserted) =
-        SccBlockTypes.insert(std::make_pair(BB, BlockType));
-    assert(IsInserted && "Duplicated block in SCC");
-  }
-}
-
-BPIConstruction::LoopBlock::LoopBlock(const BasicBlock *BB, const LoopInfo &LI,
-                                      const SccInfo &SccI)
-    : BB(BB) {
-  LD.first = LI.getLoopFor(BB);
-  if (!LD.first) {
-    LD.second = SccI.getSCCNum(BB);
-  }
-}
-
 bool BPIConstruction::isLoopEnteringEdge(const LoopEdge &Edge) const {
   const auto &SrcBlock = Edge.first;
   const auto &DstBlock = Edge.second;
-  return (DstBlock.getLoop() &&
-          !DstBlock.getLoop()->contains(SrcBlock.getLoop())) ||
-         // Assume that SCCs can't be nested.
-         (DstBlock.getSccNum() != -1 &&
-          SrcBlock.getSccNum() != DstBlock.getSccNum());
+  if (!DstBlock.getCycle()) // Edge into no-cycle is not entering.
+    return false;
+  if (!SrcBlock.getCycle()) // Edge from no-cycle into cycle is entering.
+    return true;
+  return !CI->contains(DstBlock.getCycle(), SrcBlock.getCycle());
 }
 
 bool BPIConstruction::isLoopExitingEdge(const LoopEdge &Edge) const {
@@ -478,35 +287,13 @@ bool BPIConstruction::isLoopEnteringExitingEdge(const LoopEdge &Edge) const {
   return isLoopEnteringEdge(Edge) || isLoopExitingEdge(Edge);
 }
 
-bool BPIConstruction::isLoopBackEdge(const LoopEdge &Edge) const {
-  const auto &SrcBlock = Edge.first;
-  const auto &DstBlock = Edge.second;
-  return SrcBlock.belongsToSameLoop(DstBlock) &&
-         ((DstBlock.getLoop() &&
-           DstBlock.getLoop()->getHeader() == DstBlock.getBlock()) ||
-          (DstBlock.getSccNum() != -1 &&
-           SccI->isSCCHeader(DstBlock.getBlock(), DstBlock.getSccNum())));
-}
-
 void BPIConstruction::getLoopEnterBlocks(
     const LoopBlock &LB, SmallVectorImpl<BasicBlock *> &Enters) const {
-  if (LB.getLoop()) {
-    auto *Header = LB.getLoop()->getHeader();
-    Enters.append(pred_begin(Header), pred_end(Header));
-  } else {
-    assert(LB.getSccNum() != -1 && "LB doesn't belong to any loop?");
-    SccI->getSccEnterBlocks(LB.getSccNum(), Enters);
-  }
-}
-
-void BPIConstruction::getLoopExitBlocks(
-    const LoopBlock &LB, SmallVectorImpl<BasicBlock *> &Exits) const {
-  if (LB.getLoop()) {
-    LB.getLoop()->getExitBlocks(Exits);
-  } else {
-    assert(LB.getSccNum() != -1 && "LB doesn't belong to any loop?");
-    SccI->getSccExitBlocks(LB.getSccNum(), Exits);
-  }
+  CycleRef C = LB.getCycle();
+  for (BasicBlock *Entry : CI->getEntries(C))
+    for (const auto *Pred : predecessors(Entry))
+      if (!CI->contains(C, Pred))
+        Enters.push_back(const_cast<BasicBlock *>(Pred));
 }
 
 // Propagate existing explicit probabilities from either profile data or
@@ -679,12 +466,12 @@ bool BPIConstruction::calcPointerHeuristics(const BasicBlock *BB) {
   }
 }
 
-// Compute the unlikely successors to the block BB in the loop L, specifically
+// Compute the unlikely successors to the block BB in the cycle C, specifically
 // those that are unlikely because this is a loop, and add them to the
 // UnlikelyBlocks set.
 static void
-computeUnlikelySuccessors(const BasicBlock *BB, Loop *L,
-                          SmallPtrSetImpl<const BasicBlock*> &UnlikelyBlocks) {
+computeUnlikelySuccessors(const BasicBlock *BB, const CycleInfo &CI, CycleRef C,
+                          SmallPtrSetImpl<const BasicBlock *> &UnlikelyBlocks) {
   // Sometimes in a loop we have a branch whose condition is made false by
   // taking it. This is typically something like
   //  int n = 0;
@@ -711,30 +498,30 @@ computeUnlikelySuccessors(const BasicBlock *BB, Loop *L,
     return;
 
   // Check if the branch is based on an instruction compared with a constant
-  CmpInst *CI = dyn_cast<CmpInst>(BI->getCondition());
-  if (!CI || !isa<Instruction>(CI->getOperand(0)) ||
-      !isa<Constant>(CI->getOperand(1)))
+  CmpInst *Cmp = dyn_cast<CmpInst>(BI->getCondition());
+  if (!Cmp || !isa<Instruction>(Cmp->getOperand(0)) ||
+      !isa<Constant>(Cmp->getOperand(1)))
     return;
 
   // Either the instruction must be a PHI, or a chain of operations involving
   // constants that ends in a PHI which we can then collapse into a single value
   // if the PHI value is known.
-  Instruction *CmpLHS = dyn_cast<Instruction>(CI->getOperand(0));
+  Instruction *CmpLHS = dyn_cast<Instruction>(Cmp->getOperand(0));
   PHINode *CmpPHI = dyn_cast<PHINode>(CmpLHS);
-  Constant *CmpConst = dyn_cast<Constant>(CI->getOperand(1));
+  Constant *CmpConst = dyn_cast<Constant>(Cmp->getOperand(1));
   // Collect the instructions until we hit a PHI
   SmallVector<BinaryOperator *, 1> InstChain;
   while (!CmpPHI && CmpLHS && isa<BinaryOperator>(CmpLHS) &&
          isa<Constant>(CmpLHS->getOperand(1))) {
     // Stop if the chain extends outside of the loop
-    if (!L->contains(CmpLHS))
+    if (!CI.contains(C, CmpLHS->getParent()))
       return;
     InstChain.push_back(cast<BinaryOperator>(CmpLHS));
     CmpLHS = dyn_cast<Instruction>(CmpLHS->getOperand(0));
     if (CmpLHS)
       CmpPHI = dyn_cast<PHINode>(CmpLHS);
   }
-  if (!CmpPHI || !L->contains(CmpPHI))
+  if (!CmpPHI || !CI.contains(C, CmpPHI->getParent()))
     return;
 
   // Trace the phi node to find all values that come from successors of BB
@@ -746,7 +533,7 @@ computeUnlikelySuccessors(const BasicBlock *BB, Loop *L,
     PHINode *P = WorkList.pop_back_val();
     for (BasicBlock *B : P->blocks()) {
       // Skip blocks that aren't part of the loop
-      if (!L->contains(B))
+      if (!CI.contains(C, B))
         continue;
       Value *V = P->getIncomingValueForBlock(B);
       // If the source is a PHI add it to the work list if we haven't
...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/210301


More information about the llvm-commits mailing list