Skip to content

JIT: (bug) constant-NaN Math.Min/Max folding drops the other argument's side effects #133718

Description

@EgorBo
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).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions