-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Description
Currently Rosyln zeros the the AsyncMethodBuilder field with .locals init and then assigns the result of .Create to that field.
When .Create is inlined it is also zeros; so the assignment is a second set of zeroing.
The Jit has an optimization where it will remove the second set of zeroing dotnet/runtime#36918 ("Optimization to remove redundant zero initializations"); however this only kicks in if there aren't any preceding non-zero assignments.
e.g.
using System.IO.Pipelines;
public async ValueTask<ReadResult> OuterMethod(object o)
{
return await InnerMethod(o);
static async ValueTask<ReadResult> InnerMethod(object o)
{
return default;
}
}G_M51821_IG01:
push rsi
sub rsp, 144
vzeroupper ; zero
xor rax, rax ; |
mov qword ptr [rsp+28H], rax ; |
vxorps xmm4, xmm4 ; |
mov rax, -96 ; |
vmovdqa xmmword ptr [rsp+rax+90H], xmm4 ; |
vmovdqa xmmword ptr [rsp+rax+A0H], xmm4 ; |
vmovdqa xmmword ptr [rsp+rax+B0H], xmm4 ; |
add rax, 48 ; |
jne SHORT -5 instr ; V
mov rsi, rdx
;; bbWeight=1 PerfScore 8.58
G_M51821_IG02:
mov gword ptr [rsp+28H], r8 ; save param ** blocks redundant zero elimination **
xor ecx, ecx ; re-zero
vxorps xmm0, xmm0 ; |
vmovdqu xmmword ptr [rsp+38H], xmm0 ; |
vmovdqu xmmword ptr [rsp+48H], xmm0 ; |
mov qword ptr [rsp+58H], rcx ; V
mov dword ptr [rsp+30H], -1
lea rcx, [rsp+28H]
call System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start(byref)
lea rcx, bword ptr [rsp+38H]
mov rdx, rsi
call System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder`1[ReadResult][System.IO.Pipelines.ReadResult]:get_Task():System.Threading.Tasks.ValueTask`1[ReadResult]:this
mov rax, rsiIf the call to .Create() was moved to the first step; prior to saving parameters to the fields so it should not block the redundant zero elimination optimization.
From dotnet/runtime#2325 (comment)
Regarding your second example where we first assign to a gc field and then initialize the struct field: currently my optimization doesn't handle that. It's possible to extend it to handle that case but that would require keeping track of field initializations and may be a little tricky.
However, now the answer to your question
Or would changing it to move all the zeroing above that first assignment to non-zero (which would be a much more complex refactoring in Roslyn) help?
is yes.
If the struct field zero initialization was done before the first assignment, it would be eliminated by the new optimization.