Skip to content

JIT: Check for profile consistency throughout JIT backend #111684

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 42 commits into from
Jan 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
32e7735
Use block weight helpers in more places
amanasifkhalid Jan 8, 2025
57b7705
Move profile checks to after morph
amanasifkhalid Jan 9, 2025
3f5f514
Move profile checks to after post-morph
amanasifkhalid Jan 9, 2025
3e89cef
Add metrics
amanasifkhalid Jan 9, 2025
c9272ba
Remove whitespace change
amanasifkhalid Jan 9, 2025
b73271c
Move profile checks to after loop inversion
amanasifkhalid Jan 9, 2025
174e1bf
Move profile checks to after flow opts
amanasifkhalid Jan 10, 2025
22634d9
Move profile checks to after loop recognition
amanasifkhalid Jan 10, 2025
7510444
Merge branch 'main' into profile-checks-loop-finding
amanasifkhalid Jan 14, 2025
5dbbb8f
Re-enable profile consistency checks
amanasifkhalid Jan 14, 2025
6462e26
Fix inconsistency in loop finding, block weight phases
amanasifkhalid Jan 15, 2025
68cc25a
Move profile checks to after loop opts
amanasifkhalid Jan 15, 2025
2c9afb4
Move profile checks up to late flow opts
amanasifkhalid Jan 15, 2025
83fb829
Move profile checks up to rationalization
amanasifkhalid Jan 16, 2025
a253111
Merge from main
amanasifkhalid Jan 16, 2025
69f18cd
Fix bool opts profile prop
amanasifkhalid Jan 16, 2025
9a577af
Another bool opt fix
amanasifkhalid Jan 16, 2025
690867f
Fix helper expansion
amanasifkhalid Jan 17, 2025
29f86b8
Merge branch 'main' into profile-checks-lowering
amanasifkhalid Jan 20, 2025
0ba5519
New BB helper for computing incoming weight
amanasifkhalid Jan 21, 2025
6e479bd
Use helper in a few places
amanasifkhalid Jan 21, 2025
12bdafe
Merge branch 'main' into profile-checks-lowering
amanasifkhalid Jan 21, 2025
da9ee51
Style
amanasifkhalid Jan 21, 2025
5accebe
Always check for profile consistency
amanasifkhalid Jan 21, 2025
56f19da
Actually check profile in backend
amanasifkhalid Jan 21, 2025
d65ba58
Maintain profile through switch lowering
amanasifkhalid Jan 22, 2025
32b9e6f
Maintain profile for jump sequence creation
amanasifkhalid Jan 22, 2025
347301d
Merge branch 'main' into profile-checks-everywhere
amanasifkhalid Jan 22, 2025
3ea587a
Fix optSetBlockWeights
amanasifkhalid Jan 23, 2025
bd07e75
Merge branch 'main' into fix-profile-consistency-jitstress
amanasifkhalid Jan 23, 2025
2f4a9ba
Fix handler region prolog creation
amanasifkhalid Jan 23, 2025
a41e119
Merge branch 'fix-profile-consistency-jitstress' into profile-checks-…
amanasifkhalid Jan 23, 2025
91f33d2
Fix cast expansion
amanasifkhalid Jan 23, 2025
00ff00e
Merge from main
amanasifkhalid Jan 23, 2025
21b59e6
Fix bad merge
amanasifkhalid Jan 23, 2025
86e3d05
Maintain profile through VN-based intrinsic expansion
amanasifkhalid Jan 24, 2025
6995e2e
Dump flowgraph on assertion failure
amanasifkhalid Jan 24, 2025
7d35d83
Merge branch 'main' into profile-checks-everywhere
amanasifkhalid Jan 27, 2025
082e072
Fix missing profile flag in expansion phases
amanasifkhalid Jan 27, 2025
6a1d84c
Set BBF_PROF_WEIGHT flag for filter blocks
amanasifkhalid Jan 27, 2025
3f886d0
Check for profile inconsistency in loop inversion
amanasifkhalid Jan 28, 2025
65ab853
Remove debug print
amanasifkhalid Jan 28, 2025
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
10 changes: 0 additions & 10 deletions src/coreclr/jit/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4871,11 +4871,6 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
DoPhase(this, PHASE_COMPUTE_DOMINATORS, &Compiler::fgComputeDominators);
}

// Drop back to just checking profile likelihoods.
//
activePhaseChecks &= ~PhaseChecks::CHECK_PROFILE;
activePhaseChecks |= PhaseChecks::CHECK_LIKELIHOODS;

#ifdef DEBUG
fgDebugCheckLinks();
#endif
Expand Down Expand Up @@ -5156,11 +5151,6 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
DoPhase(this, PHASE_SWITCH_RECOGNITION, &Compiler::optSwitchRecognition);
}

// Drop back to just checking profile likelihoods.
//
activePhaseChecks &= ~PhaseChecks::CHECK_PROFILE;
activePhaseChecks |= PhaseChecks::CHECK_LIKELIHOODS;

#ifdef DEBUG
// Stash the current estimate of the function's size if necessary.
if (verbose && opts.OptimizationEnabled())
Expand Down
40 changes: 22 additions & 18 deletions src/coreclr/jit/helperexpansion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -744,7 +744,7 @@ bool Compiler::fgExpandThreadLocalAccessForCallNativeAOT(BasicBlock** pBlock, St
fastPathBb->inheritWeight(prevBb);

// fallback will just execute first time
fallbackBb->bbSetRunRarely();
fallbackBb->inheritWeightPercentage(tlsRootNullCondBB, 0);
Copy link
Member Author

Choose a reason for hiding this comment

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

It looks a bit silly, but unlike bbSetRunRarely, inheritWeightPercentage propagates the BBF_PROF_WEIGHT flag from the block its deriving weight from. Changing bbSetRunRarely to propagate the flag would likely incur large diffs in the non-PGO case.


fgRedirectTargetEdge(prevBb, tlsRootNullCondBB);

Expand Down Expand Up @@ -1180,7 +1180,7 @@ bool Compiler::fgExpandThreadLocalAccessForCall(BasicBlock** pBlock, Statement*
fastPathBb->inheritWeight(prevBb);

// fallback will just execute first time
fallbackBb->bbSetRunRarely();
fallbackBb->inheritWeightPercentage(prevBb, 0);

// All blocks are expected to be in the same EH region
assert(BasicBlock::sameEHRegion(prevBb, block));
Expand Down Expand Up @@ -1545,7 +1545,7 @@ bool Compiler::fgExpandStaticInitForCall(BasicBlock** pBlock, Statement* stmt, G

block->inheritWeight(prevBb);
isInitedBb->inheritWeight(prevBb);
helperCallBb->bbSetRunRarely();
helperCallBb->inheritWeightPercentage(isInitedBb, 0);

// All blocks are expected to be in the same EH region
assert(BasicBlock::sameEHRegion(prevBb, block));
Expand Down Expand Up @@ -1847,6 +1847,7 @@ bool Compiler::fgVNBasedIntrinsicExpansionForCall_ReadUtf8(BasicBlock** pBlock,
//
// Redirect prevBb to lengthCheckBb
fgRedirectTargetEdge(prevBb, lengthCheckBb);
lengthCheckBb->inheritWeight(prevBb);
assert(prevBb->JumpsToNext());

{
Expand All @@ -1859,6 +1860,11 @@ bool Compiler::fgVNBasedIntrinsicExpansionForCall_ReadUtf8(BasicBlock** pBlock,
// review: we assume length check always succeeds??
trueEdge->setLikelihood(1.0);
falseEdge->setLikelihood(0.0);

if (lengthCheckBb->hasProfileWeight())
{
fastpathBb->setBBProfileWeight(falseEdge->getLikelyWeight());
}
}

{
Expand All @@ -1869,10 +1875,8 @@ bool Compiler::fgVNBasedIntrinsicExpansionForCall_ReadUtf8(BasicBlock** pBlock,
}

//
// Re-distribute weights
// Ensure all flow out of prevBb converges into block
//
lengthCheckBb->inheritWeight(prevBb);
fastpathBb->inheritWeight(lengthCheckBb);
block->inheritWeight(prevBb);

// All blocks are expected to be in the same EH region
Expand Down Expand Up @@ -2551,11 +2555,18 @@ bool Compiler::fgLateCastExpansionForCall(BasicBlock** pBlock, Statement* stmt,
trueEdge->setLikelihood(nullcheckTrueLikelihood);
}

// Set nullcheckBb's weight here, so we can propagate it to its successors below
nullcheckBb->inheritWeight(firstBb);

if (typeCheckNotNeeded)
{
FlowEdge* const falseEdge = fgAddRefPred(fallbackBb, nullcheckBb);
nullcheckBb->SetFalseEdge(falseEdge);
falseEdge->setLikelihood(nullcheckFalseLikelihood);
fallbackBb->inheritWeight(nullcheckBb);
fallbackBb->scaleBBWeight(nullcheckFalseLikelihood);
lastBb->inheritWeight(nullcheckBb);
lastBb->scaleBBWeight(nullcheckTrueLikelihood);

typeCheckSucceedBb = nullptr;
}
Expand Down Expand Up @@ -2631,7 +2642,6 @@ bool Compiler::fgLateCastExpansionForCall(BasicBlock** pBlock, Statement* stmt,
// The same goes for inherited weights -- the block where we test for B will have
// the weight of A times the likelihood that A's test fails, etc.
//
nullcheckBb->inheritWeight(firstBb);
weight_t sumOfPreviousLikelihood = 0;
for (int candidateId = 0; candidateId < numOfCandidates; candidateId++)
{
Expand Down Expand Up @@ -2666,28 +2676,22 @@ bool Compiler::fgLateCastExpansionForCall(BasicBlock** pBlock, Statement* stmt,
sumOfPreviousLikelihood += likelihood;
}

if (fallbackBb->KindIs(BBJ_THROW))
{
fallbackBb->bbSetRunRarely();
}
else
fallbackBb->inheritWeight(lastTypeCheckBb);
fallbackBb->scaleBBWeight(lastTypeCheckBb->GetFalseEdge()->getLikelihood());

if (fallbackBb->KindIs(BBJ_ALWAYS))
{
assert(fallbackBb->KindIs(BBJ_ALWAYS));
FlowEdge* const newEdge = fgAddRefPred(lastBb, fallbackBb);
fallbackBb->SetTargetEdge(newEdge);
fallbackBb->inheritWeight(lastTypeCheckBb);
weight_t lastTypeCheckFailedLikelihood = lastTypeCheckBb->GetFalseEdge()->getLikelihood();
fallbackBb->scaleBBWeight(lastTypeCheckFailedLikelihood);
}

if (!typeCheckNotNeeded)
{
typeCheckSucceedBb->inheritWeight(typeChecksBbs[0]);
typeCheckSucceedBb->scaleBBWeight(sumOfPreviousLikelihood);
lastBb->inheritWeight(firstBb);
}

lastBb->inheritWeight(firstBb);

//
// Validate EH regions
//
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/jiteh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2660,7 +2660,7 @@ bool Compiler::fgCreateFiltersForGenericExceptions()
filterBb->bbCodeOffs = handlerBb->bbCodeOffs;
filterBb->bbHndIndex = handlerBb->bbHndIndex;
filterBb->bbTryIndex = handlerBb->bbTryIndex;
filterBb->bbSetRunRarely();
filterBb->inheritWeightPercentage(handlerBb, 0);
filterBb->SetFlags(BBF_INTERNAL | BBF_DONT_REMOVE);

handlerBb->bbCatchTyp = BBCT_FILTER_HANDLER;
Expand Down
65 changes: 59 additions & 6 deletions src/coreclr/jit/lower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1066,11 +1066,11 @@ GenTree* Lowering::LowerSwitch(GenTree* node)
for (unsigned i = 0; i < jumpCnt - 1; ++i)
{
assert(currentBlock != nullptr);
BasicBlock* const targetBlock = jumpTab[i]->getDestinationBlock();

// Remove the switch from the predecessor list of this case target's block.
// We'll add the proper new predecessor edge later.
FlowEdge* const oldEdge = jumpTab[i];
FlowEdge* const oldEdge = jumpTab[i];
BasicBlock* const targetBlock = oldEdge->getDestinationBlock();

// Compute the likelihood that this test is successful.
// Divide by number of cases still sharing this edge (reduces likelihood)
Expand Down Expand Up @@ -1131,8 +1131,9 @@ GenTree* Lowering::LowerSwitch(GenTree* node)
{
BasicBlock* const newBlock = comp->fgNewBBafter(BBJ_ALWAYS, currentBlock, true);
FlowEdge* const newEdge = comp->fgAddRefPred(newBlock, currentBlock);
currentBlock = newBlock;
currentBBRange = &LIR::AsRange(currentBlock);
newBlock->inheritWeight(currentBlock);
currentBlock = newBlock;
currentBBRange = &LIR::AsRange(currentBlock);
afterDefaultCondBlock->SetKindAndTargetEdge(BBJ_ALWAYS, newEdge);
}

Expand Down Expand Up @@ -1207,6 +1208,25 @@ GenTree* Lowering::LowerSwitch(GenTree* node)
currentBlock->RemoveFlags(BBF_DONT_REMOVE);
comp->fgRemoveBlock(currentBlock, /* unreachable */ false); // It's an empty block.
}

// Update flow into switch targets
if (afterDefaultCondBlock->hasProfileWeight())
{
bool profileInconsistent = false;
for (unsigned i = 0; i < jumpCnt - 1; i++)
{
BasicBlock* const targetBlock = jumpTab[i]->getDestinationBlock();
targetBlock->setBBProfileWeight(targetBlock->computeIncomingWeight());
profileInconsistent |= (targetBlock->NumSucc() > 0);
}

if (profileInconsistent)
{
JITDUMP("Switch lowering: Flow out of " FMT_BB " needs to be propagated. Data %s inconsistent.\n",
afterDefaultCondBlock->bbNum, comp->fgPgoConsistent ? "is now" : "was already");
comp->fgPgoConsistent = false;
}
}
}
else
{
Expand Down Expand Up @@ -1260,11 +1280,28 @@ GenTree* Lowering::LowerSwitch(GenTree* node)
JITDUMP("Zero weight switch block " FMT_BB ", distributing likelihoods equally per case\n",
afterDefaultCondBlock->bbNum);
// jumpCnt-1 here because we peeled the default after copying this value.
weight_t const newLikelihood = 1.0 / (jumpCnt - 1);
weight_t const newLikelihood = 1.0 / (jumpCnt - 1);
bool profileInconsistent = false;
for (unsigned i = 0; i < successors.numDistinctSuccs; i++)
{
FlowEdge* const edge = successors.nonDuplicates[i];
FlowEdge* const edge = successors.nonDuplicates[i];
weight_t const oldEdgeWeight = edge->getLikelyWeight();
edge->setLikelihood(newLikelihood * edge->getDupCount());
weight_t const newEdgeWeight = edge->getLikelyWeight();

if (afterDefaultCondBlock->hasProfileWeight())
{
BasicBlock* const targetBlock = edge->getDestinationBlock();
targetBlock->increaseBBProfileWeight(newEdgeWeight - oldEdgeWeight);
profileInconsistent |= (targetBlock->NumSucc() > 0);
}
}

if (profileInconsistent)
{
JITDUMP("Switch lowering: Flow out of " FMT_BB " needs to be propagated. Data %s inconsistent.\n",
afterDefaultCondBlock->bbNum, comp->fgPgoConsistent ? "is now" : "was already");
comp->fgPgoConsistent = false;
}
}
else
Expand Down Expand Up @@ -1447,6 +1484,22 @@ bool Lowering::TryLowerSwitchToBitTest(FlowEdge* jumpTable[],

bbSwitch->SetCond(case1Edge, case0Edge);

//
// Update profile
//
if (bbSwitch->hasProfileWeight())
{
bbCase0->setBBProfileWeight(bbCase0->computeIncomingWeight());
bbCase1->setBBProfileWeight(bbCase1->computeIncomingWeight());

if ((bbCase0->NumSucc() > 0) || (bbCase1->NumSucc() > 0))
{
JITDUMP("TryLowerSwitchToBitTest: Flow out of " FMT_BB " needs to be propagated. Data %s inconsistent.\n",
bbSwitch->bbNum, comp->fgPgoConsistent ? "is now" : "was already");
comp->fgPgoConsistent = false;
}
}

var_types bitTableType = (bitCount <= (genTypeSize(TYP_INT) * 8)) ? TYP_INT : TYP_LONG;
GenTree* bitTableIcon = comp->gtNewIconNode(bitTable, bitTableType);

Expand Down
11 changes: 11 additions & 0 deletions src/coreclr/jit/optimizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2230,6 +2230,8 @@ bool Compiler::optInvertWhileLoop(BasicBlock* block)
//
bNewCond->inheritWeight(block);

const weight_t totalWeight = bTest->bbWeight;

if (haveProfileWeights)
{
bTest->decreaseBBProfileWeight(block->bbWeight);
Expand Down Expand Up @@ -2290,6 +2292,15 @@ bool Compiler::optInvertWhileLoop(BasicBlock* block)
}
}

const weight_t loopWeight = bTest->bbWeight;
const weight_t nonLoopWeight = bNewCond->bbWeight;
if (haveProfileWeights && !fgProfileWeightsConsistent(totalWeight, loopWeight + nonLoopWeight))
{
JITDUMP("Redirecting flow from " FMT_BB " to " FMT_BB " introduced inconsistency. Data %s inconsistent.\n",
bTest->bbNum, bNewCond->bbNum, fgPgoConsistent ? "is now" : "was already");
fgPgoConsistent = false;
}

#ifdef DEBUG
if (verbose)
{
Expand Down
Loading