Repository navigation
JIT: Do not mark an async call no-return because its callee has no ret - #132222
Conversation
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.
|
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. |
|
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch |
There was a problem hiding this comment.
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 duringfgFindJumpTargetsinline observation. - Prevents marking the inlining call node as
DOES_NOT_RETURNfor async calls.
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
There was a problem hiding this comment.
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
doesNotReturnis now misleading: it claims thatretBlocks == 0means the callee does not return, but the new logic intentionally treats async calls as returning (doesNotReturn=false) even whenretBlocks == 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
|
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. |
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
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.