Skip to content

Commit 496992f

Browse files
committed
More fixes
This includes various fixes that are being separately PR'ed: 1. dotnet#99744: Introduce HandleKindDataIsInvariant helper 2. dotnet#99743: Add basic support for TYP_MASK constants 3. dotnet#99742: Fix problem with scaling general loop blocks; add dumpers 4. dotnet#99740: Add edge likelihood dumping; fix one edge likelihood update case Also: 1. Add support for running JitOptRepeat under JitStress. This is still over-written by JitOptRepeat being forced on at 4 iterations.
1 parent 9629653 commit 496992f

12 files changed

+341
-93
lines changed

src/coreclr/jit/block.cpp

+44-21
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,20 @@ void FlowEdge::setLikelihood(weight_t likelihood)
7979
{
8080
assert(likelihood >= 0.0);
8181
assert(likelihood <= 1.0);
82+
83+
if (m_likelihoodSet)
84+
{
85+
JITDUMP("setting likelihood of " FMT_BB " -> " FMT_BB " from " FMT_WT " to " FMT_WT "\n", m_sourceBlock->bbNum,
86+
m_destBlock->bbNum, m_likelihood, likelihood);
87+
}
88+
else
89+
{
90+
JITDUMP("setting likelihood of " FMT_BB " -> " FMT_BB " to " FMT_WT "\n", m_sourceBlock->bbNum,
91+
m_destBlock->bbNum, likelihood);
92+
}
93+
8294
m_likelihoodSet = true;
8395
m_likelihood = likelihood;
84-
85-
JITDUMP("setting likelihood of " FMT_BB " -> " FMT_BB " to " FMT_WT "\n", m_sourceBlock->bbNum, m_destBlock->bbNum,
86-
m_likelihood);
8796
}
8897

8998
//------------------------------------------------------------------------
@@ -114,10 +123,11 @@ void FlowEdge::addLikelihood(weight_t addedLikelihood)
114123

115124
assert(newLikelihood >= 0.0);
116125
assert(newLikelihood <= 1.0);
117-
m_likelihood = newLikelihood;
118126

119-
JITDUMP("updating likelihood of " FMT_BB " -> " FMT_BB " to " FMT_WT "\n", m_sourceBlock->bbNum, m_destBlock->bbNum,
120-
m_likelihood);
127+
JITDUMP("updating likelihood of " FMT_BB " -> " FMT_BB " from " FMT_WT " to " FMT_WT "\n", m_sourceBlock->bbNum,
128+
m_destBlock->bbNum, m_likelihood, newLikelihood);
129+
130+
m_likelihood = newLikelihood;
121131
}
122132

123133
//------------------------------------------------------------------------
@@ -678,20 +688,33 @@ void BasicBlock::dspSuccs(Compiler* compiler)
678688
// things strictly.
679689
void BasicBlock::dspKind() const
680690
{
681-
auto dspBlockNum = [](const BasicBlock* b) -> const char* {
691+
auto dspBlockNum = [](const FlowEdge* e) -> const char* {
682692
static char buffers[3][64]; // static array of 3 to allow 3 concurrent calls in one printf()
683693
static int nextBufferIndex = 0;
684694

685-
auto& buffer = buffers[nextBufferIndex];
686-
nextBufferIndex = (nextBufferIndex + 1) % ArrLen(buffers);
695+
auto& buffer = buffers[nextBufferIndex];
696+
nextBufferIndex = (nextBufferIndex + 1) % ArrLen(buffers);
697+
const size_t sizeOfBuffer = ArrLen(buffer);
698+
int written;
687699

700+
const BasicBlock* b = e->getDestinationBlock();
688701
if (b == nullptr)
689702
{
690-
_snprintf_s(buffer, ArrLen(buffer), ArrLen(buffer), "NULL");
703+
written = _snprintf_s(buffer, sizeOfBuffer, sizeOfBuffer, "NULL");
691704
}
692705
else
693706
{
694-
_snprintf_s(buffer, ArrLen(buffer), ArrLen(buffer), FMT_BB, b->bbNum);
707+
written = _snprintf_s(buffer, sizeOfBuffer, sizeOfBuffer, FMT_BB, b->bbNum);
708+
}
709+
710+
const bool printEdgeLikelihoods = true; // TODO: parameterize this?
711+
if (printEdgeLikelihoods)
712+
{
713+
if (e->hasLikelihood())
714+
{
715+
written = _snprintf_s(buffer + written, sizeOfBuffer - written, sizeOfBuffer - written, "(" FMT_WT ")",
716+
e->getLikelihood());
717+
}
695718
}
696719

697720
return buffer;
@@ -715,7 +738,7 @@ void BasicBlock::dspKind() const
715738

716739
for (unsigned i = 0; i < jumpCnt; i++)
717740
{
718-
printf("%c%s", (i == 0) ? ' ' : ',', dspBlockNum(jumpTab[i]->getDestinationBlock()));
741+
printf("%c%s", (i == 0) ? ' ' : ',', dspBlockNum(jumpTab[i]));
719742
}
720743
}
721744

@@ -728,11 +751,11 @@ void BasicBlock::dspKind() const
728751
break;
729752

730753
case BBJ_EHFILTERRET:
731-
printf(" -> %s (fltret)", dspBlockNum(GetTarget()));
754+
printf(" -> %s (fltret)", dspBlockNum(GetTargetEdge()));
732755
break;
733756

734757
case BBJ_EHCATCHRET:
735-
printf(" -> %s (cret)", dspBlockNum(GetTarget()));
758+
printf(" -> %s (cret)", dspBlockNum(GetTargetEdge()));
736759
break;
737760

738761
case BBJ_THROW:
@@ -746,28 +769,28 @@ void BasicBlock::dspKind() const
746769
case BBJ_ALWAYS:
747770
if (HasFlag(BBF_KEEP_BBJ_ALWAYS))
748771
{
749-
printf(" -> %s (ALWAYS)", dspBlockNum(GetTarget()));
772+
printf(" -> %s (ALWAYS)", dspBlockNum(GetTargetEdge()));
750773
}
751774
else
752775
{
753-
printf(" -> %s (always)", dspBlockNum(GetTarget()));
776+
printf(" -> %s (always)", dspBlockNum(GetTargetEdge()));
754777
}
755778
break;
756779

757780
case BBJ_LEAVE:
758-
printf(" -> %s (leave)", dspBlockNum(GetTarget()));
781+
printf(" -> %s (leave)", dspBlockNum(GetTargetEdge()));
759782
break;
760783

761784
case BBJ_CALLFINALLY:
762-
printf(" -> %s (callf)", dspBlockNum(GetTarget()));
785+
printf(" -> %s (callf)", dspBlockNum(GetTargetEdge()));
763786
break;
764787

765788
case BBJ_CALLFINALLYRET:
766-
printf(" -> %s (callfr)", dspBlockNum(GetTarget()));
789+
printf(" -> %s (callfr)", dspBlockNum(GetTargetEdge()));
767790
break;
768791

769792
case BBJ_COND:
770-
printf(" -> %s,%s (cond)", dspBlockNum(GetTrueTarget()), dspBlockNum(GetFalseTarget()));
793+
printf(" -> %s,%s (cond)", dspBlockNum(GetTrueEdge()), dspBlockNum(GetFalseEdge()));
771794
break;
772795

773796
case BBJ_SWITCH:
@@ -779,7 +802,7 @@ void BasicBlock::dspKind() const
779802

780803
for (unsigned i = 0; i < jumpCnt; i++)
781804
{
782-
printf("%c%s", (i == 0) ? ' ' : ',', dspBlockNum(jumpTab[i]->getDestinationBlock()));
805+
printf("%c%s", (i == 0) ? ' ' : ',', dspBlockNum(jumpTab[i]));
783806

784807
const bool isDefault = bbSwtTargets->bbsHasDefault && (i == jumpCnt - 1);
785808
if (isDefault)

src/coreclr/jit/block.h

+27-2
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,13 @@ typedef BitVec_ValRet_T ASSERT_VALRET_TP;
4646
// Use this format for loop indices
4747
#define FMT_LP "L%02u"
4848

49-
// And this format for profile weights
49+
// Use this format for profile weights
5050
#define FMT_WT "%.7g"
5151

52+
// Use this format for profile weights where we want to conserve horizontal space, at the expense of displaying
53+
// less precision.
54+
#define FMT_WT_NARROW "%.3g"
55+
5256
/*****************************************************************************
5357
*
5458
* Each basic block ends with a jump which is described as a value
@@ -1037,6 +1041,27 @@ struct BasicBlock : private LIR::Range
10371041
return (bbFalseEdge == nullptr) ? nullptr : bbFalseEdge->getDestinationBlock();
10381042
}
10391043

1044+
// Return the target edge; it might be null. Only used during dumping.
1045+
FlowEdge* GetTargetEdgeRaw() const
1046+
{
1047+
assert(HasTarget());
1048+
return bbTargetEdge;
1049+
}
1050+
1051+
// Return the BBJ_COND true target edge; it might be null. Only used during dumping.
1052+
FlowEdge* GetTrueEdgeRaw() const
1053+
{
1054+
assert(KindIs(BBJ_COND));
1055+
return bbTrueEdge;
1056+
}
1057+
1058+
// Return the BBJ_COND false target edge; it might be null. Only used during dumping.
1059+
FlowEdge* GetFalseEdgeRaw() const
1060+
{
1061+
assert(KindIs(BBJ_COND));
1062+
return bbFalseEdge;
1063+
}
1064+
10401065
#endif // DEBUG
10411066

10421067
private:
@@ -1537,7 +1562,7 @@ struct BasicBlock : private LIR::Range
15371562
}
15381563

15391564
// PredBlocksEditing: convenience method for enabling range-based `for` iteration over predecessor blocks, e.g.:
1540-
// for (BasicBlock* const predBlock : block->PredBlocksList()) ...
1565+
// for (BasicBlock* const predBlock : block->PredBlocksEditing()) ...
15411566
// This iterator tolerates modifications to bbPreds.
15421567
//
15431568
PredBlockList<true> PredBlocksEditing() const

src/coreclr/jit/clrjit.natvis

+7-3
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@ The .NET Foundation licenses this file to you under the MIT license.
88
<!--
99
Visual Studio debugger visualizers for RyuJIT.
1010
11-
Documentation for VS natvis format: https://docs.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects?view=vs-2019
12-
13-
Documentation for VS debugger format specifiers: https://docs.microsoft.com/en-us/visualstudio/debugger/format-specifiers-in-cpp?view=vs-2019
11+
Documentation for VS natvis format: https://learn.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects?view=vs-2022
12+
Documentation for VS debugger format specifiers: https://learn.microsoft.com/en-us/visualstudio/debugger/format-specifiers-in-cpp?view=vs-2022
1413
-->
1514

1615
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
@@ -27,6 +26,11 @@ Documentation for VS debugger format specifiers: https://docs.microsoft.com/en-u
2726
<DisplayString>BB{bbNum,d}; {bbKind,en}</DisplayString>
2827
</Type>
2928

29+
<Type Name="FlowEdge">
30+
<DisplayString Condition="m_dupCount!=1">BB{m_sourceBlock->bbNum,d}->BB{m_destBlock->bbNum,d} ({m_likelihood,g}) (dup {m_dupCount,d})</DisplayString>
31+
<DisplayString>BB{m_sourceBlock->bbNum,d}->BB{m_destBlock->bbNum,d} ({m_likelihood,g})</DisplayString>
32+
</Type>
33+
3034
<Type Name="Compiler::LoopDsc">
3135
<DisplayString Condition="lpFlags &amp; LPFLG_REMOVED">REMOVED</DisplayString>
3236
<DisplayString Condition="lpFlags &amp; LPFLG_HAS_PREHEAD">[BB{lpTop->bbNum,d}..BB{lpBottom->bbNum,d}] pre-h:BB{lpHead->bbNum,d} e:BB{lpEntry->bbNum,d} {lpFlags,en}</DisplayString>

src/coreclr/jit/compiler.cpp

+33-11
Original file line numberDiff line numberDiff line change
@@ -2872,6 +2872,7 @@ void Compiler::compInitOptions(JitFlags* jitFlags)
28722872
opts.dspUnwind = false;
28732873
opts.compLongAddress = false;
28742874
opts.optRepeat = false;
2875+
opts.optRepeatCount = 1;
28752876

28762877
#ifdef LATE_DISASM
28772878
opts.doLateDisasm = false;
@@ -2955,13 +2956,30 @@ void Compiler::compInitOptions(JitFlags* jitFlags)
29552956

29562957
if (JitConfig.JitOptRepeat().contains(info.compMethodHnd, info.compClassHnd, &info.compMethodInfo->args))
29572958
{
2958-
opts.optRepeat = true;
2959+
opts.optRepeat = true;
2960+
opts.optRepeatCount = JitConfig.JitOptRepeatCount();
2961+
2962+
JITDUMP("\n*************** JitOptRepeat enabled; repetition count: %d\n\n", opts.optRepeatCount);
29592963
}
29602964

2961-
opts.dspMetrics = (JitConfig.JitMetrics() != 0);
2965+
if (!opts.optRepeat && compStressCompile(STRESS_OPT_REPEAT, 10))
2966+
{
2967+
// Turn on optRepeat as part of JitStress. In this case, decide how many iterations to do, from 2 to 5,
2968+
// based on a random number seeded by the method hash.
2969+
opts.optRepeat = true;
2970+
2971+
CLRRandom rng;
2972+
rng.Init(info.compMethodHash());
2973+
opts.optRepeatCount = rng.Next(4) + 2; // generates [2..5]
2974+
2975+
JITDUMP("\n*************** JitOptRepeat under stress; repetition count: %d\n\n", opts.optRepeatCount);
2976+
}
29622977

29632978
////////////////// TESTING
2964-
opts.optRepeat = true;
2979+
opts.optRepeat = true;
2980+
opts.optRepeatCount = 4;
2981+
2982+
opts.dspMetrics = (JitConfig.JitMetrics() != 0);
29652983
}
29662984

29672985
if (verboseDump)
@@ -4916,7 +4934,7 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
49164934

49174935
if (opts.optRepeat)
49184936
{
4919-
iterations = JitConfig.JitOptRepeatCount();
4937+
iterations = opts.optRepeatCount;
49204938
}
49214939
#endif // defined(OPT_CONFIG)
49224940

@@ -5033,6 +5051,13 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
50335051
DoPhase(this, PHASE_COMPUTE_EDGE_WEIGHTS2, &Compiler::fgComputeEdgeWeights);
50345052
}
50355053

5054+
#ifdef DEBUG
5055+
if (verbose && opts.optRepeat)
5056+
{
5057+
printf("\n*************** JitOptRepeat: iterations remaining: %d\n\n", iterations - 1);
5058+
}
5059+
#endif // DEBUG
5060+
50365061
// Iterate if requested, resetting annotations first.
50375062
if (--iterations == 0)
50385063
{
@@ -5045,13 +5070,6 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
50455070
//
50465071
DoPhase(this, PHASE_CANONICALIZE_ENTRY, &Compiler::fgCanonicalizeFirstBB);
50475072

5048-
#ifdef DEBUG
5049-
if (verbose)
5050-
{
5051-
printf("\n*************** JitOptRepeat: iterations remaining: %d\n\n", iterations);
5052-
}
5053-
#endif
5054-
50555073
ResetOptAnnotations();
50565074
RecomputeFlowGraphAnnotations();
50575075
}
@@ -5866,6 +5884,10 @@ void Compiler::RecomputeFlowGraphAnnotations()
58665884
fgInvalidateDfsTree();
58675885
fgDfsBlocksAndRemove();
58685886
optFindLoops();
5887+
5888+
// Should we call this using the phase method:
5889+
// DoPhase(this, PHASE_SET_BLOCK_WEIGHTS, &Compiler::optSetBlockWeights);
5890+
// ? It could be called multiple times.
58695891
optSetBlockWeights();
58705892

58715893
if (m_domTree == nullptr)

src/coreclr/jit/compiler.h

+20-5
Original file line numberDiff line numberDiff line change
@@ -1584,7 +1584,7 @@ enum class ProfileChecks : unsigned int
15841584
CHECK_NONE = 0,
15851585
CHECK_CLASSIC = 1 << 0, // check "classic" jit weights
15861586
CHECK_HASLIKELIHOOD = 1 << 1, // check all FlowEdges for hasLikelihood
1587-
CHECK_LIKELIHOODSUM = 1 << 2, // check block succesor likelihoods sum to 1
1587+
CHECK_LIKELIHOODSUM = 1 << 2, // check block successor likelihoods sum to 1
15881588
CHECK_LIKELY = 1 << 3, // fully check likelihood based weights
15891589
RAISE_ASSERT = 1 << 4, // assert on check failure
15901590
CHECK_ALL_BLOCKS = 1 << 5, // check blocks even if bbHasProfileWeight is false
@@ -1951,6 +1951,10 @@ class FlowGraphDfsTree
19511951
return m_hasCycle;
19521952
}
19531953

1954+
#ifdef DEBUG
1955+
void Dump() const;
1956+
#endif // DEBUG
1957+
19541958
bool Contains(BasicBlock* block) const;
19551959
bool IsAncestor(BasicBlock* ancestor, BasicBlock* descendant) const;
19561960
};
@@ -2230,7 +2234,7 @@ class FlowGraphNaturalLoops
22302234
return m_dfsTree;
22312235
}
22322236

2233-
size_t NumLoops()
2237+
size_t NumLoops() const
22342238
{
22352239
return m_loops.size();
22362240
}
@@ -2322,6 +2326,7 @@ class FlowGraphDominatorTree
23222326
}
23232327

23242328
static BasicBlock* IntersectDom(BasicBlock* block1, BasicBlock* block2);
2329+
23252330
public:
23262331
const FlowGraphDfsTree* GetDfsTree()
23272332
{
@@ -2355,6 +2360,10 @@ class BlockToNaturalLoopMap
23552360
FlowGraphNaturalLoop* GetLoop(BasicBlock* block);
23562361

23572362
static BlockToNaturalLoopMap* Build(FlowGraphNaturalLoops* loops);
2363+
2364+
#ifdef DEBUG
2365+
void Dump() const;
2366+
#endif // DEBUG
23582367
};
23592368

23602369
// Represents a data structure that can answer A -> B reachability queries in
@@ -6076,7 +6085,11 @@ class Compiler
60766085

60776086
void fgDispBBLiveness(BasicBlock* block);
60786087
void fgDispBBLiveness();
6079-
void fgTableDispBasicBlock(const BasicBlock* block, const BasicBlock* nextBlock = nullptr, int blockTargetFieldWidth = 21, int ibcColWidth = 0);
6088+
void fgTableDispBasicBlock(const BasicBlock* block,
6089+
const BasicBlock* nextBlock = nullptr,
6090+
bool printEdgeLikelihoods = true,
6091+
int blockTargetFieldWidth = 21,
6092+
int ibcColWidth = 0);
60806093
void fgDispBasicBlocks(BasicBlock* firstBlock, BasicBlock* lastBlock, bool dumpTrees);
60816094
void fgDispBasicBlocks(bool dumpTrees = false);
60826095
void fgDumpStmtTree(const BasicBlock* block, Statement* stmt);
@@ -9816,7 +9829,8 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
98169829
bool altJit; // True if we are an altjit and are compiling this method
98179830

98189831
#ifdef OPT_CONFIG
9819-
bool optRepeat; // Repeat optimizer phases k times
9832+
bool optRepeat; // Repeat optimizer phases k times
9833+
int optRepeatCount; // How many times to repeat. By default, comes from JitConfig.JitOptRepeatCount().
98209834
#endif
98219835

98229836
bool disAsm; // Display native code as it is generated
@@ -10061,13 +10075,14 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1006110075
STRESS_MODE(PHYSICAL_PROMOTION) /* Use physical promotion */ \
1006210076
STRESS_MODE(PHYSICAL_PROMOTION_COST) \
1006310077
STRESS_MODE(UNWIND) /* stress unwind info; e.g., create function fragments */ \
10078+
STRESS_MODE(OPT_REPEAT) /* stress JitOptRepeat */ \
1006410079
\
1006510080
/* After COUNT_VARN, stress level 2 does all of these all the time */ \
1006610081
\
1006710082
STRESS_MODE(COUNT_VARN) \
1006810083
\
1006910084
/* "Check" stress areas that can be exhaustively used if we */ \
10070-
/* dont care about performance at all */ \
10085+
/* don't care about performance at all */ \
1007110086
\
1007210087
STRESS_MODE(FORCE_INLINE) /* Treat every method as AggressiveInlining */ \
1007310088
STRESS_MODE(CHK_FLOW_UPDATE) \

0 commit comments

Comments
 (0)