Skip to content

JIT: Run profile repair after frontend phases #111915

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

Merged
merged 7 commits into from
Feb 21, 2025
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
4 changes: 4 additions & 0 deletions src/coreclr/jit/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5172,6 +5172,10 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
// Conditional to Switch conversion
//
DoPhase(this, PHASE_SWITCH_RECOGNITION, &Compiler::optSwitchRecognition);

// Run profile repair
//
DoPhase(this, PHASE_REPAIR_PROFILE, &Compiler::fgRepairProfile);
}

#ifdef DEBUG
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -6651,6 +6651,7 @@ class Compiler
}

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

//-------- Insert a statement at the start or end of a basic block --------
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/jit/compphases.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ CompPhaseNameMacro(PHASE_INSERT_GC_POLLS, "Insert GC Polls",
CompPhaseNameMacro(PHASE_CREATE_THROW_HELPERS, "Create throw helper blocks", false, -1, true)
CompPhaseNameMacro(PHASE_DETERMINE_FIRST_COLD_BLOCK, "Determine first cold block", false, -1, true)
CompPhaseNameMacro(PHASE_RATIONALIZE, "Rationalize IR", false, -1, false)
CompPhaseNameMacro(PHASE_REPAIR_PROFILE, "Repair profile", false, -1, false)

CompPhaseNameMacro(PHASE_LCLVARLIVENESS, "Local var liveness", true, -1, false)
CompPhaseNameMacro(PHASE_LCLVARLIVENESS_INIT, "Local var liveness init", false, PHASE_LCLVARLIVENESS, false)
Expand Down
31 changes: 30 additions & 1 deletion src/coreclr/jit/fgprofile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4977,9 +4977,38 @@ bool Compiler::fgDebugCheckOutgoingProfileData(BasicBlock* block, ProfileChecks

#endif // DEBUG

//------------------------------------------------------------------------
// fgRepairProfile: If we have PGO data and the profile is inconsistent,
// run synthesis to re-establish consistency.
//
// Returns:
// PhaseStatus indicating if profile synthesis ran or not.
//
PhaseStatus Compiler::fgRepairProfile()
{
if (fgIsUsingProfileWeights())
{
if (fgPgoConsistent)
{
JITDUMP("Profile is already consistent.\n");
}
else
{
ProfileSynthesis::Run(this, ProfileSynthesisOption::RetainLikelihoods);
return PhaseStatus::MODIFIED_EVERYTHING;
}
}
else
{
JITDUMP("No PGO data. Skipping profile repair.\n");
}

return PhaseStatus::MODIFIED_NOTHING;
}

//------------------------------------------------------------------------
// fgRepairProfileCondToUncond: attempt to repair profile after modifying
// a conditinal branch to an unconditional branch.
// a conditional branch to an unconditional branch.
//
// Arguments:
// block - block that was just altered
Expand Down
20 changes: 15 additions & 5 deletions src/coreclr/jit/fgprofilesynthesis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,20 @@
//
void ProfileSynthesis::Run(ProfileSynthesisOption option)
{
m_dfsTree = m_comp->fgComputeDfs();
m_loops = FlowGraphNaturalLoops::Find(m_dfsTree);
m_improperLoopHeaders = m_loops->ImproperLoopHeaders();
m_entryBlock = m_comp->opts.IsOSR() ? m_comp->fgEntryBB : m_comp->fgFirstBB;
if (m_dfsTree == nullptr)
{
m_dfsTree = m_comp->fgComputeDfs();
m_loops = FlowGraphNaturalLoops::Find(m_dfsTree);
m_improperLoopHeaders = m_loops->ImproperLoopHeaders();
}
else
{
assert(m_loops != nullptr);
}

// Profile synthesis can be run before or after morph, so tolerate (non-)canonical method entries
//
m_entryBlock = (m_comp->opts.IsOSR() && (m_comp->fgEntryBB != nullptr)) ? m_comp->fgEntryBB : m_comp->fgFirstBB;

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