Skip to content

JIT unnecessary stack load/stores for tail jump with stack args involved #105031

@huoyaoyuan

Description

@huoyaoyuan

#104731 (comment)

Good case:

    unsafe class MyDelegate3
    {
        object _target;
        delegate*<object, nint, nint, nint, void> _methodPtr;

        public void Invoke(nint arg1, nint arg2, nint arg3) => _methodPtr(_target, arg1, arg2, arg3);
    }
; Method CSPlayground.MyDelegate3:Invoke(long,long,long):this (FullOpts)
G_M6976_IG01:  ;; offset=0x0000
						;; size=0 bbWeight=1 PerfScore 0.00

G_M6976_IG02:  ;; offset=0x0000
       mov      rax, qword ptr [rcx+0x10]
       mov      rcx, gword ptr [rcx+0x08]
						;; size=8 bbWeight=1 PerfScore 4.00

G_M6976_IG03:  ;; offset=0x0008
       tail.jmp rax
						;; size=3 bbWeight=1 PerfScore 2.00
; Total bytes of code: 11

Not good case:

    unsafe class MyDelegate4
    {
        object _target;
        delegate*<object, nint, nint, nint, nint, void> _methodPtr;

        public void Invoke(nint arg1, nint arg2, nint arg3, nint arg4) => _methodPtr(_target, arg1, arg2, arg3, arg4);
    }
; Method CSPlayground.MyDelegate4:Invoke(long,long,long,long):this (FullOpts)
G_M9153_IG01:  ;; offset=0x0000
						;; size=0 bbWeight=1 PerfScore 0.00

G_M9153_IG02:  ;; offset=0x0000
       mov      rax, qword ptr [rcx+0x10]
       nop      
						;; size=5 bbWeight=1 PerfScore 2.25

G_M9153_IG03:  ;; offset=0x0005
       mov      r10, qword ptr [rsp+0x28]
       mov      qword ptr [rsp+0x28], r10
       mov      rcx, gword ptr [rcx+0x08]
						;; size=14 bbWeight=1 PerfScore 4.00

G_M9153_IG04:  ;; offset=0x0013
       tail.jmp rax
						;; size=3 bbWeight=1 PerfScore 2.00
; Total bytes of code: 22
    unsafe class MyDelegateComplex
    {
        object _target;
        delegate*<object, int, double, object, Guid, double> _methodPtr;

        public double Invoke(int a, double b, object c, Guid d) => _methodPtr(_target, a, b, c, d);
    }
; Method CSPlayground.MyDelegateComplex:Invoke(int,double,System.Object,System.Guid):double:this (FullOpts)
G_M18646_IG01:  ;; offset=0x0000
       mov      rax, bword ptr [rsp+0x28]
						;; size=5 bbWeight=1 PerfScore 1.00

G_M18646_IG02:  ;; offset=0x0005
       mov      r8, qword ptr [rcx+0x10]
       nop      
						;; size=5 bbWeight=1 PerfScore 2.25

G_M18646_IG03:  ;; offset=0x000A
       mov      bword ptr [rsp+0x28], rax
       mov      rcx, gword ptr [rcx+0x08]
						;; size=9 bbWeight=1 PerfScore 3.00

G_M18646_IG04:  ;; offset=0x0013
       tail.jmp r8
						;; size=3 bbWeight=1 PerfScore 2.00
; Total bytes of code: 22

The codegen is fine when all arguments are passed in register. Struct args can make things worse.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions