Skip to content

Improve codegen for delegate cast / type check? #55841

@stephentoub

Description

@stephentoub

Consider:

using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using System;
using System.Runtime.CompilerServices;

[DisassemblyDiagnoser]
[MemoryDiagnoser]
public class Program
{
    public static void Main(string[] args) => BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);

    private object _o = (Action)(() => { });

    [Benchmark] public void Cast() => M1(_o);
    [Benchmark] public void TypeCheck() => M2(_o);

    private void M1(object o)
    {
        if (o is Action action)
            action();
    }

    private void M2(object o)
    {
        if (o is not null && o.GetType() == typeof(Action))
            Unsafe.As<Action>(o)();
    }
}

On my machine, this results in:

Method Mean Error StdDev Gen 0 Gen 1 Gen 2 Allocated Code Size
Cast 1.1969 ns 0.0083 ns 0.0078 ns - - - - 43 B
TypeCheck 0.7173 ns 0.0064 ns 0.0060 ns - - - - 36 B

with the disassembly:

.NET 6.0.0 (42.42.42.42424), X64 RyuJIT

; Program.Cast()
       mov       rax,[rcx+8]
       test      rax,rax
       je        short M00_L00
       mov       rcx,offset MT_System.Action
       cmp       [rax],rcx
       je        short M00_L00
       xor       eax,eax
M00_L00:
       test      rax,rax
       je        short M00_L01
       mov       rcx,[rax+8]
       mov       rax,[rax+18]
       jmp       rax
M00_L01:
       ret
; Total bytes of code 43

.NET 6.0.0 (42.42.42.42424), X64 RyuJIT

; Program.TypeCheck()
       mov       rax,[rcx+8]
       test      rax,rax
       je        short M00_L00
       mov       rcx,offset MT_System.Action
       cmp       [rax],rcx
       jne       short M00_L00
       mov       rcx,[rax+8]
       mov       rax,[rax+18]
       jmp       rax
M00_L00:
       ret
; Total bytes of code 36

Is there anything we could do to eliminate the (small) gap / extra branch?

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