-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Suboptimal code generated for ValueTuple.GetHashCode() #66197
Comments
Tagging subscribers to this area: @JulieLeeMSFT Issue DetailsDescriptionGiven this code: class Program
{
int M1(int x, int y)
{
return HashCode.Combine(x, y);
}
int M2(int x, int y)
{
return (x, y).GetHashCode();
}
} The codegen for M1 and M2: ; Method Program:M1(int,int):int:this
G_M53360_IG01:
;; bbWeight=1 PerfScore 0.00
G_M53360_IG02:
mov ecx, edx
mov edx, r8d
;; bbWeight=1 PerfScore 0.50
G_M53360_IG03:
jmp System.HashCode:Combine(int,int):int
;; bbWeight=1 PerfScore 2.00
; Total bytes of code: 10
; Method Program:M2(int,int):int:this
G_M19763_IG01:
sub rsp, 40
xor eax, eax
mov qword ptr [rsp+20H], rax
;; bbWeight=1 PerfScore 1.50
G_M19763_IG02:
mov dword ptr [rsp+20H], edx
mov dword ptr [rsp+24H], r8d
lea rcx, bword ptr [rsp+20H]
call System.ValueTuple`2[Int32,Int32][System.Int32,System.Int32]:GetHashCode():int:this
nop
;; bbWeight=1 PerfScore 3.75
G_M19763_IG03:
add rsp, 40
ret
;; bbWeight=1 PerfScore 1.25
; Total bytes of code: 36
I think But even with ; Method Program:M1(int,int):int:this
G_M53360_IG01:
push rdi
push rsi
sub rsp, 40
mov esi, edx
mov edi, r8d
;; bbWeight=1 PerfScore 2.75
G_M53360_IG02:
mov rcx, 0xD1FFAB1E
mov edx, 315
call CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE
mov eax, dword ptr [reloc classVar[0xd1ffab1e]]
add eax, 0xD1FFAB1E
add eax, 8
imul edx, esi, 0xD1FFAB1E
add edx, eax
rol edx, 17
imul eax, edx, 0xD1FFAB1E
imul edx, edi, 0xD1FFAB1E
add edx, eax
rol edx, 17
imul eax, edx, 0xD1FFAB1E
mov edx, eax
shr edx, 15
xor eax, edx
imul eax, eax, 0xD1FFAB1E
mov edx, eax
shr edx, 13
xor eax, edx
imul eax, eax, 0xD1FFAB1E
mov edx, eax
shr edx, 16
xor eax, edx
;; bbWeight=1 PerfScore 19.50
G_M53360_IG03:
add rsp, 40
pop rsi
pop rdi
ret
;; bbWeight=1 PerfScore 2.25
; Total bytes of code: 119
; Method Program:M2(int,int):int:this
G_M19763_IG01:
push rdi
push rsi
sub rsp, 40
xor eax, eax
mov qword ptr [rsp+20H], rax
;; bbWeight=1 PerfScore 3.50
G_M19763_IG02:
mov dword ptr [rsp+20H], edx
mov dword ptr [rsp+24H], r8d
mov esi, dword ptr [rsp+20H]
lea rcx, bword ptr [rsp+24H]
mov edi, dword ptr [rcx]
mov rcx, 0xD1FFAB1E
mov edx, 315
call CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE
mov eax, dword ptr [reloc classVar[0xd1ffab1e]]
add eax, 0xD1FFAB1E
add eax, 8
imul edx, esi, 0xD1FFAB1E
add edx, eax
rol edx, 17
imul eax, edx, 0xD1FFAB1E
imul edx, edi, 0xD1FFAB1E
add edx, eax
rol edx, 17
imul eax, edx, 0xD1FFAB1E
mov edx, eax
shr edx, 15
xor eax, edx
imul eax, eax, 0xD1FFAB1E
mov edx, eax
shr edx, 13
xor eax, edx
imul eax, eax, 0xD1FFAB1E
mov edx, eax
shr edx, 16
xor eax, edx
;; bbWeight=1 PerfScore 25.00
G_M19763_IG03:
add rsp, 40
pop rsi
pop rdi
ret
;; bbWeight=1 PerfScore 2.25
; Total bytes of code: 141 Configuration.NET build from main branch.
|
The IL of ValueTuple<T1,T2>::GetHashCode is tricky:
inliner managed to figure out that BOX operations are foldable, but the benefit multiplier is still too low. |
Also note that some unnecessary code are generated for mov qword ptr [rsp+20H], rax
;; bbWeight=1 PerfScore 3.50
G_M19763_IG02:
mov dword ptr [rsp+20H], edx
mov dword ptr [rsp+24H], r8d
mov esi, dword ptr [rsp+20H]
lea rcx, bword ptr [rsp+24H]
mov edi, dword ptr [rcx] |
@kunalspathak please check if your PR fixes the struct issue. |
#64130 handles patterns when a struct is returned through "return buffer". This pattern is not handled. |
In the original version of
|
This won't happen in .NET 7. Moving to .NET 8. |
@jakobbotsch - can you double check if you get this pattern with physical promotion? |
(With aggressive inlining enabled) This and #87072 are the same underlying problem -- we end up with address exposure because Roslyn leaves the address of a struct live on the IL stack at the end of a basic block. I will move this to future. Also we would still need the inliner to be more aggressive here, even with a fix for #87072 (cc @EgorBo). |
With #102808 the codegen for |
Going to give this to @EgorBo since this is now a question of inlining. |
Description
Given this code:
where the implementation of
ValueTuple<,>.GetHashCode()
is:The codegen for M1 and M2:
I think in this case
ValueTuple.GetHashCode
should at least be inlined (withT1=T2=int
, bothItem1
andItem2
can not be null).But even with
DOTNET_JitAggressiveInlining=1
(which forces inliningValueTuple.GetHashCode
), the codegen for M2 is still suboptimal:Configuration
.NET build from main branch.
category:cq
theme:codegen
skill-level:expert
cost:large
impact:medium
The text was updated successfully, but these errors were encountered: