Skip to content

JIT: Reset compGenTreeID on failed Materialize to avoid leaking gen tree IDs#129528

Open
Copilot wants to merge 5 commits into
mainfrom
copilot/jit-fix-assertion-failed
Open

JIT: Reset compGenTreeID on failed Materialize to avoid leaking gen tree IDs#129528
Copilot wants to merge 5 commits into
mainfrom
copilot/jit-fix-assertion-failed

Conversation

Copilot AI commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

A Fuzzlyn-generated case tripped the m_compGenTreeID == m_compiler->compGenTreeID assertion (phase.cpp:47) during 'Optimize Induction Variables'. The phase reported MODIFIED_NOTHING, yet compGenTreeID had advanced.

Root cause

The GenTree* Materialize(Scev* scev) overload calls the internal Materialize(scev, /*createIR*/ true, ...), which allocates IR nodes (bumping compGenTreeID) as it recurses but can still return false partway through — e.g. on an AddRec, a non-null TYP_REF/TYP_BYREF constant, or a 32-bit MUL of TYP_LONG. The orphaned nodes leak their ID increments, so a phase that ultimately makes no change observes a changed compGenTreeID.

Changes

  • scev.cppGenTree* Materialize(Scev* scev): snapshot compGenTreeID before materializing IR and restore it on a false return. Since compGenTreeID is a DEBUG-only field, the snapshot and reset are guarded with INDEBUG.
INDEBUG(unsigned prevGenTreeID = m_compiler->compGenTreeID);
if (Materialize(scev, true, &result, &vnp))
{
    return result;
}

INDEBUG(m_compiler->compGenTreeID = prevGenTreeID);
return nullptr;

MaterializeVN uses createIR=false and never allocates IR, so it needs no change.

Copilot AI self-assigned this Jun 17, 2026
Copilot AI review requested due to automatic review settings June 17, 2026 14:58
Copilot AI removed the request for review from Copilot June 17, 2026 14:58
…ree IDs

Co-authored-by: jakobbotsch <7887810+jakobbotsch@users.noreply.github.com>
Copilot AI requested review from Copilot and removed request for Copilot June 17, 2026 15:02
@jakobbotsch

Copy link
Copy Markdown
Member

@copilot These fields are DEBUG only, so add #ifdef DEBUG too

Copilot AI changed the title [WIP] Fix assertion failure during optimize induction variables JIT: Reset compGenTreeID on failed Materialize to avoid leaking gen tree IDs Jun 17, 2026
Copilot AI requested a review from jakobbotsch June 17, 2026 15:06
…only

Co-authored-by: jakobbotsch <7887810+jakobbotsch@users.noreply.github.com>
Copilot AI requested review from Copilot and removed request for Copilot June 17, 2026 15:15

Copilot AI commented Jun 17, 2026

Copy link
Copy Markdown
Contributor Author

@copilot These fields are DEBUG only, so add #ifdef DEBUG too

Wrapped the snapshot/reset in INDEBUG since compGenTreeID is DEBUG-only. Verified both checked and release builds in 61314ae.

@jakobbotsch jakobbotsch marked this pull request as ready for review June 17, 2026 15:35
Copilot AI review requested due to automatic review settings June 17, 2026 15:35
@jakobbotsch

Copy link
Copy Markdown
Member

Fixes #129527

@jakobbotsch

Copy link
Copy Markdown
Member

@copilot Add the regression test from #129527. Remember not to add a .csproj for it, but to just add the .cs to the merged Regression_2.csproj instead.

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 updates JIT scalar-evolution IR materialization so that a failed attempt to materialize a Scev into GenTree IR does not advance the debug-only Compiler::compGenTreeID counter. This keeps Phase::Observations invariants intact when a phase reports MODIFIED_NOTHING but speculative IR construction partially occurred and then aborted.

Changes:

  • Snapshot m_compiler->compGenTreeID (DEBUG-only) before attempting IR materialization and restore it on failure.
  • Expand the wrapper ScalarEvolutionContext::Materialize(Scev* scev) from a single conditional expression into an explicit success/failure path with a rollback.

Co-authored-by: jakobbotsch <7887810+jakobbotsch@users.noreply.github.com>

Copilot AI commented Jun 17, 2026

Copy link
Copy Markdown
Contributor Author

@copilot Add the regression test from #129527. Remember not to add a .csproj for it, but to just add the .cs to the merged Regression_2.csproj instead.

Added the regression test in src/tests/JIT/Regression/JitBlue/Runtime_129527/Runtime_129527.cs and wired it into the merged regression project (Regression_ro_2.csproj) in commit 8975decf.

@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 17, 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.

Copilot AI review requested due to automatic review settings June 19, 2026 08:53

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.

@jakobbotsch

jakobbotsch commented Jun 19, 2026

Copy link
Copy Markdown
Member

cc @dotnet/jit-contrib PTAL @EgorBo

Debated with myself the best ways to fix this but eventually ended up with this one. There are a few:

  • Always report IR as modified after calling Materialize from IV opts, regardless of the return. Not satisfying to me because the caller should not need to be aware of such oddities.
  • Condition phase return status from IV opts also on compiler->compGenTreeID == startCompGenTreeID. Not satisfying to me because that makes the phase return status different between debug and release.
  • Remove this particular post-phase assert. This seems like the best solution if we could instead check that the actual IR hadn't been modified, but that seems hard.
  • This fix. Not satisfying because if you are breaking on "tree with some ID being created" then you may see a tree with the same ID being created twice. But to me this is the least unsatisfying fix.

@BoyBaykiller

Copy link
Copy Markdown
Contributor

Btw I believe we have the same thing in if-conversion where we always create a SELECT, but then may bail out without actually changing the IR. Currently it just always returns true from that point on.

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: Assertion failed 'm_compGenTreeID == m_compiler->compGenTreeID' during 'Optimize Induction Variables'

5 participants