@@ -51,6 +51,12 @@ cl::opt<bool>
5151 cl::desc (" Infer counts from stale profile data." ),
5252 cl::init(false ), cl::Hidden, cl::cat(BoltOptCategory));
5353
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+
5460cl::opt<unsigned > StaleMatchingMaxFuncSize (
5561 " stale-matching-max-func-size" ,
5662 cl::desc (" The maximum size of a function to consider for inference." ),
@@ -391,10 +397,9 @@ createFlowFunction(const BinaryFunction::BasicBlockOrderType &BlockOrder) {
391397// / of the basic blocks in the binary, the count is "matched" to the block.
392398// / Similarly, if both the source and the target of a count in the profile are
393399// / 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) {
398403 assert (Func.Blocks .size () == BlockOrder.size () + 1 );
399404
400405 std::vector<FlowBlock *> Blocks;
@@ -500,6 +505,8 @@ void matchWeightsByHashes(BinaryContext &BC,
500505 Block.HasUnknownWeight = false ;
501506 Block.Weight = std::max (OutWeight[Block.Index ], InWeight[Block.Index ]);
502507 }
508+
509+ return MatchedBlocks.size ();
503510}
504511
505512// / The function finds all blocks that are (i) reachable from the Entry block
@@ -575,10 +582,16 @@ void preprocessUnreachableBlocks(FlowFunction &Func) {
575582// / Decide if stale profile matching can be applied for a given function.
576583// / Currently we skip inference for (very) large instances and for instances
577584// / 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) {
579588 if (Func.Blocks .size () > opts::StaleMatchingMaxFuncSize)
580589 return false ;
581590
591+ if (MatchedBlocks * 100 <
592+ opts::StaleMatchingMinMatchedBlock * YamlBF.Blocks .size ())
593+ return false ;
594+
582595 bool HasExitBlocks = llvm::any_of (
583596 Func.Blocks , [&](const FlowBlock &Block) { return Block.isExit (); });
584597 if (!HasExitBlocks)
@@ -725,18 +738,21 @@ bool YAMLProfileReader::inferStaleProfile(
725738 const BinaryFunction::BasicBlockOrderType BlockOrder (
726739 BF.getLayout ().block_begin (), BF.getLayout ().block_end ());
727740
741+ // Tracks the number of matched blocks.
742+
728743 // Create a wrapper flow function to use with the profile inference algorithm.
729744 FlowFunction Func = createFlowFunction (BlockOrder);
730745
731746 // 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);
733749
734750 // Adjust the flow function by marking unreachable blocks Unlikely so that
735751 // they don't get any counts assigned.
736752 preprocessUnreachableBlocks (Func);
737753
738754 // Check if profile inference can be applied for the instance.
739- if (!canApplyInference (Func))
755+ if (!canApplyInference (Func, YamlBF, MatchedBlocks ))
740756 return false ;
741757
742758 // Apply the profile inference algorithm.
0 commit comments