-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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: verify full profile consistency after importation #100869
Changes from all commits
b244d01
6e61a50
18ebada
823fd99
2b41492
69c4a4a
748980f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5128,6 +5128,18 @@ void Compiler::impResetLeaveBlock(BasicBlock* block, unsigned jmpAddr) | |
// reason we don't want to remove the block at this point is that if we call | ||
// fgInitBBLookup() again we will do it wrong as the BBJ_ALWAYS block won't be | ||
// added and the linked list length will be different than fgBBcount. | ||
// | ||
// Because of this incomplete cleanup. profile data may be left inconsistent. | ||
// | ||
if (block->hasProfileWeight()) | ||
{ | ||
// We are unlikely to be able to repair the profile. | ||
// For now we don't even try. | ||
// | ||
JITDUMP("\nimpResetLeaveBlock: Profile data could not be locally repaired. Data %s inconsisent.\n", | ||
fgPgoConsistent ? "is now" : "was already"); | ||
fgPgoConsistent = false; | ||
} | ||
} | ||
|
||
/*****************************************************************************/ | ||
|
@@ -6606,7 +6618,11 @@ void Compiler::impImportBlockCode(BasicBlock* block) | |
return; | ||
} | ||
|
||
block->bbSetRunRarely(); // filters are rare | ||
if (!fgPgoSynthesized) | ||
{ | ||
// filters are rare | ||
block->bbSetRunRarely(); | ||
} | ||
|
||
if (info.compXcptnsCount == 0) | ||
{ | ||
|
@@ -7294,19 +7310,67 @@ void Compiler::impImportBlockCode(BasicBlock* block) | |
|
||
if (block->KindIs(BBJ_COND)) | ||
{ | ||
if (op1->AsIntCon()->gtIconVal) | ||
{ | ||
JITDUMP("\nThe conditional jump becomes an unconditional jump to " FMT_BB "\n", | ||
block->GetTrueTarget()->bbNum); | ||
fgRemoveRefPred(block->GetFalseEdge()); | ||
block->SetKindAndTargetEdge(BBJ_ALWAYS, block->GetTrueEdge()); | ||
} | ||
else | ||
bool const isCondTrue = op1->AsIntCon()->gtIconVal != 0; | ||
FlowEdge* const removedEdge = isCondTrue ? block->GetFalseEdge() : block->GetTrueEdge(); | ||
FlowEdge* const retainedEdge = isCondTrue ? block->GetTrueEdge() : block->GetFalseEdge(); | ||
|
||
JITDUMP("\nThe conditional jump becomes an unconditional jump to " FMT_BB "\n", | ||
retainedEdge->getDestinationBlock()->bbNum); | ||
|
||
fgRemoveRefPred(removedEdge); | ||
block->SetKindAndTargetEdge(BBJ_ALWAYS, retainedEdge); | ||
|
||
// If we removed an edge carrying profile, try to do a local repair. | ||
// | ||
if (block->hasProfileWeight()) | ||
{ | ||
assert(block->NextIs(block->GetFalseTarget())); | ||
JITDUMP("\nThe block jumps to the next " FMT_BB "\n", block->Next()->bbNum); | ||
fgRemoveRefPred(block->GetTrueEdge()); | ||
block->SetKindAndTargetEdge(BBJ_ALWAYS, block->GetFalseEdge()); | ||
bool repairWasComplete = true; | ||
weight_t const weight = removedEdge->getLikelyWeight(); | ||
|
||
if (weight > 0) | ||
{ | ||
// Target block weight will increase. | ||
// | ||
BasicBlock* const target = block->GetTarget(); | ||
assert(target->hasProfileWeight()); | ||
target->setBBProfileWeight(target->bbWeight + weight); | ||
|
||
// Alternate weight will decrease | ||
// | ||
BasicBlock* const alternate = removedEdge->getDestinationBlock(); | ||
assert(alternate->hasProfileWeight()); | ||
weight_t const alternateNewWeight = alternate->bbWeight - weight; | ||
|
||
// If profile weights are consistent, expect at worst a slight underflow. | ||
// | ||
if (fgPgoConsistent && (alternateNewWeight < 0)) | ||
{ | ||
assert(fgProfileWeightsEqual(alternateNewWeight, 0)); | ||
} | ||
alternate->setBBProfileWeight(max(0.0, alternateNewWeight)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ditto my above comment -- maybe something like |
||
|
||
// This will affect profile transitively, so in general | ||
// the profile will become inconsistent. | ||
// | ||
repairWasComplete = false; | ||
|
||
// But we can check for the special case where the | ||
// block's postdominator is target's target (simple | ||
// if/then/else/join). | ||
// | ||
if (target->KindIs(BBJ_ALWAYS)) | ||
{ | ||
repairWasComplete = alternate->KindIs(BBJ_ALWAYS) && | ||
(alternate->GetTarget() == target->GetTarget()); | ||
} | ||
} | ||
|
||
if (!repairWasComplete) | ||
{ | ||
JITDUMP("Profile data could not be locally repaired. Data %s inconsistent.\n", | ||
fgPgoConsistent ? "is now" : "was already"); | ||
fgPgoConsistent = false; | ||
} | ||
} | ||
} | ||
|
||
|
@@ -7584,6 +7648,15 @@ void Compiler::impImportBlockCode(BasicBlock* block) | |
printf("\n"); | ||
} | ||
#endif | ||
if (block->hasProfileWeight()) | ||
{ | ||
// We are unlikely to be able to repair the profile. | ||
// For now we don't even try. | ||
// | ||
JITDUMP("Profile data could not be locally repaired. Data %s inconsisent.\n", | ||
fgPgoConsistent ? "is now" : "was already"); | ||
fgPgoConsistent = false; | ||
} | ||
|
||
// Create a NOP node | ||
op1 = gtNewNothingNode(); | ||
|
@@ -10065,8 +10138,11 @@ void Compiler::impImportBlockCode(BasicBlock* block) | |
|
||
case CEE_THROW: | ||
|
||
// Any block with a throw is rarely executed. | ||
block->bbSetRunRarely(); | ||
if (!fgPgoSynthesized) | ||
{ | ||
// Any block with a throw is rarely executed. | ||
block->bbSetRunRarely(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Following up on the planned |
||
} | ||
|
||
// Pop the exception object and create the 'throw' helper call | ||
op1 = gtNewHelperCallNode(CORINFO_HELP_THROW, TYP_VOID, impPopStack().val); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this is premature, but do you think we should consider changing the block weight API surface sooner rather than later? It might be useful as we do these profile fixups to have something like
incrementBBProfileWeight
that asserts the increment amount is positive, and clears theBBF_RUN_RARELY
flag (until we decide to decouple the meaning of this flag fromBB_ZERO_WEIGHT
) -- and maybe doesn't touch theBBF_PROF_WEIGHT
flag?I'm happy to add some new helpers like this, if you think they'd be useful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we should do that -- want to get a bit more experience with the updates first, so we can see what patterns are common.