Skip to content

Fix for 126457#127050

Open
dhartglassMSFT wants to merge 7 commits intodotnet:mainfrom
dhartglassMSFT:fix_126457
Open

Fix for 126457#127050
dhartglassMSFT wants to merge 7 commits intodotnet:mainfrom
dhartglassMSFT:fix_126457

Conversation

@dhartglassMSFT
Copy link
Copy Markdown
Contributor

@dhartglassMSFT dhartglassMSFT commented Apr 17, 2026

For a bool-typed inlinee that contains a tail call, where the return is in a seperate block from the tailcall (for a single-return method, for example), the inliner inserts an int->ubyte->int normalizing cast

*  RETURN  int
\--*  CAST    int <- ubyte <- int
   \--*  LCL_VAR int    V04 tmp3

The tail-call validation in morph doesn't expect a cast there. However, a normalizing cast here may be safely ignored for tailcalls because
1 - If the calling function was not inlined, the normalizing cast is intead inserted later in morph after the tailcall transformation, and
2 - Callees are responsible for this adjustment anyway so the tailcall return value would have already been normalized

fixes #126457

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

Addresses a CoreCLR JIT debug assertion during tailcall validation when inlining introduces small-type-normalizing casts (e.g., bool normalization) between a tailcall and the return, which was triggering failures in tvos-arm64 Debug crossgen2/R2R scenarios (issue #126457).

Changes:

  • Update fgValidateIRForTailCall (DEBUG-only validation) to accept/skip normalizing GT_CAST nodes when tracing a tailcall’s return value to the final GT_RETURN.
  • Add a new JIT regression IL test (Runtime_126457) to exercise the inlinee+tailcall+separate-return-block pattern implicated in the crash.

Reviewed changes

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

File Description
src/coreclr/jit/morph.cpp Extends tailcall IR validation to tolerate small-type normalizing casts introduced by the inliner.
src/tests/JIT/Regression/JitBlue/Runtime_126457/Runtime_126457.ilproj Adds a new IL-based JIT regression test project configuration.
src/tests/JIT/Regression/JitBlue/Runtime_126457/Runtime_126457.il Adds IL repro that drives inlining + tailcall + return-flow shape relevant to the bug.

Comment thread src/coreclr/jit/morph.cpp Outdated
// (int -> ubyte -> int for bool-return-calls, for example)
// In the jit the callee is responsible for normalizing, so a tailcall
// can freely bypass this extra cast
assert(IsNormalizingCast(tree) &&
Copy link
Copy Markdown
Member

@jakobbotsch jakobbotsch Apr 17, 2026

Choose a reason for hiding this comment

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

This has to be the right type of normalizing cast -- e.g. if the inserted cast is zero-extending, then the call should also have a zero-extended return of the right size. I think you can just replace this with tree->AsCast()->CastToType() == m_tailcall->gtReturnType.

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.

Since we have fgCastNeeded you can also just use that here: fgCastNeeded(m_tailcall, tree->CastToType()))

Comment thread src/coreclr/jit/morph.cpp
{
if (node->OperIs(GT_CAST) && !m_compiler->fgCastNeeded(m_tailcall, node->AsCast()->CastToType()))
{
node = node->AsCast()->CastOp();
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.

Why move this here? It looks inconsistent with how the other cases are handled

Copy link
Copy Markdown
Contributor Author

@dhartglassMSFT dhartglassMSFT Apr 17, 2026

Choose a reason for hiding this comment

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

Are you talking about this cast stripping logic? We need this here because the GT_RETURN node calls into ValidateUse

or are you referring to the fgCastNeeded check? I can move that back into the assert, thats probably better

Copilot AI review requested due to automatic review settings April 17, 2026 20:45
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 3 out of 3 changed files in this pull request and generated 2 comments.

Comment on lines +1 to +8
.assembly extern System.Runtime
{
.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A)
}

.assembly Runtime_126457 { }
.module Runtime_126457.dll

Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

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

New IL source file is missing the standard .NET Foundation/MIT license header comment that most JIT regression .il sources include. Please add the license header at the top of this file to match repo conventions.

Copilot uses AI. Check for mistakes.
pop
ldc.i4.0
br.s DONE
CALL:
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

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

This regression is specifically about tailcall validation; to make the test deterministic across JIT configs, consider forcing the call to be a tailcall by adding the tail. IL prefix before the callvirt to ISite::tailcall() (many existing tailcall IL regressions do this). Without it, the JIT may decide not to tailcall-optimize and the test may not cover the intended scenario.

Suggested change
CALL:
CALL:
tail.

Copilot uses AI. Check for mistakes.
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.

tvos-arm64 Debug CoreCLR Helix work items fail due to crossgen2 R2R build crash

3 participants