Skip to content

Commit f75c972

Browse files
JIT: Move edge likelihood initialization to fgLinkBasicBlocks (#99100)
After #98993, the logic for initializing edge likelihoods in fgAddRefPred can potentially read uninitialized memory by calling BasicBlock::NumSucc. Avoid this by moving the edge likelihood logic to fgLinkBasicBlocks, where we can safely and cheaply determine the number of successors. Also, rename AssertionInfo::m_isNextEdgeAssertion based on feedback from #98993.
1 parent fd48b6f commit f75c972

File tree

5 files changed

+27
-55
lines changed

5 files changed

+27
-55
lines changed

src/coreclr/jit/assertionprop.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -6146,7 +6146,7 @@ ASSERT_TP* Compiler::optComputeAssertionGen()
61466146
AssertionIndex valueAssertionIndex;
61476147
AssertionIndex jumpDestAssertionIndex;
61486148

6149-
if (info.IsNextEdgeAssertion())
6149+
if (info.AssertionHoldsOnFalseEdge())
61506150
{
61516151
valueAssertionIndex = info.GetAssertionIndex();
61526152
jumpDestAssertionIndex = optFindComplementary(info.GetAssertionIndex());

src/coreclr/jit/fgbasic.cpp

+18-3
Original file line numberDiff line numberDiff line change
@@ -2979,6 +2979,17 @@ void Compiler::fgLinkBasicBlocks()
29792979
curBBdesc->SetTrueEdge(trueEdge);
29802980
curBBdesc->SetFalseEdge(falseEdge);
29812981

2982+
if (trueEdge == falseEdge)
2983+
{
2984+
assert(trueEdge->getDupCount() == 2);
2985+
trueEdge->setLikelihood(1.0);
2986+
}
2987+
else
2988+
{
2989+
trueEdge->setLikelihood(0.5);
2990+
falseEdge->setLikelihood(0.5);
2991+
}
2992+
29822993
if (trueTarget->bbNum <= curBBdesc->bbNum)
29832994
{
29842995
fgMarkBackwardJump(trueTarget, curBBdesc);
@@ -3003,6 +3014,7 @@ void Compiler::fgLinkBasicBlocks()
30033014
// Redundantly use SetKindAndTargetEdge() instead of SetTargetEdge() just this once,
30043015
// so we don't break the HasInitializedTarget() invariant of SetTargetEdge().
30053016
FlowEdge* const newEdge = fgAddRefPred<initializingPreds>(jumpDest, curBBdesc);
3017+
newEdge->setLikelihood(1.0);
30063018
curBBdesc->SetKindAndTargetEdge(curBBdesc->GetKind(), newEdge);
30073019

30083020
if (curBBdesc->GetTarget()->bbNum <= curBBdesc->bbNum)
@@ -3029,14 +3041,17 @@ void Compiler::fgLinkBasicBlocks()
30293041

30303042
case BBJ_SWITCH:
30313043
{
3032-
unsigned jumpCnt = curBBdesc->GetSwitchTargets()->bbsCount;
3033-
FlowEdge** jumpPtr = curBBdesc->GetSwitchTargets()->bbsDstTab;
3044+
const unsigned numSucc = curBBdesc->GetSwitchTargets()->bbsCount;
3045+
unsigned jumpCnt = numSucc;
3046+
FlowEdge** jumpPtr = curBBdesc->GetSwitchTargets()->bbsDstTab;
30343047

30353048
do
30363049
{
30373050
BasicBlock* jumpDest = fgLookupBB((unsigned)*(size_t*)jumpPtr);
30383051
FlowEdge* const newEdge = fgAddRefPred<initializingPreds>(jumpDest, curBBdesc);
3039-
*jumpPtr = newEdge;
3052+
3053+
newEdge->setLikelihood((1.0 / numSucc) * newEdge->getDupCount());
3054+
*jumpPtr = newEdge;
30403055
if (jumpDest->bbNum <= curBBdesc->bbNum)
30413056
{
30423057
fgMarkBackwardJump(jumpDest, curBBdesc);

src/coreclr/jit/fgflow.cpp

-43
Original file line numberDiff line numberDiff line change
@@ -136,32 +136,6 @@ FlowEdge* Compiler::fgAddRefPred(BasicBlock* block, BasicBlock* blockPred, FlowE
136136
if (flowLast->getSourceBlock() == blockPred)
137137
{
138138
flow = flowLast;
139-
140-
// This edge should have been given a likelihood when it was created.
141-
// Since we're increasing its duplicate count, update the likelihood.
142-
//
143-
assert(flow->hasLikelihood());
144-
const unsigned numSucc = blockPred->NumSucc();
145-
assert(numSucc > 0);
146-
147-
if (numSucc == 1)
148-
{
149-
// BasicBlock::NumSucc() returns 1 for BBJ_CONDs with the same true/false target.
150-
// For blocks that only ever have one successor (BBJ_ALWAYS, BBJ_LEAVE, etc.),
151-
// their successor edge should never have a duplicate count over 1.
152-
//
153-
assert(blockPred->KindIs(BBJ_COND));
154-
assert(blockPred->TrueEdgeIs(blockPred->GetFalseEdge()));
155-
flow->setLikelihood(1.0);
156-
}
157-
else
158-
{
159-
// Duplicate count isn't updated until later, so add 1 for now.
160-
//
161-
const unsigned dupCount = flow->getDupCount() + 1;
162-
assert(dupCount > 1);
163-
flow->setLikelihood((1.0 / numSucc) * dupCount);
164-
}
165139
}
166140
}
167141
}
@@ -211,19 +185,6 @@ FlowEdge* Compiler::fgAddRefPred(BasicBlock* block, BasicBlock* blockPred, FlowE
211185
if (initializingPreds)
212186
{
213187
block->bbLastPred = flow;
214-
215-
// When initializing preds, ensure edge likelihood is set,
216-
// such that this edge is as likely as any other successor edge
217-
// Note: We probably shouldn't call NumSucc on a new BBJ_COND block.
218-
// NumSucc compares bbTrueEdge and bbFalseEdge to determine if this BBJ_COND block has only one successor,
219-
// but these members are uninitialized. Aside from the fact that this compares uninitialized memory,
220-
// we don't know if the true and false targets are the same in NumSucc until both edges exist.
221-
// TODO: Move this edge likelihood logic to fgLinkBasicBlocks.
222-
//
223-
const unsigned numSucc = blockPred->NumSucc();
224-
assert(numSucc > 0);
225-
assert(flow->getDupCount() == 1);
226-
flow->setLikelihood(1.0 / numSucc);
227188
}
228189
else if ((oldEdge != nullptr) && oldEdge->hasLikelihood())
229190
{
@@ -273,10 +234,6 @@ FlowEdge* Compiler::fgAddRefPred(BasicBlock* block, BasicBlock* blockPred, FlowE
273234
//
274235
assert(block->checkPredListOrder());
275236

276-
// When initializing preds, edge likelihood should always be set.
277-
//
278-
assert(!initializingPreds || flow->hasLikelihood());
279-
280237
return flow;
281238
}
282239

src/coreclr/jit/gentree.h

+7-7
Original file line numberDiff line numberDiff line change
@@ -195,12 +195,12 @@ inline AssertionIndex GetAssertionIndex(unsigned index)
195195
class AssertionInfo
196196
{
197197
// true if the assertion holds on the false edge instead of the true edge (for GT_JTRUE nodes)
198-
unsigned short m_isNextEdgeAssertion : 1;
198+
unsigned short m_assertionHoldsOnFalseEdge : 1;
199199
// 1-based index of the assertion
200200
unsigned short m_assertionIndex : 15;
201201

202-
AssertionInfo(bool isNextEdgeAssertion, AssertionIndex assertionIndex)
203-
: m_isNextEdgeAssertion(isNextEdgeAssertion), m_assertionIndex(assertionIndex)
202+
AssertionInfo(bool assertionHoldsOnFalseEdge, AssertionIndex assertionIndex)
203+
: m_assertionHoldsOnFalseEdge(assertionHoldsOnFalseEdge), m_assertionIndex(assertionIndex)
204204
{
205205
assert(m_assertionIndex == assertionIndex);
206206
}
@@ -223,8 +223,8 @@ class AssertionInfo
223223

224224
void Clear()
225225
{
226-
m_isNextEdgeAssertion = 0;
227-
m_assertionIndex = NO_ASSERTION_INDEX;
226+
m_assertionHoldsOnFalseEdge = 0;
227+
m_assertionIndex = NO_ASSERTION_INDEX;
228228
}
229229

230230
bool HasAssertion() const
@@ -237,9 +237,9 @@ class AssertionInfo
237237
return m_assertionIndex;
238238
}
239239

240-
bool IsNextEdgeAssertion() const
240+
bool AssertionHoldsOnFalseEdge() const
241241
{
242-
return m_isNextEdgeAssertion;
242+
return m_assertionHoldsOnFalseEdge;
243243
}
244244
};
245245

src/coreclr/jit/morph.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -12993,7 +12993,7 @@ void Compiler::fgAssertionGen(GenTree* tree)
1299312993
AssertionIndex ifFalseAssertionIndex;
1299412994
AssertionIndex ifTrueAssertionIndex;
1299512995

12996-
if (info.IsNextEdgeAssertion())
12996+
if (info.AssertionHoldsOnFalseEdge())
1299712997
{
1299812998
ifFalseAssertionIndex = info.GetAssertionIndex();
1299912999
ifTrueAssertionIndex = optFindComplementary(ifFalseAssertionIndex);

0 commit comments

Comments
 (0)