Skip to content
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

JIT: Ensure BBF_PROF_WEIGHT flag is set when we have PGO data #111780

Merged
merged 1 commit into from
Jan 24, 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
2 changes: 1 addition & 1 deletion src/coreclr/jit/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4571,7 +4571,7 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
// Note: the importer is sensitive to block weights, so this has
// to happen before importation.
//
activePhaseChecks |= PhaseChecks::CHECK_PROFILE;
activePhaseChecks |= PhaseChecks::CHECK_PROFILE | PhaseChecks::CHECK_PROFILE_FLAGS;
DoPhase(this, PHASE_INCPROFILE, &Compiler::fgIncorporateProfileData);

activePhaseChecks |= PhaseChecks::CHECK_FG_INIT_BLOCK;
Expand Down
10 changes: 6 additions & 4 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -1542,8 +1542,9 @@ enum class PhaseChecks : unsigned int
CHECK_LOOPS = 1 << 4, // loop integrity/canonicalization
CHECK_LIKELIHOODS = 1 << 5, // profile data likelihood integrity
CHECK_PROFILE = 1 << 6, // profile data full integrity
CHECK_LINKED_LOCALS = 1 << 7, // check linked list of locals
CHECK_FG_INIT_BLOCK = 1 << 8, // flow graph has an init block
CHECK_PROFILE_FLAGS = 1 << 7, // blocks with profile-derived weights have BBF_PROF_WEIGHT flag set
CHECK_LINKED_LOCALS = 1 << 8, // check linked list of locals
CHECK_FG_INIT_BLOCK = 1 << 9, // flow graph has an init block
};

inline constexpr PhaseChecks operator ~(PhaseChecks a)
Expand Down Expand Up @@ -1608,8 +1609,9 @@ enum class ProfileChecks : unsigned int
CHECK_HASLIKELIHOOD = 1 << 0, // check all FlowEdges for hasLikelihood
CHECK_LIKELIHOODSUM = 1 << 1, // check block succesor likelihoods sum to 1
CHECK_LIKELY = 1 << 2, // fully check likelihood based weights
RAISE_ASSERT = 1 << 3, // assert on check failure
CHECK_ALL_BLOCKS = 1 << 4, // check blocks even if bbHasProfileWeight is false
CHECK_FLAGS = 1 << 3, // check blocks with profile-derived weights have BBF_PROF_WEIGHT flag set
RAISE_ASSERT = 1 << 4, // assert on check failure
CHECK_ALL_BLOCKS = 1 << 5, // check blocks even if bbHasProfileWeight is false
};

inline constexpr ProfileChecks operator ~(ProfileChecks a)
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/fginline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1514,7 +1514,7 @@ void Compiler::fgInsertInlineeBlocks(InlineInfo* pInlineInfo)
noway_assert(!block->hasTryIndex());
noway_assert(!block->hasHndIndex());
block->copyEHRegion(iciBlock);
block->CopyFlags(iciBlock, BBF_BACKWARD_JUMP);
block->CopyFlags(iciBlock, BBF_BACKWARD_JUMP | BBF_PROF_WEIGHT);

// Update block nums appropriately
//
Expand Down
30 changes: 27 additions & 3 deletions src/coreclr/jit/fgprofile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4571,6 +4571,12 @@ void Compiler::fgDebugCheckProfile(PhaseChecks checks)
else if (hasFlag(checks, PhaseChecks::CHECK_PROFILE))
{
ProfileChecks profileChecks = ProfileChecks::CHECK_LIKELY | ProfileChecks::RAISE_ASSERT;

if (hasFlag(checks, PhaseChecks::CHECK_PROFILE_FLAGS))
{
profileChecks |= ProfileChecks::CHECK_FLAGS;
}

fgDebugCheckProfileWeights(profileChecks);
}
else if (hasFlag(checks, PhaseChecks::CHECK_LIKELIHOODS))
Expand Down Expand Up @@ -4611,6 +4617,7 @@ bool Compiler::fgDebugCheckProfileWeights(ProfileChecks checks)
const bool verifyLikelyWeights = hasFlag(checks, ProfileChecks::CHECK_LIKELY);
const bool verifyHasLikelihood = hasFlag(checks, ProfileChecks::CHECK_HASLIKELIHOOD);
const bool verifyLikelihoodSum = hasFlag(checks, ProfileChecks::CHECK_LIKELIHOODSUM);
const bool checkProfileFlag = hasFlag(checks, ProfileChecks::CHECK_FLAGS) && fgIsUsingProfileWeights();
const bool assertOnFailure = hasFlag(checks, ProfileChecks::RAISE_ASSERT) && fgPgoConsistent;
const bool checkAllBlocks = hasFlag(checks, ProfileChecks::CHECK_ALL_BLOCKS);

Expand All @@ -4633,6 +4640,7 @@ bool Compiler::fgDebugCheckProfileWeights(ProfileChecks checks)
unsigned problemBlocks = 0;
unsigned unprofiledBlocks = 0;
unsigned profiledBlocks = 0;
unsigned unflaggedBlocks = 0;
bool entryProfiled = false;
bool exitProfiled = false;
bool hasTry = false;
Expand All @@ -4643,10 +4651,20 @@ bool Compiler::fgDebugCheckProfileWeights(ProfileChecks checks)
//
for (BasicBlock* const block : Blocks())
{
if (!block->hasProfileWeight() && !checkAllBlocks)
if (!block->hasProfileWeight())
{
unprofiledBlocks++;
continue;
if (checkProfileFlag && (block->bbPreds != nullptr))
Copy link
Member

Choose a reason for hiding this comment

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

Can you explain the exclusion for blocks with no preds?

Copy link
Member Author

Choose a reason for hiding this comment

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

For a few phases after fgAddInternal, merged return blocks are unreachable, and thus haven't had the BBF_PROF_WEIGHT flag propagated into them. I suppose I could've explicitly checked for that case here, or disabled the checks for those phases, though this should cover other cases where blocks have been created, but they don't have flow into them yet.

I guess we're losing some coverage by not catching method/region entry blocks that aren't flagged, though it seems very unlikely that these blocks would lack profile weights while their successors do have them(?)

Copy link
Member

Choose a reason for hiding this comment

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

Ah, ok... annoying but understandable that there are going to be some exclusions. We might be able to narrow the exclusions somewhat but I wouldn't bother.

{
// Block has flow into it that isn't marked as profile-derived.
//
unflaggedBlocks++;
}

if (!checkAllBlocks)
{
unprofiledBlocks++;
continue;
}
}

// There is some profile data to check.
Expand Down Expand Up @@ -4831,6 +4849,12 @@ bool Compiler::fgDebugCheckProfileWeights(ProfileChecks checks)
}
}

if (unflaggedBlocks > 0)
{
JITDUMP("%d blocks are missing BBF_PROF_WEIGHT flag.\n", unflaggedBlocks);
assert(!"Missing BBF_PROF_WEIGHT flag");
}

return (problemBlocks == 0);
}

Expand Down
Loading