aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshawbyoung <shawbyoung@gmail.com>2024-06-13 16:51:12 -0700
committershawbyoung <shawbyoung@gmail.com>2024-06-13 16:51:12 -0700
commit9cd7c8e4f939464ef1a1d8f161a2645a80b36684 (patch)
treef215d9a099de3555335a704a2efbb2b154d66e7b
parentf3b212cd123398b563da3a9a69c2903d8b355d19 (diff)
parente83a03722cbd643f3b56869a9f21b65c6113586f (diff)
downloadllvm-users/shawbyoung/spr/using-matched-block-counts-to-measure-discrepancy.zip
llvm-users/shawbyoung/spr/using-matched-block-counts-to-measure-discrepancy.tar.gz
llvm-users/shawbyoung/spr/using-matched-block-counts-to-measure-discrepancy.tar.bz2
Created using spr 1.3.4
-rw-r--r--bolt/lib/Profile/StaleProfileMatching.cpp39
1 files changed, 35 insertions, 4 deletions
diff --git a/bolt/lib/Profile/StaleProfileMatching.cpp b/bolt/lib/Profile/StaleProfileMatching.cpp
index 365bc53..cbd98f4 100644
--- a/bolt/lib/Profile/StaleProfileMatching.cpp
+++ b/bolt/lib/Profile/StaleProfileMatching.cpp
@@ -51,6 +51,12 @@ cl::opt<bool>
cl::desc("Infer counts from stale profile data."),
cl::init(false), cl::Hidden, cl::cat(BoltOptCategory));
+cl::opt<unsigned> MatchedProfileThreshold(
+ "matched-profile-threshold",
+ cl::desc("Percentage threshold of matched basic blocks at which stale "
+ "profile inference is executed."),
+ cl::init(50), cl::Hidden, cl::cat(BoltOptCategory));
+
cl::opt<unsigned> StaleMatchingMaxFuncSize(
"stale-matching-max-func-size",
cl::desc("The maximum size of a function to consider for inference."),
@@ -180,6 +186,17 @@ public:
uint8_t SuccHash{0};
};
+/// A data object containing function matching information.
+struct FunctionMatchingData {
+public:
+ /// The number of blocks matched exactly.
+ uint64_t MatchedExactBlocks{0};
+ /// The number of blocks matched loosely.
+ uint64_t MatchedLooseBlocks{0};
+ /// The number of execution counts matched.
+ uint64_t MatchedExecCounts{0};
+};
+
/// The object is used to identify and match basic blocks in a BinaryFunction
/// given their hashes computed on a binary built from several revisions behind
/// release.
@@ -394,7 +411,8 @@ createFlowFunction(const BinaryFunction::BasicBlockOrderType &BlockOrder) {
void matchWeightsByHashes(BinaryContext &BC,
const BinaryFunction::BasicBlockOrderType &BlockOrder,
const yaml::bolt::BinaryFunctionProfile &YamlBF,
- FlowFunction &Func) {
+ FlowFunction &Func,
+ FunctionMatchingData &FuncMatchingData) {
assert(Func.Blocks.size() == BlockOrder.size() + 1);
std::vector<FlowBlock *> Blocks;
@@ -434,8 +452,11 @@ void matchWeightsByHashes(BinaryContext &BC,
if (Matcher.isHighConfidenceMatch(BinHash, YamlHash)) {
++BC.Stats.NumMatchedBlocks;
BC.Stats.MatchedSampleCount += YamlBB.ExecCount;
+ FuncMatchingData.MatchedExecCounts += YamlBB.ExecCount;
+ FuncMatchingData.MatchedExactBlocks += 1;
LLVM_DEBUG(dbgs() << " exact match\n");
} else {
+ FuncMatchingData.MatchedLooseBlocks += 1;
LLVM_DEBUG(dbgs() << " loose match\n");
}
if (YamlBB.NumInstructions == BB->size())
@@ -575,10 +596,16 @@ void preprocessUnreachableBlocks(FlowFunction &Func) {
/// Decide if stale profile matching can be applied for a given function.
/// Currently we skip inference for (very) large instances and for instances
/// having "unexpected" control flow (e.g., having no sink basic blocks).
-bool canApplyInference(const FlowFunction &Func) {
+bool canApplyInference(const FlowFunction &Func,
+ const yaml::bolt::BinaryFunctionProfile &YamlBF,
+ const FunctionMatchingData &FuncMatchingData) {
if (Func.Blocks.size() > opts::StaleMatchingMaxFuncSize)
return false;
+ if ((double)FuncMatchingData.MatchedExactBlocks / YamlBF.Blocks.size() >=
+ opts::MatchedProfileThreshold / 100.0)
+ return false;
+
bool HasExitBlocks = llvm::any_of(
Func.Blocks, [&](const FlowBlock &Block) { return Block.isExit(); });
if (!HasExitBlocks)
@@ -725,18 +752,22 @@ bool YAMLProfileReader::inferStaleProfile(
const BinaryFunction::BasicBlockOrderType BlockOrder(
BF.getLayout().block_begin(), BF.getLayout().block_end());
+ // Create a containter for function matching data.
+ FunctionMatchingData FuncMatchingData;
+
// Create a wrapper flow function to use with the profile inference algorithm.
FlowFunction Func = createFlowFunction(BlockOrder);
// Match as many block/jump counts from the stale profile as possible
- matchWeightsByHashes(BF.getBinaryContext(), BlockOrder, YamlBF, Func);
+ matchWeightsByHashes(BF.getBinaryContext(), BlockOrder, YamlBF, Func,
+ FuncMatchingData);
// Adjust the flow function by marking unreachable blocks Unlikely so that
// they don't get any counts assigned.
preprocessUnreachableBlocks(Func);
// Check if profile inference can be applied for the instance.
- if (!canApplyInference(Func))
+ if (!canApplyInference(Func, YamlBF, FuncMatchingData))
return false;
// Apply the profile inference algorithm.