using System;
using System.Runtime.CompilerServices;
class P
{
static double[] a = new double[1];
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
static double Test(int i)
{
return Math.Min(a[i], double.NaN);
}
static void Main()
{
try
{
Console.WriteLine("NO EXCEPTION, result=" + Test(5));
}
catch (IndexOutOfRangeException)
{
Console.WriteLine("IndexOutOfRangeException (correct)");
}
}
}
Expected: IndexOutOfRangeException (correct) — a[5] on a length-1 array must throw before Math.Min returns.
Actual: NO EXCEPTION, result=NaN — the array load, including its bounds check, is discarded.
Notes:
run.ps1 -Cs repro.cs (csc -optimize+, Checked corerun x64). Compiling with -optimize- prints the correct IndexOutOfRangeException, so it is purely the optimized-JIT path.
src\coreclr\jit\gentree.cpp in gtNewSimdMinMaxNode: the isNaN shortcut does return cnsNode; (non-Number) / return otherNode; (Number) with no gtExtractSideEffList/COMMA for the discarded operand.
- Only on the non-AVX10v2 xarch path (the AVX10v2 branch is taken earlier and is unaffected). Same shape works for
MathF.Min, Math.Max, and the MinNumber/MaxNumber variants (drop the other operand there).
Expected:
IndexOutOfRangeException (correct)—a[5]on a length-1 array must throw beforeMath.Minreturns.Actual:
NO EXCEPTION, result=NaN— the array load, including its bounds check, is discarded.Notes:
run.ps1 -Cs repro.cs(csc-optimize+, Checked corerun x64). Compiling with-optimize-prints the correctIndexOutOfRangeException, so it is purely the optimized-JIT path.src\coreclr\jit\gentree.cppingtNewSimdMinMaxNode: theisNaNshortcut doesreturn cnsNode;(non-Number) /return otherNode;(Number) with nogtExtractSideEffList/COMMA for the discarded operand.MathF.Min,Math.Max, and theMinNumber/MaxNumbervariants (drop the other operand there).