-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JIT: Wrong result computed with forward sub enabled on x64 Windows/Linux #68049
Comments
Tagging subscribers to this area: @JulieLeeMSFT Issue DetailsDescriptionThe following program computes a wrong result when forward sub is enabled. Reproduction Steps// Generated by Fuzzlyn v1.5 on 2022-04-13 11:38:00
// Run on X64 Linux
// Seed: 1784259920377383051
// Reduced from 110.5 KiB to 0.9 KiB in 00:00:57
// Debug: Outputs 1
// Release: Outputs 0
public struct S0
{
public uint F0;
public long F1;
public S0(uint f0): this()
{
F0 = f0;
}
public ulong M5()
{
var vr1 = new ushort[]{0};
M6(vr1);
return 1;
}
public void M6(ushort[] arg0)
{
this = new S0(0);
}
}
public class Program
{
public static IRuntime s_rt;
public static void Main()
{
s_rt = new Runtime();
var vr4 = new S0[]{new S0(1)};
var vr5 = new short[]{0};
bool vr6 = M1(vr4, vr5) <= 1;
}
public static short M1(S0[] arg0, short[] arg1)
{
long var3 = arg0[0].F1;
var3 = (arg0[0].F0 & (byte)arg0[0].M5());
s_rt.WriteLine(var3);
return arg1[0];
}
}
public interface IRuntime
{
void WriteLine<T>(T value);
}
public class Runtime : IRuntime
{
public void WriteLine<T>(T value) => System.Console.WriteLine(value);
} Expected behaviorSame result. Actual behaviorDifferent result. Regression?No response Known WorkaroundsNo response ConfigurationReproduces on both x64 Windows and Linux. Other informationcc @dotnet/jit-contrib
|
Similar looking example: // Generated by Fuzzlyn v1.5 on 2022-04-13 11:57:44
// Run on X64 Windows
// Seed: 15524766127402705757
// Reduced from 138.3 KiB to 1.6 KiB in 00:02:03
// Debug: Outputs 1
// Release: Outputs 254
public struct S0
{
public short F0;
public int F3;
public byte M29(ref sbyte[] arg0)
{
if (this.F0 > this.F3)
{
this.F0 = (short)~this.F0;
sbyte[, ] var0 = new sbyte[, ]{{1}};
}
return Program.M31();
}
}
public class Program
{
public static IRuntime s_rt;
public static short[] s_2 = new short[]{0};
public static sbyte[][] s_8 = new sbyte[][]{new sbyte[]{1}};
public static byte s_9 = 28;
public static void Main()
{
CollectibleALC alc = new CollectibleALC();
System.Reflection.Assembly asm = alc.LoadFromAssemblyPath(System.Reflection.Assembly.GetExecutingAssembly().Location);
System.Reflection.MethodInfo mi = asm.GetType(typeof(Program).FullName).GetMethod(nameof(MainInner));
System.Type runtimeTy = asm.GetType(typeof(Runtime).FullName);
mi.Invoke(null, new object[]{System.Activator.CreateInstance(runtimeTy)});
}
public static void MainInner(IRuntime rt)
{
s_rt = rt;
S0[] vr2 = new S0[]{new S0()};
s_2[0] = vr2[0].F0++;
byte vr3 = (byte)(vr2[0].F0 % (long)vr2[0].M29(ref s_8[0]));
s_rt.WriteLine("c_747", vr3);
}
public static byte M31()
{
return s_9;
}
}
public interface IRuntime
{
void WriteLine<T>(string site, T value);
}
public class Runtime : IRuntime
{
public void WriteLine<T>(string site, T value) => System.Console.WriteLine(value);
}
public class CollectibleALC : System.Runtime.Loader.AssemblyLoadContext
{
public CollectibleALC(): base(true)
{
}
} Not sure why these are just showing up now. |
Yeah, seems odd -- maybe once we root cause this it will make sense. |
In the second case, it looks like during assertion prop we decide we can reverse the order of the operands to the
Note the |
Ah, looks like the culprit setting Note in the above
so the bug is that we lose flags on the first operand subtree. Before remorphing in VN:
after remorphing
and this appears to be caused by
So, need to see why morph is losing this flag. |
This seems to be the culprit: runtime/src/coreclr/jit/morph.cpp Lines 12958 to 12996 in 0b1a80d
|
Worked up a plausible fix. Testing it locally. |
Seems to be holding up: main...AndyAyersMS:Fix68049 Minimal SPMI diffs. Will put up a PR once I've set up test cases. |
Perhaps exposed by #64581? |
Definitely. We used to have two An alternative fix would be to copy the (Note that |
Morph may transform `IND(COMMA(..., z))` into `COMMA(... , IND(z))` and when doing so it was not computing appropriately conservative flags for the new `IND`. In particular it was losing `GTF_GLOB_REF`. This allowed subsequent opts to reorder operands in an unsafe manner. Fixes dotnet#68049.
Right. Went with something like this. There are a few other places in morph with similar "idoms" for setting indir flags. Perhaps what they're doing is ok. Hard to tell. Seems like we might want to set up a stress mode that reverses operands when we think it's legal to do so, regardless of whether it is "cost effective". Or perhaps a randomized costing mode that really tries to scramble things up. |
Morph may transform `IND(COMMA(..., z))` into `COMMA(... , IND(z))` and when doing so it was not computing appropriately conservative flags for the new `IND`. In particular it was losing `GTF_GLOB_REF`. This allowed subsequent opts to reorder operands in an unsafe manner. Fixes #68049.
Description
The following program computes a wrong result when forward sub is enabled.
Reproduction Steps
Expected behavior
Same result.
Actual behavior
Different result.
Regression?
No response
Known Workarounds
No response
Configuration
Reproduces on both x64 Windows and Linux.
Other information
cc @dotnet/jit-contrib
The text was updated successfully, but these errors were encountered: