dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.37k stars 4.75k forks source link

NativeAOT: improve getExactClasses to support classes as base types #88547

Closed EgorBo closed 1 year ago

EgorBo commented 1 year ago

Currently, getExactClasses gives up if the base type is not an interface so if we have something like this it won't be optimized:

using System.Runtime.CompilerServices;

public class ClassA
{
    public virtual int GetValue() => 42;
}

public class ClassB : ClassA
{
    // we don't even need to override GetValue here
}

class MyClass
{
    static void Main()
    {
        Test(new ClassB());
    }

    [MethodImpl(MethodImplOptions.NoInlining)]
    static int Test(ClassA c) => c.GetValue();
}

Current codegen of Test on NativeAOT:

; Method MyClass:Test(ClassA):int (FullOpts)
       sub      rsp, 40
       mov      rax, qword ptr [rcx]
       call     [rax+30H]ClassA:GetValue():int:this
       nop      
       add      rsp, 40
       ret      
; Total bytes of code: 16

Expected codegen:

; Method MyClass:Test(ClassA):int (FullOpts)
       cmp      byte  ptr [rcx], cl ; nullcheck
       mov      eax, 42
       ret      
; Total bytes of code: 8

Presumably, this needs no changes on the jit side, only that getExactClasses should be improved on the NAOT side.

cc @dotnet/ilc-contrib

ghost commented 1 year ago

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch See info in area-owners.md if you want to be subscribed.

Issue Details
Currently, `getExactClasses` [gives up](https://github.com/dotnet/runtime/blob/b6266a6e4ceac8708304eed764e25777d08cf184/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs#L2213-L2217) if the base type is not an interface so if we have something like this it won't be optimized: ```cs public abstract class IValue { public abstract int GetValue(); } public class ValueImpl : IValue { public override int GetValue() => 42; } [MethodImpl(MethodImplOptions.NoInlining)] static int Test(IValue f) => f.GetValue(); ``` Current codegen of `Test` on NativeAOT: ```asm ; Method Prog:Test(IValue):int (FullOpts) sub rsp, 40 mov rax, qword ptr [rcx] call [rax+30H]IValue:GetValue():int:this nop add rsp, 40 ret ; Total bytes of code: 16 ``` Expected codegen: ```asm ; Method Prog:Test(ValueImpl):int (FullOpts) cmp byte ptr [rcx], cl ; nullcheck mov eax, 42 ret ; Total bytes of code: 8 ``` Presumably, this needs no changes on the jit side, only that `getExactClasses` should be improved on the [NAOT side](https://github.com/dotnet/runtime/blob/b6266a6e4ceac8708304eed764e25777d08cf184/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs#L2213-L2217). cc @dotnet/ilc-contrib
Author: EgorBo
Assignees: -
Labels: `area-CodeGen-coreclr`
Milestone: -
ghost commented 1 year ago

Tagging subscribers to this area: @agocke, @MichalStrehovsky, @jkotas See info in area-owners.md if you want to be subscribed.

Issue Details
Currently, `getExactClasses` [gives up](https://github.com/dotnet/runtime/blob/b6266a6e4ceac8708304eed764e25777d08cf184/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs#L2213-L2217) if the base type is not an interface so if we have something like this it won't be optimized: ```cs public abstract class IValue { public abstract int GetValue(); } public class ValueImpl : IValue { public override int GetValue() => 42; } [MethodImpl(MethodImplOptions.NoInlining)] static int Test(IValue f) => f.GetValue(); ``` Current codegen of `Test` on NativeAOT: ```asm ; Method Prog:Test(IValue):int (FullOpts) sub rsp, 40 mov rax, qword ptr [rcx] call [rax+30H]IValue:GetValue():int:this nop add rsp, 40 ret ; Total bytes of code: 16 ``` Expected codegen: ```asm ; Method Prog:Test(ValueImpl):int (FullOpts) cmp byte ptr [rcx], cl ; nullcheck mov eax, 42 ret ; Total bytes of code: 8 ``` Presumably, this needs no changes on the jit side, only that `getExactClasses` should be improved on the [NAOT side](https://github.com/dotnet/runtime/blob/b6266a6e4ceac8708304eed764e25777d08cf184/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs#L2213-L2217). cc @dotnet/ilc-contrib
Author: EgorBo
Assignees: -
Labels: `untriaged`, `area-NativeAOT-coreclr`
Milestone: -