Skip to content

Commit ea43e17

Browse files
JIT: Run profile repair after frontend phases (#111915)
Part of #107749. Introduce a repair phase that runs profile synthesis if the profile was marked inconsistent at some point, and call it at the end of the JIT frontend. LSRA and block layout are likely to benefit from profile consistency, and this is late enough in the JIT that the sources of diffs should be relatively obvious.
1 parent 9e94b77 commit ea43e17

File tree

5 files changed

+51
-6
lines changed

5 files changed

+51
-6
lines changed

src/coreclr/jit/compiler.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5172,6 +5172,10 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
51725172
// Conditional to Switch conversion
51735173
//
51745174
DoPhase(this, PHASE_SWITCH_RECOGNITION, &Compiler::optSwitchRecognition);
5175+
5176+
// Run profile repair
5177+
//
5178+
DoPhase(this, PHASE_REPAIR_PROFILE, &Compiler::fgRepairProfile);
51755179
}
51765180

51775181
#ifdef DEBUG

src/coreclr/jit/compiler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6654,6 +6654,7 @@ class Compiler
66546654
}
66556655

66566656
void fgRemoveProfileData(const char* reason);
6657+
PhaseStatus fgRepairProfile();
66576658
void fgRepairProfileCondToUncond(BasicBlock* block, FlowEdge* retainedEdge, FlowEdge* removedEdge, int* metric = nullptr);
66586659

66596660
//-------- Insert a statement at the start or end of a basic block --------

src/coreclr/jit/compphases.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ CompPhaseNameMacro(PHASE_INSERT_GC_POLLS, "Insert GC Polls",
115115
CompPhaseNameMacro(PHASE_CREATE_THROW_HELPERS, "Create throw helper blocks", false, -1, true)
116116
CompPhaseNameMacro(PHASE_DETERMINE_FIRST_COLD_BLOCK, "Determine first cold block", false, -1, true)
117117
CompPhaseNameMacro(PHASE_RATIONALIZE, "Rationalize IR", false, -1, false)
118+
CompPhaseNameMacro(PHASE_REPAIR_PROFILE, "Repair profile", false, -1, false)
118119

119120
CompPhaseNameMacro(PHASE_LCLVARLIVENESS, "Local var liveness", true, -1, false)
120121
CompPhaseNameMacro(PHASE_LCLVARLIVENESS_INIT, "Local var liveness init", false, PHASE_LCLVARLIVENESS, false)

src/coreclr/jit/fgprofile.cpp

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4977,9 +4977,38 @@ bool Compiler::fgDebugCheckOutgoingProfileData(BasicBlock* block, ProfileChecks
49774977

49784978
#endif // DEBUG
49794979

4980+
//------------------------------------------------------------------------
4981+
// fgRepairProfile: If we have PGO data and the profile is inconsistent,
4982+
// run synthesis to re-establish consistency.
4983+
//
4984+
// Returns:
4985+
// PhaseStatus indicating if profile synthesis ran or not.
4986+
//
4987+
PhaseStatus Compiler::fgRepairProfile()
4988+
{
4989+
if (fgIsUsingProfileWeights())
4990+
{
4991+
if (fgPgoConsistent)
4992+
{
4993+
JITDUMP("Profile is already consistent.\n");
4994+
}
4995+
else
4996+
{
4997+
ProfileSynthesis::Run(this, ProfileSynthesisOption::RetainLikelihoods);
4998+
return PhaseStatus::MODIFIED_EVERYTHING;
4999+
}
5000+
}
5001+
else
5002+
{
5003+
JITDUMP("No PGO data. Skipping profile repair.\n");
5004+
}
5005+
5006+
return PhaseStatus::MODIFIED_NOTHING;
5007+
}
5008+
49805009
//------------------------------------------------------------------------
49815010
// fgRepairProfileCondToUncond: attempt to repair profile after modifying
4982-
// a conditinal branch to an unconditional branch.
5011+
// a conditional branch to an unconditional branch.
49835012
//
49845013
// Arguments:
49855014
// block - block that was just altered

src/coreclr/jit/fgprofilesynthesis.cpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,20 @@
3030
//
3131
void ProfileSynthesis::Run(ProfileSynthesisOption option)
3232
{
33-
m_dfsTree = m_comp->fgComputeDfs();
34-
m_loops = FlowGraphNaturalLoops::Find(m_dfsTree);
35-
m_improperLoopHeaders = m_loops->ImproperLoopHeaders();
36-
m_entryBlock = m_comp->opts.IsOSR() ? m_comp->fgEntryBB : m_comp->fgFirstBB;
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+
// Profile synthesis can be run before or after morph, so tolerate (non-)canonical method entries
45+
//
46+
m_entryBlock = (m_comp->opts.IsOSR() && (m_comp->fgEntryBB != nullptr)) ? m_comp->fgEntryBB : m_comp->fgFirstBB;
3747

3848
// Retain or compute edge likelihood information
3949
//
@@ -104,7 +114,7 @@ void ProfileSynthesis::Run(ProfileSynthesisOption option)
104114
// belief that the profile should be somewhat flatter.
105115
//
106116
unsigned retries = 0;
107-
while (m_approximate && (retries < maxRepairRetries))
117+
while ((option != ProfileSynthesisOption::RetainLikelihoods) && m_approximate && (retries < maxRepairRetries))
108118
{
109119
JITDUMP("\n\n[%d] Retrying reconstruction with blend factor " FMT_WT ", because %s\n", retries, m_blendFactor,
110120
m_cappedCyclicProbabilities ? "capped cyclic probabilities" : "solver failed to converge");

0 commit comments

Comments
 (0)