From a64735e622b7b55e2d02d1975826f5ca9f101d96 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Wed, 28 May 2025 04:12:19 +0200 Subject: [PATCH 1/2] Trust single-edge synthetic profile --- src/coreclr/jit/compiler.h | 1 + src/coreclr/jit/fgprofile.cpp | 11 +++++++++++ src/coreclr/jit/fgprofilesynthesis.cpp | 11 +++++++++++ 3 files changed, 23 insertions(+) diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 70edd4d4ae2e57..f44cedaf19290f 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -6479,6 +6479,7 @@ class Compiler bool fgPgoSynthesized; bool fgPgoDynamic; bool fgPgoConsistent; + bool fgPgoSingleEdge = false; #ifdef DEBUG bool fgPgoDeferredInconsistency; diff --git a/src/coreclr/jit/fgprofile.cpp b/src/coreclr/jit/fgprofile.cpp index ba6a17697b6413..9dd8ad2c0272d2 100644 --- a/src/coreclr/jit/fgprofile.cpp +++ b/src/coreclr/jit/fgprofile.cpp @@ -89,6 +89,11 @@ bool Compiler::fgHaveSufficientProfileWeights() case ICorJitInfo::PgoSource::Blend: return true; + case ICorJitInfo::PgoSource::Synthesis: + // Single-edge methods always have sufficient profile data. + // Assuming we don't synthesize value and class profile data (which we don't currently). + return fgPgoSingleEdge; + case ICorJitInfo::PgoSource::Static: { // We sometimes call this very early, eg evaluating the prejit root. @@ -134,6 +139,12 @@ bool Compiler::fgHaveTrustedProfileWeights() case ICorJitInfo::PgoSource::Blend: case ICorJitInfo::PgoSource::Text: return true; + + case ICorJitInfo::PgoSource::Synthesis: + // Single-edge methods with synthetic profile are trustful. + // Assuming we don't synthesize value and class profile data (which we don't currently). + return fgPgoSingleEdge; + default: return false; } diff --git a/src/coreclr/jit/fgprofilesynthesis.cpp b/src/coreclr/jit/fgprofilesynthesis.cpp index fd9caa31eec15d..0c2418e5478288 100644 --- a/src/coreclr/jit/fgprofilesynthesis.cpp +++ b/src/coreclr/jit/fgprofilesynthesis.cpp @@ -148,6 +148,17 @@ void ProfileSynthesis::Run(ProfileSynthesisOption option) m_comp->fgPgoSynthesized = true; m_comp->fgPgoConsistent = !m_approximate; + // A simple check whether the current method has more than one edge. + m_comp->fgPgoSingleEdge = true; + for (BasicBlock* const block : m_comp->Blocks()) + { + if (!block->KindIs(BBJ_ALWAYS, BBJ_RETURN)) + { + m_comp->fgPgoSingleEdge = false; + break; + } + } + m_comp->Metrics.ProfileSynthesizedBlendedOrRepaired++; if (m_approximate) From 07ec3e4976e80f6a6add4beaf2e97f7669d5651d Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Wed, 28 May 2025 04:18:02 +0200 Subject: [PATCH 2/2] Update src/coreclr/jit/fgprofilesynthesis.cpp Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/coreclr/jit/fgprofilesynthesis.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/jit/fgprofilesynthesis.cpp b/src/coreclr/jit/fgprofilesynthesis.cpp index 0c2418e5478288..63fd3fd489d26d 100644 --- a/src/coreclr/jit/fgprofilesynthesis.cpp +++ b/src/coreclr/jit/fgprofilesynthesis.cpp @@ -152,7 +152,7 @@ void ProfileSynthesis::Run(ProfileSynthesisOption option) m_comp->fgPgoSingleEdge = true; for (BasicBlock* const block : m_comp->Blocks()) { - if (!block->KindIs(BBJ_ALWAYS, BBJ_RETURN)) + if (block->NumSucc() > 1) { m_comp->fgPgoSingleEdge = false; break;