Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/coreclr/jit/gentree.h
Original file line number Diff line number Diff line change
Expand Up @@ -6710,6 +6710,10 @@ struct GenTreeVecCon : public GenTree
{
assert(varTypeIsSIMD(type));

// Some uses of GenTreeVecCon do not specify all bits in the vector they are using but failing to zero out the
// buffer will cause determinism issues with the compiler.
memset(&gtSimdVal, 0, sizeof(gtSimdVal));

#if defined(TARGET_XARCH)
assert(sizeof(simd_t) == sizeof(simd64_t));
#else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ public TValue GetOrAdd(TKey key)
public sealed class NodeFactoryOptimizationFlags
{
public bool OptimizeAsyncMethods;
public int DeterminismStress;
public bool PrintReproArgs;
}

// To make the code future compatible to the composite R2R story
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,8 @@ public sealed class ReadyToRunCodegenCompilation : Compilation

public ProfileDataManager ProfileData => _profileData;

public bool DeterminismCheckFailed { get; set; }

public ReadyToRunSymbolNodeFactory SymbolNodeFactory { get; }
public ReadyToRunCompilationModuleGroupBase CompilationModuleGroup { get; }
private readonly int _customPESectionAlignment;
Expand Down Expand Up @@ -806,9 +808,9 @@ void CompileOneMethod(DependencyNodeCore<NodeFactory> dependency, int compileThr
Logger.Writer.WriteLine("Compiling " + methodName);
}

if (_printReproInstructions != null)
if (_nodeFactory.OptimizationFlags.PrintReproArgs)
{
Logger.Writer.WriteLine($"Single method repro args:{_printReproInstructions(method)}");
Logger.Writer.WriteLine($"Single method repro args:{GetReproInstructions(method)}");
}

try
Expand Down Expand Up @@ -885,5 +887,10 @@ public override void Dispose()
{
Array.Clear(_corInfoImpls);
}

public string GetReproInstructions(MethodDesc method)
{
return _printReproInstructions(method);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
using ILCompiler.DependencyAnalysis;
using ILCompiler.DependencyAnalysis.ReadyToRun;
using System.Text;
using System.Runtime.CompilerServices;

namespace Internal.JitInterface
{
Expand Down Expand Up @@ -631,10 +632,50 @@ private static bool FunctionJustThrows(MethodIL ilBody)
return false;
}

class DeterminismData
{
public int Iterations = 0;
public int HashCode = 0;
}

private ConditionalWeakTable<MethodDesc, DeterminismData> _determinismTable = new ConditionalWeakTable<MethodDesc, DeterminismData>();

partial void DetermineIfCompilationShouldBeRetried(ref CompilationResult result)
{
if ((_ilBodiesNeeded == null) && _compilation.NodeFactory.OptimizationFlags.DeterminismStress > 0)
{
HashCode hashCode = default(HashCode);
hashCode.AddBytes(_code);
hashCode.AddBytes(_roData);
int functionOutputHashCode = hashCode.ToHashCode();

lock (_determinismTable)
{
DeterminismData data = _determinismTable.GetOrCreateValue(MethodBeingCompiled);
if (data.Iterations == 0)
{
data.Iterations = 1;
data.HashCode = functionOutputHashCode;
}
else
{
data.Iterations++;
}

if (data.HashCode != functionOutputHashCode)
{
_compilation.DeterminismCheckFailed = true;
_compilation.Logger.LogMessage($"ERROR: Determinism check compiling method '{MethodBeingCompiled}' failed. Use '{_compilation.GetReproInstructions(MethodBeingCompiled)}' on command line to reproduce the failure.");
}
else if (data.Iterations <= _compilation.NodeFactory.OptimizationFlags.DeterminismStress)
{
result = CompilationResult.CompilationRetryRequested;
}
}
}

// If any il bodies need to be recomputed, force recompilation
if ((_ilBodiesNeeded != null) || InfiniteCompileStress.Enabled)
if ((_ilBodiesNeeded != null) || InfiniteCompileStress.Enabled || result == CompilationResult.CompilationRetryRequested)
{
_compilation.PrepareForCompilationRetry(_methodCodeNode, _ilBodiesNeeded);
result = CompilationResult.CompilationRetryRequested;
Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/tools/aot/crossgen2/Crossgen2RootCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,9 @@ internal class Crossgen2RootCommand : RootCommand
public Option<bool> SynthesizeRandomMibc { get; } =
new(new[] { "--synthesize-random-mibc" });

public Option<int> DeterminismStress { get; } =
new(new[] { "--determinism-stress" });

public bool CompositeOrInputBubble { get; private set; }
public OptimizationMode OptimizationMode { get; private set; }
public ParseResult Result { get; private set; }
Expand Down Expand Up @@ -249,6 +252,7 @@ public Crossgen2RootCommand(string[] args) : base(SR.Crossgen2BannerText)
AddOption(MakeReproPath);
AddOption(HotColdSplitting);
AddOption(SynthesizeRandomMibc);
AddOption(DeterminismStress);

this.SetHandler(context =>
{
Expand Down
8 changes: 6 additions & 2 deletions src/coreclr/tools/aot/crossgen2/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,8 @@ private void RunSingleCompilation(Dictionary<string, string> inFilePaths, Instru

NodeFactoryOptimizationFlags nodeFactoryFlags = new NodeFactoryOptimizationFlags();
nodeFactoryFlags.OptimizeAsyncMethods = Get(_command.AsyncMethodOptimization);
nodeFactoryFlags.DeterminismStress = Get(_command.DeterminismStress);
nodeFactoryFlags.PrintReproArgs = Get(_command.PrintReproInstructions);

builder
.UseMapFile(Get(_command.Map))
Expand Down Expand Up @@ -608,8 +610,7 @@ private void RunSingleCompilation(Dictionary<string, string> inFilePaths, Instru
.UseCompilationRoots(compilationRoots)
.UseOptimizationMode(optimizationMode);

if (Get(_command.PrintReproInstructions))
builder.UsePrintReproInstructions(CreateReproArgumentString);
builder.UsePrintReproInstructions(CreateReproArgumentString);

compilation = builder.ToCompilation();

Expand All @@ -620,6 +621,9 @@ private void RunSingleCompilation(Dictionary<string, string> inFilePaths, Instru
compilation.WriteDependencyLog(dgmlLogFileName);

compilation.Dispose();

if (((ReadyToRunCodegenCompilation)compilation).DeterminismCheckFailed)
throw new Exception("Determinism Check Failed");
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/tests/Common/scripts/crossgen2_comparison.py
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,8 @@ def _build_args_crossgen_il_file(self, il_filename, ni_filename, platform_assemb
args.append('-r')
args.append('"' + platform_assemblies_paths + self.platform_directory_sep + '*.dll"' )
args.append('-O')
args.append('--determinism-stress')
args.append('3')
args.append('--out')
args.append(ni_filename)
args.append('--targetos ')
Expand Down