Skip to content

Make Type.IsGenericType and GetGenericTypeDefinition() JIT intrinsics (and JIT time constants) #96898

Closed
@Sergio0694

Description

@Sergio0694

Overview

This is one more codegen improvement we could leverage for CsWinRT, related to #95929. One scenario we have (here) is to check whether a given type T is some KeyValuePair<,> instantiation. This needs to be marshalled in a specific way to match the expectations of WinRT. Right now however, the only way we have to check for this case is to use IsGenericType and GetGenericTypeDefinition(), which are not JIT intrinsics. This makes the linker not see this special case, and therefore not correctly trim the code away (or just specialize it on the other hand). This is both marginally slower, but most importantly leaves some codegen size reduction opportunities on the table. We're seeing a bunch of KeyValuePair<__Canon, __Canon> instantiations in sizoscope even in sample WinRT components that never use KeyValuePair<,> at all anywhere. It would be nice if this could just be properly inlined as a constant instead.

Codegen

using SharpLab.Runtime;

[JitGeneric(typeof(System.Collections.Generic.KeyValuePair<int, int>))]
[JitGeneric(typeof(int))]
static bool IsKVP<T>()
{
    return typeof(T).IsGenericType && typeof(T).GetGenericTypeDefinition() == typeof(System.Collections.Generic.KeyValuePair<,>);
}

Current codegen on .NET 8 x64 (sharplab):

Program.<<Main>$>g__IsKVP|0_0[[System.Collections.Generic.KeyValuePair`2[[System.Int32, System.Private.CoreLib],[System.Int32, System.Private.CoreLib]], System.Private.CoreLib]]()
    L0000: sub rsp, 0x28
    L0004: mov rcx, 0x23e784e3260
    L000e: call qword ptr [0x7ffb1060a518]
    L0014: test eax, eax
    L0016: je short L0040
    L0018: mov rcx, 0x23e784e3260
    L0022: call qword ptr [0x7ffb1060a568]
    L0028: mov rcx, 0x23e783e2728
    L0032: cmp rax, rcx
    L0035: sete al
    L0038: movzx eax, al
    L003b: add rsp, 0x28
    L003f: ret
    L0040: xor eax, eax
    L0042: add rsp, 0x28
    L0046: ret

Program.<<Main>$>g__IsKVP|0_0[[System.Int32, System.Private.CoreLib]]()
    ; pretty much the same as above

Expected codegen:

Program.<<Main>$>g__IsKVP|0_0[[System.Collections.Generic.KeyValuePair`2[[System.Int32, System.Private.CoreLib],[System.Int32, System.Private.CoreLib]], System.Private.CoreLib]]()
    L0000: mov eax, 1
    L0005: ret

Program.<<Main>$>g__IsKVP|0_0[[System.Int32, System.Private.CoreLib]]()
    L0000: xor eax, eax
    L0002: ret

cc. @jkoritzinsky @MichalStrehovsky @EgorBo

Metadata

Metadata

Assignees

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIin-prThere is an active PR which will close this issue when it is merged

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions