Skip to content

JIT: Do not mark an async call no-return because its callee has no ret - #132222

Merged
jakobbotsch merged 2 commits into
dotnet:mainfrom
jakobbotsch:async-nothrow-fix
Aug 12, 2026
Merged

jakobbotsch merged 2 commits into
dotnet:mainfrom
jakobbotsch:async-nothrow-fix

Conversation

@jakobbotsch

Copy link
Copy Markdown
Member

fgFindJumpTargets marks the inlining call no-return when the callee's IL has no return blocks. For async calls, however, suspensions in the callee will still run suspension code in the caller.

Skip the no-return logic for async calls. This is a bit more conservative than necessary, but simplifies the reasoning for these no-return calls throughout the JIT.

fgFindJumpTargets marks the inlining call no-return when the callee's IL has no
return blocks. For async calls, however, suspensions in the callee will
still run suspension code in the caller.

Skip the no-return logic for async calls. This is a bit more
conservative than necessary, but simplifies the reasoning for these
no-return calls throughout the JIT.
Copilot AI lite review requested due to automatic review settings August 12, 2026 17:24
@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 Aug 12, 2026
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 5 pipeline(s).
11 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.

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 adjusts JIT inline-candidate scanning so that async call sites are not treated as “no-return” solely because the inlinee’s IL has no return blocks, avoiding incorrect no-return propagation into the caller’s async suspension/continuation code.

Changes:

  • Adds an IsAsync()-based guard to skip “no-return” handling for async call sites during fgFindJumpTargets inline observation.
  • Prevents marking the inlining call node as DOES_NOT_RETURN for async calls.

Comment thread src/coreclr/jit/fgbasic.cpp Resolved
Record the CALLEE_DOES_NOT_RETURN observation unconditionally (forced to
false for async call sites) so inline policies still see it, and use
compIsAsync() instead of dereferencing impInlineInfo, which can be null
during the AOT prejit inline-candidate scan.

Co-authored-by: Copilot <[email protected]>
Copilot-Session: 58aa07e4-1b5e-4b68-b502-bde0eb47a5b3
Copilot AI review requested due to automatic review settings August 12, 2026 18:26

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

Suppressed comments (1)

src/coreclr/jit/fgbasic.cpp:2426

  • The comment above doesNotReturn is now misleading: it claims that retBlocks == 0 means the callee does not return, but the new logic intentionally treats async calls as returning (doesNotReturn=false) even when retBlocks == 0. Consider updating the wording (and fix the existing grammar issue) so it reflects the new semantics.
        // If there are no return blocks we know it does not return, however if there
        // return blocks we don't know it returns as it may be counting unreachable code.
        // However we will still make the CALLEE_DOES_NOT_RETURN observation.

        // We never mark async calls as no-return, since suspensions do end up

@jakobbotsch

jakobbotsch commented Aug 12, 2026 •

Copy link
Copy Markdown
Member Author

cc @dotnet/jit-contrib PTAL @AndyAyersMS @EgorBo

With async inlining I found cases where we deleted suspension code after a call that we thought was no-return. No-return calls can still suspend and require the caller to run its own suspension code.

jakobbotsch added a commit to jakobbotsch/runtime that referenced this pull request Aug 12, 2026
fgFindJumpTargets makes inline observations both when inlining and when
compiling a prejit root. impInlineInfo is null in the latter case, so hoisting
the async check out from behind the isInlining guard faulted on every root
method crossgen2 compiled.

Ask compIsAsync() instead. That is a property of the method whose IL is being
scanned, so it is available in both cases and answers the same question: for an
inline it is the callee, whose call site is the async call in question.

Matches the fix in dotnet#132222.

Co-authored-by: Copilot <[email protected]>
Copilot-Session: 9ed3e552-b907-4815-9683-56a7fed2cdf3
@jakobbotsch

Copy link
Copy Markdown
Member Author

/ba-g Failures are #132030 and #131989

@jakobbotsch
jakobbotsch merged commit de224a4 into dotnet:main Aug 12, 2026
124 of 129 checks passed
@jakobbotsch
jakobbotsch deleted the async-nothrow-fix branch August 12, 2026 23:08
@dotnet-milestone-bot dotnet-milestone-bot Bot added this to the 11.0-rc1 milestone Aug 13, 2026
@github-actions github-actions Bot locked and limited conversation to collaborators Sep 14, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI runtime-async

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants