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
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ namespace ILCompiler.DependencyAnalysis
public abstract partial class SortableDependencyNode : DependencyNodeCore<NodeFactory>, ISortableNode
{
#if !SUPPORT_JIT
// Custom sort order. Used to override the default sorting mechanics.
public int CustomSort = int.MaxValue;

/// <summary>
/// Allows grouping of <see cref="ObjectNode"/> instances such that all nodes in a lower phase
/// will be ordered before nodes in a later phase.
Expand Down Expand Up @@ -148,8 +151,6 @@ public int Compare(DependencyNodeCore<NodeFactory> x1, DependencyNodeCore<NodeFa
}
}

static partial void ApplyCustomSort(SortableDependencyNode x, SortableDependencyNode y, ref int result);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int CompareImpl(SortableDependencyNode x, SortableDependencyNode y, CompilerComparer comparer)
{
Expand All @@ -158,8 +159,7 @@ public static int CompareImpl(SortableDependencyNode x, SortableDependencyNode y

if (phaseX == phaseY)
{
int customSort = 0;
ApplyCustomSort(x, y, ref customSort);
int customSort = x.CustomSort.CompareTo(y.CustomSort);
if (customSort != 0)
return customSort;

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,20 @@
using Internal.TypeSystem;

using ILCompiler.DependencyAnalysis;
#if READYTORUN
using ILCompiler.DependencyAnalysis.ReadyToRun;
#endif
using ILCompiler.DependencyAnalysisFramework;
using System.Linq;
using System.Collections.Immutable;
using System.Text;
using System.Reflection.Metadata.Ecma335;
using ILCompiler.PettisHansenSort;

#if !READYTORUN
using MethodWithGCInfo = ILCompiler.DependencyAnalysis.MethodCodeNode;
#endif

namespace ILCompiler
{
public enum ReadyToRunMethodLayoutAlgorithm
Expand All @@ -24,7 +30,9 @@ public enum ReadyToRunMethodLayoutAlgorithm
ExclusiveWeight,
HotCold,
HotWarmCold,
#if READYTORUN
CallFrequency,
#endif
PettisHansen,
Random,
}
Expand Down Expand Up @@ -79,11 +87,13 @@ public ImmutableArray<DependencyNodeCore<NodeFactory>> ApplyProfilerGuidedMethod
foreach (var methodNode in sortedMethodsList)
{
methodNode.CustomSort = sortOrder;
#if READYTORUN
MethodColdCodeNode methodColdCodeNode = methodNode.ColdCodeNode;
if (methodColdCodeNode != null)
{
methodColdCodeNode.CustomSort = sortOrder + sortedMethodsList.Count;
}
#endif
sortOrder++;
}

Expand Down Expand Up @@ -164,9 +174,11 @@ int ComputeHotWarmColdRegion(MethodWithGCInfo method)
};
break;

#if READYTORUN
case ReadyToRunMethodLayoutAlgorithm.CallFrequency:
methods = MethodCallFrequencySort(methods);
break;
#endif

case ReadyToRunMethodLayoutAlgorithm.PettisHansen:
methods = PettisHansenSort(methods);
Expand Down Expand Up @@ -216,6 +228,7 @@ public CallerCalleeCount(MethodDesc caller, MethodDesc callee, int count)
}
}

#if READYTORUN
/// <summary>
/// Use callchain profile information to generate method ordering. We place
/// callers and callees by traversing the caller-callee pairs in the callchain
Expand Down Expand Up @@ -268,6 +281,7 @@ private List<MethodWithGCInfo> MethodCallFrequencySort(List<MethodWithGCInfo> me
Debug.Assert(outputMethods.Count == methodsToPlace.Count);
return outputMethods;
}
#endif

/// <summary>
/// Sort methods with Pettis-Hansen using call graph data from profile.
Expand Down Expand Up @@ -303,7 +317,9 @@ private List<MethodWithGCInfo> PettisHansenSort(List<MethodWithGCInfo> methodsTo

if (!any)
{
#if READYTORUN
_logger.Writer.WriteLine("Warning: no call graph data was found or a .mibc file was not specified. Skipping Pettis Hansen method ordering.");
#endif
return methodsToPlace;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,6 @@
<Compile Include="Compiler\DependencyAnalysis\ReadyToRun\VirtualResolutionFixupSignature.cs" />
<Compile Include="Compiler\DependencyAnalysis\ReadyToRun\Win32ResourcesNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\ReadyToRunSymbolNodeFactory.cs" />
<Compile Include="Compiler\DependencyAnalysis\SortableDependencyNodeCompilerSpecific.cs" />
<Compile Include="Compiler\DependencyAnalysis\TypeAndMethod.cs" />
<Compile Include="Compiler\IRootingServiceProvider.cs" />
<Compile Include="Compiler\ReadyToRunCompilationModuleGroupBase.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public sealed class RyuJitCompilation : Compilation
private readonly ConditionalWeakTable<Thread, CorInfoImpl> _corinfos = new ConditionalWeakTable<Thread, CorInfoImpl>();
internal readonly RyuJitCompilationOptions _compilationOptions;
private readonly ProfileDataManager _profileDataManager;
private readonly ReadyToRunFileLayoutOptimizer _fileLayoutOptimizer;
private readonly MethodImportationErrorProvider _methodImportationErrorProvider;
private readonly ReadOnlyFieldPolicy _readOnlyFieldPolicy;
private readonly int _parallelism;
Expand All @@ -44,6 +45,8 @@ internal RyuJitCompilation(
MethodImportationErrorProvider errorProvider,
ReadOnlyFieldPolicy readOnlyFieldPolicy,
RyuJitCompilationOptions options,
ReadyToRunMethodLayoutAlgorithm methodLayoutAlgorithm,
ReadyToRunFileLayoutAlgorithm fileLayoutAlgorithm,
int parallelism)
: base(dependencyGraph, nodeFactory, roots, ilProvider, debugInformationProvider, inliningPolicy, logger)
{
Expand All @@ -57,6 +60,8 @@ internal RyuJitCompilation(
_readOnlyFieldPolicy = readOnlyFieldPolicy;

_parallelism = parallelism;

_fileLayoutOptimizer = new ReadyToRunFileLayoutOptimizer(logger, methodLayoutAlgorithm, fileLayoutAlgorithm, profileDataManager, nodeFactory);
}

public ProfileDataManager ProfileData => _profileDataManager;
Expand Down Expand Up @@ -89,6 +94,8 @@ protected override void CompileInternal(string outputFile, ObjectDumper dumper)
_dependencyGraph.ComputeMarkedNodes();
var nodes = _dependencyGraph.MarkedNodeList;

nodes = _fileLayoutOptimizer.ApplyProfilerGuidedMethodSort(nodes);

NodeFactory.SetMarkingComplete();

ObjectWritingOptions options = default;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public sealed class RyuJitCompilationBuilder : CompilationBuilder
// These need to provide reasonable defaults so that the user can optionally skip
// calling the Use/Configure methods and still get something reasonable back.
private KeyValuePair<string, string>[] _ryujitOptions = Array.Empty<KeyValuePair<string, string>>();
private ReadyToRunMethodLayoutAlgorithm _methodLayoutAlgorithm;
private ReadyToRunFileLayoutAlgorithm _fileLayoutAlgorithm;
private ILProvider _ilProvider = new NativeAotILProvider();
private ProfileDataManager _profileDataManager;
private string _jitPath;
Expand All @@ -39,6 +41,13 @@ public RyuJitCompilationBuilder UseJitPath(string jitPath)
return this;
}

public RyuJitCompilationBuilder FileLayoutAlgorithms(ReadyToRunMethodLayoutAlgorithm methodLayoutAlgorithm, ReadyToRunFileLayoutAlgorithm fileLayoutAlgorithm)
{
_methodLayoutAlgorithm = methodLayoutAlgorithm;
_fileLayoutAlgorithm = fileLayoutAlgorithm;
return this;
}

public override CompilationBuilder UseBackendOptions(IEnumerable<string> options)
{
var builder = default(ArrayBuilder<KeyValuePair<string, string>>);
Expand Down Expand Up @@ -126,7 +135,21 @@ public override ICompilation ToCompilation()

JitConfigProvider.Initialize(_context.Target, jitFlagBuilder.ToArray(), _ryujitOptions, _jitPath);
DependencyAnalyzerBase<NodeFactory> graph = CreateDependencyGraph(factory, new ObjectNode.ObjectNodeComparer(CompilerComparer.Instance));
return new RyuJitCompilation(graph, factory, _compilationRoots, _ilProvider, _debugInformationProvider, _logger, _inliningPolicy ?? _compilationGroup, _instructionSetSupport, _profileDataManager, _methodImportationErrorProvider, _readOnlyFieldPolicy, options, _parallelism);
return new RyuJitCompilation(graph,
factory,
_compilationRoots,
_ilProvider,
_debugInformationProvider,
_logger,
_inliningPolicy ?? _compilationGroup,
_instructionSetSupport,
_profileDataManager,
_methodImportationErrorProvider,
_readOnlyFieldPolicy,
options,
_methodLayoutAlgorithm,
_fileLayoutAlgorithm,
_parallelism);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
binaries are up to date and which are stale. -->
<GenerateDependencyFile>false</GenerateDependencyFile>
<Configurations>Debug;Release;Checked</Configurations>
<RunAnalyzers>false</RunAnalyzers>
Copy link
Member

@jkotas jkotas Apr 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intentional?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Matches ILCompiler.ReadyToRun, there are several low value warnings and I'm honestly growing tired of the analyzers and pragma warning suppresions we're accumulating as a result and decided to just take a page from the crossgen project.

</PropertyGroup>

<ItemGroup>
Expand Down Expand Up @@ -98,5 +99,9 @@

<Compile Include="..\ILCompiler.ReadyToRun\Compiler\ProfileData.cs" Link="Pgo\ProfileData.cs" />

<Compile Include="..\ILCompiler.ReadyToRun\Compiler\PettisHansenSort\CallGraphNode.cs" Link="Compiler\PettisHansenSort\CallGraphNode.cs" />
<Compile Include="..\ILCompiler.ReadyToRun\Compiler\PettisHansenSort\DisjointSetForest.cs" Link="Compiler\PettisHansenSort\DisjointSetForest.cs" />
<Compile Include="..\ILCompiler.ReadyToRun\Compiler\PettisHansenSort\PettisHansen.cs" Link="Compiler\PettisHansenSort\PettisHansen.cs" />
<Compile Include="..\ILCompiler.ReadyToRun\Compiler\ReadyToRunFileLayoutOptimizer.cs" Link="Compiler\ReadyToRunFileLayoutOptimizer.cs" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to drop ReadyToRun prefix for this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, just wanted to keep the diff small

</ItemGroup>
</Project>
36 changes: 36 additions & 0 deletions src/coreclr/tools/aot/ILCompiler/ILCompilerRootCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ internal sealed class ILCompilerRootCommand : RootCommand
new("--optimize-time", "--Ot") { Description = "Enable optimizations, favor code speed" };
public Option<string[]> MibcFilePaths { get; } =
new("--mibc", "-m") { DefaultValueFactory = _ => Array.Empty<string>(), Description = "Mibc file(s) for profile guided optimization" };
public Option<ReadyToRunMethodLayoutAlgorithm> MethodLayout { get; } =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do these options have the right default? Or is that a future item?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a copypaste from crossgen - this should default to 0, which means don't do it.

new("--method-layout") { CustomParser = MakeReadyToRunMethodLayoutAlgorithm, DefaultValueFactory = MakeReadyToRunMethodLayoutAlgorithm, Description = "Layout algorithm used by profile-driven optimization for arranging methods in a file.", HelpName = "arg" };
public Option<ReadyToRunFileLayoutAlgorithm> FileLayout { get; } =
new("--file-layout") { CustomParser = MakeReadyToRunFileLayoutAlgorithm, DefaultValueFactory = MakeReadyToRunFileLayoutAlgorithm, Description = "Layout algorithm used by profile-driven optimization for arranging non-method contents in a file.", HelpName = "arg" };
public Option<string[]> SatelliteFilePaths { get; } =
new("--satellite") { DefaultValueFactory = _ => Array.Empty<string>(), Description = "Satellite assemblies associated with inputs/references" };
public Option<bool> EnableDebugInfo { get; } =
Expand Down Expand Up @@ -187,6 +191,8 @@ public ILCompilerRootCommand(string[] args) : base(".NET Native IL Compiler")
Options.Add(OptimizeSpace);
Options.Add(OptimizeTime);
Options.Add(MibcFilePaths);
Options.Add(MethodLayout);
Options.Add(FileLayout);
Options.Add(SatelliteFilePaths);
Options.Add(EnableDebugInfo);
Options.Add(UseDwarf5);
Expand Down Expand Up @@ -411,6 +417,36 @@ private static int MakeParallelism(ArgumentResult result)
return parallelism;
}

private static ReadyToRunMethodLayoutAlgorithm MakeReadyToRunMethodLayoutAlgorithm(ArgumentResult result)
{
if (result.Tokens.Count == 0)
return ReadyToRunMethodLayoutAlgorithm.DefaultSort;

return result.Tokens[0].Value.ToLowerInvariant() switch
{
"defaultsort" => ReadyToRunMethodLayoutAlgorithm.DefaultSort,
"exclusiveweight" => ReadyToRunMethodLayoutAlgorithm.ExclusiveWeight,
"hotcold" => ReadyToRunMethodLayoutAlgorithm.HotCold,
"hotwarmcold" => ReadyToRunMethodLayoutAlgorithm.HotWarmCold,
"pettishansen" => ReadyToRunMethodLayoutAlgorithm.PettisHansen,
"random" => ReadyToRunMethodLayoutAlgorithm.Random,
_ => throw new CommandLineException(result.Tokens[0].Value)
};
}

private static ReadyToRunFileLayoutAlgorithm MakeReadyToRunFileLayoutAlgorithm(ArgumentResult result)
{
if (result.Tokens.Count == 0)
return ReadyToRunFileLayoutAlgorithm.DefaultSort;

return result.Tokens[0].Value.ToLowerInvariant() switch
{
"defaultsort" => ReadyToRunFileLayoutAlgorithm.DefaultSort,
"methodorder" => ReadyToRunFileLayoutAlgorithm.MethodOrder,
_ => throw new CommandLineException(result.Tokens[0].Value)
};
}

#if DEBUG
private static bool DumpReproArguments(CodeGenerationFailedException ex)
{
Expand Down
6 changes: 3 additions & 3 deletions src/coreclr/tools/aot/ILCompiler/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -348,10 +348,10 @@ public int Run()
// Compile
//

var builder = new RyuJitCompilationBuilder(typeSystemContext, compilationGroup);

string compilationUnitPrefix = multiFile ? Path.GetFileNameWithoutExtension(outputFilePath) : "";
builder.UseCompilationUnitPrefix(compilationUnitPrefix);
var builder = new RyuJitCompilationBuilder(typeSystemContext, compilationGroup)
.FileLayoutAlgorithms(Get(_command.MethodLayout), Get(_command.FileLayout))
.UseCompilationUnitPrefix(compilationUnitPrefix);

string[] mibcFilePaths = Get(_command.MibcFilePaths);
if (mibcFilePaths.Length > 0)
Expand Down
Loading