Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NativeAOT: Guarded devirtualization #64497

Merged
merged 40 commits into from
Aug 15, 2022
Merged

NativeAOT: Guarded devirtualization #64497

merged 40 commits into from
Aug 15, 2022

Conversation

EgorBo
Copy link
Member

@EgorBo EgorBo commented Jan 29, 2022

Contributes to #64242

This PR introduces getExactClasses JIT-EE API, VM may give JIT a hint that a specific virtual call will always be of one of the specific classes and no other class can be loaded/added so we can skip "fallback" path.

Current implementation only handles single-impl/subclass/struct case, will be extended to multiple with #59604

Example:

public interface IFoo
{
    void SayHello();
}

public class FooImpl : IFoo
{
    public void SayHello() => Console.WriteLine("Hello!");
}

class Test
{
    static void Main()
    {
        Test(new FooImpl());
        Console.ReadKey();
    }

    [MethodImpl(MethodImplOptions.NoInlining)]
    static void Test(IFoo f) => f.SayHello();
}

Codegen for Test:

; Method MyType:Test(IFoo)
G_M19269_IG01:
       sub      rsp, 40
G_M19269_IG02:
       cmp      dword ptr [rcx], ecx
       mov      rcx, 0xD1FFAB1E      ; "Hello!"
       mov      rcx, gword ptr [rcx]
       call     System.Console:WriteLine(System.String) ; <-- SayHello was devirtualized & inlined
       nop      ; <-- no fallbacks as with PGO on CoreCLR
G_M19269_IG03:
       add      rsp, 40
       ret      
; Total bytes of code: 30

(I was using JIT for demo, getExactClasses is not implemented on VM side yet, @MichalStrehovsky any pointers how to get all possible implementations/subclasses for a specific type? (see https://github.com/dotnet/runtime/pull/64497/files#diff-132a77bcd3f74cf0e0b04fbccda246c97c91e40562d78cb01fff61cf69403573R2930)

TODO:

  • Implement VM's side
  • Remove "must be inlineable" requirement for GDV candidates

@ghost ghost assigned EgorBo Jan 29, 2022
@dotnet-issue-labeler dotnet-issue-labeler bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Jan 29, 2022
@ghost
Copy link

ghost commented Jan 29, 2022

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

Issue Details

This PR introduces getExactClasses JIT-EE API, VM may give JIT a hint that a specific virtual call will always be of one of the specific classes and no other class can be loaded/added so we can skip "fallback" path.

Current implementation only handles single-impl/subclasses/class case, will be extended to multiple with #59604

Example:

public interface IFoo
{
    void SayHello();
}

public class FooImpl : IFoo
{
    public void SayHello() => Console.WriteLine("Hello!");
}

class Test
{
    static void Main()
    {
        Test(new FooImpl());
        Console.ReadKey();
    }

    [MethodImpl(MethodImplOptions.NoInlining)]
    static void Test(IFoo f) => f.SayHello();
}

Codegen for Test:

; Method MyType:Test(IFoo)
G_M19269_IG01:
       sub      rsp, 40
G_M19269_IG02:
       cmp      dword ptr [rcx], ecx
       mov      rcx, 0xD1FFAB1E      ; "Hello!"
       mov      rcx, gword ptr [rcx]
       call     System.Console:WriteLine(System.String) ; <-- SayHello was devirtualized & inlined
       nop      ; <-- no fallbacks as with PGO on CoreCLR
G_M19269_IG03:
       add      rsp, 40
       ret      
; Total bytes of code: 30

(I was using JIT for demo, getExactClasses is not implemented on VM side yet, @MichalStrehovsky any pointers how to get all possible implementations/subclasses for a specific type? (see )

Author: EgorBo
Assignees: EgorBo
Labels:

area-CodeGen-coreclr

Milestone: -

@MichalStrehovsky
Copy link
Member

Spicy pull request!

@MichalStrehovsky any pointers how to get all possible implementations/subclasses for a specific type?

Here's a blueprint of what should work:

We'll have to be a little careful about generic classes/interfaces because new instantiations of those can happen at runtime (e.g. if we compiled/saw List<__Canon>/List<string>, we could still end up seeing a List<object> at runtime because they can be created after compilation with MakeGenericType). Maybe for now it might be easiest to disallow generics - if an interface/base class (even non-generic) is implemented by a generic type that has a shared form, forget about devirtualizing the interface/base type.

…iveaot

# Conflicts:
#	src/coreclr/inc/jiteeversionguid.h
#	src/coreclr/tools/Common/JitInterface/CorInfoBase.cs
#	src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
#	src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h
#	src/coreclr/vm/jitinterface.cpp
@EgorBo
Copy link
Member Author

EgorBo commented Mar 28, 2022

Ping myself

@kant2002
Copy link
Contributor

@EgorBo friendly ping.

@MichalStrehovsky
Copy link
Member

Is the remaining work on the guarded devirtualization on the VM side or jit side? I could help pick up the VM side. This would be a very cool thing to have

@EgorBo
Copy link
Member Author

EgorBo commented Jul 16, 2022

@MichalStrehovsky @kant2002 ah, completely forgot about this one - I'll finish it tomorrow 🙂

# Conflicts:
#	src/coreclr/inc/jiteeversionguid.h
#	src/coreclr/jit/importer.cpp
#	src/coreclr/tools/Common/JitInterface/CorInfoBase.cs
#	src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
#	src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ILScanner.cs
@EgorBo
Copy link
Member Author

EgorBo commented Aug 12, 2022

@MichalStrehovsky could you please help me to figure out how to incorporate changes from #73218 (I fixed the merge conflict with "using mine")

@MichalStrehovsky
Copy link
Member

@MichalStrehovsky could you please help me to figure out how to incorporate changes from #73218 (I fixed the merge conflict with "using mine")

Another conflict is incoming in #73839 and that one is a fix for a blocking bug. We can try after

@MichalStrehovsky
Copy link
Member

/azp run runtime-extra-platforms

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@MichalStrehovsky
Copy link
Member

The NativeAOT runs look good. The failures exist in the baseline, but if I don't baseline them apparently nobody else will... (I'm looking into baselining them)

@@ -3174,6 +3174,16 @@ void Compiler::lvaSetClass(unsigned varNum, CORINFO_CLASS_HANDLE clsHnd, bool is
return;
}

if (clsHnd != NO_CLASS_HANDLE && !isExact && IsTargetAbi(CORINFO_NATIVEAOT_ABI))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a meaningful perf saving from skipping getExactClasses call outside NATIVEAOT_ABI? I assume it would just be a no-op. Not doing this outside NativeAOT is a policy decision and JIT generally tries to leave those to the EE side.

Could we instead key this off of JitEnableDevirtualization (or maybe a new config switch specifically for this)? Just so we have some way to see the impact of this or disable it if it misbehaves. On ilc side we have --noscan that would disable this, but it also disables a bunch of other things because it's for the whole program analysis in general.

@JulieLeeMSFT JulieLeeMSFT added this to the 7.0.0 milestone Aug 15, 2022
Copy link
Member

@jakobbotsch jakobbotsch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, are there any concerns about a JIT-EE GUID change this close to the snap if we take it?

@EgorBo
Copy link
Member Author

EgorBo commented Aug 15, 2022

LGTM, are there any concerns about a JIT-EE GUID change this close to the snap if we take it?

I personally don't see any

Merging now, CI is green (except the spmi jobs which fail due to jit-ee guid update)

@EgorBo EgorBo merged commit a85b782 into dotnet:main Aug 15, 2022
@BruceForstall
Copy link
Member

I personally don't see any

Any further "last minute" .NET 7 PRs will fail SPMI jobs until the collection happens, which will complete after the fork.

@EgorBo
Copy link
Member Author

EgorBo commented Aug 15, 2022

I personally don't see any

Any further "last minute" .NET 7 PRs will fail SPMI jobs until the collection happens, which will complete after the fork.

Right, which is why merging this last minute is fine, new PRs which will be rebased won't make it to green anyway (20 minutes left) - am I right?

@EgorBo EgorBo deleted the gdv-nativeaot branch August 15, 2022 18:42
@AndyAyersMS
Copy link
Member

Snap is at 4pm PDT, so there are 4+ hours left....

@EgorBo
Copy link
Member Author

EgorBo commented Aug 15, 2022

Snap is at 4pm PDT, so there are 4+ hours left....

Oops, I thought it's noon 🙁

@TIHan
Copy link
Contributor

TIHan commented Aug 16, 2022

@EgorBo I think this change is causing SuperPMI collection to fail even on a simple "hello world" app - GetExactClasses is null when it is trying to be used in recGetExactClasses.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants