[llvm] [BFI] Solve irreducible SCCs instead of splitting their headers (PR #215170)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Aug 9 19:56:02 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-aarch64
@llvm/pr-subscribers-pgo
Author: Fangrui Song (MaskRay)
<details>
<summary>Changes</summary>
In 2014, c5a3139ebd0d approximated irreducible control flow by modelling
an SCC as a loop with multiple headers. http://reviews.llvm.org/D10348
re-distributes the loop mass across the headers in proportion to the
backedge mass each one received -- one step of the same power iteration,
from an assumed split.
Delete that mechanism, package the SCC with a single representative and
solve it instead. `solveIrreducibleMass` iterates the SCC's internal
chain towards its dominant eigenvector and reads the member masses, the
exits and the circulating mass off that, so the entries' relative
frequencies come out of the solve. Power iteration rather than a
relaxation of `f = e + f*P`: the mass `e` entering the SCC is unknown
here, so there is no fixed point to relax towards, only a direction.
Relative error against an exact rationale solve has improved.
```
higher is better | relative error (lower is better)
exact within 1% within 10% | p50 p90 max
before 93 111 118 | 0.99 5.27 521.6
after 93 112 129 | 0.77 2.40 46.2
```
Among the lit tests, selfloops and unequalrows reach their exact ratios,
and nonentry's worst block is off by 1.9x rather than 31.5x.
Bound the iteration rather than run it to convergence: a periodic SCC
oscillates and never terminates, and over that corpus the error
distribution is the same at 16 iterations as at 1000, moving
non-monotonically in between.
This does not subsume -use-iterative-bfi-inference (0a0800c4d10c), which
relaxes the same equations over the whole function, where the entry mass
is known. On yyparse_1 in profile-correlation-irreducible-loops.ll the
solve alone puts b2 at 2.1x the entry against an exact 586.19x, and
inference reaches 586.19x either way. Over the corpus above the two
stack: enabling inference takes within 10% from 118 to 137 functions
before this patch and from 129 to 144 after.
CFGMST weights edges by BFI, so the instrumentation counter indices
permute. Re-record Inputs/irreducible{,_entry}.proftext under the new
numbering; the block counts the tests check are unchanged.
LLM-assisted
---
Patch is 43.76 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/215170.diff
11 Files Affected:
- (modified) llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h (+147-163)
- (modified) llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp (+25-89)
- (modified) llvm/test/Analysis/BlockFrequencyInfo/irreducible.ll (+13-13)
- (modified) llvm/test/Analysis/BlockFrequencyInfo/irreducible_pgo.ll (+26-1)
- (modified) llvm/test/CodeGen/AArch64/late-taildup-computed-goto.ll (+19-19)
- (modified) llvm/test/CodeGen/X86/basic-block-address-map-pgo-features.ll (+5-5)
- (modified) llvm/test/CodeGen/X86/fold-loop-of-urem.ll (+10-9)
- (modified) llvm/test/CodeGen/X86/pr38795.ll (+22-14)
- (modified) llvm/test/Transforms/PGOProfile/Inputs/irreducible.proftext (+3-3)
- (modified) llvm/test/Transforms/PGOProfile/Inputs/irreducible_entry.proftext (+2-2)
- (modified) llvm/test/Transforms/SampleProfile/profile-correlation-irreducible-loops.ll (+2-1)
``````````diff
diff --git a/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h b/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h
index a056c59f3d48f..050cccb7709a1 100644
--- a/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h
+++ b/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h
@@ -16,7 +16,6 @@
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/GenericCycleInfo.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/PostOrderIterator.h"
@@ -48,6 +47,7 @@
#include <optional>
#include <queue>
#include <string>
+#include <tuple>
#include <utility>
#include <vector>
@@ -221,61 +221,34 @@ class LLVM_ABI BlockFrequencyInfoImplBase {
struct LoopData {
using ExitMap = SmallVector<std::pair<BlockNode, BlockMass>, 4>;
using NodeList = SmallVector<BlockNode, 4>;
- using HeaderMassList = SmallVector<BlockMass, 1>;
- LoopData *Parent; ///< The parent loop.
- bool IsPackaged = false; ///< Whether this has been packaged.
+ LoopData *Parent; ///< The parent loop.
+ bool IsPackaged = false; ///< Whether this has been packaged.
// Has an irreducible SCC in its own nodes; sub-loops package theirs first.
bool ContainsIrreducible = false;
- // Headers are Nodes[0, NumHeaders), sorted. For an irreducible loop, the
- // SCC's entries and the nodes a retreating edge from a non-entry reaches.
- uint32_t NumHeaders = 1;
- ExitMap Exits; ///< Successor edges (and weights).
- NodeList Nodes; ///< Header and the members of the loop.
- HeaderMassList BackedgeMass; ///< Mass returned to each loop header.
+ // A multi-entry SCC rather than a natural loop.
+ bool IsIrreducible = false;
+ ExitMap Exits; ///< Successor edges (and weights).
+ NodeList Nodes; ///< Header and the members of the loop.
+ BlockMass BackedgeMass; ///< Mass that circulates, not exits.
BlockMass Mass;
Scaled64 Scale;
LoopData(LoopData *Parent, const BlockNode &Header)
- : Parent(Parent), Nodes(1, Header), BackedgeMass(1) {}
+ : Parent(Parent), Nodes(1, Header) {}
- template <class It>
- LoopData(LoopData *Parent, It FirstHeader, It LastHeader)
- : Parent(Parent), Nodes(FirstHeader, LastHeader) {
- NumHeaders = Nodes.size();
- BackedgeMass.resize(NumHeaders);
- }
+ /// An irreducible SCC. Its entries are equivalent as far as the enclosing
+ /// region is concerned, so the lowest-RPO member stands for the package
+ /// and solveIrreducibleMass distributes mass among them all.
+ LoopData(LoopData *Parent, NodeList &&Members)
+ : Parent(Parent), IsIrreducible(true), Nodes(std::move(Members)) {}
- template <class It1, class It2>
- LoopData(LoopData *Parent, It1 FirstHeader, It1 LastHeader, It2 FirstOther,
- It2 LastOther)
- : Parent(Parent), Nodes(FirstHeader, LastHeader) {
- NumHeaders = Nodes.size();
- Nodes.insert(Nodes.end(), FirstOther, LastOther);
- BackedgeMass.resize(NumHeaders);
- }
-
- bool isHeader(const BlockNode &Node) const {
- if (isIrreducible())
- return std::binary_search(Nodes.begin(), Nodes.begin() + NumHeaders,
- Node);
- return Node == Nodes[0];
- }
+ bool isHeader(const BlockNode &Node) const { return Node == Nodes[0]; }
BlockNode getHeader() const { return Nodes[0]; }
- bool isIrreducible() const { return NumHeaders > 1; }
-
- HeaderMassList::difference_type getHeaderIndex(const BlockNode &B) {
- assert(isHeader(B) && "this is only valid on loop header blocks");
- if (isIrreducible())
- return std::lower_bound(Nodes.begin(), Nodes.begin() + NumHeaders, B) -
- Nodes.begin();
- return 0;
- }
+ bool isIrreducible() const { return IsIrreducible; }
- NodeList::const_iterator members_begin() const {
- return Nodes.begin() + NumHeaders;
- }
+ NodeList::const_iterator members_begin() const { return Nodes.begin() + 1; }
NodeList::const_iterator members_end() const { return Nodes.end(); }
iterator_range<NodeList::const_iterator> members() const {
@@ -295,8 +268,8 @@ class LLVM_ABI BlockFrequencyInfoImplBase {
/// The innermost loop containing Node that Node does not head.
///
- /// A block can head several nested loops: createIrreducibleLoop() reuses
- /// an SCC's entry blocks as the irreducible loop's headers.
+ /// A block can head several nested loops: an irreducible SCC's
+ /// representative may also head a sub-loop.
LoopData *getContainingLoop() const {
LoopData *L = Loop;
while (L && L->isHeader(Node))
@@ -481,18 +454,6 @@ class LLVM_ABI BlockFrequencyInfoImplBase {
/// Compute the loop scale for a loop.
void computeLoopScale(LoopData &Loop);
- /// Adjust the mass of all headers in an irreducible loop.
- ///
- /// Initially, irreducible loops are assumed to distribute their mass
- /// equally among its headers. This can lead to wrong frequency estimates
- /// since some headers may be executed more frequently than others.
- ///
- /// This adjusts header mass distribution so it matches the weights of
- /// the backedges going into each of the loop headers.
- void adjustLoopHeaderMass(LoopData &Loop);
-
- void distributeIrrLoopHeaderMass(Distribution &Dist);
-
/// Package up a loop.
void packageLoop(LoopData &Loop);
@@ -688,15 +649,10 @@ void IrreducibleGraph::addEdges(const BlockNode &Node,
///
/// In addition to loops, this algorithm has limited support for irreducible
/// SCCs, which are SCCs with multiple entry blocks. Irreducible SCCs are
-/// found from CycleInfo before any mass is distributed, and modelled as loops
-/// with multiple headers.
-///
-/// The headers of irreducible sub-SCCs consist of its entry blocks and all
-/// nodes that are targets of a backedge within it (excluding backedges within
-/// true sub-loops). Block frequency calculations act as if a block is
-/// inserted that intercepts all the edges to the headers. All backedges and
-/// entries point to this block. Its successors are the headers, which split
-/// the frequency evenly.
+/// found from CycleInfo before any mass is distributed, and packaged like a
+/// loop, with the lowest-RPO member standing for the package. There is no
+/// header to sweep from, so \a solveIrreducibleMass() distributes mass among
+/// the members by power iteration instead.
///
/// This algorithm leverages BlockMass and ScaledNumber to maintain precision,
/// separates mass distribution from loop scaling, and dithers to eliminate
@@ -759,16 +715,9 @@ void IrreducibleGraph::addEdges(const BlockNode &Node,
/// - Distribute the mass accordingly, dithering to minimize mass loss,
/// as described in \a distributeMass().
///
-/// In the case of irreducible loops, instead of a single loop header,
-/// there will be several. The computation of backedge masses is similar
-/// but instead of having a single backedge mass, there will be one
-/// backedge per loop header. In these cases, each backedge will carry
-/// a mass proportional to the edge weights along the corresponding
-/// path.
-///
-/// At the end of propagation, the full mass assigned to the loop will be
-/// distributed among the loop headers proportionally according to the
-/// mass flowing through their backedges.
+/// An irreducible SCC is not swept. \a solveIrreducibleMass() iterates
+/// the SCC's internal chain towards its dominant eigenvector and reads the
+/// member masses, the exits and the circulating mass off that.
///
/// Finally, calculate the loop scale from the accumulated backedge mass.
///
@@ -795,37 +744,13 @@ void IrreducibleGraph::addEdges(const BlockNode &Node,
///
/// - The model of irreducible control flow is a rough approximation.
///
-/// Modelling irreducible control flow exactly involves setting up and
-/// solving a group of infinite geometric series. Such precision is
-/// unlikely to be worthwhile, since most of our algorithms give up on
-/// irreducible control flow anyway.
-///
-/// Nevertheless, we might find that we need to get closer. Here's a sort
-/// of TODO list for the model with diminishing returns, to be completed as
-/// necessary.
-///
-/// - The headers for the \a LoopData representing an irreducible SCC
-/// include non-entry blocks. When these extra blocks exist, they
-/// indicate a self-contained irreducible sub-SCC. We could treat them
-/// as sub-loops, rather than arbitrarily shoving the problematic
-/// blocks into the headers of the main irreducible SCC.
-///
-/// - Entry frequencies are assumed to be evenly split between the
-/// headers of a given irreducible SCC, which is the only option if we
-/// need to compute mass in the SCC before its parent loop. Instead,
-/// we could partially compute mass in the parent loop, and stop when
-/// we get to the SCC. Here, we have the correct ratio of entry
-/// masses, which we can use to adjust their relative frequencies.
-/// Compute mass in the SCC, and then continue propagation in the
-/// parent.
-///
-/// - We can propagate mass iteratively through the SCC, for some fixed
-/// number of iterations. Each iteration starts by assigning the entry
-/// blocks their backedge mass from the prior iteration. The final
-/// mass for each block (and each exit, and the total backedge mass
-/// used for computing loop scale) is the sum of all iterations.
-/// (Running this until fixed point would "solve" the geometric
-/// series by simulation.)
+/// \a solveIrreducibleMass() settles an SCC's internal chain, but the mass
+/// entering each entry is unknown until the parent loop is distributed, so
+/// it aims at the quasi-stationary vector rather than the true occupancy.
+/// To get closer, partially compute mass in the parent loop and stop at
+/// the SCC: that gives the correct ratio of entry masses to adjust their
+/// relative frequencies with. Compute mass in the SCC, then continue
+/// propagation in the parent.
template <class BT> class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase {
using BlockT = typename bfi_detail::TypeMap<BT>::BlockT;
using FunctionT = typename bfi_detail::TypeMap<BT>::FunctionT;
@@ -885,10 +810,11 @@ template <class BT> class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase {
/// and \a computeIrreducibleMass() for \c Loop if it contains irreducible
/// control flow.
void computeMassInLoop(LoopData &Loop);
+ void solveIrreducibleMass(LoopData &Loop);
- /// Distribute mass in a multi-header loop, seeding the headers from
- /// irr_loop_header_weight metadata and marking them in IsIrrLoopHeader.
- void computeMassInIrreducibleLoop(LoopData &Loop);
+ /// Collect \c Node's successors, resolved through any package, with weights.
+ void getSuccWeights(const BlockNode &Node,
+ SmallVectorImpl<std::pair<BlockNode, uint64_t>> &Out);
/// Compute mass in (and package up) irreducible SCCs.
///
@@ -1205,7 +1131,7 @@ void BlockFrequencyInfoImpl<BT>::computeMassInLoop(LoopData &Loop) {
if (Loop.isIrreducible()) {
LLVM_DEBUG(dbgs() << "isIrreducible = true\n");
- computeMassInIrreducibleLoop(Loop);
+ solveIrreducibleMass(Loop);
} else {
Working[Loop.getHeader().Index].getMass() = BlockMass::getFull();
propagateMassToSuccessors(&Loop, Loop.getHeader());
@@ -1218,60 +1144,119 @@ void BlockFrequencyInfoImpl<BT>::computeMassInLoop(LoopData &Loop) {
}
template <class BT>
-void BlockFrequencyInfoImpl<BT>::computeMassInIrreducibleLoop(LoopData &Loop) {
- Distribution Dist;
- unsigned NumHeadersWithWeight = 0;
- std::optional<uint64_t> MinHeaderWeight;
- DenseSet<uint32_t> HeadersWithoutWeight;
- HeadersWithoutWeight.reserve(Loop.NumHeaders);
- for (uint32_t H = 0; H < Loop.NumHeaders; ++H) {
- auto &HeaderNode = Loop.Nodes[H];
- const BlockT *Block = getBlock(HeaderNode);
- IsIrrLoopHeader.set(Loop.Nodes[H].Index);
- std::optional<uint64_t> HeaderWeight = Block->getIrrLoopHeaderWeight();
- if (!HeaderWeight) {
- LLVM_DEBUG(dbgs() << "Missing irr loop header metadata on "
- << getBlockName(HeaderNode) << "\n");
- HeadersWithoutWeight.insert(H);
+void BlockFrequencyInfoImpl<BT>::getSuccWeights(
+ const BlockNode &Node,
+ SmallVectorImpl<std::pair<BlockNode, uint64_t>> &Out) {
+ Out.clear();
+ if (auto *L = Working[Node.Index].getPackagedLoop()) {
+ for (const auto &E : L->Exits)
+ Out.emplace_back(Working[E.first.Index].getResolvedNode(),
+ E.second.getMass());
+ return;
+ }
+ const BlockT *BB = getBlock(Node);
+ for (auto It : enumerate(children<const BlockT *>(BB))) {
+ BlockNode Succ = getNode(It.value());
+ if (!Succ.isValid())
continue;
+ uint64_t W =
+ getWeightFromBranchProb(BPI->getEdgeProbability(BB, It.index()));
+ Out.emplace_back(Working[Succ.Index].getResolvedNode(),
+ std::max<uint64_t>(1, W));
+ }
+}
+
+// Distribute an irreducible SCC's mass among its members, and record the
+// exits and circulating mass computeLoopScale() needs. For the transition
+// matrix restricted to SCC members, use power iteration to find an approximate
+// solution.
+template <class BT>
+void BlockFrequencyInfoImpl<BT>::solveIrreducibleMass(LoopData &Loop) {
+ const size_t N = Loop.Nodes.size();
+ // Intra-SCC edges (src, dst) and exit edges (src, target), both in src order.
+ SmallVector<std::tuple<uint32_t, uint32_t, Scaled64>> P;
+ SmallVector<std::tuple<uint32_t, BlockNode, Scaled64>> Ex;
+ SmallVector<std::pair<BlockNode, uint64_t>, 8> Succs;
+ for (size_t I = 0; I != N; ++I) {
+ getSuccWeights(Loop.Nodes[I], Succs);
+ uint64_t Total = llvm::sum_of(llvm::make_second_range(Succs));
+ if (!Total)
+ continue;
+ Scaled64 InvTotal = Scaled64::getInverse(Total);
+ for (const auto &S : Succs) {
+ Scaled64 Pr = Scaled64(S.second, 0) * InvTotal;
+ // createIrreducibleLoop sorted Nodes, so a member's position in the
+ // matrix is where it lands in that list.
+ auto It = llvm::lower_bound(Loop.Nodes, S.first);
+ if (It != Loop.Nodes.end() && *It == S.first)
+ P.emplace_back(I, It - Loop.Nodes.begin(), Pr);
+ else
+ Ex.emplace_back(I, S.first, Pr);
+ }
+ }
+
+ // irr_loop_header_weight is a measured block frequency, so pin the members
+ // that carry one and let the rest settle around them. Weights that are all
+ // zero anchor no scale, so start from a uniform split instead.
+ SmallVector<Scaled64> F(N), G(N);
+ SmallVector<bool> Pinned(N, false);
+ Scaled64 Sum;
+ for (size_t I = 0; I != N; ++I)
+ if (auto W = getBlock(Loop.Nodes[I])->getIrrLoopHeaderWeight()) {
+ F[I] = Scaled64(*W, 0);
+ Pinned[I] = true;
+ Sum += F[I];
}
- LLVM_DEBUG(dbgs() << getBlockName(HeaderNode)
- << " has irr loop header weight " << *HeaderWeight
- << "\n");
- NumHeadersWithWeight++;
- uint64_t HeaderWeightValue = *HeaderWeight;
- if (!MinHeaderWeight || HeaderWeightValue < MinHeaderWeight)
- MinHeaderWeight = HeaderWeightValue;
- if (HeaderWeightValue) {
- Dist.addLocal(HeaderNode, HeaderWeightValue);
+ if (Sum.isZero()) {
+ Pinned.assign(N, false);
+ F.assign(N, Scaled64::getInverse(N));
+ Sum = llvm::sum_of(F, Scaled64::getZero());
+ }
+
+ // A backstop, not a convergence criterion: a periodic SCC never settles.
+ const unsigned MaxIterations = 16;
+ // Mass leaks out of the SCC, so F decays geometrically. Sum tracks the
+ // decay; Ratio divides it out so Delta compares directions, not sizes.
+ for (unsigned It = 0; It != MaxIterations; ++It) {
+ G.assign(N, Scaled64::getZero());
+ for (auto [I, J, Pr] : P)
+ G[J] += F[I] * Pr;
+ Scaled64 New;
+ for (size_t I = 0; I != N; ++I) {
+ if (Pinned[I])
+ G[I] = F[I];
+ New += G[I];
}
+ if (New.isZero())
+ break; // nothing circulates; keep the uniform split
+ Scaled64 Ratio = New / Sum;
+ Scaled64 Delta;
+ for (size_t I = 0; I != N; ++I) {
+ Scaled64 Was = Ratio * F[I];
+ Delta += G[I] >= Was ? G[I] - Was : Was - G[I];
+ F[I] = G[I];
+ }
+ Sum = New;
+ if (Delta < New * Scaled64(1, -32))
+ break;
}
- // As a heuristic, if some headers don't have a weight, give them the
- // minimum weight seen (not to disrupt the existing trends too much by
- // using a weight that's in the general range of the other headers' weights,
- // and the minimum seems to perform better than the average.)
- // FIXME: better update in the passes that drop the header weight.
- // If no headers have a weight, give them even weight (use weight 1).
- if (!MinHeaderWeight)
- MinHeaderWeight = 1;
- for (uint32_t H : HeadersWithoutWeight) {
- auto &HeaderNode = Loop.Nodes[H];
- assert(!getBlock(HeaderNode)->getIrrLoopHeaderWeight() &&
- "Shouldn't have a weight metadata");
- uint64_t MinWeight = *MinHeaderWeight;
- LLVM_DEBUG(dbgs() << "Giving weight " << MinWeight << " to "
- << getBlockName(HeaderNode) << "\n");
- if (MinWeight)
- Dist.addLocal(HeaderNode, MinWeight);
+
+ if (!Sum.isZero())
+ for (auto &X : F)
+ X = X / Sum;
+
+ for (size_t I = 0; I != N; ++I)
+ Working[Loop.Nodes[I].Index].getMass() = BlockMass(F[I].scale(UINT64_MAX));
+
+ BlockMass TotalExit;
+ for (auto [I, Succ, Pr] : Ex) {
+ uint64_t M = (F[I] * Pr).scale(UINT64_MAX);
+ if (!M)
+ continue;
+ Loop.Exits.emplace_back(Succ, BlockMass(M));
+ TotalExit += BlockMass(M);
}
- distributeIrrLoopHeaderMass(Dist);
- // Seeded headers are ordered first. Any retreating edge from a non-header
- // targets a header.
- for (const BlockNode &M : Loop.Nodes)
- propagateMassToSuccessors(&Loop, M);
- if (NumHeadersWithWeight == 0)
- // No headers have a metadata. Adjust header mass.
- adjustLoopHeaderMass(Loop);
+ Loop.BackedgeMass = BlockMass::getFull() - TotalExit;
}
template <class BT> void BlockFrequencyInfoImpl<BT>::computeMassInFunction() {
@@ -1601,8 +1586,7 @@ void BlockFrequencyInfoImpl<BT>::computeIrreducibleMass(
// Drop the nodes the new packages absorbed.
assert(OuterLoop->Exits.empty() && "unexpected exits before distribution");
- assert(llvm::all_of(OuterLoop->BackedgeMass,
- [](BlockMass M) { return M.isEmpty(); }) &&
+ assert(OuterLoop->BackedgeMass.isEmpty() &&
"unexpected backedge mass before distribution");
auto O = OuterLoop->Nodes.begin() + 1;
for (auto I = O, E = OuterLoop->Nodes.end(); I != E; ++I)
diff --git a/llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp b/llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp
index fee82843e87dc..27c52afc3baab 100644
--- a/llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp
+++ b/llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp
@@ -350,12 +350,10 @@ void BlockFrequencyInfoImplBase::addToDist(Distribution &Dist,
return;
}
- if (Resolved < Pred) {
- // Every irreducible SCC is packaged before mass distribution, so this is
- // a false backedge from a secondary header of an irreducible OuterLoop.
- assert(isLoopHeader(Pred) && OuterLoop->isIrreducible() &&
- "unhandled irreducible control flow");
- }
+ // Every irreducible SCC is packaged before mass distribution and an
+ // irreducible package is solved rather than swept, so the only retreating
+ // edge left is the one to OuterLoop's header, handled above.
+ assert(Resolved >= Pred && "unhandled irreducible control flow");
LLVM_DEBUG(debugSuccessor(" local "));
Dist.addLocal(Resolved, Weight);
@@ -386,10 +384,7 @@ void BlockFrequencyInfoImplBase::computeLoopScale(LoopData &Loop) {
// LoopScale == 1 / ExitMass
// ExitMass == HeadMass - BackedgeMass
- BlockMass TotalBackedgeMass;
- for (auto &Mass : Loop.BackedgeMass)
- TotalBackedgeMass += Mass;
- BlockMass ExitMass = BlockMass::getFull() - TotalBackedgeMass;
+ BlockMass ExitMass = Block...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/215170
More information about the llvm-commits
mailing list