Collect an SPMI collection for the following simple app:
using System.Runtime.CompilerServices;
class Prog
{
static void Main(string[] args) => Test<string>();
[MethodImpl(MethodImplOptions.NoInlining)]
static void Test<T>()
{
for (int i = 0; i < 100; i++)
Callee<T>();
}
static bool Callee<T>() => typeof(T) == typeof(int);
}
Now replay it with JitDisasm="Test", SPMI will print:
[17:28:31] ; Assembly listing for method Prog:Test[System.__Canon]()
[17:28:31] ; Emitting BLENDED_CODE for X64 CPU with AVX - Windows
[17:28:31] ; optimized code
[17:28:31] ; rsp based frame
[17:28:31] ; partially interruptible
[17:28:31] ; No matching PGO data
[17:28:31] ; Final local variable assignments
[17:28:31] ;
[17:28:31] ; V00 TypeCtx [V00,T01] ( 4, 7 ) long -> rsi single-def
[17:28:31] ; V01 loc0 [V01,T00] ( 4, 13 ) int -> rdi
[17:28:31] ; V02 OutArgs [V02 ] ( 1, 1 ) lclBlk (32) [rsp+00H] "OutgoingArgSpace"
[17:28:31] ;
[17:28:31] ; Lcl frame size = 40
[17:28:31]
[17:28:31] G_M2205_IG01: ;; offset=0000H
[17:28:31] 57 push rdi
[17:28:31] 56 push rsi
[17:28:31] 4883EC28 sub rsp, 40
[17:28:31] 48894C2420 mov qword ptr [rsp+20H], rcx
[17:28:31] 488BF1 mov rsi, rcx
[17:28:31] ;; size=14 bbWeight=1 PerfScore 3.50
[17:28:31] G_M2205_IG02: ;; offset=000EH
[17:28:31] 33FF xor edi, edi
[17:28:31] ;; size=2 bbWeight=1 PerfScore 0.25
[17:28:31] G_M2205_IG03: ;; offset=0010H
[17:28:31] 488BCE mov rcx, rsi
[17:28:31] FF1500000000 call [Prog:Callee[System.__Canon]():bool]
[17:28:31] FFC7 inc edi
[17:28:31] 83FF64 cmp edi, 100
[17:28:31] 7CF0 jl SHORT G_M2205_IG03
[17:28:31] ;; size=16 bbWeight=4 PerfScore 19.00
[17:28:31] G_M2205_IG04: ;; offset=0020H
[17:28:31] 4883C428 add rsp, 40
[17:28:31] 5E pop rsi
[17:28:31] 5F pop rdi
[17:28:31] C3 ret
[17:28:31] ;; size=7 bbWeight=1 PerfScore 2.25
[17:28:31]
[17:28:31] ; Total bytes of code 39
No any runtime lookup in the codegen!
While real JIT prints:
; Assembly listing for method Prog:Test[System.__Canon]()
; 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,T03] ( 5, 5 ) long -> rsi single-def
; V01 loc0 [V01,T00] ( 4, 13 ) int -> rdi
; V02 OutArgs [V02 ] ( 1, 1 ) lclBlk (32) [rsp+00H] "OutgoingArgSpace"
; V03 tmp1 [V03,T01] ( 3, 12 ) long -> rcx "spilling Runtime Lookup tree"
; V04 cse0 [V04,T02] ( 3, 9 ) long -> rcx "CSE - aggressive"
; V05 cse1 [V05,T04] ( 2, 5 ) long -> rbx "CSE - aggressive"
;
; Lcl frame size = 48
G_M2205_IG01: ;; offset=0000H
57 push rdi
56 push rsi
53 push rbx
4883EC30 sub rsp, 48
48894C2428 mov qword ptr [rsp+28H], rcx
488BF1 mov rsi, rcx
;; size=15 bbWeight=1 PerfScore 4.50
G_M2205_IG02: ;; offset=000FH
33FF xor edi, edi
488B5E38 mov rbx, qword ptr [rsi+38H]
;; size=6 bbWeight=1 PerfScore 2.25
G_M2205_IG03: ;; offset=0015H
488B4B10 mov rcx, qword ptr [rbx+10H]
4885C9 test rcx, rcx
7402 je SHORT G_M2205_IG05
;; size=9 bbWeight=4 PerfScore 13.00
G_M2205_IG04: ;; offset=001EH
EB15 jmp SHORT G_M2205_IG06
;; size=2 bbWeight=1 PerfScore 2.00
G_M2205_IG05: ;; offset=0020H
488BCE mov rcx, rsi
48BA20FE91D4FB7F0000 mov rdx, 0x7FFBD491FE20 ; global ptr
E8BE3E505F call CORINFO_HELP_RUNTIMEHANDLE_METHOD
488BC8 mov rcx, rax
;; size=21 bbWeight=1 PerfScore 1.75
G_M2205_IG06: ;; offset=0035H
FF150DFD6000 call [Prog:Callee[System.__Canon]():bool]
FFC7 inc edi
83FF64 cmp edi, 100
7CD3 jl SHORT G_M2205_IG03
;; size=13 bbWeight=4 PerfScore 18.00
G_M2205_IG07: ;; offset=0042H
4883C430 add rsp, 48
5B pop rbx
5E pop rsi
5F pop rdi
C3 ret
;; size=8 bbWeight=1 PerfScore 2.75
; Total bytes of code 74
It seems that SPMI lies about runtime lookup somewhere. cc @dotnet/jit-contrib
Collect an SPMI collection for the following simple app:
Now replay it with JitDisasm="Test", SPMI will print:
No any runtime lookup in the codegen!
While real JIT prints:
It seems that SPMI lies about runtime lookup somewhere. cc @dotnet/jit-contrib