Closed
Description
The JIT has an optimization to treat typeof(T).IsValueType
as a const based on the T being specified, but in some cases the presence of the check is still having an impact on the generated asm.
Non-sensical repro (derived from much more complicated real-world scenario in dotnet/roslyn#51383):
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[DisassemblyDiagnoser]
public class Program
{
static void Main(string[] args) => BenchmarkSwitcher.FromAssemblies(new[] { typeof(Program).Assembly }).Run(args);
}
[DisassemblyDiagnoser]
public class Benchmarks
{
private Wrapper<int> _array = new Wrapper<int>(new int[1]);
private int _offset = 0;
[Benchmark]
public void Test1() => _array.Get1(_offset) = default;
[Benchmark]
public void Test2() => _array.Get2(_offset) = default;
}
public struct Wrapper<T>
{
private T[] _items;
public Wrapper(T[] item) => _items = item;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ref T Get1(int index)
{
return ref _items[index];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ref T Get2(int index)
{
if (typeof(T).IsValueType)
{
return ref _items[index];
}
return ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(_items), index);
}
}
The non-value type branch in Get2 should in theory be removed completely, but using a recent .NET 6 nightly, this results in:
.NET 6.0.0 (6.0.21.11705), X64 RyuJIT
; Benchmarks.Test1()
sub rsp,28
lea rax,[rcx+10]
mov edx,[rcx+8]
mov rax,[rax]
cmp edx,[rax+8]
jae short M00_L00
movsxd rdx,edx
xor ecx,ecx
mov [rax+rdx*4+10],ecx
add rsp,28
ret
M00_L00:
call CORINFO_HELP_RNGCHKFAIL
int 3
; Total bytes of code 39
.NET 6.0.0 (6.0.21.11705), X64 RyuJIT
; Benchmarks.Test2()
sub rsp,28
lea rax,[rcx+10]
mov edx,[rcx+8]
mov rax,[rax]
cmp edx,[rax+8]
jae short M00_L00
movsxd rdx,edx
lea rax,[rax+rdx*4+10]
xor edx,edx
mov [rax],edx
add rsp,28
ret
M00_L00:
call CORINFO_HELP_RNGCHKFAIL
int 3
; Total bytes of code 42
Note the difference between:
xor ecx,ecx
mov [rax+rdx*4+10],ecx
and
lea rax,[rax+rdx*4+10]
xor edx,edx
mov [rax],edx
category:cq
theme:optimization
skill-level:expert
cost:large
impact:medium