@@ -596,6 +596,26 @@ void BlockCountInstrumentor::Instrument(BasicBlock* block, Schema& schema, uint8
596
596
(entry.InstrumentationKind == ICorJitInfo::PgoInstrumentationKind::BasicBlockLongCount));
597
597
uint8_t * addrOfCurrentExecutionCount = entry.Offset + profileMemory;
598
598
599
+ #ifdef DEBUG
600
+ if (JitConfig.JitPropagateSynthesizedCountsToProfileData () > 0 )
601
+ {
602
+ // Write the current synthesized count as the profile data
603
+ //
604
+ weight_t blockWeight = block->bbWeight ;
605
+
606
+ if (entry.InstrumentationKind == ICorJitInfo::PgoInstrumentationKind::EdgeIntCount)
607
+ {
608
+ *((uint32_t *)addrOfCurrentExecutionCount) = (uint32_t )blockWeight;
609
+ }
610
+ else
611
+ {
612
+ *((uint64_t *)addrOfCurrentExecutionCount) = (uint64_t )blockWeight;
613
+ }
614
+
615
+ return ;
616
+ }
617
+ #endif
618
+
599
619
var_types typ =
600
620
entry.InstrumentationKind == ICorJitInfo::PgoInstrumentationKind::BasicBlockIntCount ? TYP_INT : TYP_LONG;
601
621
@@ -1742,6 +1762,32 @@ void EfficientEdgeCountInstrumentor::Instrument(BasicBlock* block, Schema& schem
1742
1762
1743
1763
uint8_t * addrOfCurrentExecutionCount = profileMemory + entry.Offset ;
1744
1764
1765
+ #ifdef DEBUG
1766
+ if (JitConfig.JitPropagateSynthesizedCountsToProfileData () > 0 )
1767
+ {
1768
+ // Write the current synthesized count as the profile data
1769
+ //
1770
+ // Todo: handle pseudo edges!
1771
+ FlowEdge* const edge = m_comp->fgGetPredForBlock (source, target);
1772
+
1773
+ if (edge != nullptr )
1774
+ {
1775
+ weight_t edgeWeight = edge->getLikelyWeight ();
1776
+
1777
+ if (entry.InstrumentationKind == ICorJitInfo::PgoInstrumentationKind::EdgeIntCount)
1778
+ {
1779
+ *((uint32_t *)addrOfCurrentExecutionCount) = (uint32_t )edgeWeight;
1780
+ }
1781
+ else
1782
+ {
1783
+ *((uint64_t *)addrOfCurrentExecutionCount) = (uint64_t )edgeWeight;
1784
+ }
1785
+ }
1786
+
1787
+ return ;
1788
+ }
1789
+ #endif
1790
+
1745
1791
// Determine where to place the probe.
1746
1792
//
1747
1793
BasicBlock* instrumentedBlock = nullptr ;
@@ -2428,7 +2474,7 @@ PhaseStatus Compiler::fgIncorporateProfileData()
2428
2474
}
2429
2475
2430
2476
#ifdef DEBUG
2431
- // Optionally just run synthesis
2477
+ // Optionally run synthesis
2432
2478
//
2433
2479
if ((JitConfig.JitSynthesizeCounts () > 0 ) && !compIsForInlining ())
2434
2480
{
@@ -2439,6 +2485,17 @@ PhaseStatus Compiler::fgIncorporateProfileData()
2439
2485
return PhaseStatus::MODIFIED_EVERYTHING;
2440
2486
}
2441
2487
}
2488
+
2489
+ // Or run synthesis and save the data out as the actual profile data
2490
+ //
2491
+ if (opts.jitFlags ->IsSet (JitFlags::JIT_FLAG_BBINSTR) &&
2492
+ (JitConfig.JitPropagateSynthesizedCountsToProfileData () > 0 ) && !compIsForInlining ())
2493
+ {
2494
+ JITDUMP (" Synthesizing profile data and writing it out as the actual profile data\n " );
2495
+ ProfileSynthesis::Run (this , ProfileSynthesisOption::AssignLikelihoods);
2496
+ fgPgoHaveWeights = false ;
2497
+ return PhaseStatus::MODIFIED_EVERYTHING;
2498
+ }
2442
2499
#endif
2443
2500
2444
2501
// Do we have profile data?
@@ -4845,15 +4902,8 @@ bool Compiler::fgProfileWeightsConsistent(weight_t weight1, weight_t weight2)
4845
4902
// (or nearly so)
4846
4903
//
4847
4904
// Notes:
4848
- // For each profiled block, check that the flow of counts into
4849
- // the block matches the flow of counts out of the block.
4850
- //
4851
- // We ignore EH flow as we don't have explicit edges and generally
4852
- // we expect EH edge counts to be small, so errors from ignoring
4853
- // them should be rare.
4854
- //
4855
- // There's no point checking until we've built pred lists, as
4856
- // we can't easily reason about consistency without them.
4905
+ // Does nothing, if profile checks are disabled, or there are
4906
+ // no profile weights or pred lists.
4857
4907
//
4858
4908
void Compiler::fgDebugCheckProfileWeights ()
4859
4909
{
@@ -4865,13 +4915,37 @@ void Compiler::fgDebugCheckProfileWeights()
4865
4915
return ;
4866
4916
}
4867
4917
4918
+ fgDebugCheckProfileWeights ((ProfileChecks)JitConfig.JitProfileChecks ());
4919
+ }
4920
+
4921
+ // ------------------------------------------------------------------------
4922
+ // fgDebugCheckProfileWeights: verify profile weights are self-consistent
4923
+ // (or nearly so)
4924
+ //
4925
+ // Arguments:
4926
+ // checks - checker options
4927
+ //
4928
+ // Notes:
4929
+ // For each profiled block, check that the flow of counts into
4930
+ // the block matches the flow of counts out of the block.
4931
+ //
4932
+ // We ignore EH flow as we don't have explicit edges and generally
4933
+ // we expect EH edge counts to be small, so errors from ignoring
4934
+ // them should be rare.
4935
+ //
4936
+ // There's no point checking until we've built pred lists, as
4937
+ // we can't easily reason about consistency without them.
4938
+ //
4939
+ void Compiler::fgDebugCheckProfileWeights (ProfileChecks checks)
4940
+ {
4868
4941
// We can check classic (min/max, late computed) weights
4869
4942
// and/or
4870
4943
// new likelyhood based weights.
4871
4944
//
4872
- const bool verifyClassicWeights = fgEdgeWeightsComputed && (JitConfig.JitProfileChecks () & 0x1 ) == 0x1 ;
4873
- const bool verifyLikelyWeights = (JitConfig.JitProfileChecks () & 0x2 ) == 0x2 ;
4874
- const bool assertOnFailure = (JitConfig.JitProfileChecks () & 0x4 ) == 0x4 ;
4945
+ const bool verifyClassicWeights = fgEdgeWeightsComputed && hasFlag (checks, ProfileChecks::CHECK_CLASSIC);
4946
+ const bool verifyLikelyWeights = hasFlag (checks, ProfileChecks::CHECK_LIKELY);
4947
+ const bool assertOnFailure = hasFlag (checks, ProfileChecks::RAISE_ASSERT);
4948
+ const bool checkAllBlocks = hasFlag (checks, ProfileChecks::CHECK_ALL_BLOCKS);
4875
4949
4876
4950
if (!(verifyClassicWeights || verifyLikelyWeights))
4877
4951
{
@@ -4891,7 +4965,7 @@ void Compiler::fgDebugCheckProfileWeights()
4891
4965
//
4892
4966
for (BasicBlock* const block : Blocks ())
4893
4967
{
4894
- if (!block->hasProfileWeight ())
4968
+ if (!block->hasProfileWeight () && !checkAllBlocks )
4895
4969
{
4896
4970
unprofiledBlocks++;
4897
4971
continue ;
@@ -4929,8 +5003,11 @@ void Compiler::fgDebugCheckProfileWeights()
4929
5003
//
4930
5004
if (block->KindIs (BBJ_RETURN, BBJ_THROW))
4931
5005
{
4932
- exitWeight += blockWeight;
4933
- exitProfiled = !opts.IsOSR ();
5006
+ if (BasicBlock::sameHndRegion (block, fgFirstBB))
5007
+ {
5008
+ exitWeight += blockWeight;
5009
+ exitProfiled = !opts.IsOSR ();
5010
+ }
4934
5011
verifyOutgoing = false ;
4935
5012
}
4936
5013
@@ -4969,12 +5046,12 @@ void Compiler::fgDebugCheckProfileWeights()
4969
5046
4970
5047
if (verifyIncoming)
4971
5048
{
4972
- incomingConsistent = fgDebugCheckIncomingProfileData (block);
5049
+ incomingConsistent = fgDebugCheckIncomingProfileData (block, checks );
4973
5050
}
4974
5051
4975
5052
if (verifyOutgoing)
4976
5053
{
4977
- outgoingConsistent = fgDebugCheckOutgoingProfileData (block);
5054
+ outgoingConsistent = fgDebugCheckOutgoingProfileData (block, checks );
4978
5055
}
4979
5056
4980
5057
if (!incomingConsistent || !outgoingConsistent)
@@ -4987,7 +5064,13 @@ void Compiler::fgDebugCheckProfileWeights()
4987
5064
//
4988
5065
if (entryProfiled && exitProfiled)
4989
5066
{
4990
- if (!fgProfileWeightsConsistent (entryWeight, exitWeight))
5067
+ // Note these may not agree, if fgEntryBB is a loop header.
5068
+ //
5069
+ if (fgFirstBB->bbRefs > 1 )
5070
+ {
5071
+ JITDUMP (" Method entry " FMT_BB " is loop head, can't check entry/exit balance\n " );
5072
+ }
5073
+ else if (!fgProfileWeightsConsistent (entryWeight, exitWeight))
4991
5074
{
4992
5075
problemBlocks++;
4993
5076
JITDUMP (" Method entry " FMT_WT " method exit " FMT_WT " weight mismatch\n " , entryWeight, exitWeight);
@@ -5025,18 +5108,19 @@ void Compiler::fgDebugCheckProfileWeights()
5025
5108
// block matches the profile weight of the block.
5026
5109
//
5027
5110
// Arguments:
5028
- // block - block to check
5111
+ // block - block to check
5112
+ // checks - checker options
5029
5113
//
5030
5114
// Returns:
5031
5115
// true if counts consistent or checking disabled, false otherwise.
5032
5116
//
5033
5117
// Notes:
5034
5118
// Only useful to call on blocks with predecessors.
5035
5119
//
5036
- bool Compiler::fgDebugCheckIncomingProfileData (BasicBlock* block)
5120
+ bool Compiler::fgDebugCheckIncomingProfileData (BasicBlock* block, ProfileChecks checks )
5037
5121
{
5038
- const bool verifyClassicWeights = fgEdgeWeightsComputed && (JitConfig. JitProfileChecks () & 0x1 ) == 0x1 ;
5039
- const bool verifyLikelyWeights = (JitConfig. JitProfileChecks () & 0x2 ) == 0x2 ;
5122
+ const bool verifyClassicWeights = fgEdgeWeightsComputed && hasFlag (checks, ProfileChecks::CHECK_CLASSIC) ;
5123
+ const bool verifyLikelyWeights = hasFlag (checks, ProfileChecks::CHECK_LIKELY) ;
5040
5124
5041
5125
if (!(verifyClassicWeights || verifyLikelyWeights))
5042
5126
{
@@ -5056,7 +5140,10 @@ bool Compiler::fgDebugCheckIncomingProfileData(BasicBlock* block)
5056
5140
incomingWeightMax += predEdge->edgeWeightMax ();
5057
5141
if (predEdge->hasLikelihood ())
5058
5142
{
5059
- incomingLikelyWeight += predEdge->getLikelyWeight ();
5143
+ if (BasicBlock::sameHndRegion (block, predEdge->getSourceBlock ()))
5144
+ {
5145
+ incomingLikelyWeight += predEdge->getLikelyWeight ();
5146
+ }
5060
5147
}
5061
5148
else
5062
5149
{
@@ -5122,17 +5209,18 @@ bool Compiler::fgDebugCheckIncomingProfileData(BasicBlock* block)
5122
5209
//
5123
5210
// Arguments:
5124
5211
// block - block to check
5212
+ // checks - checker options
5125
5213
//
5126
5214
// Returns:
5127
5215
// true if counts consistent or checking disabled, false otherwise.
5128
5216
//
5129
5217
// Notes:
5130
5218
// Only useful to call on blocks with successors.
5131
5219
//
5132
- bool Compiler::fgDebugCheckOutgoingProfileData (BasicBlock* block)
5220
+ bool Compiler::fgDebugCheckOutgoingProfileData (BasicBlock* block, ProfileChecks checks )
5133
5221
{
5134
- const bool verifyClassicWeights = fgEdgeWeightsComputed && (JitConfig. JitProfileChecks () & 0x1 ) == 0x1 ;
5135
- const bool verifyLikelyWeights = (JitConfig. JitProfileChecks () & 0x2 ) == 0x2 ;
5222
+ const bool verifyClassicWeights = fgEdgeWeightsComputed && hasFlag (checks, ProfileChecks::CHECK_CLASSIC) ;
5223
+ const bool verifyLikelyWeights = hasFlag (checks, ProfileChecks::CHECK_LIKELY) ;
5136
5224
5137
5225
if (!(verifyClassicWeights || verifyLikelyWeights))
5138
5226
{
0 commit comments