Description
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