-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Open
Labels
area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMICLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMItenet-performancePerformance related issuePerformance related issue
Milestone
Description
Description
It appears that JIT is not able to propagate concrete type information through struct fields typed as the type's abstract parent.
The example below matches the shape of stateless FSharpFunc<T1...Tn>
instantiations by F#.
Given reduced repro:
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
BenchmarkRunner.Run<Benchmarks>(args: args);
[ShortRunJob]
[DisassemblyDiagnoser]
public class Benchmarks {
[Benchmark]
public int Example() {
var wrapper = default(Wrapper2<int, int>);
wrapper.F1 = MyFuncImpl1.Instance;
wrapper.F2 = MyFuncImpl2.Instance;
var v1 = wrapper.F1.Invoke(42);
var v2 = wrapper.F2.Invoke(v1);
return v2 + 1;
}
}
abstract class MyFunc<T, U> {
public abstract U Invoke(T value);
}
sealed class MyFuncImpl1: MyFunc<int, int> {
public static readonly MyFuncImpl1 Instance = new();
public override int Invoke(int value) => value + 4;
}
sealed class MyFuncImpl2: MyFunc<int, int> {
public static readonly MyFuncImpl2 Instance = new();
public override int Invoke(int value) => value * 2;
}
struct Wrapper2<T, U> {
public MyFunc<T, U> F1;
public MyFunc<T, U> F2;
}
The Tier1-PGO compilation of Example()
is
; Benchmarks.Dummy()
push rbx
sub rsp,20
mov rax,2907B8012E8
mov rcx,[rax]
mov rax,2907B8012F0
mov rbx,[rax]
mov rax,offset MT_MyFuncImpl1
cmp [rcx],rax
jne short M00_L01
mov edx,2E
mov rax,offset MT_MyFuncImpl2
cmp [rbx],rax
jne short M00_L02
mov eax,5C
M00_L00:
inc eax
add rsp,20
pop rbx
ret
M00_L01:
mov edx,2A
mov rax,[rcx]
mov rax,[rax+40]
call qword ptr [rax+20]
mov edx,eax
M00_L02:
mov rcx,rbx
mov rax,[rbx]
mov rax,[rax+40]
call qword ptr [rax+20]
jmp short M00_L00
; Total bytes of code 111
It would be great if JIT could propagate the concrete type here through the field and not rely on DPGO to devirtualize the func types back. This also does not devirtualize on NativeAOT for more than single MyFunc
implementation. Thanks!
Configuration
.NET SDK:
Version: 9.0.100
Commit: 59db016f11
Workload version: 9.0.100-manifests.3068a692
MSBuild version: 17.12.7+5b8665660
Runtime Environment:
OS Name: Windows
OS Version: 10.0.22631
OS Platform: Windows
RID: win-x64
Base Path: C:\Program Files\dotnet\sdk\9.0.100\
Regression?
Not tested on .NET 8
Metadata
Metadata
Assignees
Labels
area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMICLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMItenet-performancePerformance related issuePerformance related issue