Skip to content

JIT: dominating redundant branch opt#126587

Open
AndyAyersMS wants to merge 5 commits intodotnet:mainfrom
AndyAyersMS:DominatedBranchRBO
Open

JIT: dominating redundant branch opt#126587
AndyAyersMS wants to merge 5 commits intodotnet:mainfrom
AndyAyersMS:DominatedBranchRBO

Conversation

@AndyAyersMS
Copy link
Copy Markdown
Member

In some cases we can optimize a dominating branch, if its predicate is implied by a dominated branch. For example in

if (x > 0) if (x > 1) S();

if (x > 0) can be optimized away.

Closes #126554

In some cases we can optimize a dominating branch, if its predicate is
implied by a dominated branch. For example in

```if (x > 0) if (x > 1) S();```

`if (x > 0)` can be optimized away.

Closes dotnet#126554
Copilot AI review requested due to automatic review settings April 6, 2026 20:48
@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 Apr 6, 2026
@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

@EgorBo PTAL
FYI @dotnet/jit-contrib

A few hundred diffs; one common case is System.Numerics.INumber`1[char]:Max(char,char):

;; ------ BASE 

G_M16163_IG02:        ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref, isz
       movzx    rax, cx
       movzx    rcx, dx
       cmp      eax, ecx
       je       SHORT G_M16163_IG05
						;; size=10 bbWeight=1 PerfScore 1.75
G_M16163_IG03:        ; bbWeight=1.00, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref, isz
       cmp      ecx, eax
       jge      SHORT G_M16163_IG05
						;; size=4 bbWeight=1.00 PerfScore 1.25
G_M16163_IG04:        ; bbWeight=0.53, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref, epilog, nogc
       ret      
						;; size=1 bbWeight=0.53 PerfScore 0.53
G_M16163_IG05:        ; bbWeight=0.47, gcVars=0000000000000000 {}, gcrefRegs=0000 {}, byrefRegs=0000 {}, gcvars, byref
       mov      eax, ecx
						;; size=2 bbWeight=0.47 PerfScore 0.12
G_M16163_IG06:        ; bbWeight=0.47, epilog, nogc, extend
       ret  

;; ------ DIFF

G_M16163_IG02:        ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref, isz
       movzx    rax, dx
       movzx    rcx, cx
       cmp      eax, ecx
       cmovl    eax, ecx
						;; size=11 bbWeight=1 PerfScore 1.00
G_M16163_IG03:        ; bbWeight=1, epilog, nogc, extend
       ret   

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

Adds a new redundant-branch optimization to the CoreCLR JIT that can eliminate an outer (dominating) conditional branch when an inner (dominated) conditional implies it, improving code quality for certain nested-if patterns (e.g., issue #126554).

Changes:

  • Add optRedundantDominatingBranch to identify and constant-fold dominating BBJ_COND branches when implied by a dominated compare.
  • Introduce BasicBlock::hasSideEffects() helper used to ensure it’s safe to speculatively execute dominated blocks.
  • Add a new JIT regression test covering dominating-branch elimination scenarios.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/coreclr/jit/redundantbranchopts.cpp Implements the new “dominating redundant branch” optimization and wires it into the RBO phase.
src/coreclr/jit/compiler.h Declares the new optimizer entrypoint.
src/coreclr/jit/block.h Adds BasicBlock::hasSideEffects() helper used by the optimization.
src/tests/JIT/opt/RedundantBranch/RedundantBranchDominating.csproj New test project for the regression coverage.
src/tests/JIT/opt/RedundantBranch/RedundantBranchDominating.cs New functional test cases that exercise dominating-branch elimination patterns.

Comment on lines +742 to +743
{
if (!block->KindIs(BBJ_COND))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this check already exists at the call-site, so perhaps should be an assert?

Copy link
Copy Markdown
Member

@EgorBo EgorBo left a comment

Choose a reason for hiding this comment

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

makes sense to me, would like to see the CI status/diffs


if (!tree->OperIsCompare())
{
return false;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: in many places in JIT we copy this logic, we should probably either have a helper like "isCanonincalJtrue" or make it a hard rule how JTRUE's last statement should look like

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good idea. I will do this as a no-diff follow-up.


// Always preserve side effects in the dominating relop.
//
if ((domTree->gtFlags & GTF_SIDE_EFFECT) != 0)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

maybe it could use gtWrapWithSideEffects here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I'll also do this as a no-diff follow up, since the same pattern exists in optRedundantBranch

Copilot AI review requested due to automatic review settings April 7, 2026 16:21
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

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

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.

JIT: RBO can remove outer branch if its implied by inner branch

3 participants