-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Closed
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 SuperPMIbug
Milestone
Description
Reproduction:
using System.Runtime.CompilerServices;
Problem(default);
[MethodImpl(MethodImplOptions.NoInlining)]
static void JitUse<T>(T arg) { }
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
static void Problem(ArrayWrapper a)
{
a = GetArrayLong();
JitUse(a);
JitUse(a);
for (int i = 0; i < 10000; i++)
{
a = GetArray();
JitUse(a.Array[i]);
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
static ArrayWrapper GetArray() => new() { Array = new int[0] };
[MethodImpl(MethodImplOptions.NoInlining)]
static ArrayWrapper GetArrayLong() => new() { Array = new int[10000] };
struct ArrayWrapper
{
public int[] Array;
}We expect to get an IndexOutOfRangeException here, but instead get an AV.
The cause is that loop cloning thinks that the promoted struct's field is invariant in the loop and deletes the bounds check. The reason it thinks it is invariant is because this is a special case in block morphing, where we leave an independently promoted struct alone, and it looks like optIsVarAssgCB does not account for this. I thus conjecture this will also reproduce for the multi-reg assignment form.
Found while experimenting with morphing of the "one field" case into ASG(LCL_VAR(promoted field), BITCAST(field type(CALL))).
@dotnet/jit-contrib
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 SuperPMIbug