Skip to content

Commit 572533b

Browse files
JIT: Try to retain entry weight during profile synthesis (dotnet#111971)
Part of dotnet#107749. Prerequisite to dotnet#111915. Regardless of the profile synthesis option used, we ought to maintain the method's entry weight, which is computed by summing all non-flow weight into the entry block. Ideally, we'd use fgCalledCount here, but this isn't computed until after morph, and we need to tolerate the existence of multiple entry blocks for methods with OSR pre-morph.
1 parent 847a8c2 commit 572533b

File tree

3 files changed

+32
-52
lines changed

3 files changed

+32
-52
lines changed

src/coreclr/jit/fgprofile.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -2942,7 +2942,7 @@ PhaseStatus Compiler::fgIncorporateProfileData()
29422942

29432943
// We now always run repair, to get consistent initial counts
29442944
//
2945-
JITDUMP("\n%sRepairing profile...\n", opts.IsOSR() ? "blending" : "repairing");
2945+
JITDUMP("\nRepairing profile...\n");
29462946
ProfileSynthesis::Run(this, ProfileSynthesisOption::RepairLikelihoods);
29472947
}
29482948

src/coreclr/jit/fgprofilesynthesis.cpp

+29-50
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ void ProfileSynthesis::Run(ProfileSynthesisOption option)
3333
m_dfsTree = m_comp->fgComputeDfs();
3434
m_loops = FlowGraphNaturalLoops::Find(m_dfsTree);
3535
m_improperLoopHeaders = m_loops->ImproperLoopHeaders();
36+
m_entryBlock = m_comp->opts.IsOSR() ? m_comp->fgEntryBB : m_comp->fgFirstBB;
3637

3738
// Retain or compute edge likelihood information
3839
//
@@ -71,13 +72,18 @@ void ProfileSynthesis::Run(ProfileSynthesisOption option)
7172
break;
7273
}
7374

75+
// Save entry block's weight.
76+
// If the entry block is a loop header, its weight will be overwritten by ComputeCyclicProbabilities.
77+
//
78+
weight_t entryBlockWeight = m_entryBlock->bbWeight;
79+
7480
// Determine cyclic probabilities
7581
//
7682
ComputeCyclicProbabilities();
7783

7884
// Assign weights to entry points in the flow graph
7985
//
80-
AssignInputWeights(option);
86+
AssignInputWeights(entryBlockWeight);
8187

8288
// Compute the block weights given the inputs and edge likelihoods
8389
//
@@ -108,12 +114,13 @@ void ProfileSynthesis::Run(ProfileSynthesisOption option)
108114
m_approximate = false;
109115
m_overflow = false;
110116
m_cappedCyclicProbabilities = 0;
117+
entryBlockWeight = m_entryBlock->bbWeight;
111118

112119
// Regularize the edge likelihoods...
113120
//
114121
BlendLikelihoods();
115122
ComputeCyclicProbabilities();
116-
AssignInputWeights(option);
123+
AssignInputWeights(entryBlockWeight);
117124
ComputeBlockWeights();
118125

119126
// Increase blend factor and decrease synthetic loop likelihoods
@@ -975,7 +982,7 @@ void ProfileSynthesis::ComputeCyclicProbabilities(FlowGraphNaturalLoop* loop)
975982
// fgAssignInputWeights: provide initial profile weights for all blocks
976983
//
977984
// Arguments:
978-
// option - profile synthesis option
985+
// entryBlockWeight - total flow (including method call count) into the entry block
979986
//
980987
// Notes:
981988
// For finallys we will pick up new entry weights when we process
@@ -986,51 +993,26 @@ void ProfileSynthesis::ComputeCyclicProbabilities(FlowGraphNaturalLoop* loop)
986993
//
987994
// Some parts of the jit are sensitive to the absolute weights.
988995
//
989-
void ProfileSynthesis::AssignInputWeights(ProfileSynthesisOption option)
996+
void ProfileSynthesis::AssignInputWeights(weight_t entryBlockWeight)
990997
{
991-
// Determine input weight for method entry
998+
// Determine input weight for method entry.
999+
// Ideally, we'd use fgCalledCount, but it may not be available yet.
9921000
//
993-
BasicBlock* const entryBlock = m_comp->opts.IsOSR() ? m_comp->fgEntryBB : m_comp->fgFirstBB;
994-
weight_t entryWeight = BB_UNITY_WEIGHT;
1001+
weight_t entryWeight = entryBlockWeight;
1002+
FlowGraphNaturalLoop* const loop = m_loops->GetLoopByHeader(m_entryBlock);
9951003

996-
switch (option)
1004+
if (loop != nullptr)
9971005
{
998-
case ProfileSynthesisOption::BlendLikelihoods:
999-
case ProfileSynthesisOption::RepairLikelihoods:
1000-
{
1001-
// Try and retain entryBlock's weight.
1002-
// Easiest to do when the block has no preds.
1003-
//
1004-
if (entryBlock->hasProfileWeight())
1005-
{
1006-
weight_t currentEntryWeight = entryBlock->bbWeight;
1007-
1008-
if (!Compiler::fgProfileWeightsEqual(currentEntryWeight, 0.0, epsilon))
1009-
{
1010-
if (entryBlock->bbPreds == nullptr)
1011-
{
1012-
entryWeight = currentEntryWeight;
1013-
}
1014-
else
1015-
{
1016-
// TODO: something similar to how we compute fgCalledCount;
1017-
// try and sum return weights?
1018-
}
1019-
}
1020-
else
1021-
{
1022-
// Entry weight was zero or nearly zero, just use default
1023-
}
1024-
}
1025-
else
1026-
{
1027-
// Entry was unprofiled, just use default
1028-
}
1029-
break;
1030-
}
1006+
const weight_t cyclicProbability = m_cyclicProbabilities[loop->GetIndex()];
1007+
assert(cyclicProbability != BB_ZERO_WEIGHT);
1008+
entryWeight /= cyclicProbability;
1009+
}
10311010

1032-
default:
1033-
break;
1011+
// Fall back to BB_UNITY_WEIGHT if we have zero entry weight
1012+
//
1013+
if (Compiler::fgProfileWeightsEqual(entryWeight, BB_ZERO_WEIGHT, epsilon))
1014+
{
1015+
entryWeight = BB_UNITY_WEIGHT;
10341016
}
10351017

10361018
// Reset existing weights
@@ -1042,8 +1024,8 @@ void ProfileSynthesis::AssignInputWeights(ProfileSynthesisOption option)
10421024

10431025
// Set entry weight
10441026
//
1045-
JITDUMP("Synthesis: entry " FMT_BB " has input weight " FMT_WT "\n", entryBlock->bbNum, entryWeight);
1046-
entryBlock->setBBProfileWeight(entryWeight);
1027+
JITDUMP("Synthesis: entry " FMT_BB " has input weight " FMT_WT "\n", m_entryBlock->bbNum, entryWeight);
1028+
m_entryBlock->setBBProfileWeight(entryWeight);
10471029

10481030
// Determine input weight for EH regions, if any.
10491031
//
@@ -1210,9 +1192,6 @@ void ProfileSynthesis::GaussSeidelSolver()
12101192
bool checkEntryExitWeight = true;
12111193
bool showDetails = false;
12121194

1213-
// Remember the entry block
1214-
//
1215-
BasicBlock* const entryBlock = m_comp->opts.IsOSR() ? m_comp->fgEntryBB : m_comp->fgFirstBB;
12161195
JITDUMP("Synthesis solver: flow graph has %u improper loop headers\n", m_improperLoopHeaders);
12171196

12181197
// This is an iterative solver, and it may require a lot of iterations
@@ -1268,7 +1247,7 @@ void ProfileSynthesis::GaussSeidelSolver()
12681247

12691248
// Some blocks have additional profile weights that don't come from flow edges.
12701249
//
1271-
if (block == entryBlock)
1250+
if (block == m_entryBlock)
12721251
{
12731252
newWeight = block->bbWeight;
12741253
entryWeight = newWeight;
@@ -1459,7 +1438,7 @@ void ProfileSynthesis::GaussSeidelSolver()
14591438
if (entryExitRelResidual > relResidual)
14601439
{
14611440
relResidual = entryExitRelResidual;
1462-
relResidualBlock = entryBlock;
1441+
relResidualBlock = m_entryBlock;
14631442
}
14641443
}
14651444

src/coreclr/jit/fgprofilesynthesis.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ class ProfileSynthesis
7575
void ComputeCyclicProbabilities();
7676
void ComputeCyclicProbabilities(FlowGraphNaturalLoop* loop);
7777

78-
void AssignInputWeights(ProfileSynthesisOption option);
78+
void AssignInputWeights(weight_t entryBlockWeight);
7979

8080
void ComputeBlockWeights();
8181
void ComputeBlockWeight(BasicBlock* block);
@@ -86,6 +86,7 @@ class ProfileSynthesis
8686
Compiler* const m_comp;
8787
FlowGraphDfsTree* m_dfsTree = nullptr;
8888
FlowGraphNaturalLoops* m_loops = nullptr;
89+
BasicBlock* m_entryBlock = nullptr;
8990
weight_t* m_cyclicProbabilities = nullptr;
9091
weight_t m_blendFactor = initialBlendFactor;
9192
weight_t m_loopExitLikelihood = loopExitLikelihood;

0 commit comments

Comments
 (0)