Skip to content

JIT: Intrinsify Task/ValueTask factory methods - #129810

Merged
jakobbotsch merged 2 commits into
dotnet:mainfrom
jakobbotsch:optimize-async-task-valuetask
Jun 26, 2026
Merged

JIT: Intrinsify Task/ValueTask factory methods#129810
jakobbotsch merged 2 commits into
dotnet:mainfrom
jakobbotsch:optimize-async-task-valuetask

Conversation

@jakobbotsch

Copy link
Copy Markdown
Member

Intrinsify and recognize the following methods when used directly in runtime async context:

  • Task.FromResult
  • Task.CompletedTask
  • ValueTask.FromResult
  • ValueTask.CompletedTask
  • new ValueTask()
  • ValueTask-typed default
  • new ValueTask<T>(T value)
Example

Before:

publicstaticasyncTaskMain(){awaitTaskCallee1();awaitTaskCallee2();awaitValueTaskCallee1();awaitValueTaskCallee2();awaitValueTaskCallee3();awaitValueTaskCallee4();awaitValueTaskCallee5();awaitValueTaskCallee6();}[MethodImpl(MethodImplOptions.NoInlining)]privatestaticTask<string>TaskCallee1(){returnTask.FromResult("abc");}[MethodImpl(MethodImplOptions.NoInlining)]privatestaticTaskTaskCallee2(){returnTask.CompletedTask;}[MethodImpl(MethodImplOptions.NoInlining)]privatestaticValueTaskValueTaskCallee1(){returnValueTask.CompletedTask;}[MethodImpl(MethodImplOptions.NoInlining)]privatestaticValueTaskValueTaskCallee2(){returndefault;}[MethodImpl(MethodImplOptions.NoInlining)]privatestaticValueTaskValueTaskCallee3(){returnnewValueTask();}[MethodImpl(MethodImplOptions.NoInlining)]privatestaticValueTask<string>ValueTaskCallee4(){returnValueTask.FromResult("abc");}[MethodImpl(MethodImplOptions.NoInlining)]privatestaticValueTask<string>ValueTaskCallee5(){returnnewValueTask<string>("abc");}[MethodImpl(MethodImplOptions.NoInlining)]privatestaticValueTask<Guid>ValueTaskCallee6(){returnnewValueTask<Guid>(Guid.NewGuid());}
; Assembly listing for method Program:TaskCallee1():System.String (FullOpts)G_M49327_IG01: ;; offset=0x0000pushrbxsubrsp,32 ;; size=5 bbWeight=1 PerfScore 1.25G_M49327_IG02: ;; offset=0x0005testrcx,rcxjne G_M49327_IG11movrcx,0x7FF9D8B84FF0 ; System.Threading.Tasks.Task`1[System.String]call CORINFO_HELP_NEWSFASTmovrbx,raxtest byte ptr [(reloc 0x7ff9d8b220e8)],1 ; global ptrje SHORT G_M49327_IG08 ;; size=36 bbWeight=1 PerfScore 5.75G_M49327_IG03: ;; offset=0x0029mov dword ptr [rbx+0x34],0x1000000movrcx,0x2A1BCEF3500 ; 'abc'mov gword ptr [rbx+0x38],rcxmovrcx,0x7FF9D8B66530 ; System.Threading.Tasks.Task:FromResult[System.String](System.String):System.Stringmovrcx, qword ptr [rcx+0x48]movrcx, qword ptr [rcx+0x10]testrcx,rcxje SHORT G_M49327_IG07 ;; size=44 bbWeight=1 PerfScore 7.75G_M49327_IG04: ;; offset=0x0055movr8,rbxxorrdx,rdxcall[System.Runtime.CompilerServices.AsyncHelpers:TransparentAwaitWithResult[System.__Canon](System.Threading.Tasks.Task`1[System.__Canon]):System.__Canon]testrcx,rcxjne SHORT G_M49327_IG09 ;; size=16 bbWeight=1 PerfScore 4.75G_M49327_IG05: ;; offset=0x0065xorecx,ecx ;; size=2 bbWeight=1 PerfScore 0.25G_M49327_IG06: ;; offset=0x0067addrsp,32poprbxret ;; size=6 bbWeight=1 PerfScore 1.75G_M49327_IG07: ;; offset=0x006Dmovrcx,0x7FF9D8B66530 ; System.Threading.Tasks.Task:FromResult[System.String](System.String):System.Stringmovrdx,0x7FF9D8B978D8 ; global ptrcall[CORINFO_HELP_RUNTIMEHANDLE_METHOD]movrcx,raxjmp SHORT G_M49327_IG04 ;; size=31 bbWeight=0.20 PerfScore 1.15G_M49327_IG08: ;; offset=0x008Cmovrcx,0x7FF9D8B21DA0 ; System.Threading.Tasks.Taskcall[CORINFO_HELP_GET_NONGCSTATIC_BASE]jmp SHORT G_M49327_IG03 ;; size=18 bbWeight=0 PerfScore 0.00G_M49327_IG09: ;; offset=0x009Emovrdx,0x7FF9D8B88EC0 ; Continuation_16_0_2call[CORINFO_HELP_ALLOC_CONTINUATION]movrbx,raxlearax,[reloc @RWD00]mov qword ptr [rbx+0x10],raxmov qword ptr [rbx+0x18],0x808call[System.Runtime.CompilerServices.AsyncHelpers:CaptureExecutionContext():System.Threading.ExecutionContext]movrdx,raxlearcx, bword ptr [rbx+0x20]call CORINFO_HELP_ASSIGN_REFmovrcx,rbxxoreax,eax ;; size=61 bbWeight=0 PerfScore 0.00G_M49327_IG10: ;; offset=0x00DBaddrsp,32poprbxret ;; size=6 bbWeight=0 PerfScore 0.00G_M49327_IG11: ;; offset=0x00E1movrax, gword ptr [rcx+0x28]xorrdx,rdxmov gword ptr [rcx+0x28],rdxjmp G_M49327_IG05 ;; size=15 bbWeight=0 PerfScore 0.00RWD00 dq	(dynamicClass):IL_STUB_AsyncResume_TaskCallee1_Optimized(System.Object,byref):System.Objectdq	G_M49327_IG09; Total bytes of code 240, prolog size 5, PerfScore 22.65, instruction count 53, allocated bytes for code 240 (MethodHash=c5e23f50) for method Program:TaskCallee1():System.String (FullOpts); ============================================================; Assembly listing for method Program:TaskCallee2() (FullOpts)G_M59144_IG01: ;; offset=0x0000pushrbxsubrsp,32 ;; size=5 bbWeight=1 PerfScore 1.25G_M59144_IG02: ;; offset=0x0005testrcx,rcxjne SHORT G_M59144_IG03movrdx,0x291A6000258 ; const ptrmovrdx, gword ptr [rdx]xorrcx,rcxcall[System.Runtime.CompilerServices.AsyncHelpers:TransparentAwaitWithResult(System.Threading.Tasks.Task)]testrcx,rcxjne SHORT G_M59144_IG05 ;; size=31 bbWeight=1 PerfScore 8.00G_M59144_IG03: ;; offset=0x0024xorecx,ecx ;; size=2 bbWeight=1 PerfScore 0.25G_M59144_IG04: ;; offset=0x0026addrsp,32poprbxret ;; size=6 bbWeight=1 PerfScore 1.75G_M59144_IG05: ;; offset=0x002Cmovrdx,0x7FF9D8BB2CD0 ; Continuation_8_0_1call[CORINFO_HELP_ALLOC_CONTINUATION]movrbx,raxlearax,[reloc @RWD00]mov qword ptr [rbx+0x10],raxmov qword ptr [rbx+0x18],8call[System.Runtime.CompilerServices.AsyncHelpers:CaptureExecutionContext():System.Threading.ExecutionContext]movrdx,raxlearcx, bword ptr [rbx+0x20]call CORINFO_HELP_ASSIGN_REFmovrcx,rbx ;; size=59 bbWeight=0 PerfScore 0.00G_M59144_IG06: ;; offset=0x0067addrsp,32poprbxret ;; size=6 bbWeight=0 PerfScore 0.00RWD00 dq	(dynamicClass):IL_STUB_AsyncResume_TaskCallee2_Optimized(System.Object,byref):System.Objectdq	G_M59144_IG05; Total bytes of code 109, prolog size 5, PerfScore 11.25, instruction count 28, allocated bytes for code 109 (MethodHash=f60418f7) for method Program:TaskCallee2() (FullOpts); ============================================================; Assembly listing for method Program:ValueTaskCallee1() (FullOpts)G_M60608_IG01: ;; offset=0x0000pushrbxsubrsp,48xoreax,eaxmov qword ptr [rsp+0x20],rax ;; size=12 bbWeight=1 PerfScore 2.50G_M60608_IG02: ;; offset=0x000Ctestrcx,rcxjne SHORT G_M60608_IG03xorrdx,rdxmov gword ptr [rsp+0x20],rdxmov word ptr [rsp+0x28],0mov byte ptr [rsp+0x2A],0leardx,[rsp+0x20]xorrcx,rcxcall[System.Runtime.CompilerServices.AsyncHelpers:TransparentAwaitWithResult(System.Threading.Tasks.ValueTask)]testrcx,rcxjne SHORT G_M60608_IG05 ;; size=42 bbWeight=1 PerfScore 9.50G_M60608_IG03: ;; offset=0x0036xorecx,ecx ;; size=2 bbWeight=1 PerfScore 0.25G_M60608_IG04: ;; offset=0x0038addrsp,48poprbxret ;; size=6 bbWeight=1 PerfScore 1.75G_M60608_IG05: ;; offset=0x003Emovrdx,0x7FF9D8BB2CD0 ; Continuation_8_0_1call[CORINFO_HELP_ALLOC_CONTINUATION]movrbx,raxlearax,[reloc @RWD00]mov qword ptr [rbx+0x10],raxmov qword ptr [rbx+0x18],8call[System.Runtime.CompilerServices.AsyncHelpers:CaptureExecutionContext():System.Threading.ExecutionContext]movrdx,raxlearcx, bword ptr [rbx+0x20]call CORINFO_HELP_ASSIGN_REFmovrcx,rbx ;; size=59 bbWeight=0 PerfScore 0.00G_M60608_IG06: ;; offset=0x0079addrsp,48poprbxret ;; size=6 bbWeight=0 PerfScore 0.00RWD00 dq	(dynamicClass):IL_STUB_AsyncResume_ValueTaskCallee1_Optimized(System.Object,byref):System.Objectdq	G_M60608_IG05; Total bytes of code 127, prolog size 12, PerfScore 14.00, instruction count 33, allocated bytes for code 127 (MethodHash=fdfd133f) for method Program:ValueTaskCallee1() (FullOpts); ============================================================; Assembly listing for method Program:ValueTaskCallee2() (FullOpts)G_M59587_IG01: ;; offset=0x0000subrsp,56xoreax,eaxmov qword ptr [rsp+0x28],raxmov qword ptr [rsp+0x30],rax ;; size=16 bbWeight=1 PerfScore 2.50G_M59587_IG02: ;; offset=0x0010xorrdx,rdxmov gword ptr [rsp+0x28],rdxmov word ptr [rsp+0x30],0mov byte ptr [rsp+0x32],0leardx,[rsp+0x28]xorrcx,rcxcall[System.Runtime.CompilerServices.AsyncHelpers:TransparentAwaitWithResult(System.Threading.Tasks.ValueTask)]testrcx,rcxjne SHORT G_M59587_IG04xorecx,ecx ;; size=39 bbWeight=1 PerfScore 8.50G_M59587_IG03: ;; offset=0x0037addrsp,56ret ;; size=5 bbWeight=1 PerfScore 1.25G_M59587_IG04: ;; offset=0x003Caddrsp,56ret ;; size=5 bbWeight=0 PerfScore 0.00; Total bytes of code 65, prolog size 16, PerfScore 12.25, instruction count 18, allocated bytes for code 65 (MethodHash=fdfd173c) for method Program:ValueTaskCallee2() (FullOpts); ============================================================; Assembly listing for method Program:ValueTaskCallee3() (FullOpts)G_M62786_IG01: ;; offset=0x0000subrsp,56xoreax,eaxmov qword ptr [rsp+0x28],raxmov qword ptr [rsp+0x30],rax ;; size=16 bbWeight=1 PerfScore 2.50G_M62786_IG02: ;; offset=0x0010xorrdx,rdxmov gword ptr [rsp+0x28],rdxmov word ptr [rsp+0x30],0mov byte ptr [rsp+0x32],0leardx,[rsp+0x28]xorrcx,rcxcall[System.Runtime.CompilerServices.AsyncHelpers:TransparentAwaitWithResult(System.Threading.Tasks.ValueTask)]testrcx,rcxjne SHORT G_M62786_IG04xorecx,ecx ;; size=39 bbWeight=1 PerfScore 8.50G_M62786_IG03: ;; offset=0x0037addrsp,56ret ;; size=5 bbWeight=1 PerfScore 1.25G_M62786_IG04: ;; offset=0x003Caddrsp,56ret ;; size=5 bbWeight=0 PerfScore 0.00; Total bytes of code 65, prolog size 16, PerfScore 12.25, instruction count 18, allocated bytes for code 65 (MethodHash=fdfd0abd) for method Program:ValueTaskCallee3() (FullOpts); ============================================================; Assembly listing for method Program:ValueTaskCallee4():System.String (FullOpts)G_M17761_IG01: ;; offset=0x0000pushrbxsubrsp,64 vxorps xmm4,xmm4,xmm4 vmovdqu xmmword ptr [rsp+0x28],xmm4xoreax,eaxmov qword ptr [rsp+0x38],rax ;; size=22 bbWeight=1 PerfScore 3.83G_M17761_IG02: ;; offset=0x0016testrcx,rcxjne G_M17761_IG09movrcx,0x7FF9D8BB50C8 ; System.Threading.Tasks.ValueTask:FromResult[System.String](System.String):System.Stringmovrcx, qword ptr [rcx+0x48]movrcx, qword ptr [rcx+0x10]testrcx,rcxje SHORT G_M17761_IG06 ;; size=32 bbWeight=1 PerfScore 6.75G_M17761_IG03: ;; offset=0x0036xorr8,r8mov gword ptr [rsp+0x28],r8movr8,0x2A1BCEF3500 ; 'abc'mov gword ptr [rsp+0x30],r8mov word ptr [rsp+0x38],0mov byte ptr [rsp+0x3A],1lear8,[rsp+0x28]xorrdx,rdxcall[System.Runtime.CompilerServices.AsyncHelpers:TransparentAwaitWithResult[System.__Canon](System.Threading.Tasks.ValueTask`1[System.__Canon]):System.__Canon]testrcx,rcxjne SHORT G_M17761_IG07 ;; size=53 bbWeight=1 PerfScore 9.50G_M17761_IG04: ;; offset=0x006Bxorecx,ecx ;; size=2 bbWeight=1 PerfScore 0.25G_M17761_IG05: ;; offset=0x006Daddrsp,64poprbxret ;; size=6 bbWeight=1 PerfScore 1.75G_M17761_IG06: ;; offset=0x0073movrcx,0x7FF9D8BB50C8 ; System.Threading.Tasks.ValueTask:FromResult[System.String](System.String):System.Stringmovrdx,0x7FF9D8BC17D0 ; global ptrcall CORINFO_HELP_RUNTIMEHANDLE_METHODmovrcx,raxjmp SHORT G_M17761_IG03 ;; size=30 bbWeight=0.20 PerfScore 0.75G_M17761_IG07: ;; offset=0x0091movrdx,0x7FF9D8B88EC0 ; Continuation_16_0_2call[CORINFO_HELP_ALLOC_CONTINUATION]movrbx,raxlearax,[reloc @RWD00]mov qword ptr [rbx+0x10],raxmov qword ptr [rbx+0x18],0x808call[System.Runtime.CompilerServices.AsyncHelpers:CaptureExecutionContext():System.Threading.ExecutionContext]movrdx,raxlearcx, bword ptr [rbx+0x20]call CORINFO_HELP_ASSIGN_REFmovrcx,rbxxoreax,eax ;; size=61 bbWeight=0 PerfScore 0.00G_M17761_IG08: ;; offset=0x00CEaddrsp,64poprbxret ;; size=6 bbWeight=0 PerfScore 0.00G_M17761_IG09: ;; offset=0x00D4movrax, gword ptr [rcx+0x28]xorrdx,rdxmov gword ptr [rcx+0x28],rdxjmp SHORT G_M17761_IG04 ;; size=12 bbWeight=0 PerfScore 0.00RWD00 dq	(dynamicClass):IL_STUB_AsyncResume_ValueTaskCallee4_Optimized(System.Object,byref):System.Objectdq	G_M17761_IG07; Total bytes of code 224, prolog size 22, PerfScore 22.83, instruction count 52, allocated bytes for code 224 (MethodHash=85dfba9e) for method Program:ValueTaskCallee4():System.String (FullOpts); ============================================================; Assembly listing for method Program:ValueTaskCallee5():System.String (FullOpts)G_M17504_IG01: ;; offset=0x0000subrsp,56 vxorps xmm4,xmm4,xmm4 vmovdqa xmmword ptr [rsp+0x20],xmm4xoreax,eaxmov qword ptr [rsp+0x30],rax ;; size=21 bbWeight=1 PerfScore 2.83G_M17504_IG02: ;; offset=0x0015xorr8,r8mov gword ptr [rsp+0x20],r8movr8,0x2A1BCEF3500 ; 'abc'mov gword ptr [rsp+0x28],r8mov word ptr [rsp+0x30],0mov byte ptr [rsp+0x32],1lear8,[rsp+0x20]movrcx,0x7FF9D8BB8000 ; System.Runtime.CompilerServices.AsyncHelpers:TransparentAwaitWithResult[System.String](System.Threading.Tasks.ValueTask`1[System.String]):System.Stringxorrdx,rdxcall[System.Runtime.CompilerServices.AsyncHelpers:TransparentAwaitWithResult[System.__Canon](System.Threading.Tasks.ValueTask`1[System.__Canon]):System.__Canon]testrcx,rcxjne SHORT G_M17504_IG04xorecx,ecx ;; size=65 bbWeight=1 PerfScore 10.00G_M17504_IG03: ;; offset=0x0056addrsp,56ret ;; size=5 bbWeight=1 PerfScore 1.25G_M17504_IG04: ;; offset=0x005Bxoreax,eax ;; size=2 bbWeight=0 PerfScore 0.00G_M17504_IG05: ;; offset=0x005Daddrsp,56ret ;; size=5 bbWeight=0 PerfScore 0.00; Total bytes of code 98, prolog size 21, PerfScore 14.08, instruction count 23, allocated bytes for code 98 (MethodHash=0100bb9f) for method Program:ValueTaskCallee5():System.String (FullOpts); ============================================================; Assembly listing for method Program:ValueTaskCallee6():System.Guid (FullOpts)G_M18761_IG01: ;; offset=0x0000pushrbppushr15pushr14pushr13pushr12pushrdipushrsipushrbxsubrsp,152vzeroupperlearbp,[rsp+0xD0]xoreax,eaxmov qword ptr [rbp-0x58],rax vxorps xmm4,xmm4,xmm4 vmovdqa xmmword ptr [rbp-0x50],xmm4mov qword ptr [rbp-0x40],raxmovrbx,rcx ;; size=52 bbWeight=1 PerfScore 13.58G_M18761_IG02: ;; offset=0x0034learcx,[rbp-0xB0]call CORINFO_HELP_INIT_PINVOKE_FRAMEmovrsi,raxmovrcx,rspmov qword ptr [rbp-0x98],rcxmovrcx,rbpmov qword ptr [rbp-0x88],rcxlearcx,[rbp-0x78]movrax,0x7FF9D8BBD8D8 ; function addressmov qword ptr [rbp-0xA0],raxlearax, G_M18761_IG04mov qword ptr [rbp-0x90],raxlearax,[rbp-0xB0]mov qword ptr [rsi+0x08],raxmov byte ptr [rsi+0x04],0 ;; size=85 bbWeight=1 PerfScore 10.50G_M18761_IG03: ;; offset=0x0089call[Interop+Ole32:CoCreateGuid(ptr):int] ;; size=6 bbWeight=1 PerfScore 3.00G_M18761_IG04: ;; offset=0x008Fmov byte ptr [rsi+0x04],1cmp dword ptr [(reloc 0x7ffa384dce38)],0je SHORT G_M18761_IG05call[CORINFO_HELP_STOP_FOR_GC] ;; size=19 bbWeight=1 PerfScore 7.00G_M18761_IG05: ;; offset=0x00A2movrcx, qword ptr [rbp-0xA8]mov qword ptr [rsi+0x08],rcxtesteax,eaxjne SHORT G_M18761_IG07vmovupsxmm0, xmmword ptr [rbp-0x78]vmovups xmmword ptr [rbp-0x4C],xmm0xorrcx,rcxmov gword ptr [rbp-0x58],rcxmov byte ptr [rbp-0x4E],1mov word ptr [rbp-0x50],0learcx,[rbp-0x68]lear8,[rbp-0x58]xorrdx,rdxcall[System.Runtime.CompilerServices.AsyncHelpers:TransparentAwaitWithResult[System.Guid](System.Threading.Tasks.ValueTask`1[System.Guid]):System.Guid]testrcx,rcxjne SHORT G_M18761_IG08vmovupsxmm0, xmmword ptr [rbp-0x68]vmovups xmmword ptr [rbx],xmm0movrax,rbxxorecx,ecx ;; size=76 bbWeight=1 PerfScore 16.50G_M18761_IG06: ;; offset=0x00EEaddrsp,152poprbxpoprsipoprdipopr12popr13popr14popr15poprbpret ;; size=20 bbWeight=1 PerfScore 5.25G_M18761_IG07: ;; offset=0x0102movecx,eaxcall[System.Guid:ThrowForHr(int)]int3 ;; size=9 bbWeight=0 PerfScore 0.00G_M18761_IG08: ;; offset=0x010Baddrsp,152poprbxpoprsipoprdipopr12popr13popr14popr15poprbpret ;; size=20 bbWeight=0 PerfScore 0.00; Total bytes of code 287, prolog size 49, PerfScore 55.83, instruction count 80, allocated bytes for code 287 (MethodHash=8d4cb6b6) for method Program:ValueTaskCallee6():System.Guid (FullOpts); ============================================================

After:

; Assembly listing for method Program:TaskCallee1():System.String (FullOpts)G_M49327_IG01: ;; offset=0x0000 ;; size=0 bbWeight=1 PerfScore 0.00G_M49327_IG02: ;; offset=0x0000movrax,0x2E8B7A73500 ; 'abc'xorecx,ecx ;; size=12 bbWeight=1 PerfScore 0.50G_M49327_IG03: ;; offset=0x000Cret ;; size=1 bbWeight=1 PerfScore 1.00; Total bytes of code 13, prolog size 0, PerfScore 1.50, instruction count 3, allocated bytes for code 13 (MethodHash=c5e23f50) for method Program:TaskCallee1():System.String (FullOpts); ============================================================; Assembly listing for method Program:TaskCallee2() (FullOpts)G_M59144_IG01: ;; offset=0x0000 ;; size=0 bbWeight=1 PerfScore 0.00G_M59144_IG02: ;; offset=0x0000xorecx,ecx ;; size=2 bbWeight=1 PerfScore 0.25G_M59144_IG03: ;; offset=0x0002ret ;; size=1 bbWeight=1 PerfScore 1.00; Total bytes of code 3, prolog size 0, PerfScore 1.25, instruction count 2, allocated bytes for code 3 (MethodHash=f60418f7) for method Program:TaskCallee2() (FullOpts); ============================================================; Assembly listing for method Program:ValueTaskCallee1() (FullOpts)G_M60608_IG01: ;; offset=0x0000 ;; size=0 bbWeight=1 PerfScore 0.00G_M60608_IG02: ;; offset=0x0000xorecx,ecx ;; size=2 bbWeight=1 PerfScore 0.25G_M60608_IG03: ;; offset=0x0002ret ;; size=1 bbWeight=1 PerfScore 1.00; Total bytes of code 3, prolog size 0, PerfScore 1.25, instruction count 2, allocated bytes for code 3 (MethodHash=fdfd133f) for method Program:ValueTaskCallee1() (FullOpts); ============================================================; Assembly listing for method Program:ValueTaskCallee2() (FullOpts)G_M59587_IG01: ;; offset=0x0000 ;; size=0 bbWeight=1 PerfScore 0.00G_M59587_IG02: ;; offset=0x0000xorecx,ecx ;; size=2 bbWeight=1 PerfScore 0.25G_M59587_IG03: ;; offset=0x0002ret ;; size=1 bbWeight=1 PerfScore 1.00; Total bytes of code 3, prolog size 0, PerfScore 1.25, instruction count 2, allocated bytes for code 3 (MethodHash=fdfd173c) for method Program:ValueTaskCallee2() (FullOpts); ============================================================; Assembly listing for method Program:ValueTaskCallee3() (FullOpts)G_M62786_IG01: ;; offset=0x0000 ;; size=0 bbWeight=1 PerfScore 0.00G_M62786_IG02: ;; offset=0x0000xorecx,ecx ;; size=2 bbWeight=1 PerfScore 0.25G_M62786_IG03: ;; offset=0x0002ret ;; size=1 bbWeight=1 PerfScore 1.00; Total bytes of code 3, prolog size 0, PerfScore 1.25, instruction count 2, allocated bytes for code 3 (MethodHash=fdfd0abd) for method Program:ValueTaskCallee3() (FullOpts); ============================================================; Assembly listing for method Program:ValueTaskCallee4():System.String (FullOpts)G_M17761_IG01: ;; offset=0x0000 ;; size=0 bbWeight=1 PerfScore 0.00G_M17761_IG02: ;; offset=0x0000movrax,0x2E8B7A73500 ; 'abc'xorecx,ecx ;; size=12 bbWeight=1 PerfScore 0.50G_M17761_IG03: ;; offset=0x000Cret ;; size=1 bbWeight=1 PerfScore 1.00; Total bytes of code 13, prolog size 0, PerfScore 1.50, instruction count 3, allocated bytes for code 13 (MethodHash=85dfba9e) for method Program:ValueTaskCallee4():System.String (FullOpts); ============================================================; Assembly listing for method Program:ValueTaskCallee5():System.String (FullOpts)G_M17504_IG01: ;; offset=0x0000 ;; size=0 bbWeight=1 PerfScore 0.00G_M17504_IG02: ;; offset=0x0000movrax,0x2E8B7A73500 ; 'abc'xorecx,ecx ;; size=12 bbWeight=1 PerfScore 0.50G_M17504_IG03: ;; offset=0x000Cret ;; size=1 bbWeight=1 PerfScore 1.00; Total bytes of code 13, prolog size 0, PerfScore 1.50, instruction count 3, allocated bytes for code 13 (MethodHash=0100bb9f) for method Program:ValueTaskCallee5():System.String (FullOpts); ============================================================; Assembly listing for method Program:ValueTaskCallee6():System.Guid (FullOpts)G_M18761_IG01: ;; offset=0x0000pushrbppushr15pushr14pushr13pushr12pushrdipushrsipushrbxsubrsp,104vzeroupperlearbp,[rsp+0xA0]movrbx,rcx ;; size=30 bbWeight=1 PerfScore 10.00G_M18761_IG02: ;; offset=0x001Elearcx,[rbp-0x80]call CORINFO_HELP_INIT_PINVOKE_FRAMEmovrsi,raxmovrcx,rspmov qword ptr [rbp-0x68],rcxmovrcx,rbpmov qword ptr [rbp-0x58],rcxlearcx,[rbp-0x48]movrax,0x7FF9D8B7A8D8 ; function addressmov qword ptr [rbp-0x70],raxlearax, G_M18761_IG04mov qword ptr [rbp-0x60],raxlearax,[rbp-0x80]mov qword ptr [rsi+0x08],raxmov byte ptr [rsi+0x04],0 ;; size=67 bbWeight=1 PerfScore 10.50G_M18761_IG03: ;; offset=0x0061call[Interop+Ole32:CoCreateGuid(ptr):int] ;; size=6 bbWeight=1 PerfScore 3.00G_M18761_IG04: ;; offset=0x0067mov byte ptr [rsi+0x04],1cmp dword ptr [(reloc 0x7ffa384dcdb8)],0je SHORT G_M18761_IG05call[CORINFO_HELP_STOP_FOR_GC] ;; size=19 bbWeight=1 PerfScore 7.00G_M18761_IG05: ;; offset=0x007Amovrcx, qword ptr [rbp-0x78]mov qword ptr [rsi+0x08],rcxmovecx,eaxtestecx,ecxjne SHORT G_M18761_IG07vmovupsxmm0, xmmword ptr [rbp-0x48]vmovups xmmword ptr [rbx],xmm0movrax,rbxxorecx,ecx ;; size=28 bbWeight=1 PerfScore 6.00G_M18761_IG06: ;; offset=0x0096addrsp,104poprbxpoprsipoprdipopr12popr13popr14popr15poprbpret ;; size=17 bbWeight=1 PerfScore 5.25G_M18761_IG07: ;; offset=0x00A7call[System.Guid:ThrowForHr(int)]int3 ;; size=7 bbWeight=0 PerfScore 0.00; Total bytes of code 174, prolog size 27, PerfScore 41.75, instruction count 53, allocated bytes for code 174 (MethodHash=8d4cb6b6) for method Program:ValueTaskCallee6():System.Guid (FullOpts); ============================================================

Intrinsify and recognize the following methods when used directly in
runtime async variants:
- `Task.FromResult`
- `Task.CompletedTask`
- `ValueTask.FromResult`
- `ValueTask.CompletedTask`
- `new ValueTask()`
- `ValueTask`-typed `default`
- `new ValueTask<T>(T value)`
CopilotAI review requested due to automatic review settings June 24, 2026 17:37
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Jun 24, 2026
@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.

CopilotAI 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 extends the CoreCLR JIT’s “runtime async” optimization pipeline by marking common Task/ValueTask factory helpers as intrinsics and teaching the importer to fold/avoid AsyncHelpers.TransparentAwaitWithResult in more cases, reducing call/alloc overhead in optimized async-return paths.

Changes:

  • Mark Task.CompletedTask, Task.FromResult, ValueTask.CompletedTask, ValueTask.FromResult, and ValueTask<TResult>(TResult) with [Intrinsic] to enable JIT recognition.
  • Add new JIT NamedIntrinsic IDs plus importer expansion logic for async-callconv FromResult / CompletedTask, and add a new impFoldAwaitedTopOfStack fast-path for certain ValueTask return patterns.
  • Improve debug local naming by labeling ASYNC_CONTINUATION_ILNUM locals as AsyncCont.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 6 comments.

Show a summary per file
FileDescription
src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/ValueTask.csAdds [Intrinsic] to ValueTask.CompletedTask, ValueTask.FromResult, and ValueTask<TResult>(TResult) ctor to enable JIT recognition.
src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Task.csAdds [Intrinsic] to Task.CompletedTask getter and Task.FromResult to enable async-callconv intrinsic expansion.
src/coreclr/jit/namedintrinsiclist.hIntroduces new NamedIntrinsic entries for Task/ValueTask factory methods used by the importer.
src/coreclr/jit/importercalls.cppImplements async-callconv intrinsic expansion/folding for FromResult/CompletedTask, and extends intrinsic lookup for Task/ValueTask methods.
src/coreclr/jit/importer.cppRefactors return/await wrapping logic and adds impFoldAwaitedTopOfStack to avoid unnecessary TransparentAwaitWithResult calls.
src/coreclr/jit/gentree.cppImproves local name printing by labeling async continuation locals as AsyncCont.
src/coreclr/jit/compiler.hAdds the impFoldAwaitedTopOfStack declaration.

Comment threadsrc/coreclr/jit/importer.cpp
Comment threadsrc/coreclr/jit/importer.cpp Outdated
Comment threadsrc/coreclr/jit/importer.cpp Outdated
Comment threadsrc/coreclr/jit/importer.cpp
Comment threadsrc/coreclr/jit/importercalls.cpp
Comment threadsrc/coreclr/jit/importercalls.cpp
@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

cc @dotnet/jit-contrib PTAL @EgorBo

@jakobbotsch
jakobbotsch requested a review from EgorBoJune 25, 2026 19:44

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

@jakobbotsch
jakobbotsch merged commit 6066f76 into dotnet:mainJun 26, 2026
174 of 176 checks passed
@jakobbotsch
jakobbotsch deleted the optimize-async-task-valuetask branch June 26, 2026 07:28
@dotnet-milestone-botdotnet-milestone-botBot added this to the 11.0-preview7 milestone Jun 28, 2026
eiriktsarpalis pushed a commit that referenced this pull request Jul 15, 2026
Intrinsify and recognize the following methods when used directly in
runtime async context:
- `Task.FromResult`
- `Task.CompletedTask`
- `ValueTask.FromResult`
- `ValueTask.CompletedTask`
- `new ValueTask()`
- `ValueTask`-typed `default`
- `new ValueTask<T>(T value)`
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 29, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR 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.

3 participants

@jakobbotsch@EgorBo