Skip to content

Commit 92b9dca

Browse files
JIT: Use likelihood-based edge weights (#99736)
Part of #93020. Removes FlowEdge::m_edgeWeightMin and FlowEdge::m_edgeWeightMax, and relies on block weights and edge likelihoods to determine edge weights via FlowEdge::getLikelyWeight.
1 parent 5646095 commit 92b9dca

14 files changed

+161
-1370
lines changed

src/coreclr/jit/block.h

-24
Original file line numberDiff line numberDiff line change
@@ -587,10 +587,6 @@ struct FlowEdge
587587
// The destination of the control flow
588588
BasicBlock* m_destBlock;
589589

590-
// Edge weights
591-
weight_t m_edgeWeightMin;
592-
weight_t m_edgeWeightMax;
593-
594590
// Likelihood that m_sourceBlock transfers control along this edge.
595591
// Values in range [0..1]
596592
weight_t m_likelihood;
@@ -606,8 +602,6 @@ struct FlowEdge
606602
: m_nextPredEdge(rest)
607603
, m_sourceBlock(sourceBlock)
608604
, m_destBlock(destBlock)
609-
, m_edgeWeightMin(0)
610-
, m_edgeWeightMax(0)
611605
, m_likelihood(0)
612606
, m_dupCount(0)
613607
#ifdef DEBUG
@@ -655,24 +649,6 @@ struct FlowEdge
655649
m_destBlock = newBlock;
656650
}
657651

658-
weight_t edgeWeightMin() const
659-
{
660-
return m_edgeWeightMin;
661-
}
662-
663-
weight_t edgeWeightMax() const
664-
{
665-
return m_edgeWeightMax;
666-
}
667-
668-
// These two methods are used to set new values for edge weights.
669-
// They return false if the newWeight is not between the current [min..max]
670-
// when slop is non-zero we allow for the case where our weights might be off by 'slop'
671-
//
672-
bool setEdgeWeightMinChecked(weight_t newWeight, BasicBlock* bDst, weight_t slop, bool* wbUsedSlop);
673-
bool setEdgeWeightMaxChecked(weight_t newWeight, BasicBlock* bDst, weight_t slop, bool* wbUsedSlop);
674-
void setEdgeWeights(weight_t newMinWeight, weight_t newMaxWeight, BasicBlock* bDst);
675-
676652
weight_t getLikelihood() const
677653
{
678654
assert(m_likelihoodSet);

src/coreclr/jit/codegencommon.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -1831,8 +1831,7 @@ void CodeGen::genGenerateMachineCode()
18311831

18321832
if (compiler->fgHaveProfileWeights())
18331833
{
1834-
printf("; with %s: edge weights are %s, and fgCalledCount is " FMT_WT "\n",
1835-
compiler->compGetPgoSourceName(), compiler->fgHaveValidEdgeWeights ? "valid" : "invalid",
1834+
printf("; with %s: fgCalledCount is " FMT_WT "\n", compiler->compGetPgoSourceName(),
18361835
compiler->fgCalledCount);
18371836
}
18381837

src/coreclr/jit/compiler.cpp

+2-6
Original file line numberDiff line numberDiff line change
@@ -4910,9 +4910,9 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
49104910
//
49114911
DoPhase(this, PHASE_GS_COOKIE, &Compiler::gsPhase);
49124912

4913-
// Compute the block and edge weights
4913+
// Compute the block weights
49144914
//
4915-
DoPhase(this, PHASE_COMPUTE_EDGE_WEIGHTS, &Compiler::fgComputeBlockAndEdgeWeights);
4915+
DoPhase(this, PHASE_COMPUTE_BLOCK_WEIGHTS, &Compiler::fgComputeBlockWeights);
49164916

49174917
if (UsesFunclets())
49184918
{
@@ -5148,10 +5148,6 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
51485148
// update the flowgraph if we modified it during the optimization phase
51495149
//
51505150
DoPhase(this, PHASE_OPT_UPDATE_FLOW_GRAPH, &Compiler::fgUpdateFlowGraphPhase);
5151-
5152-
// Recompute the edge weight if we have modified the flow graph
5153-
//
5154-
DoPhase(this, PHASE_COMPUTE_EDGE_WEIGHTS2, &Compiler::fgComputeEdgeWeights);
51555151
}
51565152

51575153
// Iterate if requested, resetting annotations first.

src/coreclr/jit/compiler.h

+10-17
Original file line numberDiff line numberDiff line change
@@ -1593,12 +1593,11 @@ enum API_ICorJitInfo_Names
15931593
enum class ProfileChecks : unsigned int
15941594
{
15951595
CHECK_NONE = 0,
1596-
CHECK_CLASSIC = 1 << 0, // check "classic" jit weights
1597-
CHECK_HASLIKELIHOOD = 1 << 1, // check all FlowEdges for hasLikelihood
1598-
CHECK_LIKELIHOODSUM = 1 << 2, // check block successor likelihoods sum to 1
1599-
CHECK_LIKELY = 1 << 3, // fully check likelihood based weights
1600-
RAISE_ASSERT = 1 << 4, // assert on check failure
1601-
CHECK_ALL_BLOCKS = 1 << 5, // check blocks even if bbHasProfileWeight is false
1596+
CHECK_HASLIKELIHOOD = 1 << 0, // check all FlowEdges for hasLikelihood
1597+
CHECK_LIKELIHOODSUM = 1 << 1, // check block succesor likelihoods sum to 1
1598+
CHECK_LIKELY = 1 << 2, // fully check likelihood based weights
1599+
RAISE_ASSERT = 1 << 3, // assert on check failure
1600+
CHECK_ALL_BLOCKS = 1 << 4, // check blocks even if bbHasProfileWeight is false
16021601
};
16031602

16041603
inline constexpr ProfileChecks operator ~(ProfileChecks a)
@@ -5207,14 +5206,10 @@ class Compiler
52075206
// - Rationalization links all nodes into linear form which is kept until
52085207
// the end of compilation. The first and last nodes are stored in the block.
52095208
NodeThreading fgNodeThreading;
5210-
bool fgCanRelocateEHRegions; // true if we are allowed to relocate the EH regions
5211-
bool fgEdgeWeightsComputed; // true after we have called fgComputeEdgeWeights
5212-
bool fgHaveValidEdgeWeights; // true if we were successful in computing all of the edge weights
5213-
bool fgSlopUsedInEdgeWeights; // true if their was some slop used when computing the edge weights
5214-
bool fgRangeUsedInEdgeWeights; // true if some of the edgeWeight are expressed in Min..Max form
5215-
weight_t fgCalledCount; // count of the number of times this method was called
5216-
// This is derived from the profile data
5217-
// or is BB_UNITY_WEIGHT when we don't have profile data
5209+
bool fgCanRelocateEHRegions; // true if we are allowed to relocate the EH regions
5210+
weight_t fgCalledCount; // count of the number of times this method was called
5211+
// This is derived from the profile data
5212+
// or is BB_UNITY_WEIGHT when we don't have profile data
52185213

52195214
bool fgFuncletsCreated; // true if the funclet creation phase has been run
52205215

@@ -6047,10 +6042,9 @@ class Compiler
60476042
#ifdef DEBUG
60486043
void fgPrintEdgeWeights();
60496044
#endif
6050-
PhaseStatus fgComputeBlockAndEdgeWeights();
6045+
PhaseStatus fgComputeBlockWeights();
60516046
bool fgComputeMissingBlockWeights(weight_t* returnWeight);
60526047
bool fgComputeCalledCount(weight_t returnWeight);
6053-
PhaseStatus fgComputeEdgeWeights();
60546048

60556049
bool fgReorderBlocks(bool useProfile);
60566050

@@ -6868,7 +6862,6 @@ class Compiler
68686862
BasicBlock* optTryAdvanceLoopCompactionInsertionPoint(FlowGraphNaturalLoop* loop, BasicBlock* insertionPoint, BasicBlock* top, BasicBlock* bottom);
68696863
bool optCreatePreheader(FlowGraphNaturalLoop* loop);
68706864
void optSetWeightForPreheaderOrExit(FlowGraphNaturalLoop* loop, BasicBlock* block);
6871-
weight_t optEstimateEdgeLikelihood(BasicBlock* from, BasicBlock* to, bool* fromProfile);
68726865

68736866
bool optCanonicalizeExits(FlowGraphNaturalLoop* loop);
68746867
bool optCanonicalizeExit(FlowGraphNaturalLoop* loop, BasicBlock* exit);

src/coreclr/jit/compphases.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ CompPhaseNameMacro(PHASE_MORPH_GLOBAL, "Morph - Global",
5555
CompPhaseNameMacro(PHASE_POST_MORPH, "Post-Morph", false, -1, false)
5656
CompPhaseNameMacro(PHASE_MORPH_END, "Morph - Finish", false, -1, true)
5757
CompPhaseNameMacro(PHASE_GS_COOKIE, "GS Cookie", false, -1, false)
58-
CompPhaseNameMacro(PHASE_COMPUTE_EDGE_WEIGHTS, "Compute edge weights (1, false)",false, -1, false)
58+
CompPhaseNameMacro(PHASE_COMPUTE_BLOCK_WEIGHTS, "Compute block weights", false, -1, false)
5959
CompPhaseNameMacro(PHASE_CREATE_FUNCLETS, "Create EH funclets", false, -1, false)
6060
CompPhaseNameMacro(PHASE_HEAD_TAIL_MERGE, "Head and tail merge", false, -1, false)
6161
CompPhaseNameMacro(PHASE_MERGE_THROWS, "Merge throw blocks", false, -1, false)
@@ -95,7 +95,6 @@ CompPhaseNameMacro(PHASE_ASSERTION_PROP_MAIN, "Assertion prop",
9595
CompPhaseNameMacro(PHASE_IF_CONVERSION, "If conversion", false, -1, false)
9696
CompPhaseNameMacro(PHASE_VN_BASED_DEAD_STORE_REMOVAL,"VN-based dead store removal", false, -1, false)
9797
CompPhaseNameMacro(PHASE_OPT_UPDATE_FLOW_GRAPH, "Update flow graph opt pass", false, -1, false)
98-
CompPhaseNameMacro(PHASE_COMPUTE_EDGE_WEIGHTS2, "Compute edge weights (2, false)",false, -1, false)
9998
CompPhaseNameMacro(PHASE_STRESS_SPLIT_TREE, "Stress gtSplitTree", false, -1, false)
10099
CompPhaseNameMacro(PHASE_EXPAND_RTLOOKUPS, "Expand runtime lookups", false, -1, true)
101100
CompPhaseNameMacro(PHASE_EXPAND_STATIC_INIT, "Expand static init", false, -1, true)

src/coreclr/jit/fgbasic.cpp

+5-28
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,8 @@ void Compiler::fgInit()
2323
/* We haven't yet computed the bbPreds lists */
2424
fgPredsComputed = false;
2525

26-
/* We haven't yet computed the edge weight */
27-
fgEdgeWeightsComputed = false;
28-
fgHaveValidEdgeWeights = false;
29-
fgSlopUsedInEdgeWeights = false;
30-
fgRangeUsedInEdgeWeights = true;
31-
fgCalledCount = BB_ZERO_WEIGHT;
26+
/* We haven't yet computed block weights */
27+
fgCalledCount = BB_ZERO_WEIGHT;
3228

3329
/* Initialize the basic block list */
3430

@@ -5446,6 +5442,7 @@ BasicBlock* Compiler::fgConnectFallThrough(BasicBlock* bSrc, BasicBlock* bDst)
54465442
// Add a new block after bSrc which jumps to 'bDst'
54475443
jmpBlk = fgNewBBafter(BBJ_ALWAYS, bSrc, true);
54485444
FlowEdge* const oldEdge = bSrc->GetFalseEdge();
5445+
54495446
// Access the likelihood of oldEdge before
54505447
// it gets reset by SetTargetEdge below.
54515448
//
@@ -5457,29 +5454,9 @@ BasicBlock* Compiler::fgConnectFallThrough(BasicBlock* bSrc, BasicBlock* bDst)
54575454

54585455
// When adding a new jmpBlk we will set the bbWeight and bbFlags
54595456
//
5460-
if (fgHaveValidEdgeWeights && fgHaveProfileWeights())
5457+
if (fgHaveProfileWeights())
54615458
{
5462-
jmpBlk->bbWeight = (newEdge->edgeWeightMin() + newEdge->edgeWeightMax()) / 2;
5463-
if (bSrc->bbWeight == BB_ZERO_WEIGHT)
5464-
{
5465-
jmpBlk->bbWeight = BB_ZERO_WEIGHT;
5466-
}
5467-
5468-
if (jmpBlk->bbWeight == BB_ZERO_WEIGHT)
5469-
{
5470-
jmpBlk->SetFlags(BBF_RUN_RARELY);
5471-
}
5472-
5473-
weight_t weightDiff = (newEdge->edgeWeightMax() - newEdge->edgeWeightMin());
5474-
weight_t slop = BasicBlock::GetSlopFraction(bSrc, bDst);
5475-
//
5476-
// If the [min/max] values for our edge weight is within the slop factor
5477-
// then we will set the BBF_PROF_WEIGHT flag for the block
5478-
//
5479-
if (weightDiff <= slop)
5480-
{
5481-
jmpBlk->SetFlags(BBF_PROF_WEIGHT);
5482-
}
5459+
jmpBlk->setBBProfileWeight(newEdge->getLikelyWeight());
54835460
}
54845461
else
54855462
{

src/coreclr/jit/fgdiagnostic.cpp

+20-51
Original file line numberDiff line numberDiff line change
@@ -28,26 +28,17 @@ void Compiler::fgPrintEdgeWeights()
2828

2929
printf(FMT_BB " ", bSrc->bbNum);
3030

31-
if (edge->edgeWeightMin() < BB_MAX_WEIGHT)
31+
const weight_t weight = edge->getLikelyWeight();
32+
33+
if (weight < BB_MAX_WEIGHT)
3234
{
33-
printf("(%f", edge->edgeWeightMin());
35+
printf("(%f)", weight);
3436
}
3537
else
3638
{
37-
printf("(MAX");
38-
}
39-
if (edge->edgeWeightMin() != edge->edgeWeightMax())
40-
{
41-
if (edge->edgeWeightMax() < BB_MAX_WEIGHT)
42-
{
43-
printf("..%f", edge->edgeWeightMax());
44-
}
45-
else
46-
{
47-
printf("..MAX");
48-
}
39+
printf("(MAX)");
4940
}
50-
printf(")");
41+
5142
if (edge->getNextPredEdge() != nullptr)
5243
{
5344
printf(", ");
@@ -735,7 +726,6 @@ bool Compiler::fgDumpFlowGraph(Phases phase, PhasePosition pos)
735726
JITDUMP("Writing out flow graph %s phase %s\n", (pos == PhasePosition::PrePhase) ? "before" : "after",
736727
PhaseNames[phase]);
737728

738-
bool validWeights = fgHaveValidEdgeWeights;
739729
double weightDivisor = (double)BasicBlock::getCalledCount(this);
740730
const char* escapedString;
741731
const char* regionString = "NONE";
@@ -791,14 +781,6 @@ bool Compiler::fgDumpFlowGraph(Phases phase, PhasePosition pos)
791781
{
792782
fprintf(fgxFile, "\n hasLoops=\"true\"");
793783
}
794-
if (validWeights)
795-
{
796-
fprintf(fgxFile, "\n validEdgeWeights=\"true\"");
797-
if (!fgSlopUsedInEdgeWeights && !fgRangeUsedInEdgeWeights)
798-
{
799-
fprintf(fgxFile, "\n exactEdgeWeights=\"true\"");
800-
}
801-
}
802784
if (fgFirstColdBlock != nullptr)
803785
{
804786
fprintf(fgxFile, "\n firstColdBlock=\"%d\"", fgFirstColdBlock->bbNum);
@@ -1081,11 +1063,8 @@ bool Compiler::fgDumpFlowGraph(Phases phase, PhasePosition pos)
10811063
fprintf(fgxFile, " [");
10821064
}
10831065

1084-
if (validWeights)
1085-
{
1086-
weight_t edgeWeight = (edge->edgeWeightMin() + edge->edgeWeightMax()) / 2;
1087-
fprintf(fgxFile, "%slabel=\"%7.2f\"", sep, (double)edgeWeight / weightDivisor);
1088-
}
1066+
const weight_t edgeWeight = edge->getLikelyWeight();
1067+
fprintf(fgxFile, "%slabel=\"%7.2f\"", sep, (double)edgeWeight / weightDivisor);
10891068

10901069
fprintf(fgxFile, "];\n");
10911070
}
@@ -1106,32 +1085,22 @@ bool Compiler::fgDumpFlowGraph(Phases phase, PhasePosition pos)
11061085
fprintf(fgxFile, "\n switchDefault=\"true\"");
11071086
}
11081087
}
1109-
if (validWeights)
1110-
{
1111-
weight_t edgeWeight = (edge->edgeWeightMin() + edge->edgeWeightMax()) / 2;
1112-
fprintf(fgxFile, "\n weight=");
1113-
fprintfDouble(fgxFile, ((double)edgeWeight) / weightDivisor);
11141088

1115-
if (edge->edgeWeightMin() != edge->edgeWeightMax())
1089+
const weight_t edgeWeight = edge->getLikelyWeight();
1090+
fprintf(fgxFile, "\n weight=");
1091+
fprintfDouble(fgxFile, ((double)edgeWeight) / weightDivisor);
1092+
1093+
if (edgeWeight > 0)
1094+
{
1095+
if (edgeWeight < bSource->bbWeight)
11161096
{
1117-
fprintf(fgxFile, "\n minWeight=");
1118-
fprintfDouble(fgxFile, ((double)edge->edgeWeightMin()) / weightDivisor);
1119-
fprintf(fgxFile, "\n maxWeight=");
1120-
fprintfDouble(fgxFile, ((double)edge->edgeWeightMax()) / weightDivisor);
1097+
fprintf(fgxFile, "\n out=");
1098+
fprintfDouble(fgxFile, ((double)edgeWeight) / sourceWeightDivisor);
11211099
}
1122-
1123-
if (edgeWeight > 0)
1100+
if (edgeWeight < bTarget->bbWeight)
11241101
{
1125-
if (edgeWeight < bSource->bbWeight)
1126-
{
1127-
fprintf(fgxFile, "\n out=");
1128-
fprintfDouble(fgxFile, ((double)edgeWeight) / sourceWeightDivisor);
1129-
}
1130-
if (edgeWeight < bTarget->bbWeight)
1131-
{
1132-
fprintf(fgxFile, "\n in=");
1133-
fprintfDouble(fgxFile, ((double)edgeWeight) / targetWeightDivisor);
1134-
}
1102+
fprintf(fgxFile, "\n in=");
1103+
fprintfDouble(fgxFile, ((double)edgeWeight) / targetWeightDivisor);
11351104
}
11361105
}
11371106
}

src/coreclr/jit/fgflow.cpp

-36
Original file line numberDiff line numberDiff line change
@@ -191,42 +191,6 @@ FlowEdge* Compiler::fgAddRefPred(BasicBlock* block, BasicBlock* blockPred, FlowE
191191
//
192192
flow->setLikelihood(oldEdge->getLikelihood());
193193
}
194-
195-
if (fgHaveValidEdgeWeights)
196-
{
197-
// We are creating an edge from blockPred to block
198-
// and we have already computed the edge weights, so
199-
// we will try to setup this new edge with valid edge weights.
200-
//
201-
if (oldEdge != nullptr)
202-
{
203-
// If our caller has given us the old edge weights
204-
// then we will use them.
205-
//
206-
flow->setEdgeWeights(oldEdge->edgeWeightMin(), oldEdge->edgeWeightMax(), block);
207-
}
208-
else
209-
{
210-
// Set the max edge weight to be the minimum of block's or blockPred's weight
211-
//
212-
weight_t newWeightMax = min(block->bbWeight, blockPred->bbWeight);
213-
214-
// If we are inserting a conditional block the minimum weight is zero,
215-
// otherwise it is the same as the edge's max weight.
216-
if (blockPred->NumSucc() > 1)
217-
{
218-
flow->setEdgeWeights(BB_ZERO_WEIGHT, newWeightMax, block);
219-
}
220-
else
221-
{
222-
flow->setEdgeWeights(flow->edgeWeightMax(), newWeightMax, block);
223-
}
224-
}
225-
}
226-
else
227-
{
228-
flow->setEdgeWeights(BB_ZERO_WEIGHT, BB_MAX_WEIGHT, block);
229-
}
230194
}
231195

232196
// Pred list should (still) be ordered.

0 commit comments

Comments
 (0)