Skip to content

[Release Mode] Conditional check against byte.MaxValue unexpectedly ignored in .NET 9 #118317

@TheRangerr

Description

@TheRangerr

Description

With this code by running dotnet net -c Release

var bytes = new List<byte>();
const int length = 9501;
for(int i = 0; i < length; i++)
    bytes.Add(byte.MaxValue);

for (var i = 0; i < length; i++)
{
    byte value = bytes[i];
    if (value == int.MaxValue) continue; // the bug happens because of this line (remove it and the code will work normally)
    if (value == byte.MaxValue) continue; // it gets skipped
    Console.WriteLine($"{value} == {byte.MaxValue} ? {(value == byte.MaxValue)}");
}

it prints "255 == 255 ? True" but 4 times, and 2 times if length is 9500
however in SharpLab or by running COMPlus_TC_QuickJit=0 dotnet run -c release, it prints "255 == 255 ? False" many times

and if we run this

var bytes = new List<byte>();
const int length = 9501;
for(int i = 0; i < length; i++)
    bytes.Add(byte.MaxValue);

for (int y = 0; y < 128; y++)
{
    for (int x = 0; x < 128; x++)
    {
    
    }   
}

for (var i = 0; i < length; i++)
{
    byte value = bytes[i];
    if (value == int.MaxValue) continue;
    if (value == byte.MaxValue) continue; // it gets skipped
    Console.WriteLine($"{value} == {byte.MaxValue} ? {(value == byte.MaxValue)}"); // Prints "255 == 255 ? False"
}

whether COMPlus_TC_QuickJit=0 is included or not, it will normally print "255 == 255 ? False"
however, if x and y loops to 96 instead of 128, with COMPlus_TC_QuickJit=0 it will print "255 == 255 ? False", and "255 == 255 ? True" without it

and if we run this

var bytes = new List<byte>();
const int length = 9501;
for(int i = 0; i < length; i++)
    bytes.Add(byte.MaxValue);

for (int i = 0; i < 128 * 128; i++) /
{

}
for (var i = 0; i < length; i++)
{
    byte value = bytes[i];
    if (value == int.MaxValue) continue;
    if (value == byte.MaxValue) continue; // gets skipped
    Console.WriteLine($"{value} == {byte.MaxValue} ? {(value == byte.MaxValue)}");
}

with COMPlus_TC_QuickJit=0 it prints "255 == 255 ? False" and "255 == 255 ? True" without it

if we run this

bool IsBugThere(byte u)  // u is byte.MaxValue
{ 
    byte value = u;
    if (value == UInt16.MaxValue) return false;
    if (value == byte.MaxValue) return false;
    Console.WriteLine($"{value} == {byte.MaxValue} ? {(value == byte.MaxValue)}");
    return true;
}

it simply returns false and it doesn't print, however with COMPlus_TC_QuickJit=0 it prints "255 == 255 ? False" and returns true

and if we run this

for(int i = 0; i < 5; i++)
{
    for(int j = 0; j < 1000; j++)
    {
        IsBugThere(255);
    }
    Thread.Sleep(100);
    Console.WriteLine(IsBugThere(byte.MaxValue));
}

it Prints False 4 times then True on the 5th time, however with COMPlus_TC_QuickJit=0 it will print False 5 times

but if we removed the Console.WriteLine from the IsBugThere method,
whether COMPlus_TC_QuickJit=0 is included or not, it returns False in both cases

Reproduction Steps

In the Description

Expected behavior

if (value == byte.MaxValue) continue; should be called if value is 255

Actual behavior

if (value == byte.MaxValue) continue; is being skipped

Regression?

Untested

Known Workarounds

No response

Configuration

.NET 9
Arch Linux
x64
Release Mode

Other information

This bug doesn't seem to exist on .Net 10 Preview from what I've been told

Metadata

Metadata

Assignees

No one assigned

    Labels

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

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions