-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
JIT cannot devirtualize interface call in trivial cases #63283
Comments
Tagging subscribers to this area: @JulieLeeMSFT Issue DetailsDescriptionJIT cannot devirtualize interface call in very trivial cases. Source code: using System;
using System.Runtime.CompilerServices;
public static class C {
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static T As<T>(T obj) where T : class => obj;
public static int Cmp(String str) => As<IComparable<string>>(str).CompareTo(string.Empty);
public static int Cmp2(String str) => str.CompareTo(string.Empty);
public static int Cmp3(String str) => ((IComparable<string>)str).CompareTo(string.Empty);
public static int Cmp4(IComparable<string> str) => str.CompareTo(string.Empty);
} Output assembly: C.Cmp(System.String)
L0000: push ebp
L0001: mov ebp, esp
L0003: mov edx, [0x8d72018]
L0009: call dword ptr [0x11317000]
L000f: pop ebp
L0010: ret
C.Cmp2(System.String)
L0000: mov edx, [0x8d72018]
L0006: cmp [ecx], ecx
L0008: push 0
L000a: call System.String.Compare(System.String, System.String, System.StringComparison)
L000f: ret
C.Cmp3(System.String)
L0000: push ebp
L0001: mov ebp, esp
L0003: mov edx, [0x8d72018]
L0009: call dword ptr [0x11317004]
L000f: pop ebp
L0010: ret
C.Cmp4(System.IComparable`1<System.String>)
L0000: push ebp
L0001: mov ebp, esp
L0003: mov edx, [0x8d72018]
L0009: call dword ptr [0x11317008]
L000f: pop ebp
L0010: ret
Configuration.NET 6.0.101 Regression?Probably yes, but I didn't check.
|
But it does happen when Dynamic PGO is turned on. |
Any chance to backport JIT behavior as you described to .NET 6 ? |
Dynamic PGO? you can enable it in .NET 6.0, see https://gist.github.com/EgorBo/dc181796683da3d905a5295bfd3dd95b#how-can-i-try-it-on-my-production |
No, not Dynamic PGO. I'm talking about to have the same codegen for |
Unlikely, the bar to backport changes to .NET 6.0 is very high to include an optimization. |
I think we should be able to get the
|
Seems like the issue is that in the When we propagate a return value out of a generic method to the non-generic root, we ideally should be able to determine the proper unshared type for that value. This might work roughly as follows:
|
Another perhaps more robust option would be to retype the return value, if it's a ref type, and we have a context. |
If we have a non-inline candidate call with generics context, save the context so it's available for late devirtualization. Fixes a missing devirtualization reported in dotnet#63283. I am deliberately leaving `LateDevirtualizationInfo` more general than necessary as it may serve as a jumping-off point for enabling late inlining.
Fix for this in PR #63420. |
If we have a non-inline candidate call with generics context, save the context so it's available for late devirtualization. Fixes a missing devirtualization reported in #63283. I am deliberately leaving `LateDevirtualizationInfo` more general than necessary as it may serve as a jumping-off point for enabling late inlining.
Closing issue as PR has been merged. |
Description
JIT cannot devirtualize interface call in very trivial cases.
Source code:
Output assembly:
Cmp2
is correctly devirtualized and inlined. I'm expecting that the assembly code should be the same for all cases exceptCmp4
.Configuration
.NET 6.0.101
Ubuntu 20.04.3 5.4.0-91-generic x86_64
Regression?
Probably yes, but I didn't check.
The text was updated successfully, but these errors were encountered: