Closed
Description
Reproduction:
public class Program
{
private static int _intStatic;
private static void Main()
{
for (int i = 0; i < Environment.ProcessorCount; i++)
{
new Thread(() =>
{
while (true)
{
Volatile.Write(ref _intStatic, 0);
Volatile.Write(ref _intStatic, 1);
}
}).Start();
}
while (true)
{
Problem(ref _intStatic);
}
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
private static void Problem(ref int a)
{
var b = Volatile.Read(ref a) == 0;
var c = b;
if (b)
{
Assert(c);
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static void Assert(bool b)
{
if (!b)
{
throw new Exception("!!!");
}
}
}
Eventually this program will throw an exception, even as one would think it never should.
The cause is that in the branch forward substitution optimization, we copy the indirection and end up with two indirections (that can, naturally, disagree).
It is unclear to me whether this new behavior can be considered correct or not.
@dotnet/jit-contrib