Skip to content

JIT: check guard types during CEA cloning - #137092

Merged
AndyAyersMS merged 3 commits into
dotnet:mainfrom
AndyAyersMS:fix-137063-guard-types
Nov 13, 2026
Merged

AndyAyersMS merged 3 commits into
dotnet:mainfrom
AndyAyersMS:fix-137063-guard-types

Conversation

@AndyAyersMS

Copy link
Copy Markdown
Member

Only specialize GDV guards that match the allocation's type during CEA cloning. Previously, a cloned boxed List enumerator could take an array-enumerator fast path.

Add a regression with opposing factory and iteration profiles and multiple GDV type checks.

Validation: Checked JIT build passed; the regression fails before the fix and passes afterward. Six neighboring test wrappers passed. The original NativeAOT repro improves from 2/5 to 5/5 correct results.

SPMI: 2,081,803 cached contexts, no assembly diffs or failing compiles; one context lacks data in both JITs. The 3,328-context NativeAOT repro collection changes only Dfa.DfaBuilder.Closure: 1,032 -> 1,130 bytes (+98 bytes, +9.50%). Stack allocation is retained.

Resolves #137063

Note

This PR description was generated by GitHub Copilot.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c987451d-dcb7-4398-a2d6-8c2ab3f3a8ca
@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 Nov 6, 2026
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 5 pipeline(s).
10 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@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

Note this bug is currently NAOT specific, it only happens when we allow multiple GDV checks (NAOT enables 3 by default) and have a polymorphic profile. If we have this setup then we need to ensure that in the CEA clone we specialize the right checks (since there is more than one to choose from at each site).

Also note we are not anti-specializing the known to be wrong checks, which means the cloned code is slightly inefficient coming out of CEA, but these get cleaned up later on by RBO/AP.

If we just have a single GDV check and a polymorphic profile (which is what we normally see during jitting) then a diverging GDV will cause CEA to fail.

We apparently don't enable multi-guess GDV in PGO stress modes. Seems like we should.

@AndyAyersMS
AndyAyersMS requested review from jakobbotsch and a balanced review from Copilot November 6, 2026 18:15
@AndyAyersMS

Copy link
Copy Markdown
Member Author

@jakobbotsch PTAL
fyi @dotnet/jit-contrib

Will probably want to backport this.

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.

🟢 Approval recommended

No active review issues are reported for the change restricting guard specialization to matching allocation types.

No open issues 🎉

What changed in this PR

This PR fixes incorrect guarded devirtualization during conditional escape analysis (CEA) cloning in the JIT by requiring guards to match the allocation’s type.

Changes:

  • Restricts guard specialization to matching allocation types.
  • Adds a regression with opposing factory-call and iteration profiles.
  • Configures the regression for tiered compilation, dynamic profile-guided optimization, and multiple type checks.
File Description
src/​tests/​JIT/​opt/​ObjectStackAllocation/​Runtime_137063.csproj Configures isolated execution and optimization settings for the regression.
src/​tests/​JIT/​opt/​ObjectStackAllocation/​Runtime_137063.cs Tests enumeration counts with conflicting type profiles.
src/​coreclr/​jit/​objectalloc.cpp Checks guard type equality before specializing during cloning.

Review effort: Balanced

@JulieLeeMSFT JulieLeeMSFT left a comment

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.

LGTM. The fix adds a type-match check so CEA uses the guard for the correct type when a call site has multiple GDV checks.

@JulieLeeMSFT

Copy link
Copy Markdown
Member

Will probably want to backport this.

The author said that backport would work for them. We can skip backports.

@AndyAyersMS

Copy link
Copy Markdown
Member Author

Will probably want to backport this.

The author said that backport would work for them. We can skip backports.

Did you mean to write "will not"? I think we should consider fixing this...

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c987451d-dcb7-4398-a2d6-8c2ab3f3a8ca
@AndyAyersMS

Copy link
Copy Markdown
Member Author

Formatter failure looks like a .NET 10 servicing timing glitch, fails looking for 10.0.15. Will retry in an hour or so.

@JulieLeeMSFT

Copy link
Copy Markdown
Member

Will probably want to backport this.

The author said that backport would work for them. We can skip backports.

Did you mean to write "will not"? I think we should consider fixing this...

I mean workaround works for them -- #137063 (comment).

AndyAyersMS added a commit that referenced this pull request Nov 11, 2026
<!-- -->

Add `fullpgo_multiguess_gdv`, based on `fullpgo` with
`JitGuardedDevirtualizationMaxTypeChecks=3`. Keep the existing modes
unchanged.

Run it in the runtime and libraries PGO stress groups. Leave the reduced
Windows arm64 scenario lists unchanged because of their existing timeout
constraints.

Local validation: generated and checked 16 Windows/Unix environment
scripts and parsed both changed pipeline YAML files. The new mode emits
two guesses at both iterator call sites in the positive control; it
fails with the baseline JIT and passes with the fix. Ordinary `fullpgo`
still passes on the baseline.

Complements #137092.

> [!NOTE]
> This PR description was generated by GitHub Copilot.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c987451d-dcb7-4398-a2d6-8c2ab3f3a8ca
@AndyAyersMS

Copy link
Copy Markdown
Member Author

/azp run runtime

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@AndyAyersMS
AndyAyersMS merged commit 7a535aa into dotnet:main Nov 13, 2026
79 of 84 checks passed
@dotnet-milestone-bot dotnet-milestone-bot Bot added this to the 12.0-preview1 milestone Nov 13, 2026
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.

Native AOT: a static profile (MibcFile) makes ILC miscompile a foreach over IEnumerable<int> passed an int[]

4 participants