JIT: Use a "resumed?" indicator variable in runtime async instead of lvaAsyncContinuationArg != nullptr#128152
JIT: Use a "resumed?" indicator variable in runtime async instead of lvaAsyncContinuationArg != nullptr#128152jakobbotsch wants to merge 4 commits into
lvaAsyncContinuationArg != nullptr#128152Conversation
We will need this to enable inlining.
|
cc @AndyAyersMS, this is the PR with the indicator variables we discussed |
|
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch |
There was a problem hiding this comment.
Pull request overview
Replaces the implicit "have we resumed?" check (lvaAsyncContinuationArg != nullptr) with an explicit boolean indicator local (lvaResumedIndicator). The root motivation is to enable async inlining, where the existing check is not valid for inlinees. Two new pseudo-args (AsyncResumedUse / AsyncResumedDef) are threaded through every async call so each callsite can read the indicator and the resumption path can write 1 back into it; the JIT machinery (lcl morph, address-of escape analysis, fgInline, local def visitors, diagnostic checks) is updated to recognize the new defined-via-address local.
Changes:
- Introduce
lvaResumedIndicator(TYP_UBYTE) and initialize it in the prolog / OSR entry / loops, replacing the inline-special-casedcontinuation != nullrecipe at all uses. - Add
WellKnownArg::AsyncResumedUse/AsyncResumedDefplusgtCallGetDefinedAsyncResumedLclAddr, and propagate them through arg setup, IR sequencing, escape analysis, local-def visiting, and diagnostic checks. - In
AsyncTransformation, store1to the indicator on the resumption path, add common-def head-merging into the resumption switch, and add a shared "resumed" temp for shared finish-context handling.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/coreclr/jit/async.h | Declares new shared resumed var, helper signatures, and updated parameter lists for finish-context BB construction. |
| src/coreclr/jit/async.cpp | Core change: introduces indicator local, initializes it, threads new well-known args through calls, writes 1 on resumption, and implements common-def head merging. |
| src/coreclr/jit/compiler.h / compiler.cpp | Adds lvaResumedIndicator field and includes it in the OSR-local sanity check. |
| src/coreclr/jit/compiler.hpp | Extends VisitLocalDefs / VisitLocalDefNodes to also visit the async-resumed def on calls. |
| src/coreclr/jit/gentree.h / gentree.cpp | Adds the two new WellKnownArg values, their names, and gtCallGetDefinedAsyncResumedLclAddr. |
| src/coreclr/jit/morph.cpp | Wires the new well-known arg names into getWellKnownArgName. |
| src/coreclr/jit/importer.cpp / fginline.cpp | Skips the new pseudo-args in inline arg-info construction and prepend-statements. |
| src/coreclr/jit/lclmorph.cpp | Generalizes the callsite address-escape logic to recognize the resumed def (size 1) alongside retbuf, and sequences the def address. |
| src/coreclr/jit/lclvars.cpp | Minor cleanup: uses INDEBUG(...) macro for SetDefinedViaAddress. |
| src/coreclr/jit/fgdiagnostic.cpp | Extends linked-locals debug check to also push/expect the async-resumed def. |
We will need this to enable inlining, since
lvaAsyncContinuationArg != nullptris not a correct way to compute this value for inlinees.Diffs are pretty mixed and not generally improvements since we have to generate stores to this local now. One possibility is that we use
lvaAsyncContinuationArg != nullfor the root function and only use indicator locals in inlinees instead. This would also make things simpler for OSR.