The behavior change in #73606 is due to a JIT bug no longer triggering, which was bisected to be a side effect of #66887.
@markples tracked down that we are in fact seeing new runtime lookups due to this change. We are not quite sure whether these are necessary or not. Simple example:
usingSystem;usingSystem.Runtime.CompilerServices;publicclassProgram{publicstaticvoidMain(){Console.WriteLine(CallFoo(newC()));}[MethodImpl(MethodImplOptions.NoInlining)]privatestaticintCallFoo<T>(Tval)whereT:IFace{returnval.Foo();}}publicinterfaceIFace{intFoo();}publicclassC:IFace{publicintFoo()=>0;}Codegen before #66887:
; Assembly listing for method Program:CallFoo(System.__Canon):int; Emitting BLENDED_CODE for X64 CPU with AVX - Windows; optimized code; rsp based frame; partially interruptible; No PGO data; Final local variable assignments;;* V00 TypeCtx [V00 ] ( 0, 0 ) long -> zero-ref single-def; V01 arg0 [V01,T00] ( 3, 3 ) ref -> rdx ld-addr-op class-hnd single-def; V02 OutArgs [V02 ] ( 1, 1 ) lclBlk (32) [rsp+00H] "OutgoingArgSpace";; Lcl frame size = 40G_M39006_IG01:subrsp,40 ;; size=4 bbWeight=1 PerfScore 0.25G_M39006_IG02:movrcx,rdxmovr11,0xD1FFAB1Ecall[r11]IFace:Foo():int:thisnop ;; size=17 bbWeight=1 PerfScore 3.75G_M39006_IG03:addrsp,40ret ;; size=5 bbWeight=1 PerfScore 1.25; Total bytes of code 26, prolog size 4, PerfScore 7.85, instruction count 7, allocated bytes for code 26 (MethodHash=972067a1) for method Program:CallFoo(System.__Canon):int; ============================================================
Codegen on current main:
; Assembly listing for method Program:CallFoo(System.__Canon):int; Emitting BLENDED_CODE for X64 CPU with AVX - Windows; optimized code; rsp based frame; partially interruptible; No PGO data; Final local variable assignments;; V00 TypeCtx [V00,T00] ( 5, 4.25) long -> rcx single-def; V01 arg0 [V01,T02] ( 3, 3 ) ref -> rsi ld-addr-op class-hnd single-def; V02 OutArgs [V02 ] ( 1, 1 ) lclBlk (32) [rsp+00H] "OutgoingArgSpace"; V03 tmp1 [V03,T01] ( 4, 5 ) long -> r11 "spilling Runtime Lookup tree";* V04 tmp2 [V04 ] ( 0, 0 ) long -> zero-ref "VirtualCall with runtime lookup"; V05 cse0 [V05,T03] ( 3, 2.25) long -> r11 "CSE - aggressive";; Lcl frame size = 48G_M39006_IG01:pushrsisubrsp,48mov qword ptr [rsp+28H],rcxmovrsi,rdx ;; size=13 bbWeight=1 PerfScore 2.50G_M39006_IG02:movrdx, qword ptr [rcx+56]movr11, qword ptr [rdx+16]testr11,r11je SHORT G_M39006_IG04 ;; size=13 bbWeight=1 PerfScore 5.25G_M39006_IG03:jmp SHORT G_M39006_IG05 ;; size=2 bbWeight=0.25 PerfScore 0.50G_M39006_IG04:movrdx,0xD1FFAB1E ; global ptrcall CORINFO_HELP_RUNTIMEHANDLE_METHODmovr11,rax ;; size=18 bbWeight=0.25 PerfScore 0.38G_M39006_IG05:movrcx,rsicall[r11]nop ;; size=7 bbWeight=1 PerfScore 3.50G_M39006_IG06:addrsp,48poprsiret ;; size=6 bbWeight=1 PerfScore 1.75; Total bytes of code 59, prolog size 10, PerfScore 19.78, instruction count 18, allocated bytes for code 59 (MethodHash=972067a1) for method Program:CallFoo(System.__Canon):int; ============================================================
Aside from the perf regression, fixing this should return the behavior of #73606 back to what it was previously. Then we plan to fix the underlying Roslyn and JIT issues (#73615) in .NET 8.
cc @trylek@davidwrighton@jaredpar@VSadov
The behavior change in #73606 is due to a JIT bug no longer triggering, which was bisected to be a side effect of #66887.
@markples tracked down that we are in fact seeing new runtime lookups due to this change. We are not quite sure whether these are necessary or not. Simple example:
Codegen before #66887:
Codegen on current main:
Aside from the perf regression, fixing this should return the behavior of #73606 back to what it was previously. Then we plan to fix the underlying Roslyn and JIT issues (#73615) in .NET 8.
cc @trylek@davidwrighton@jaredpar@VSadov