Skip to content
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

Add ability for crossgen2 to synthesize PGO histograms #77683

Merged
merged 38 commits into from
Nov 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
255a128
Add ability for crossgen2 to synthesize PGO histograms
jakobbotsch Oct 31, 2022
82430a9
Fix embedding synthesized PGO data
jakobbotsch Nov 1, 2022
c1f63dc
Fix isSynthesized out var
jakobbotsch Nov 1, 2022
f94760f
JIT: Support profiles with only histograms
jakobbotsch Nov 1, 2022
5b13d09
JitDisasm header nit
jakobbotsch Nov 1, 2022
e9b3e90
Iterate profile right after retrieving it
jakobbotsch Nov 1, 2022
e6c0ace
Revert profile weight schema element
jakobbotsch Nov 1, 2022
75d7737
Support type based GDV too
jakobbotsch Nov 1, 2022
b13d824
Avoid empty histograms
jakobbotsch Nov 2, 2022
6e518d4
Merge branch 'main' of github.com:dotnet/runtime into crossgen2-synth…
jakobbotsch Nov 2, 2022
e825974
Move to PublishCode
jakobbotsch Nov 2, 2022
8a48190
Remove dead code
jakobbotsch Nov 2, 2022
58b4007
Nits
jakobbotsch Nov 2, 2022
47c0bbd
Remove more dead code, use List<T>.Contains
jakobbotsch Nov 2, 2022
e1421e9
Avoid multiple iteration
jakobbotsch Nov 2, 2022
70001b6
Fix build
jakobbotsch Nov 2, 2022
8979a0d
Add to crossgen2 test wrapper script invocation
jakobbotsch Nov 2, 2022
a8ff57f
Unrelated R2R comment fix
jakobbotsch Nov 2, 2022
545744c
Fix concurrency
jakobbotsch Nov 2, 2022
30eacb4
Add some EH
jakobbotsch Nov 2, 2022
d1a2124
Fix wrong metadata name in test
jakobbotsch Nov 2, 2022
d651826
Unify RunCrossGen2 environment variable to be set to 1 instead of "true"
jakobbotsch Nov 2, 2022
00b702a
Also do it for LargeVersionBubble and fix comment
jakobbotsch Nov 2, 2022
a262bc1
Merge branch 'main' of github.com:dotnet/runtime into crossgen2-synth…
jakobbotsch Nov 3, 2022
beee8e1
Try to ensure synthesized types/methods are loadable
jakobbotsch Nov 4, 2022
1ac4985
Hook up to testing, mark a test as incompatible with synthesis
jakobbotsch Nov 4, 2022
31864dc
Fix rerunning crossgen2 tests
jakobbotsch Nov 4, 2022
fa0c61b
Merge branch 'main' of github.com:dotnet/runtime into crossgen2-synth…
jakobbotsch Nov 7, 2022
9332810
Skip generic types/methods in histograms
jakobbotsch Nov 7, 2022
88bc9ed
Revert "Unrelated R2R comment fix"
jakobbotsch Nov 7, 2022
0c6b101
Nit
jakobbotsch Nov 7, 2022
a3d6c7a
Nit
jakobbotsch Nov 7, 2022
636ef8e
Check IsTypicalMethodDefinition for delegate invoke too
jakobbotsch Nov 7, 2022
85f8425
Merge branch 'main' of github.com:dotnet/runtime into crossgen2-synth…
jakobbotsch Nov 12, 2022
0db6992
Add some comments
jakobbotsch Nov 7, 2022
eff1b82
Unify crossgen2 and ILC's additional dependencies handling
jakobbotsch Nov 15, 2022
5fc9321
Merge branch 'main' of github.com:dotnet/runtime into crossgen2-synth…
jakobbotsch Nov 17, 2022
0943776
Fix build after merge
jakobbotsch Nov 17, 2022
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
37 changes: 28 additions & 9 deletions src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
using ILCompiler.DependencyAnalysis.ReadyToRun;
#endif

using DependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore<ILCompiler.DependencyAnalysis.NodeFactory>.DependencyList;

#pragma warning disable IDE0060

namespace Internal.JitInterface
Expand Down Expand Up @@ -556,10 +558,15 @@ private void PublishCode()
}
}
}

if (_synthesizedPgoDependencies != null)
{
Debug.Assert(_compilation.NodeFactory.InstrumentationDataTable != null, "Expected InstrumentationDataTable to be non-null with synthesized PGO data to embed");
_compilation.NodeFactory.InstrumentationDataTable.EmbedSynthesizedPgoDataForMethods(ref _additionalDependencies, _synthesizedPgoDependencies);
}
#else
var methodIL = (MethodIL)HandleToObject((void*)_methodScope);
CodeBasedDependencyAlgorithm.AddDependenciesDueToMethodCodePresence(ref _additionalDependencies, _compilation.NodeFactory, MethodBeingCompiled, methodIL);
_methodCodeNode.InitializeNonRelocationDependencies(_additionalDependencies);
_methodCodeNode.InitializeDebugInfo(_debugInfo);

LocalVariableDefinition[] locals = methodIL.GetLocals();
Expand All @@ -569,6 +576,8 @@ private void PublishCode()

_methodCodeNode.InitializeLocalTypes(localTypes);
#endif

_methodCodeNode.InitializeNonRelocationDependencies(_additionalDependencies);
}

private void PublishROData()
Expand Down Expand Up @@ -659,12 +668,12 @@ private void CompileMethodCleanup()

_gcInfo = null;
_ehClauses = null;
_additionalDependencies = null;

#if !READYTORUN
_debugInfo = null;

_additionalDependencies = null;
#endif

_debugLocInfos = null;
_debugVarInfos = null;
_lastException = null;
Expand All @@ -677,6 +686,7 @@ private void CompileMethodCleanup()
_stashedPrecodeFixups.Clear();
_stashedInlinedMethods.Clear();
_ilBodiesNeeded = null;
_synthesizedPgoDependencies = null;
#endif

_instantiationToJitVisibleInstantiation = null;
Expand Down Expand Up @@ -3427,6 +3437,8 @@ private bool getTailCallHelpers(ref CORINFO_RESOLVED_TOKEN callToken, CORINFO_SI
private byte[] _gcInfo;
private CORINFO_EH_CLAUSE[] _ehClauses;

private DependencyList _additionalDependencies;

private void allocMem(ref AllocMemArgs args)
{
args.hotCodeBlock = (void*)GetPin(_code = new byte[args.hotCodeSize]);
Expand Down Expand Up @@ -3951,11 +3963,6 @@ private uint getJitFlags(ref CORJIT_FLAGS flags, uint sizeInBytes)
return (uint)sizeof(CORJIT_FLAGS);
}

private PgoSchemaElem[] getPgoInstrumentationResults(MethodDesc method)
{
return _compilation.ProfileData[method]?.SchemaData;
}

private MemoryStream _cachedMemoryStream = new MemoryStream();

public static void ComputeJitPgoInstrumentationSchema(Func<object, IntPtr> objectToHandle, PgoSchemaElem[] pgoResultsSchemas, out PgoInstrumentationSchema[] nativeSchemas, MemoryStream instrumentationData, Func<TypeDesc, bool> typeFilter = null)
Expand Down Expand Up @@ -4033,7 +4040,19 @@ private HRESULT getPgoInstrumentationResults(CORINFO_METHOD_STRUCT_* ftnHnd, ref

if (!_pgoResults.TryGetValue(methodDesc, out PgoInstrumentationResults pgoResults))
{
var pgoResultsSchemas = getPgoInstrumentationResults(methodDesc);
#if READYTORUN
PgoSchemaElem[] pgoResultsSchemas = _compilation.ProfileData.GetAllowSynthesis(_compilation, methodDesc, out bool isSynthesized)?.SchemaData;

if (pgoResultsSchemas != null && isSynthesized && _compilation.ProfileData.EmbedPgoDataInR2RImage)
{
if (_synthesizedPgoDependencies == null)
_synthesizedPgoDependencies = new HashSet<MethodDesc>();

_synthesizedPgoDependencies.Add(methodDesc);
}
#else
PgoSchemaElem[] pgoResultsSchemas = _compilation.ProfileData[methodDesc]?.SchemaData;
#endif
if (pgoResultsSchemas == null)
{
pgoResults.hr = HRESULT.E_NOTIMPL;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
Expand All @@ -22,13 +23,12 @@ public class InstrumentationDataTableNode : HeaderTableNode
{
private readonly NodeFactory _factory;
private ReadyToRunSymbolNodeFactory _symbolNodeFactory;
private readonly MethodDesc[] _instrumentationDataMethods;
private readonly ProfileDataManager _profileDataManager;
private readonly HashSet<MethodDesc> _methodsWithSynthesizedPgoData = new HashSet<MethodDesc>();

public InstrumentationDataTableNode(NodeFactory factory, MethodDesc[] instrumentationDataMethods, ProfileDataManager profileDataManager)
public InstrumentationDataTableNode(NodeFactory factory, ProfileDataManager profileDataManager)
{
_factory = factory;
_instrumentationDataMethods = instrumentationDataMethods;
_profileDataManager = profileDataManager;
}

Expand Down Expand Up @@ -183,12 +183,44 @@ public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilde
sb.Append("__ReadyToRunInstrumentationDataTable");
}

// Register some MDs that had synthesized PGO data created to be physically embedded by this node, and add
// the appropriate dependencies of the embedding to a dependency list.
public void EmbedSynthesizedPgoDataForMethods(ref DependencyList dependencies, IEnumerable<MethodDesc> mds)
{
PgoValueEmitter pgoEmitter = new PgoValueEmitter(_factory.CompilationModuleGroup, _symbolNodeFactory, false);
foreach (MethodDesc md in mds)
{
PgoSchemaElem[] schema = _profileDataManager[md].SchemaData;
Debug.Assert(schema != null);

lock (_methodsWithSynthesizedPgoData)
{
_methodsWithSynthesizedPgoData.Add(md);
}

PgoProcessor.EncodePgoData(schema, pgoEmitter, false);
}

foreach (Import imp in pgoEmitter.ReferencedImports)
{
dependencies ??= new DependencyList();
dependencies.Add(imp, "Dependency of synthesized PGO data");
}
}

protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory)
{
PgoValueEmitter pgoEmitter = new PgoValueEmitter(_factory.CompilationModuleGroup, _symbolNodeFactory, false);
foreach (MethodDesc method in _instrumentationDataMethods)
foreach (EcmaModule inputModule in _factory.CompilationModuleGroup.CompilationModuleSet)
{
PgoProcessor.EncodePgoData(_profileDataManager[method].SchemaData, pgoEmitter, false);
foreach (MethodDesc method in _profileDataManager.GetInputProfileDataMethodsForModule(inputModule))
{
PgoSchemaElem[] schema = _profileDataManager[method].SchemaData;
if (schema != null)
{
PgoProcessor.EncodePgoData(schema, pgoEmitter, false);
}
}
}
DependencyListEntry[] symbols = new DependencyListEntry[pgoEmitter.ReferencedImports.Count];
for (int i = 0; i < symbols.Length; i++)
Expand All @@ -199,7 +231,6 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact
return new DependencyList(symbols);
}


public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
if (relocsOnly)
Expand All @@ -216,7 +247,25 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)

Dictionary<byte[], BlobVertex> uniqueInstrumentationData = new Dictionary<byte[], BlobVertex>(ByteArrayComparer.Instance);

foreach (MethodDesc method in _instrumentationDataMethods)
HashSet<MethodDesc> methodsToInsert = new();
foreach (EcmaModule inputModule in _factory.CompilationModuleGroup.CompilationModuleSet)
{
foreach (MethodDesc method in _profileDataManager.GetInputProfileDataMethodsForModule(inputModule))
{
PgoSchemaElem[] schema = _profileDataManager[method].SchemaData;
if (schema != null)
{
methodsToInsert.Add(method);
}
}
}

methodsToInsert.UnionWith(_methodsWithSynthesizedPgoData);

MethodDesc[] methods = methodsToInsert.ToArray();
methods.MergeSort(TypeSystemComparer.Instance.Compare);

foreach (MethodDesc method in methods)
{
pgoEmitter.Clear();
PgoProcessor.EncodePgoData(CorInfoImpl.ConvertTypeHandleHistogramsToCompactTypeHistogramFormat(_profileDataManager[method].SchemaData, factory.CompilationModuleGroup), pgoEmitter, false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Diagnostics;
using System.Linq;
using Internal.JitInterface;
using Internal.Pgo;
using Internal.Text;
using Internal.TypeSystem;
using Internal.TypeSystem.Ecma;
Expand All @@ -29,6 +30,7 @@ public class MethodWithGCInfo : ObjectNode, IMethodBodyNode, ISymbolDefinitionNo
private List<ISymbolNode> _fixups;
private MethodDesc[] _inlinedMethods;
private bool _lateTriggeredCompilation;
private DependencyList _nonRelocationDependencies;

public MethodWithGCInfo(MethodDesc methodDesc)
{
Expand Down Expand Up @@ -272,6 +274,11 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact
dependencyList.Add(node, "classMustBeLoadedBeforeCodeIsRun");
}

if (_nonRelocationDependencies != null)
{
dependencyList.AddRange(_nonRelocationDependencies);
}

return dependencyList;
}

Expand Down Expand Up @@ -382,6 +389,11 @@ public void InitializeInliningInfo(MethodDesc[] inlinedMethods, NodeFactory fact
RegisterInlineeModuleIndices(factory);
}

public void InitializeNonRelocationDependencies(DependencyList dependencies)
{
_nonRelocationDependencies = dependencies;
}

public int Offset => 0;
public override bool IsShareable => throw new NotImplementedException();
public override bool ShouldSkipEmittingObjectNode(NodeFactory factory) => IsEmpty;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -779,22 +779,26 @@ public void AttachToDependencyGraph(DependencyAnalyzerBase<NodeFactory> graph, I
if ((ProfileDataManager != null) && (ProfileDataManager.EmbedPgoDataInR2RImage))
{
// Profile instrumentation data attaches here
HashSet<MethodDesc> methodsToInsertInstrumentationDataFor = new HashSet<MethodDesc>();
foreach (EcmaModule inputModule in CompilationModuleGroup.CompilationModuleSet)

bool HasAnyProfileDataForInput()
{
foreach (MethodDesc method in ProfileDataManager.GetMethodsForModuleDesc(inputModule))
foreach (EcmaModule inputModule in CompilationModuleGroup.CompilationModuleSet)
{
if (ProfileDataManager[method].SchemaData != null)
foreach (MethodDesc method in ProfileDataManager.GetInputProfileDataMethodsForModule(inputModule))
{
methodsToInsertInstrumentationDataFor.Add(method);
if (ProfileDataManager[method].SchemaData != null)
{
return true;
}
}
}

return false;
}
if (methodsToInsertInstrumentationDataFor.Count != 0)

if (ProfileDataManager.SynthesizeRandomPgoData || HasAnyProfileDataForInput())
{
MethodDesc[] methodsToInsert = methodsToInsertInstrumentationDataFor.ToArray();
methodsToInsert.MergeSort(TypeSystemComparer.Instance.Compare);
InstrumentationDataTable = new InstrumentationDataTableNode(this, methodsToInsert, ProfileDataManager);
InstrumentationDataTable = new InstrumentationDataTableNode(this, ProfileDataManager);
Header.Add(Internal.Runtime.ReadyToRunSectionType.PgoInstrumentationData, InstrumentationDataTable, InstrumentationDataTable);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,8 @@ public abstract class ProfileData
public abstract IEnumerable<MethodProfileData> GetAllMethodProfileData();
public abstract byte[] GetMethodBlockCount(MethodDesc m);

public static void MergeProfileData(ref bool partialNgen, Dictionary<MethodDesc, MethodProfileData> mergedProfileData, ProfileData profileData)
public static void MergeProfileData(Dictionary<MethodDesc, MethodProfileData> mergedProfileData, ProfileData profileData)
{
if (profileData.PartialNGen)
partialNgen = true;

PgoSchemaElem[][] schemaElemMergerArray = new PgoSchemaElem[2][];

foreach (MethodProfileData data in profileData.GetAllMethodProfileData())
Expand Down
Loading