Skip to content

JIT: Ensure profile synthesis converges for trivial cases #116502

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

Conversation

amanasifkhalid
Copy link
Member

While triaging regressions from profile maintenance work, I noticed profile repair passes regularly fail to converge and mark the profile as inconsistent, despite the weights clearly being consistent. This is because the Gauss-Seidel solver will only run for one iteration when a method doesn't have unnatural loops, but the first iteration's relative residual calculation is always too large to be considered converged. We should skip the residual checks for trivial flowgraph shapes to avoid this (like we already do during profile incorporation), but we still need some mechanism to detect if the weight coming out of a loop exceeds the weight into it; so far, I think checking method entry/exit weights for balance is sufficient.

Here's an example of the behavior this fixes:

*************** Starting PHASE Repair profile post-morph
ccp: BB26 :: 1.0 (header)
ccp: BB12 :: 0
ccp: BB11 :: 1
ccp: BB06 :: 0.01460244
ccp backedge BB06 (0.01460244) -> BB26 likelihood 0.9466215
For loop at BB26 cyclic weight is 0.01382299 cyclic probability is 1.014017
Synthesis: entry BB01 has input weight 149534
Synthesis: exception weight 1e-05
Computing block weights
Synthesis solver: flow graph has 0 improper loop headers
Entry weight 149534 exit weight 149534 residual 2.910383e-11
iteration 0: max residual is at BB01 : 149534
iteration 0: max rel residual is at BB01 : 1.49534e+17

failed to converge at iteration 1 rel residual 1.49534e+17 eigenvalue 0
Profile is inconsistent. Bypassing post-phase consistency checks.
fgCalledCount is 149534

*************** Finishing PHASE Repair profile post-morph
Trees after Repair profile post-morph

---------------------------------------------------------------------------------------------------------------------------------------------------------------------
BBnum BBid ref try hnd preds           weight      IBC [IL range]   [jump]                            [EH region]        [flags]
---------------------------------------------------------------------------------------------------------------------------------------------------------------------
BB01 [0000]  1                             1    149534 [000..003)-> BB03(0.769),BB25(0.231) ( cond )                   i IBC
BB03 [0002]  1       BB01                  0.77 114934 [005..009)-> BB25(0.0534),BB28(0.947)  ( cond )                   i IBC idxlen
BB28 [0031]  1       BB03                  0.73 108799 [009..???)-> BB26(1)                 (always)                   IBC internal
BB26 [0029]  2       BB06,BB28             0.74 110324 [009..00A)-> BB12(0),BB11(1)         ( cond )                   i IBC idxlen bwd
BB11 [0009]  1       BB26                  0.74 110324 [009..00A)-> BB06(0.0146),BB05(0.985)  ( cond )                   i IBC bwd
BB12 [0010]  1       BB26                  0         0 [009..017)-> BB06(0.0146),BB05(0.985)  ( cond )                   i IBC rare hascall gcsafe bwd
BB06 [0005]  2       BB11,BB12             0.01   1611 [019..026)-> BB26(0.947),BB29(0.0534)  ( cond )                   i IBC idxlen bwd
BB05 [0004]  2       BB11,BB12             0.73 108713 [017..019)                           (return)                   i IBC
BB29 [0032]  1       BB06                  0.00     86 [003..???)-> BB25(1)                 (always)                   IBC internal
BB25 [0028]  3       BB01,BB03,BB29        0.27  40821 [003..028)                           (return)                   i IBC
---------------------------------------------------------------------------------------------------------------------------------------------------------------------

This should improve TP a bit, as we won't needlessly run repair as often.

@Copilot Copilot AI review requested due to automatic review settings June 10, 2025 21:00
@github-actions github-actions bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Jun 10, 2025
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes an issue where the Gauss-Seidel profile synthesis does not converge for trivial flowgraph shapes by skipping unnecessary residual checks and adding a weight balance check instead.

  • Fixed a typo in a comment within flowgraph.cpp.
  • Adjusted the convergence logic in fgprofilesynthesis.cpp to check entry/exit weight balance when synthesis runs after the importer.

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/coreclr/jit/flowgraph.cpp Corrected a typo in a comment.
src/coreclr/jit/fgprofilesynthesis.cpp Updated solver logic to check weight balance for convergence.

@@ -582,7 +582,7 @@ PhaseStatus Compiler::fgImport()
}

// Now that we've made it through the importer, we know the IL was valid.
// If we synthesized profile data and though it should be consistent,
// If we synthesized profile data and thought it should be consistent,
Copy link
Preview

Copilot AI Jun 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment typo has been fixed. This update improves clarity by correcting 'though' to 'thought'.

Suggested change
// If we synthesized profile data and thought it should be consistent,
// If we synthesized profile data and though it should be consistent,

Copilot uses AI. Check for mistakes.

{
converged = true;
converged = !m_comp->fgImportDone || m_comp->fgProfileWeightsConsistent(entryWeight, exitWeight);
Copy link
Preview

Copilot AI Jun 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Consider splitting this compound condition into separate if/else branches or adding inline comments to enhance readability and clarify the two distinct cases being handled.

Suggested change
converged = !m_comp->fgImportDone || m_comp->fgProfileWeightsConsistent(entryWeight, exitWeight);
// Case 1: If the importer is not done, we consider it converged.
if (!m_comp->fgImportDone)
{
converged = true;
}
// Case 2: Check if the profile weights are consistent.
else if (m_comp->fgProfileWeightsConsistent(entryWeight, exitWeight)
{
converged = true;
}
else
{
converged = false;
}

Copilot uses AI. Check for mistakes.

Copy link
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

@amanasifkhalid
Copy link
Member Author

cc @dotnet/jit-contrib, @AndyAyersMS PTAL. Small diffs from floating-point precision changes in block weights. CI failures dead-lettered and/or have missing logs -- I suspect they aren't related. Thanks!

@amanasifkhalid
Copy link
Member Author

/ba-g unrelated infra failures

@amanasifkhalid amanasifkhalid merged commit cd1f465 into dotnet:main Jun 11, 2025
107 of 110 checks passed
@amanasifkhalid amanasifkhalid deleted the fgPgoConsistent-precision branch June 11, 2025 15:04
@github-actions github-actions bot locked and limited conversation to collaborators Jul 12, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants