Skip to content

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

Open

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

Activity

  1. added
    needs-area-labelAn area label is needed to ensure this gets routed to the appropriate area owners
    on Aug 3, 2025
  2. added
    area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI
    and removed
    needs-area-labelAn area label is needed to ensure this gets routed to the appropriate area owners
    on Aug 3, 2025
  3. dotnet-policy-service commented on Aug 3, 2025

    @dotnet-policy-service
    Contributor

    Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
    See info in area-owners.md if you want to be subscribed.

  4. AndyAyersMS commented on Aug 4, 2025

    @AndyAyersMS
    Member

    FYI @dotnet/jit-contrib

  5. added this to the 10.0.0 milestone on Aug 4, 2025
  6. removed
    untriagedNew issue has not been triaged by the area owner
    on Aug 4, 2025
  7. jakobbotsch commented on Aug 5, 2025

    @jakobbotsch
    Member

    This was fixed by #110171.

    @TheRangerr would you like to see this fix backported to .NET 9, or are you able to switch to use .NET 10 to work around this issue?

  8. modified the milestones: 10.0.0, 9.0.x on Aug 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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