runtime: Wrong integer promotion in release

For .NET core 2.1, the following program outputs 1023 in debug, but 255 in release.

using System;

class C0
{
    public sbyte F;
}

public class Program
{
    public static void Main()
    {
        C0 var0 = new C0 { F = -1 };
        ulong var1 = (ulong)(1000 | (byte)var0.F);
        Console.WriteLine(var1);
    }
}

This issue repros on .NET framework 4.6.1 as well with 64-bit JIT (it does not repro with 32-bit JIT). The compiler used is csc.exe 2.8.3.62923 (7aafab56).

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 20 (20 by maintainers)

Commits related to this issue

Most upvoted comments

I opened dotnet/coreclr#18238.

And out of curiosity - how did you come up with this example?

As a project for a university course we wrote a fuzzer that generates C# programs, https://github.com/jakobbotsch/Fuzzlyn. It generates a program, then compares the results of all static and local variables when running in debug and release mode. I have many more examples, but we have no automatic reducer yet, so I have been reducing them to minimal repros by hand. I am not too familiar with the JIT internals, so it is a little hard for me to know which problems are new and which aren’t.

EDIT: It is of course heavily inspired by Csmith, which I’m sure you’re familiar with.

I spent the weekend writing an automatic reducer and running it on all our examples. The programs can be seen here. I have looked through most of them and I believe they are all instances of the bugs I have already reported. though it’s hard for me to tell for sure. Once these issues are fixed I will rerun and filter away the non-interesting programs.

Here is a case which looks different, although from some experiments I am guessing it is also related to CSE:

Yep, it’s the same incorrect value numbering of indirs. var2[0] and var1[0] have the same value number (even if one produces 0xffff and the other 0xffffffff) and CSE replaces var1[0] with the value produced earlier by var2[0].

And incorrect value numbering aside, CSE is dubious anyway. It doesn’t make sense to introduce a new temporary variable to hold the result of var2[0] when this is actually a constant. And even if it’s not a constant it would make more sense to re-use whatever value was used to initialize var1[0] so that the temporary has a shorter life.

@mikedn

though it mentions a different exception!?

OverflowException derives from ArithmeticException, so if OverflowException is thrown, both specs should be satisfied.

As a project for a university course we wrote a fuzzer that generates C# programs, https://github.com/jakobbotsch/Fuzzlyn.

@jakobbotsch Very good work - does it test all possible syntax variations or just a subset of C#/IL?