Skip to content

JIT: Fix for IV opt to preserve updates to a counter that is live into an EH handler#129058

Open
JulieLeeMSFT wants to merge 2 commits into
dotnet:mainfrom
JulieLeeMSFT:fix-jit-128392-iv-eh-liveness
Open

JIT: Fix for IV opt to preserve updates to a counter that is live into an EH handler#129058
JulieLeeMSFT wants to merge 2 commits into
dotnet:mainfrom
JulieLeeMSFT:fix-jit-128392-iv-eh-liveness

Conversation

@JulieLeeMSFT

Copy link
Copy Markdown
Member

optLocalHasNonLoopUses relied on lvDoNotEnregister to detect locals live into exceptional exits. PR #127932 decoupled DNER from liveness (DNER is now set during LSRA/lowering, after optInductionVariables runs), so an induction variable live into a catch handler was no longer detected and its in-loop self-update was removed by optRemoveUnusedIVs, producing wrong results under full-opt codegen (crossgen2, jitstress, AggressiveOptimization).

Add an explicit lvTracked && IsLiveInOutOfHandler() check, since VisitRegularExitBlocks deliberately excludes handler blocks.

Fixes #128392.

…handlers

optLocalHasNonLoopUses relied on lvDoNotEnregister to detect locals live
into exceptional exits. PR dotnet#127932 decoupled DNER from liveness (DNER is
now set during LSRA/lowering, after optInductionVariables runs), so an
induction variable live into a catch handler was no longer detected and
its in-loop self-update was removed by optRemoveUnusedIVs, producing wrong
results under full-opt codegen (crossgen2, jitstress, AggressiveOptimization).

Add an explicit lvTracked && IsLiveInOutOfHandler() check, since
VisitRegularExitBlocks deliberately excludes handler blocks. Update two
stale comments referencing the old DNER behavior.

Fixes dotnet#128392.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 5, 2026 21:59
@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 Jun 5, 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.

@JulieLeeMSFT JulieLeeMSFT added this to the 11.0.0 milestone Jun 5, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 fixes a correctness hole in CoreCLR JIT induction-variable optimizations where a loop IV update could be removed even though the IV is live into an EH handler (e.g., used by a catch). The change makes optLocalHasNonLoopUses explicitly treat “live into handler” as a non-loop use, preventing optRemoveUnusedIVs from dropping the in-loop update.

Changes:

  • Update optLocalHasNonLoopUses to conservatively return true when a tracked local is IsLiveInOutOfHandler().
  • Adjust a comment in IV widening logic to reflect that exceptional-exit-live IVs are not profitable candidates (rather than relying on DNER being set).
  • Add a JIT regression test (Runtime_128392) and include it in the regression csproj.

Reviewed changes

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

File Description
src/coreclr/jit/inductionvariableopts.cpp Adds an explicit EH-handler liveness check in optLocalHasNonLoopUses to avoid removing IV updates that are observable via exceptional control flow.
src/tests/JIT/Regression/JitBlue/Runtime_128392/Runtime_128392.cs New xUnit regression covering an IV read in a catch after an exception thrown mid-loop.
src/tests/JIT/Regression/Regression_ro_2.csproj Includes the new regression test source file in the build.

@JulieLeeMSFT JulieLeeMSFT changed the title IV opt preserves updates to a counter that is live into an EH handler JIT: IV opt preserves updates to a counter that is live into an EH handler Jun 5, 2026
@JulieLeeMSFT JulieLeeMSFT changed the title JIT: IV opt preserves updates to a counter that is live into an EH handler JIT: Fix for IV opt to preserve updates to a counter that is live into an EH handler Jun 5, 2026
@AndyAyersMS

Copy link
Copy Markdown
Member

Is this 11.0 or 10.0?

@jakobbotsch

Copy link
Copy Markdown
Member

Is this 11.0 or 10.0?

This is a regression from #127932

Comment on lines 1331 to 1336
if (varDsc->lvDoNotEnregister)
{
// This filters out locals that may be live into exceptional exits.
// We cannot reason precisely about uses of locals that are not
// enregisterable, so be conservative.
return true;
}

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.

I think this check should just be removed.

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.

@copilot, please remove this check if (varDsc->lvDoNotEnregister).

Comment thread src/coreclr/jit/inductionvariableopts.cpp Outdated
@jakobbotsch

Copy link
Copy Markdown
Member

Can you introduce a similar assert as

#ifdef DEBUG
// We currently do not expect to ever widen IVs that are live into
// exceptional exits. Such IVs are not currently register candidates (EH
// write-thru is only for single def locals) which makes it unprofitable.
// If this ever changes we need some more expansive handling here.
loop->VisitLoopBlocks([=](BasicBlock* block) {
block->VisitAllSuccs(this, [=](BasicBlock* succ) {
if (!loop->ContainsBlock(succ) && bbIsHandlerBeg(succ))
{
assert(!optLocalIsLiveIntoBlock(lclNum, succ) &&
"Candidate IV for widening is live into exceptional exit");
}
return BasicBlockVisit::Continue;
});
return BasicBlockVisit::Continue;
});
#endif

at the end of optLocalHasNonLoopUses?

Co-authored-by: Jakob Botsch Nielsen <Jakob.botsch.nielsen@gmail.com>
Copilot AI review requested due to automatic review settings June 8, 2026 20:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 3 out of 3 changed files in this pull request and generated no new comments.

@JulieLeeMSFT

Copy link
Copy Markdown
Member Author

#ifdef DEBUG
// We currently do not expect to ever widen IVs that are live into
// exceptional exits. Such IVs are not currently register candidates (EH
// write-thru is only for single def locals) which makes it unprofitable.
// If this ever changes we need some more expansive handling here.
loop->VisitLoopBlocks([=](BasicBlock* block) {
block->VisitAllSuccs(this, [=](BasicBlock* succ) {
if (!loop->ContainsBlock(succ) && bbIsHandlerBeg(succ))
{
assert(!optLocalIsLiveIntoBlock(lclNum, succ) &&
"Candidate IV for widening is live into exceptional exit");
}

         return BasicBlockVisit::Continue; 
     }); 

     return BasicBlockVisit::Continue; 
 }); 

#endif

@copilot, please add this code to the end of optLocalHasNonLoopUses before return false;.

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.

Test failure: System.Security.Cryptography.X509Certificates.Tests.CollectionTests.X509Certificate2CollectionRemoveRangeArray

4 participants