Skip to content

Comments

JIT: Add a "default value analysis" for async hoisting#124514

Merged
jakobbotsch merged 23 commits intodotnet:mainfrom
jakobbotsch:fix-124512
Feb 21, 2026
Merged

JIT: Add a "default value analysis" for async hoisting#124514
jakobbotsch merged 23 commits intodotnet:mainfrom
jakobbotsch:fix-124512

Conversation

@jakobbotsch
Copy link
Member

@jakobbotsch jakobbotsch commented Feb 17, 2026

This analysis computes the set of locals that still have their default value and uses it to skip hoisting these locals into continuations around async suspension points.

Fix #124512

Example from #124512:

using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;

public class Program
{
    public static async Task Main()
    {
        await FooAsync();
    }

    private static async Task FooAsync()
    {
        await Task.Yield();
        Inline();
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    private static void Inline()
    {
        S s = new S();
        Console.WriteLine(s.A);
    }

    private struct S
    {
        public long A, B, C, D, E;
        public object F;

        [MethodImpl(MethodImplOptions.NoInlining)]
        public S()
        {
            A = B = C = D = E = 10;
            F = null;
        }
    }
}
...
@@ -137,15 +130,10 @@ G_M000_IG19:
        mov      rdx, 0xD1FFAB1E
        call     [CORINFO_HELP_ALLOC_CONTINUATION]
        mov      rbx, rax
-       lea      rcx, [reloc @RWD00]
-       mov      qword ptr [rbx+0x10], rcx
-       xor      ecx, ecx
-       mov      qword ptr [rbx+0x18], rcx
-       lea      rdi, bword ptr [rbx+0x28]
-       lea      rsi, bword ptr [rbp-0x58]
-       call     CORINFO_HELP_ASSIGN_BYREF
-       mov      ecx, 5
-       rep movsq 
+       lea      rax, [reloc @RWD00]
+       mov      qword ptr [rbx+0x10], rax
+       xor      eax, eax
+       mov      qword ptr [rbx+0x18], rax
        call     [System.Runtime.CompilerServices.AsyncHelpers:CaptureExecutionContext():System.Threading.ExecutionContext]
        lea      rcx, bword ptr [rbx+0x20]
        mov      rdx, rax
@@ -153,55 +141,43 @@ G_M000_IG19:
        cmp      gword ptr [rbp+0x10], 0
        setne    cl
        movzx    rcx, cl
-       mov      rdx, gword ptr [rbp-0x20]
-       mov      r8, gword ptr [rbp-0x28]
+       mov      rdx, gword ptr [rbp-0x18]
+       mov      r8, gword ptr [rbp-0x20]
        call     [System.Runtime.CompilerServices.AsyncHelpers:RestoreContextsOnSuspension(bool,System.Threading.ExecutionContext,System.Threading.SynchronizationContext)]
        mov      rcx, rbx
  
 G_M000_IG20:
-       vzeroupper 
-       add      rsp, 104
+       add      rsp, 96
        pop      rbx
        pop      rsi
-       pop      rdi
        pop      rbp
        ret      
  
 G_M000_IG21:
-       mov      rdx, gword ptr [rbp+0x10]
-       mov      rcx, gword ptr [rdx+0x20]
+       mov      rcx, gword ptr [rbp+0x10]
+       mov      rcx, gword ptr [rcx+0x20]
        call     [System.Runtime.CompilerServices.AsyncHelpers:RestoreExecutionContext(System.Threading.ExecutionContext)]
- 
-G_M000_IG22:
-       mov      rdx, gword ptr [rbp+0x10]
-       vmovdqu  ymm0, ymmword ptr [rdx+0x28]
-       vmovdqu  ymmword ptr [rbp-0x58], ymm0
-       vmovdqu  xmm0, xmmword ptr [rdx+0x48]
-       vmovdqu  xmmword ptr [rbp-0x38], xmm0
- 
-G_M000_IG23:
        jmp      G_M000_IG05
  
-G_M000_IG24:
+G_M000_IG22:
        sub      rsp, 40
  
-G_M000_IG25:
+G_M000_IG23:
        cmp      gword ptr [rbp+0x10], 0
        setne    cl
        movzx    rcx, cl
-       mov      rdx, gword ptr [rbp-0x20]
-       mov      r8, gword ptr [rbp-0x28]
+       mov      rdx, gword ptr [rbp-0x18]
+       mov      r8, gword ptr [rbp-0x20]
        call     [System.Runtime.CompilerServices.AsyncHelpers:RestoreContexts(bool,System.Threading.ExecutionContext,System.Threading.SynchronizationContext)]
        nop      
  
-G_M000_IG26:
-       vzeroupper 
+G_M000_IG24:
        add      rsp, 40
        ret      
  
 RWD00  	dq	(dynamicClass):IL_STUB_AsyncResume(System.Object,byref):System.Object
 	dq	G_M000_IG19
 
-; Total bytes of code 544
+; Total bytes of code 471

Copilot AI review requested due to automatic review settings February 17, 2026 14:31
@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 Feb 17, 2026
@dotnet-policy-service
Copy link
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

Copy link
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

This PR adds a new "default value analysis" for async hoisting to address issue #124512, where the JIT incorrectly hoists default-valued locals at async suspension points. The issue occurs when the JIT suppresses explicit zeroing of locals (expecting them to be zeroed by the prolog), but then hoists these uninitialized locals into async continuations when their address is taken.

Changes:

  • Introduces a two-phase DefaultValueAnalysis class that tracks which locals retain their default (zero) values through program execution
  • Integrates this analysis with the existing AsyncLiveness class to skip hoisting locals that are live but still have default values at suspension points
  • Handles promoted struct fields correctly by checking if all fields have default values

Copilot AI review requested due to automatic review settings February 18, 2026 15:25
Copy link
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.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copy link
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 2 out of 2 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

src/coreclr/jit/async.cpp:597

  • There's an extra line separator here (line 597). Following the pattern seen elsewhere in the file, function header comments should start with a single line separator, not a double one.
//------------------------------------------------------------------------

Copilot AI review requested due to automatic review settings February 19, 2026 14:03
Copy link
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 2 out of 2 changed files in this pull request and generated 4 comments.

Copilot AI review requested due to automatic review settings February 19, 2026 14:22
Copy link
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 2 out of 2 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

src/coreclr/jit/async.cpp:583

  • There are duplicate comment separator lines (------------------------------------------------------------------------). The second separator on line 583 should be removed as it's redundant.
//------------------------------------------------------------------------
//------------------------------------------------------------------------

@jakobbotsch
Copy link
Member Author

cc @dotnet/jit-contrib PTAL @AndyAyersMS

Diffs. Throughput wise pretty much a wash.

The analysis here was written almost completely autonomously by Copilot with Opus 4.6. I made a few changes:

  • I added handling for promoted locals
  • The bit vector handling was pretty wasteful, so I optimized it a bit
  • I added correct handling for locals not initialized in prolog

Still, I was quite impressed by the result.

Copy link
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 2 out of 2 changed files in this pull request and generated 2 comments.

@jakobbotsch
Copy link
Member Author

/azp run runtime-nativeaot-outerloop

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

Copy link
Member

@AndyAyersMS AndyAyersMS left a comment

Choose a reason for hiding this comment

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

Just a comment nit you can fix later.

@jakobbotsch
Copy link
Member Author

/ba-g Failure looks similar to #124370 and not related to async

@jakobbotsch jakobbotsch merged commit c5d5be4 into dotnet:main Feb 21, 2026
148 of 154 checks passed
@jakobbotsch jakobbotsch deleted the fix-124512 branch February 21, 2026 14:00
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: Investigate interaction between suppressions of explicit inits and async hoisting

2 participants