[llvm] [BFI] Solve irreducible SCCs instead of splitting their headers (PR #215170)

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Sat Aug 15 13:30:16 PDT 2026


MaskRay wrote:

Measured it. Dropping `hasProfileData()` and defaulting the flag on, keeping the
irreducible-CFG condition ([branch](https://llvm-compile-time-tracker.com/compare.php?from=0c2e521f8b587b0c3fb5825fb157c3938fef4ff6&to=cb1f9afc556bd732278a6d937511c3a0a03e8241&stat=instructions:u),
[same on top of this PR](https://llvm-compile-time-tracker.com/compare.php?from=0c2e521f8b587b0c3fb5825fb157c3938fef4ff6&to=90e51b02faad113603907702e5e4d1be86e75d32&stat=instructions:u)),
`instructions:u` geomean against 0c2e521f8b58:

```
                       inference on   + this patch
stage1-O3                   +3.09%         +3.35%
stage1-ReleaseThinLTO       +3.03%         +3.55%
stage1-ReleaseLTO-g         +3.65%         +5.45%
stage1-aarch64-O3           +2.88%         +2.99%
stage2-O3                   +3.16%         +3.43%
stage1-O0-g                 +0.00%         -0.00%
clang build                 +0.54%         +0.69%
```

sqlite3 +19.42%, ClamAV +7.69%, SPASS +4.74% at stage1-O3; SPASS reaches +23.81% at ReleaseLTO-g.

**Iterative inference costs far more than what I expected**. Rarity does not help because the cost scales with the whole function's block count, not the SCC's -- one irreducible SCC anywhere relaxes every reachable block, bounded by `1000 * block_count`, and the functions that have irreducible CFGs are the large computed-goto dispatches. On sqlite3
the only significant one is `sqlite3VdbeExec`, at 1083-2276 blocks over 7 BFI rebuilds at
IR level and 2239-2740 at MIR.

In contrast, **this patch's cost is bounded by the size of the irreducible SCC rather than by the function**. It can never be as accurate, though: the solve recovers only the SCC's stationary direction and does not model the mass arriving at each of its entries.

I also expected a better initial estimate to save inference iterations. It does not.

**The end state I am proposing is this PR (#215170) alone** at least for non-profile builds. I would also note that this is a **net decrease of number
of lines of code** and drops several bandaids (e.g.
https://reviews.llvm.org/D10348) on the initial irreducible loop handling code.
The solve is unconditional and free; inference is a 3% geomean tax that cannot
be enabled broadly without work on its cost.

On the motivation behind this work: I was learning BFI and wanted to simplify the code.
Irreducible CFGs barely exist in IR (3 of 64391
functions I sampled) and are manufactured by CodeGen -- tail duplication of computed-goto
dispatch, 22 of 221703 at MIR.

On `findReachableBlocks`: agreed, and your framing is better than mine. A reachable closed
SCC has unbounded expected counts, so `f = e + f*P` has no finite solution and declining
is correct. BFI's own path cannot decline -- it must hand placement a number for that
shape regardless -- so the two are answering different questions rather than the same one
twice. I will drop the "declines one CFG shape" wording.

On accuracy where inference runs: agreed, it is a wash (within-10% 22 -> 22, better on 60
and worse on 41). I am not claiming this improves on inference. The claim is narrower --
it improves the unconditional path, which is what every non-PGO compile uses and what
inference itself starts from.


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


More information about the llvm-commits mailing list