Open
Description
From #49608 (review)
A type check e.g. if (typeof(T) == typeof(string))
in a shared generic doesn't eliminate casts to and from a confirmed exact type
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
public class HashSet<T>
{
private IEqualityComparer<T>? _comparer;
public HashSet(IEqualityComparer<T>? comparer)
{
if (comparer is not null && comparer != EqualityComparer<T>.Default)
{
_comparer = comparer;
}
if (typeof(T) == typeof(string))
{
// Double casts to concrete and back to generic not eliminated
_comparer = (IEqualityComparer<T>?)
NonRandomizedStringEqualityComparer.GetStringComparer(
(IEqualityComparer<string>?)_comparer);
}
}
}
public static class NonRandomizedStringEqualityComparer
{
[MethodImpl(MethodImplOptions.NoInlining)]
public static IEqualityComparer<string>? GetStringComparer(IEqualityComparer<string>? comparer)
{
return comparer;
}
}
Data
Ideally the non Unsafe version:
if (typeof(T) == typeof(string))
{
_comparer = (IEqualityComparer<T>?)NonRandomizedStringEqualityComparer
.GetStringComparer((IEqualityComparer<string>?)_comparer);
}
Would produce the same asm as the Unsafe version:
if (typeof(T) == typeof(string))
{
_comparer = Unsafe.As<IEqualityComparer<T>?>(
NonRandomizedStringEqualityComparer.GetStringComparer(
Unsafe.As<IEqualityComparer<string>?>(_comparer)));
}
However the regular casting includes a double cast even though its passed the typeof(TKey) == typeof(string)
guard which implies the casts will always succeed.
G_M17833_IG07:
mov rcx, qword ptr [rsi]
call [CORINFO_HELP_READYTORUN_GENERIC_HANDLE]
cmp rax, qword ptr [(reloc)]
jne SHORT G_M17833_IG09
;; bbWeight=1 PerfScore 8.00
G_M17833_IG08:
- mov rcx, qword ptr [rsi]
- call [CORINFO_HELP_READYTORUN_GENERIC_HANDLE]
- mov rdi, rax
mov rcx, gword ptr [rsi+24]
- call [CORINFO_HELP_READYTORUN_CHKCAST]
- mov rcx, rax
call [NonRandomizedStringEqualityComparer:GetStringComparer(IEqualityComparer`1):IEqualityComparer`1]
- mov rdx, rax
- mov rcx, rdi
- call [CORINFO_HELP_CHKCASTANY]
lea rcx, bword ptr [rsi+24]
mov rdx, rax
call [CORINFO_HELP_ASSIGN_REF]
- ;; bbWeight=0.50 PerfScore 10.38
+ ;; bbWeight=0.50 PerfScore 4.38
G_M17833_IG09:
nop
;; bbWeight=1 PerfScore 0.25
category:cq
theme:generics
skill-level:expert
cost:medium
impact:small