Skip to content

Commit b3e1d4a

Browse files
JIT: Add post-morph profile repair phase (#113896)
Part of #107749. The latter half of the JIT frontend contains numerous optimizations that rely on block weights to compute the profitability of their transformations, and may benefit from more consistent profile data. Morph and flow opts frequently redirect flow out of blocks and into other ones, and the corresponding tweaks to the profile are usually too local to reduce/increase flow along affected paths. This gives downstream phases inaccurate ideas about which blocks are newly cold/hot, and other profile transformations (such as fgExpandRarelyRunBlocks) can further propagate inaccuracies. Thus, re-running synthesis shortly after morph seems like an opportune and cheap place to fix the profile. Like the late profile synthesis run, we aren't interested in changing edge likelihoods here -- we just want to propagate changes in block weights through the flowgraph. I also included some dead code cleanup I meant to do in a previous PR.
1 parent 3564cb9 commit b3e1d4a

File tree

6 files changed

+30
-87
lines changed

6 files changed

+30
-87
lines changed

src/coreclr/jit/compiler.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4657,6 +4657,10 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
46574657
//
46584658
DoPhase(this, PHASE_FIND_LOOPS, &Compiler::optFindLoopsPhase);
46594659

4660+
// Re-establish profile consistency, now that inlining and morph have run.
4661+
//
4662+
DoPhase(this, PHASE_REPAIR_PROFILE_POST_MORPH, &Compiler::fgRepairProfile);
4663+
46604664
// Scale block weights and mark run rarely blocks.
46614665
//
46624666
DoPhase(this, PHASE_SET_BLOCK_WEIGHTS, &Compiler::optSetBlockWeights);
@@ -4962,9 +4966,9 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
49624966
//
49634967
DoPhase(this, PHASE_OPTIMIZE_PRE_LAYOUT, &Compiler::optOptimizePreLayout);
49644968

4965-
// Run profile repair
4969+
// Ensure profile is consistent before starting backend phases
49664970
//
4967-
DoPhase(this, PHASE_REPAIR_PROFILE, &Compiler::fgRepairProfile);
4971+
DoPhase(this, PHASE_REPAIR_PROFILE_PRE_LAYOUT, &Compiler::fgRepairProfile);
49684972
}
49694973

49704974
#ifdef DEBUG

src/coreclr/jit/compiler.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6139,8 +6139,6 @@ class Compiler
61396139

61406140
void fgCompactBlock(BasicBlock* block);
61416141

6142-
BasicBlock* fgConnectFallThrough(BasicBlock* bSrc, BasicBlock* bDst);
6143-
61446142
bool fgRenumberBlocks();
61456143

61466144
bool fgExpandRarelyRunBlocks();

src/coreclr/jit/compphases.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,8 @@ CompPhaseNameMacro(PHASE_INSERT_GC_POLLS, "Insert GC Polls",
116116
CompPhaseNameMacro(PHASE_CREATE_THROW_HELPERS, "Create throw helper blocks", false, -1, true)
117117
CompPhaseNameMacro(PHASE_DETERMINE_FIRST_COLD_BLOCK, "Determine first cold block", false, -1, true)
118118
CompPhaseNameMacro(PHASE_RATIONALIZE, "Rationalize IR", false, -1, false)
119-
CompPhaseNameMacro(PHASE_REPAIR_PROFILE, "Repair profile", false, -1, false)
119+
CompPhaseNameMacro(PHASE_REPAIR_PROFILE_POST_MORPH, "Repair profile post-morph", false, -1, false)
120+
CompPhaseNameMacro(PHASE_REPAIR_PROFILE_PRE_LAYOUT, "Repair profile pre-layout", false, -1, false)
120121

121122
CompPhaseNameMacro(PHASE_LCLVARLIVENESS, "Local var liveness", true, -1, false)
122123
CompPhaseNameMacro(PHASE_LCLVARLIVENESS_INIT, "Local var liveness init", false, PHASE_LCLVARLIVENESS, false)

src/coreclr/jit/fgbasic.cpp

Lines changed: 0 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -5248,68 +5248,6 @@ void Compiler::fgPrepareCallFinallyRetForRemoval(BasicBlock* block)
52485248
block->SetKind(BBJ_ALWAYS);
52495249
}
52505250

5251-
//------------------------------------------------------------------------
5252-
// fgConnectFallThrough: fix flow from a block that previously had a fall through
5253-
//
5254-
// Arguments:
5255-
// bSrc - source of fall through
5256-
// bDst - target of fall through
5257-
//
5258-
// Returns:
5259-
// Newly inserted block after bSrc that jumps to bDst,
5260-
// or nullptr if bSrc already falls through to bDst
5261-
//
5262-
BasicBlock* Compiler::fgConnectFallThrough(BasicBlock* bSrc, BasicBlock* bDst)
5263-
{
5264-
assert(bSrc != nullptr);
5265-
assert(fgPredsComputed);
5266-
BasicBlock* jmpBlk = nullptr;
5267-
5268-
/* If bSrc falls through to a block that is not bDst, we will insert a jump to bDst */
5269-
5270-
if (bSrc->KindIs(BBJ_COND) && bSrc->FalseTargetIs(bDst) && !bSrc->NextIs(bDst))
5271-
{
5272-
// Add a new block after bSrc which jumps to 'bDst'
5273-
jmpBlk = fgNewBBafter(BBJ_ALWAYS, bSrc, true);
5274-
FlowEdge* const oldEdge = bSrc->GetFalseEdge();
5275-
5276-
// Access the likelihood of oldEdge before
5277-
// it gets reset by SetTargetEdge below.
5278-
//
5279-
FlowEdge* const newEdge = fgAddRefPred(jmpBlk, bSrc, oldEdge);
5280-
fgReplacePred(oldEdge, jmpBlk);
5281-
jmpBlk->SetTargetEdge(oldEdge);
5282-
assert(jmpBlk->TargetIs(bDst));
5283-
bSrc->SetFalseEdge(newEdge);
5284-
5285-
// When adding a new jmpBlk we will set the bbWeight and bbFlags
5286-
//
5287-
if (fgHaveProfileWeights())
5288-
{
5289-
jmpBlk->setBBProfileWeight(newEdge->getLikelyWeight());
5290-
}
5291-
else
5292-
{
5293-
// We set the bbWeight to the smaller of bSrc->bbWeight or bDst->bbWeight
5294-
if (bSrc->bbWeight < bDst->bbWeight)
5295-
{
5296-
jmpBlk->bbWeight = bSrc->bbWeight;
5297-
jmpBlk->CopyFlags(bSrc, BBF_RUN_RARELY);
5298-
}
5299-
else
5300-
{
5301-
jmpBlk->bbWeight = bDst->bbWeight;
5302-
jmpBlk->CopyFlags(bDst, BBF_RUN_RARELY);
5303-
}
5304-
}
5305-
5306-
JITDUMP("Added an unconditional jump to " FMT_BB " after block " FMT_BB "\n", jmpBlk->GetTarget()->bbNum,
5307-
bSrc->bbNum);
5308-
}
5309-
5310-
return jmpBlk;
5311-
}
5312-
53135251
//------------------------------------------------------------------------
53145252
// fgRenumberBlocks: update block bbNums to reflect bbNext order
53155253
//

src/coreclr/jit/fgprofilesynthesis.cpp

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -30,26 +30,6 @@
3030
//
3131
void ProfileSynthesis::Run(ProfileSynthesisOption option)
3232
{
33-
if (m_dfsTree == nullptr)
34-
{
35-
m_dfsTree = m_comp->fgComputeDfs();
36-
m_loops = FlowGraphNaturalLoops::Find(m_dfsTree);
37-
m_improperLoopHeaders = m_loops->ImproperLoopHeaders();
38-
}
39-
else
40-
{
41-
assert(m_loops != nullptr);
42-
}
43-
44-
if (m_loops->NumLoops() > 0)
45-
{
46-
m_cyclicProbabilities = new (m_comp, CMK_Pgo) weight_t[m_loops->NumLoops()];
47-
}
48-
49-
// Profile synthesis can be run before or after morph, so tolerate (non-)canonical method entries
50-
//
51-
m_entryBlock = (m_comp->opts.IsOSR() && (m_comp->fgEntryBB != nullptr)) ? m_comp->fgEntryBB : m_comp->fgFirstBB;
52-
5333
// Retain or compute edge likelihood information
5434
//
5535
switch (option)

src/coreclr/jit/fgprofilesynthesis.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,29 @@ class ProfileSynthesis
4242
private:
4343
ProfileSynthesis(Compiler* compiler)
4444
: m_comp(compiler)
45+
, m_dfsTree(compiler->m_dfsTree)
46+
, m_loops(compiler->m_loops)
47+
// Profile synthesis can be run before or after morph, so tolerate (non-)canonical method entries
48+
, m_entryBlock((compiler->opts.IsOSR() && (compiler->fgEntryBB != nullptr)) ? compiler->fgEntryBB
49+
: compiler->fgFirstBB)
4550
{
51+
// If the Compiler object didn't give us flowgraph annotations to use, re-compute them
52+
if (m_dfsTree == nullptr)
53+
{
54+
m_dfsTree = compiler->fgComputeDfs();
55+
m_loops = FlowGraphNaturalLoops::Find(m_dfsTree);
56+
}
57+
else
58+
{
59+
assert(m_loops != nullptr);
60+
}
61+
62+
m_improperLoopHeaders = m_loops->ImproperLoopHeaders();
63+
64+
if (m_loops->NumLoops() > 0)
65+
{
66+
m_cyclicProbabilities = new (compiler, CMK_Pgo) weight_t[m_loops->NumLoops()];
67+
}
4668
}
4769

4870
static constexpr weight_t exceptionWeight = 0.00001;

0 commit comments

Comments
 (0)