Skip to content

JIT: support SSA-aware PHI jump threading#126812

Open
AndyAyersMS wants to merge 1 commit intodotnet:mainfrom
AndyAyersMS:RboSimpleSSAUpdates
Open

JIT: support SSA-aware PHI jump threading#126812
AndyAyersMS wants to merge 1 commit intodotnet:mainfrom
AndyAyersMS:RboSimpleSSAUpdates

Conversation

@AndyAyersMS
Copy link
Copy Markdown
Member

@AndyAyersMS AndyAyersMS commented Apr 12, 2026

Teach redundant branch elimination to keep jump threading through PHI- based blocks when the PHI uses can be fully accounted for in the block and its immediate successors. Rewrite the affected successor SSA/VN uses, keep dominating-block threading conservative, and add focused regression coverage for the new PHI-based cases.

Fixes #126703 (not quite, yet)

Teach redundant branch elimination to keep jump threading through PHI-
based blocks when the PHI uses can be fully accounted for in the block
and its immediate successors. Rewrite the affected successor SSA/VN uses,
keep dominating-block threading conservative, and add focused regression
coverage for the new PHI-based cases.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 12, 2026 20:29
@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 12, 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.

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 extends CoreCLR JIT redundant branch optimization (jump threading) to support PHI-based threading when PHI definitions have non-local uses, by accounting for those uses within the threaded block and its immediate successors and rewriting successor SSA/VN uses accordingly. It also adds a focused JIT regression test to cover the new PHI-based scenario.

Changes:

  • Add tracking of PHI SSA uses in the candidate block/successors and rewrite successor SSA/VN uses when threading bypasses the PHI block.
  • Refine jump-thread eligibility checking to return a richer classification (including “needs PHI use resolution”).
  • Add a new JIT test case (JumpThreadPhi) to validate the new behavior.

Reviewed changes

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

Show a summary per file
File Description
src/coreclr/jit/redundantbranchopts.cpp Implements PHI-use discovery and successor SSA/VN rewriting; updates jump-thread check flow.
src/coreclr/jit/compiler.h Introduces JumpThreadCheckResult and declares new helper methods for PHI-use analysis/rewriting.
src/coreclr/jit/compmemkind.h Adds a dedicated allocator kind for redundant-branch/jump-threading data.
src/tests/JIT/opt/RedundantBranch/JumpThreadPhi.cs Adds regression coverage for PHI-based jump threading through a PHI-producing pattern.
src/tests/JIT/opt/RedundantBranch/JumpThreadPhi.csproj Adds the test project definition consistent with existing tests in the folder.

//
// Returns:
// True if the block is suitable for jump threading.
// Viability of jump threading: either CannotThread, CanThread, or CanThreadWithPhiBasedRBO.
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

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

The comment for optJumpThreadCheck’s return value list is out of date: it mentions “CanThreadWithPhiBasedRBO”, but the actual result type is JumpThreadCheckResult with values CannotThread/CanThread/NeedsPhiUseResolution. Please update the comment to match the enum to avoid confusion for future maintainers.

Suggested change
// Viability of jump threading: either CannotThread, CanThread, or CanThreadWithPhiBasedRBO.
// Viability of jump threading: either CannotThread, CanThread, or NeedsPhiUseResolution.

Copilot uses AI. Check for mistakes.
Comment on lines +1467 to +1496
for (GenTreePhi::Use& use : phi->Uses())
{
GenTreePhiArg* const phiArgNode = use.GetNode()->AsPhiArg();
BasicBlock* const predBlock = phiArgNode->gtPredBB;
bool const isTruePred = BitVecOps::IsMember(&jti.traits, jti.m_truePreds, predBlock->bbPostorderNum);
bool const isAmbiguousPred = BitVecOps::IsMember(&jti.traits, jti.m_ambiguousPreds, predBlock->bbPostorderNum);

if (isAmbiguousPred)
{
continue;
}

BasicBlock* const predTarget = isTruePred ? jti.m_trueTarget : jti.m_falseTarget;
if (predTarget != successor)
{
continue;
}

*hasThreadedPreds = true;

if (!foundReplacement)
{
replacementSsa = phiArgNode->GetSsaNum();
foundReplacement = true;
}
else if (replacementSsa != phiArgNode->GetSsaNum())
{
return false;
}
}
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

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

optGetThreadedSsaNumForSuccessor does not verify that every predecessor that will be redirected to the given successor has a corresponding PhiArg entry in the PHI. If SSA has been made stale (which this file already notes can happen), missing PhiArgs would be silently ignored and the function could incorrectly report a unique replacement SSA. Consider explicitly validating coverage for each (non-ambiguous) pred that targets this successor and failing the rewrite if any pred is not represented in the PHI args.

Copilot uses AI. Check for mistakes.
unsigned* replacementSsaNum)
{
assert(successor != nullptr);

Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

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

optGetThreadedSsaNumForSuccessor relies on the caller to initialize the out parameter *hasThreadedPreds before the call. Since this is an [OUT] parameter, it would be safer/clearer to set *hasThreadedPreds = false (and *replacementSsaNum = RESERVED) at function entry so the helper can’t be misused accidentally later.

Suggested change
*hasThreadedPreds = false;
*replacementSsaNum = SsaConfig::RESERVED_SSA_NUM;

Copilot uses AI. Check for mistakes.
@AndyAyersMS
Copy link
Copy Markdown
Member Author

Follow-on to #126711.

If all the uses of a global phi in a jump-threading candidate block are in the block and its successors, we can (in most cases) allow jump threading and rewrite the successor uses to the appropriate new ssa def & vn.

We avoid cases where the successors already have PHIs or would need to have new PHIs. These seem somewhat rare.

@EgorBo PTAL
fyi @dotnet/jit-contrib

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: missing opportunity for RBO

2 participants