Skip to content

JIT: skip loop inversion for loops that are already bottom-tested#128459

Open
AndyAyersMS wants to merge 1 commit into
dotnet:mainfrom
AndyAyersMS:LessLoopInversion
Open

JIT: skip loop inversion for loops that are already bottom-tested#128459
AndyAyersMS wants to merge 1 commit into
dotnet:mainfrom
AndyAyersMS:LessLoopInversion

Conversation

@AndyAyersMS
Copy link
Copy Markdown
Member

In optTryInvertWhileLoop, bail out when the loop's back-edge already controls loop continuation. Two shapes count:

  • a BBJ_COND latch that exits the loop
  • a BBJ_ALWAYS latch (installed by optCanonicalizeBackedges for loops that originally had multiple backedges) with an in-loop predecessor that is a BBJ_COND exiting the loop

In either case the candidate condBlock is some other early-exit test; inverting it just adds a redundant test above the loop and splits the body into two branches per iteration where there was one.

The existing 'already inverted' checks only catch single-block self- loops and loops whose latch test was recognized as the IV test by AnalyzeIteration. Loops with an unrecognized bottom test plus a separate early-exit BBJ_COND in the body fell through and got inverted on top of an already bottom-tested shape.

PR #116104 made this more visible by always computing loop iteration estimates from profile data, which pushes more loops past the size budget threshold where inversion is attempted.

Fixes #118494.

In optTryInvertWhileLoop, bail out when the loop's back-edge already
controls loop continuation. Two shapes count:

  * a BBJ_COND latch that exits the loop
  * a BBJ_ALWAYS latch (installed by optCanonicalizeBackedges for loops
    that originally had multiple backedges) with an in-loop predecessor
    that is a BBJ_COND exiting the loop

In either case the candidate condBlock is some other early-exit test;
inverting it just adds a redundant test above the loop and splits the
body into two branches per iteration where there was one.

The existing 'already inverted' checks only catch single-block self-
loops and loops whose latch test was recognized as the IV test by
AnalyzeIteration. Loops with an unrecognized bottom test plus a
separate early-exit BBJ_COND in the body fell through and got
inverted on top of an already bottom-tested shape.

PR dotnet#116104 made this more visible by always computing loop iteration
estimates from profile data, which pushes more loops past the size
budget threshold where inversion is attempted.

Fixes dotnet#118494.
Copilot AI review requested due to automatic review settings May 21, 2026 20:56
@github-actions github-actions Bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label May 21, 2026
@AndyAyersMS
Copy link
Copy Markdown
Member Author

(meant to create as draft, but fine this way too)

@dotnet-policy-service
Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

@AndyAyersMS
Copy link
Copy Markdown
Member Author

Another idea for multi-exit loops is to see if the exit blocks dominate one another. If so they divide the loop up into segments: [head, exit 1), [exit 1, exit 2), ... We can try and rotate so that there is no computation after the last exit (bottom test) and that the first segment has the best hoisting opportunities.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates CoreCLR JIT loop inversion (optTryInvertWhileLoop) to skip loop inversion when the loop is already bottom-tested by its backedge structure. The goal is to avoid introducing a redundant preheader test and extra per-iteration control flow when the loop’s continuation is already governed by a bottom test (including the canonicalized multi-backedge “BBJ_ALWAYS latch” shape).

Changes:

  • Add an early bail-out in optTryInvertWhileLoop when a backedge source is an exiting BBJ_COND latch.
  • Extend the bail-out to cover the canonical multi-backedge case where a BBJ_ALWAYS latch’s in-loop predecessor is an exiting BBJ_COND.

@AndyAyersMS
Copy link
Copy Markdown
Member Author

Diffs

Fairly extensive code size and tp reduction. Suggests we are perhaps being too aggressive with our current approach?

I will do some targeted benchmarking here, but it's hard to envision how to assess this as a whole without actually enabling it and then seeing what happens.

@AndyAyersMS
Copy link
Copy Markdown
Member Author

@EgorBot -arm -linux_arm64 -intel -linux_x64 "System.Text.Tests.Perf_Encoding"

@EgorBo
Copy link
Copy Markdown
Member

EgorBo commented May 21, 2026

@EgorBot -arm -linux_arm64 -intel -linux_x64 "System.Text.Tests.Perf_Encoding"

@AndyAyersMS I haven't enabled the smart mode yet in the bot (to use AI to parse arguments), but you're expected to use BDN's arguments after bot specific ones, so it should be --filter ...

@AndyAyersMS
Copy link
Copy Markdown
Member Author

@EgorBot -arm -linux_arm64 -intel -linux_x64 "System.Text.Tests.Perf_Encoding"

Yeah operator error, it was there initially.

@AndyAyersMS
Copy link
Copy Markdown
Member Author

@EgorBot -arm -linux_arm64 -intel -linux_x64 --filter "System.Text.Tests.Perf_Encoding"

@AndyAyersMS
Copy link
Copy Markdown
Member Author

Also it is eating the wildcards, so probably needs more tweaking.

@AndyAyersMS
Copy link
Copy Markdown
Member Author

@EgorBot -arm -linux_arm64 -intel -linux_x64 --filter "System.Text.Tests.Perf_Encoding*"

@EgorBo
Copy link
Copy Markdown
Member

EgorBo commented May 22, 2026

Also it is eating the wildcards, so probably needs more tweaking.

it should be passed to the bot correctly, it's just github renders them as italic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Perf] Linux/arm64: 1 Regression on 8/5/2025 9:21:29 PM +00:00

3 participants