@@ -51,6 +51,12 @@ cl::opt<bool>
51
51
cl::desc (" Infer counts from stale profile data." ),
52
52
cl::init(false ), cl::Hidden, cl::cat(BoltOptCategory));
53
53
54
+ cl::opt<unsigned > StaleMatchingMinMatchedBlock (
55
+ " stale-matching-min-matched-block" ,
56
+ cl::desc (" Percentage threshold of matched basic blocks at which stale "
57
+ " profile inference is executed." ),
58
+ cl::init(0 ), cl::Hidden, cl::cat(BoltOptCategory));
59
+
54
60
cl::opt<unsigned > StaleMatchingMaxFuncSize (
55
61
" stale-matching-max-func-size" ,
56
62
cl::desc (" The maximum size of a function to consider for inference." ),
@@ -391,10 +397,9 @@ createFlowFunction(const BinaryFunction::BasicBlockOrderType &BlockOrder) {
391
397
// / of the basic blocks in the binary, the count is "matched" to the block.
392
398
// / Similarly, if both the source and the target of a count in the profile are
393
399
// / matched to a jump in the binary, the count is recorded in CFG.
394
- void matchWeightsByHashes (BinaryContext &BC,
395
- const BinaryFunction::BasicBlockOrderType &BlockOrder,
396
- const yaml::bolt::BinaryFunctionProfile &YamlBF,
397
- FlowFunction &Func) {
400
+ size_t matchWeightsByHashes (
401
+ BinaryContext &BC, const BinaryFunction::BasicBlockOrderType &BlockOrder,
402
+ const yaml::bolt::BinaryFunctionProfile &YamlBF, FlowFunction &Func) {
398
403
assert (Func.Blocks .size () == BlockOrder.size () + 1 );
399
404
400
405
std::vector<FlowBlock *> Blocks;
@@ -500,6 +505,8 @@ void matchWeightsByHashes(BinaryContext &BC,
500
505
Block.HasUnknownWeight = false ;
501
506
Block.Weight = std::max (OutWeight[Block.Index ], InWeight[Block.Index ]);
502
507
}
508
+
509
+ return MatchedBlocks.size ();
503
510
}
504
511
505
512
// / The function finds all blocks that are (i) reachable from the Entry block
@@ -575,10 +582,16 @@ void preprocessUnreachableBlocks(FlowFunction &Func) {
575
582
// / Decide if stale profile matching can be applied for a given function.
576
583
// / Currently we skip inference for (very) large instances and for instances
577
584
// / having "unexpected" control flow (e.g., having no sink basic blocks).
578
- bool canApplyInference (const FlowFunction &Func) {
585
+ bool canApplyInference (const FlowFunction &Func,
586
+ const yaml::bolt::BinaryFunctionProfile &YamlBF,
587
+ const uint64_t &MatchedBlocks) {
579
588
if (Func.Blocks .size () > opts::StaleMatchingMaxFuncSize)
580
589
return false ;
581
590
591
+ if (MatchedBlocks * 100 <
592
+ opts::StaleMatchingMinMatchedBlock * YamlBF.Blocks .size ())
593
+ return false ;
594
+
582
595
bool HasExitBlocks = llvm::any_of (
583
596
Func.Blocks , [&](const FlowBlock &Block) { return Block.isExit (); });
584
597
if (!HasExitBlocks)
@@ -725,18 +738,21 @@ bool YAMLProfileReader::inferStaleProfile(
725
738
const BinaryFunction::BasicBlockOrderType BlockOrder (
726
739
BF.getLayout ().block_begin (), BF.getLayout ().block_end ());
727
740
741
+ // Tracks the number of matched blocks.
742
+
728
743
// Create a wrapper flow function to use with the profile inference algorithm.
729
744
FlowFunction Func = createFlowFunction (BlockOrder);
730
745
731
746
// Match as many block/jump counts from the stale profile as possible
732
- matchWeightsByHashes (BF.getBinaryContext (), BlockOrder, YamlBF, Func);
747
+ size_t MatchedBlocks =
748
+ matchWeightsByHashes (BF.getBinaryContext (), BlockOrder, YamlBF, Func);
733
749
734
750
// Adjust the flow function by marking unreachable blocks Unlikely so that
735
751
// they don't get any counts assigned.
736
752
preprocessUnreachableBlocks (Func);
737
753
738
754
// Check if profile inference can be applied for the instance.
739
- if (!canApplyInference (Func))
755
+ if (!canApplyInference (Func, YamlBF, MatchedBlocks ))
740
756
return false ;
741
757
742
758
// Apply the profile inference algorithm.
0 commit comments