-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
RyuJIT properly optimizes structs with a single field if the field type is int but not if it is double #4323
Comments
This is indirectly caused by the following code from #ifdef _TARGET_AMD64_
// on AMD don't promote structs with a single float field
// Promoting it would just cause us to shuffle it back and forth between int and float regs.
// On ARM this would be an HFA and passed/returned in float regs.
if (structPromotionInfo.fieldCnt==1
&& varTypeIsFloating(structPromotionInfo.fields[0].fldType))
{
JITDUMP("Not promoting promotable struct local V%02u: #fields = %d because it is a struct with single float field.\n",
lclNum, structPromotionInfo.fieldCnt);
continue;
}
#endif I don't know what that comment is trying to say about shuffling the value between int and float regs but adding a second field to the It's interesting that if the restriction is removed an assert fires in lsra.cpp, that probably means that constant propagation and folding still fails to work even if the struct is promoted. |
The int-float shuffling is probably a reference to the fact that the inliner insists on using the ABI rules of returning |
😞 |
Hmm, this looks like a case for |
This was originally issue 1161 in dotnet/coreclr, and there is a test, JIT\Regression\JitBlue\GitHub_1161, that captures this (to enable improvements or regressions to show up when we run jit diffs). |
I don't think we will fix this in 7.0, so moving to future |
@sandreenko should we unassign you? |
Codegen today is the same for both versions: ; Assembly listing for method Program:Main():int
; Emitting BLENDED_CODE for X64 CPU with AVX - Windows
; optimized code
; rsp based frame
; partially interruptible
; No PGO data
; 0 inlinees with PGO data; 5 single block inlinees; 0 inlinees without PGO data
; Final local variable assignments
;
;* V00 loc0 [V00 ] ( 0, 0 ) struct ( 8) zero-ref single-def
;# V01 OutArgs [V01 ] ( 1, 1 ) lclBlk ( 0) [rsp+00H] "OutgoingArgSpace"
;* V02 tmp1 [V02 ] ( 0, 0 ) struct ( 8) zero-ref "impAppendStmt"
;* V03 tmp2 [V03 ] ( 0, 0 ) struct ( 8) zero-ref "struct address for call/obj"
;* V04 tmp3 [V04,T00] ( 0, 0 ) struct ( 8) zero-ref do-not-enreg[SF] ld-addr-op "Inline ldloca(s) first use temp"
;* V05 tmp4 [V05,T01] ( 0, 0 ) struct ( 8) zero-ref do-not-enreg[SF] ld-addr-op "Inline ldloca(s) first use temp"
;* V06 tmp5 [V06 ] ( 0, 0 ) struct ( 8) zero-ref do-not-enreg[SF] "Inlining Arg"
;* V07 tmp6 [V07 ] ( 0, 0 ) struct ( 8) zero-ref do-not-enreg[SF] "Inlining Arg"
;* V08 tmp7 [V08,T02] ( 0, 0 ) struct ( 8) zero-ref do-not-enreg[SF] ld-addr-op "Inline ldloca(s) first use temp"
;* V09 tmp8 [V09 ] ( 0, 0 ) double -> zero-ref "Inlining Arg"
;* V10 tmp9 [V10 ] ( 0, 0 ) struct ( 8) zero-ref do-not-enreg[SF] "Inlining Arg"
;* V11 cse0 [V11,T03] ( 0, 0 ) double -> zero-ref "CSE - aggressive"
;* V12 cse1 [V12,T04] ( 0, 0 ) double -> zero-ref "CSE - aggressive"
;
; Lcl frame size = 0
G_M24375_IG01:
;; size=0 bbWeight=1 PerfScore 0.00
G_M24375_IG02:
mov eax, 6
;; size=5 bbWeight=1 PerfScore 0.25
G_M24375_IG03:
ret
;; size=1 bbWeight=1 PerfScore 1.00
; Total bytes of code 6, prolog size 0, PerfScore 1.85, instruction count 2, allocated bytes for code 6 (MethodHash=d9b8a0c8) for method Program:Main():int
; ============================================================ Looks fixed. |
Sample C# code:
A portion of the generated code:
If
int
is used intstead ofdouble
or ifdouble
is used directly instead ofNumber
then the generated code is simplymov eax, 6
.category:cq
theme:structs
skill-level:expert
cost:medium
impact:medium
The text was updated successfully, but these errors were encountered: