https://github.com/shawbyoung updated https://github.com/llvm/llvm-project/pull/99891
>From 0274f697376264c2d77816190f9a434f64e79089 Mon Sep 17 00:00:00 2001 From: shawbyoung <shawbyo...@gmail.com> Date: Mon, 22 Jul 2024 11:56:23 -0700 Subject: [PATCH 01/19] Changed assignment of profiles with pseudo probe index Created using spr 1.3.4 --- bolt/lib/Profile/StaleProfileMatching.cpp | 85 +++++++++++++++---- .../X86/match-blocks-with-pseudo-probes.test | 25 ++---- 2 files changed, 78 insertions(+), 32 deletions(-) diff --git a/bolt/lib/Profile/StaleProfileMatching.cpp b/bolt/lib/Profile/StaleProfileMatching.cpp index 4105f626fb5b6..c135ee5ff4837 100644 --- a/bolt/lib/Profile/StaleProfileMatching.cpp +++ b/bolt/lib/Profile/StaleProfileMatching.cpp @@ -195,11 +195,15 @@ class StaleMatcher { void init(const std::vector<FlowBlock *> &Blocks, const std::vector<BlendedBlockHash> &Hashes, const std::vector<uint64_t> &CallHashes, - std::optional<uint64_t> YamlBFGUID) { + const std::unordered_map<uint64_t, + std::vector<const MCDecodedPseudoProbe *>> + IndexToBinaryPseudoProbes, + const std::unordered_map<const MCDecodedPseudoProbe *, FlowBlock *> + BinaryPseudoProbeToBlock, + const uint64_t YamlBFGUID) { assert(Blocks.size() == Hashes.size() && Hashes.size() == CallHashes.size() && "incorrect matcher initialization"); - for (size_t I = 0; I < Blocks.size(); I++) { FlowBlock *Block = Blocks[I]; uint16_t OpHash = Hashes[I].OpcodeHash; @@ -209,6 +213,8 @@ class StaleMatcher { std::make_pair(Hashes[I], Block)); this->Blocks.push_back(Block); } + this->IndexToBinaryPseudoProbes = IndexToBinaryPseudoProbes; + this->BinaryPseudoProbeToBlock = BinaryPseudoProbeToBlock; this->YamlBFGUID = YamlBFGUID; } @@ -234,10 +240,14 @@ class StaleMatcher { using HashBlockPairType = std::pair<BlendedBlockHash, FlowBlock *>; std::unordered_map<uint16_t, std::vector<HashBlockPairType>> OpHashToBlocks; std::unordered_map<uint64_t, std::vector<HashBlockPairType>> CallHashToBlocks; - std::vector<FlowBlock *> Blocks; + std::unordered_map<uint64_t, std::vector<const MCDecodedPseudoProbe *>> + IndexToBinaryPseudoProbes; + std::unordered_map<const MCDecodedPseudoProbe *, FlowBlock *> + BinaryPseudoProbeToBlock; + std::vector<const FlowBlock *> Blocks; // If the pseudo probe checksums of the profiled and binary functions are // equal, then the YamlBF's GUID is defined and used to match blocks. - std::optional<uint64_t> YamlBFGUID; + uint64_t YamlBFGUID; // Uses OpcodeHash to find the most similar block for a given hash. const FlowBlock *matchWithOpcodes(BlendedBlockHash BlendedHash) const { @@ -284,7 +294,7 @@ class StaleMatcher { // Searches for the pseudo probe attached to the matched function's block, // ignoring pseudo probes attached to function calls and inlined functions' // blocks. - outs() << "match with pseudo probes\n"; + std::vector<const yaml::bolt::PseudoProbeInfo *> BlockPseudoProbes; for (const auto &PseudoProbe : PseudoProbes) { // Ensures that pseudo probe information belongs to the appropriate // function and not an inlined function. @@ -293,11 +303,30 @@ class StaleMatcher { // Skips pseudo probes attached to function calls. if (PseudoProbe.Type != static_cast<uint8_t>(PseudoProbeType::Block)) continue; - assert(PseudoProbe.Index < Blocks.size() && - "pseudo probe index out of range"); - return Blocks[PseudoProbe.Index]; + + BlockPseudoProbes.push_back(&PseudoProbe); } - return nullptr; + + // Returns nullptr if there is not a 1:1 mapping of the yaml block pseudo + // probe and binary pseudo probe. + if (BlockPseudoProbes.size() == 0 || BlockPseudoProbes.size() > 1) + return nullptr; + + uint64_t Index = BlockPseudoProbes[0]->Index; + assert(Index < Blocks.size() && "Invalid pseudo probe index"); + + auto It = IndexToBinaryPseudoProbes.find(Index); + assert(It != IndexToBinaryPseudoProbes.end() && + "All blocks should have a pseudo probe"); + if (It->second.size() > 1) + return nullptr; + + const MCDecodedPseudoProbe *BinaryPseudoProbe = It->second[0]; + auto BinaryPseudoProbeIt = BinaryPseudoProbeToBlock.find(BinaryPseudoProbe); + assert(BinaryPseudoProbeIt != BinaryPseudoProbeToBlock.end() && + "All binary pseudo probes should belong a binary basic block"); + + return BinaryPseudoProbeIt->second; } }; @@ -491,6 +520,11 @@ size_t matchWeightsByHashes( std::vector<uint64_t> CallHashes; std::vector<FlowBlock *> Blocks; std::vector<BlendedBlockHash> BlendedHashes; + std::unordered_map<uint64_t, std::vector<const MCDecodedPseudoProbe *>> + IndexToBinaryPseudoProbes; + std::unordered_map<const MCDecodedPseudoProbe *, FlowBlock *> + BinaryPseudoProbeToBlock; + const MCPseudoProbeDecoder *PseudoProbeDecoder = BC.getPseudoProbeDecoder(); for (uint64_t I = 0; I < BlockOrder.size(); I++) { const BinaryBasicBlock *BB = BlockOrder[I]; assert(BB->getHash() != 0 && "empty hash of BinaryBasicBlock"); @@ -510,9 +544,27 @@ size_t matchWeightsByHashes( Blocks.push_back(&Func.Blocks[I + 1]); BlendedBlockHash BlendedHash(BB->getHash()); BlendedHashes.push_back(BlendedHash); + if (PseudoProbeDecoder) { + const AddressProbesMap &ProbeMap = + PseudoProbeDecoder->getAddress2ProbesMap(); + const uint64_t FuncAddr = BF.getAddress(); + const std::pair<uint64_t, uint64_t> &BlockRange = + BB->getInputAddressRange(); + const auto &BlockProbes = + llvm::make_range(ProbeMap.lower_bound(FuncAddr + BlockRange.first), + ProbeMap.lower_bound(FuncAddr + BlockRange.second)); + for (const auto &[_, Probes] : BlockProbes) { + for (const MCDecodedPseudoProbe &Probe : Probes) { + IndexToBinaryPseudoProbes[Probe.getIndex()].push_back(&Probe); + BinaryPseudoProbeToBlock[&Probe] = Blocks[I]; + } + } + } + LLVM_DEBUG(dbgs() << "BB with index " << I << " has hash = " << Twine::utohexstr(BB->getHash()) << "\n"); } + uint64_t BFPseudoProbeDescHash = 0; if (BF.hasPseudoProbe()) { const MCPseudoProbeDecoder *PseudoProbeDecoder = BC.getPseudoProbeDecoder(); @@ -521,14 +573,15 @@ size_t matchWeightsByHashes( BFPseudoProbeDescHash = PseudoProbeDecoder->getFuncDescForGUID(BF.getGUID())->FuncHash; } - bool MatchWithPseudoProbes = - BFPseudoProbeDescHash && YamlBF.PseudoProbeDescHash - ? BFPseudoProbeDescHash == YamlBF.PseudoProbeDescHash - : false; + uint64_t YamlBFGUID = + BFPseudoProbeDescHash && YamlBF.PseudoProbeDescHash && + BFPseudoProbeDescHash == YamlBF.PseudoProbeDescHash + ? static_cast<uint64_t>(YamlBF.GUID) + : 0; + StaleMatcher Matcher; - Matcher.init(Blocks, BlendedHashes, CallHashes, - MatchWithPseudoProbes ? std::make_optional(YamlBF.GUID) - : std::nullopt); + Matcher.init(Blocks, BlendedHashes, CallHashes, IndexToBinaryPseudoProbes, + BinaryPseudoProbeToBlock, YamlBFGUID); // Index in yaml profile => corresponding (matched) block DenseMap<uint64_t, const FlowBlock *> MatchedBlocks; diff --git a/bolt/test/X86/match-blocks-with-pseudo-probes.test b/bolt/test/X86/match-blocks-with-pseudo-probes.test index e0adb6948e206..1d74b92a11c56 100644 --- a/bolt/test/X86/match-blocks-with-pseudo-probes.test +++ b/bolt/test/X86/match-blocks-with-pseudo-probes.test @@ -5,7 +5,7 @@ # RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %t/main.s -o %t.o # RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -nostdlib # RUN: llvm-bolt %t.exe -o %t.out --data %t/yaml -v=2 \ -# RUN: --print-cfg --funcs=main --profile-ignore-hash=0 2>&1 | FileCheck %s +# RUN: --print-cfg --funcs=main --profile-ignore-hash=0 --infer-stale-profile 2>&1 | FileCheck %s # CHECK: BOLT-INFO: matched 0 functions with similar names @@ -47,23 +47,16 @@ header: dfs-order: false hash-func: xxh3 functions: - - name: main - fid: 0 - hash: 0x0000000000000001 - exec: 1 - nblocks: 6 + - name: main + fid: 0 + hash: 0x0000000000000001 + exec: 1 + nblocks: 6 + guid: 0xDB956436E78DD5FA + pseudo_probe_desc_hash: 15822663052811949562 #lookup in code in a second blocks: - bid: 1 hash: 0x0000000000000001 insns: 1 succ: [ { bid: 3, cnt: 1} ] - - name: foo - fid: 1 - hash: 0x0000000000000002 - exec: 1 - nblocks: 6 - blocks: - - bid: 1 - hash: 0x0000000000000002 - insns: 1 - succ: [ { bid: 3, cnt: 1} ] + pseudo_probes: [ { guid: 0xDB956436E78DD5FA, id: 0, type: 0 } ] >From 7e3d8d6b171954836c858f0814befc54f70bd3aa Mon Sep 17 00:00:00 2001 From: shawbyoung <shawbyo...@gmail.com> Date: Mon, 22 Jul 2024 14:27:44 -0700 Subject: [PATCH 02/19] Edit test and assert Created using spr 1.3.4 --- bolt/lib/Profile/StaleProfileMatching.cpp | 2 +- bolt/test/X86/match-blocks-with-pseudo-probes.test | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bolt/lib/Profile/StaleProfileMatching.cpp b/bolt/lib/Profile/StaleProfileMatching.cpp index c135ee5ff4837..71e0579415fc6 100644 --- a/bolt/lib/Profile/StaleProfileMatching.cpp +++ b/bolt/lib/Profile/StaleProfileMatching.cpp @@ -313,7 +313,7 @@ class StaleMatcher { return nullptr; uint64_t Index = BlockPseudoProbes[0]->Index; - assert(Index < Blocks.size() && "Invalid pseudo probe index"); + assert(Index <= Blocks.size() && "Invalid pseudo probe index"); auto It = IndexToBinaryPseudoProbes.find(Index); assert(It != IndexToBinaryPseudoProbes.end() && diff --git a/bolt/test/X86/match-blocks-with-pseudo-probes.test b/bolt/test/X86/match-blocks-with-pseudo-probes.test index 1d74b92a11c56..6dc01eb492eae 100644 --- a/bolt/test/X86/match-blocks-with-pseudo-probes.test +++ b/bolt/test/X86/match-blocks-with-pseudo-probes.test @@ -53,10 +53,10 @@ functions: exec: 1 nblocks: 6 guid: 0xDB956436E78DD5FA - pseudo_probe_desc_hash: 15822663052811949562 #lookup in code in a second + pseudo_probe_desc_hash: 4294967295 #lookup in code in a second blocks: - bid: 1 hash: 0x0000000000000001 insns: 1 succ: [ { bid: 3, cnt: 1} ] - pseudo_probes: [ { guid: 0xDB956436E78DD5FA, id: 0, type: 0 } ] + pseudo_probes: [ { guid: 0xDB956436E78DD5FA, id: 1, type: 0 } ] >From 780a07ee5a4b2bc3f5bd6e33fb072d67d1113c89 Mon Sep 17 00:00:00 2001 From: shawbyoung <shawbyo...@gmail.com> Date: Tue, 23 Jul 2024 11:37:14 -0700 Subject: [PATCH 03/19] Fixed failing asserts, pruned prospective pseudo probes for matching Created using spr 1.3.4 --- bolt/lib/Profile/StaleProfileMatching.cpp | 56 ++++++++++++++++------- 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/bolt/lib/Profile/StaleProfileMatching.cpp b/bolt/lib/Profile/StaleProfileMatching.cpp index 71e0579415fc6..d45066ed66ef2 100644 --- a/bolt/lib/Profile/StaleProfileMatching.cpp +++ b/bolt/lib/Profile/StaleProfileMatching.cpp @@ -45,6 +45,7 @@ namespace opts { extern cl::opt<bool> TimeRewrite; extern cl::OptionCategory BoltOptCategory; +extern cl::opt<unsigned> Verbosity; cl::opt<bool> InferStaleProfile("infer-stale-profile", @@ -197,9 +198,9 @@ class StaleMatcher { const std::vector<uint64_t> &CallHashes, const std::unordered_map<uint64_t, std::vector<const MCDecodedPseudoProbe *>> - IndexToBinaryPseudoProbes, + &IndexToBinaryPseudoProbes, const std::unordered_map<const MCDecodedPseudoProbe *, FlowBlock *> - BinaryPseudoProbeToBlock, + &BinaryPseudoProbeToBlock, const uint64_t YamlBFGUID) { assert(Blocks.size() == Hashes.size() && Hashes.size() == CallHashes.size() && @@ -294,6 +295,9 @@ class StaleMatcher { // Searches for the pseudo probe attached to the matched function's block, // ignoring pseudo probes attached to function calls and inlined functions' // blocks. + if (opts::Verbosity >= 2) + outs() << "BOLT-INFO: attempting to match block with pseudo probes\n"; + std::vector<const yaml::bolt::PseudoProbeInfo *> BlockPseudoProbes; for (const auto &PseudoProbe : PseudoProbes) { // Ensures that pseudo probe information belongs to the appropriate @@ -306,26 +310,41 @@ class StaleMatcher { BlockPseudoProbes.push_back(&PseudoProbe); } - // Returns nullptr if there is not a 1:1 mapping of the yaml block pseudo // probe and binary pseudo probe. - if (BlockPseudoProbes.size() == 0 || BlockPseudoProbes.size() > 1) + if (BlockPseudoProbes.size() == 0) { + if (opts::Verbosity >= 2) + errs() << "BOLT-WARNING: no pseudo probes in profile block\n"; return nullptr; - + } + if (BlockPseudoProbes.size() > 1) { + if (opts::Verbosity >= 2) + errs() << "BOLT-WARNING: more than 1 pseudo probes in profile block\n"; + return nullptr; + } uint64_t Index = BlockPseudoProbes[0]->Index; - assert(Index <= Blocks.size() && "Invalid pseudo probe index"); - + if (Index > Blocks.size()) { + if (opts::Verbosity >= 2) + errs() << "BOLT-WARNING: invalid index block pseudo probe index\n"; + return nullptr; + } auto It = IndexToBinaryPseudoProbes.find(Index); - assert(It != IndexToBinaryPseudoProbes.end() && - "All blocks should have a pseudo probe"); - if (It->second.size() > 1) + if (It == IndexToBinaryPseudoProbes.end()) { + if (opts::Verbosity >= 2) + errs() << "BOLT-WARNING: no block pseudo probes found within binary " + "block at index\n"; return nullptr; - + } + if (It->second.size() > 1) { + if (opts::Verbosity >= 2) + errs() << "BOLT-WARNING: more than 1 block pseudo probes in binary " + "block at index\n"; + return nullptr; + } const MCDecodedPseudoProbe *BinaryPseudoProbe = It->second[0]; auto BinaryPseudoProbeIt = BinaryPseudoProbeToBlock.find(BinaryPseudoProbe); assert(BinaryPseudoProbeIt != BinaryPseudoProbeToBlock.end() && "All binary pseudo probes should belong a binary basic block"); - return BinaryPseudoProbeIt->second; } }; @@ -555,6 +574,10 @@ size_t matchWeightsByHashes( ProbeMap.lower_bound(FuncAddr + BlockRange.second)); for (const auto &[_, Probes] : BlockProbes) { for (const MCDecodedPseudoProbe &Probe : Probes) { + if (Probe.getInlineTreeNode()->hasInlineSite()) + continue; + if (Probe.getType() != static_cast<uint8_t>(PseudoProbeType::Block)) + continue; IndexToBinaryPseudoProbes[Probe.getIndex()].push_back(&Probe); BinaryPseudoProbeToBlock[&Probe] = Blocks[I]; } @@ -566,12 +589,13 @@ size_t matchWeightsByHashes( } uint64_t BFPseudoProbeDescHash = 0; - if (BF.hasPseudoProbe()) { - const MCPseudoProbeDecoder *PseudoProbeDecoder = BC.getPseudoProbeDecoder(); + if (BF.getGUID() != 0) { assert(PseudoProbeDecoder && "If BF has pseudo probe, BC should have a pseudo probe decoder"); - BFPseudoProbeDescHash = - PseudoProbeDecoder->getFuncDescForGUID(BF.getGUID())->FuncHash; + auto &GUID2FuncDescMap = PseudoProbeDecoder->getGUID2FuncDescMap(); + auto It = GUID2FuncDescMap.find(BF.getGUID()); + if (It != GUID2FuncDescMap.end()) + BFPseudoProbeDescHash = It->second.FuncHash; } uint64_t YamlBFGUID = BFPseudoProbeDescHash && YamlBF.PseudoProbeDescHash && >From 1638ac1dacec63d9099ae3c19f2fee7c0797ed71 Mon Sep 17 00:00:00 2001 From: shawbyoung <shawbyo...@gmail.com> Date: Tue, 23 Jul 2024 14:24:02 -0700 Subject: [PATCH 04/19] Added logging for pseudo probe block matching Created using spr 1.3.4 --- bolt/include/bolt/Core/BinaryContext.h | 12 ++++++--- bolt/lib/Passes/BinaryPasses.cpp | 18 +++++++++++--- bolt/lib/Profile/StaleProfileMatching.cpp | 30 +++++++++++++++++------ 3 files changed, 44 insertions(+), 16 deletions(-) diff --git a/bolt/include/bolt/Core/BinaryContext.h b/bolt/include/bolt/Core/BinaryContext.h index b3cf9f834cc08..39f2ac512d305 100644 --- a/bolt/include/bolt/Core/BinaryContext.h +++ b/bolt/include/bolt/Core/BinaryContext.h @@ -717,12 +717,16 @@ class BinaryContext { /// Stats for stale profile matching: /// the total number of basic blocks in the profile uint32_t NumStaleBlocks{0}; - /// the number of matched basic blocks - uint32_t NumMatchedBlocks{0}; + /// the number of exactly matched basic blocks + uint32_t NumExactMatchedBlocks{0}; + /// the number of pseudo probe matched basic blocks + uint32_t NumPseudoProbeMatchedBlocks{0}; /// the total count of samples in the profile uint64_t StaleSampleCount{0}; - /// the count of matched samples - uint64_t MatchedSampleCount{0}; + /// the count of exactly matched samples + uint64_t ExactMatchedSampleCount{0}; + /// the count of pseudo probe matched samples + uint64_t PseudoProbeMatchedSampleCount{0}; /// the number of stale functions that have matching number of blocks in /// the profile uint64_t NumStaleFuncsWithEqualBlockCount{0}; diff --git a/bolt/lib/Passes/BinaryPasses.cpp b/bolt/lib/Passes/BinaryPasses.cpp index fa95ad7324ac1..b786f07a6a665 100644 --- a/bolt/lib/Passes/BinaryPasses.cpp +++ b/bolt/lib/Passes/BinaryPasses.cpp @@ -1519,10 +1519,20 @@ Error PrintProgramStats::runOnFunctions(BinaryContext &BC) { "BOLT-INFO: inference found an exact match for %.2f%% of basic blocks" " (%zu out of %zu stale) responsible for %.2f%% samples" " (%zu out of %zu stale)\n", - 100.0 * BC.Stats.NumMatchedBlocks / BC.Stats.NumStaleBlocks, - BC.Stats.NumMatchedBlocks, BC.Stats.NumStaleBlocks, - 100.0 * BC.Stats.MatchedSampleCount / BC.Stats.StaleSampleCount, - BC.Stats.MatchedSampleCount, BC.Stats.StaleSampleCount); + 100.0 * BC.Stats.NumExactMatchedBlocks / BC.Stats.NumStaleBlocks, + BC.Stats.NumExactMatchedBlocks, BC.Stats.NumStaleBlocks, + 100.0 * BC.Stats.ExactMatchedSampleCount / BC.Stats.StaleSampleCount, + BC.Stats.ExactMatchedSampleCount, BC.Stats.StaleSampleCount); + BC.outs() << format( + "BOLT-INFO: inference found a pseudo probe match for %.2f%% of basic " + "blocks" + " (%zu out of %zu stale) responsible for %.2f%% samples" + " (%zu out of %zu stale)\n", + 100.0 * BC.Stats.NumPseudoProbeMatchedBlocks / BC.Stats.NumStaleBlocks, + BC.Stats.NumPseudoProbeMatchedBlocks, BC.Stats.NumStaleBlocks, + 100.0 * BC.Stats.PseudoProbeMatchedSampleCount / + BC.Stats.StaleSampleCount, + BC.Stats.PseudoProbeMatchedSampleCount, BC.Stats.StaleSampleCount); } if (const uint64_t NumUnusedObjects = BC.getNumUnusedProfiledObjects()) { diff --git a/bolt/lib/Profile/StaleProfileMatching.cpp b/bolt/lib/Profile/StaleProfileMatching.cpp index d45066ed66ef2..919f3a732b355 100644 --- a/bolt/lib/Profile/StaleProfileMatching.cpp +++ b/bolt/lib/Profile/StaleProfileMatching.cpp @@ -220,13 +220,14 @@ class StaleMatcher { } /// Find the most similar block for a given hash. - const FlowBlock *matchBlock( - BlendedBlockHash BlendedHash, uint64_t CallHash, - const std::vector<yaml::bolt::PseudoProbeInfo> &PseudoProbes) const { + const FlowBlock * + matchBlock(BlendedBlockHash BlendedHash, uint64_t CallHash, + const std::vector<yaml::bolt::PseudoProbeInfo> &PseudoProbes) { const FlowBlock *BestBlock = matchWithOpcodes(BlendedHash); BestBlock = BestBlock ? BestBlock : matchWithCalls(BlendedHash, CallHash); - return BestBlock || !YamlBFGUID ? BestBlock - : matchWithPseudoProbes(PseudoProbes); + return BestBlock || !YamlBFGUID + ? BestBlock + : matchWithPseudoProbes(BlendedHash, PseudoProbes); } /// Returns true if the two basic blocks (in the binary and in the profile) @@ -237,6 +238,11 @@ class StaleMatcher { return Hash1.InstrHash == Hash2.InstrHash; } + bool isPseudoProbeMatch(BlendedBlockHash YamlBBHash) { + return MatchedWithPseudoProbes.find(YamlBBHash.combine()) != + MatchedWithPseudoProbes.end(); + } + private: using HashBlockPairType = std::pair<BlendedBlockHash, FlowBlock *>; std::unordered_map<uint16_t, std::vector<HashBlockPairType>> OpHashToBlocks; @@ -245,6 +251,7 @@ class StaleMatcher { IndexToBinaryPseudoProbes; std::unordered_map<const MCDecodedPseudoProbe *, FlowBlock *> BinaryPseudoProbeToBlock; + std::unordered_set<uint64_t> MatchedWithPseudoProbes; std::vector<const FlowBlock *> Blocks; // If the pseudo probe checksums of the profiled and binary functions are // equal, then the YamlBF's GUID is defined and used to match blocks. @@ -291,7 +298,8 @@ class StaleMatcher { // Uses pseudo probe information to attach the profile to the appropriate // block. const FlowBlock *matchWithPseudoProbes( - const std::vector<yaml::bolt::PseudoProbeInfo> &PseudoProbes) const { + BlendedBlockHash BlendedHash, + const std::vector<yaml::bolt::PseudoProbeInfo> &PseudoProbes) { // Searches for the pseudo probe attached to the matched function's block, // ignoring pseudo probes attached to function calls and inlined functions' // blocks. @@ -345,6 +353,8 @@ class StaleMatcher { auto BinaryPseudoProbeIt = BinaryPseudoProbeToBlock.find(BinaryPseudoProbe); assert(BinaryPseudoProbeIt != BinaryPseudoProbeToBlock.end() && "All binary pseudo probes should belong a binary basic block"); + + MatchedWithPseudoProbes.insert(BlendedHash.combine()); return BinaryPseudoProbeIt->second; } }; @@ -639,9 +649,13 @@ size_t matchWeightsByHashes( << "\n"); // Update matching stats accounting for the matched block. if (Matcher.isHighConfidenceMatch(BinHash, YamlHash)) { - ++BC.Stats.NumMatchedBlocks; - BC.Stats.MatchedSampleCount += YamlBB.ExecCount; + ++BC.Stats.NumExactMatchedBlocks; + BC.Stats.ExactMatchedSampleCount += YamlBB.ExecCount; LLVM_DEBUG(dbgs() << " exact match\n"); + } else if (Matcher.isPseudoProbeMatch(YamlHash)) { + ++BC.Stats.NumPseudoProbeMatchedBlocks; + BC.Stats.PseudoProbeMatchedSampleCount += YamlBB.ExecCount; + LLVM_DEBUG(dbgs() << " pseudo probe match\n"); } else { LLVM_DEBUG(dbgs() << " loose match\n"); } >From 144716be84d2207ee98fb238b88c6495942dec21 Mon Sep 17 00:00:00 2001 From: shawbyoung <shawbyo...@gmail.com> Date: Tue, 23 Jul 2024 15:41:31 -0700 Subject: [PATCH 05/19] Changed pseudo probe matching failure logging to v=3 Created using spr 1.3.4 --- bolt/lib/Profile/StaleProfileMatching.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/bolt/lib/Profile/StaleProfileMatching.cpp b/bolt/lib/Profile/StaleProfileMatching.cpp index 919f3a732b355..2d1a73bd60e8f 100644 --- a/bolt/lib/Profile/StaleProfileMatching.cpp +++ b/bolt/lib/Profile/StaleProfileMatching.cpp @@ -255,7 +255,7 @@ class StaleMatcher { std::vector<const FlowBlock *> Blocks; // If the pseudo probe checksums of the profiled and binary functions are // equal, then the YamlBF's GUID is defined and used to match blocks. - uint64_t YamlBFGUID; + uint64_t YamlBFGUID{0}; // Uses OpcodeHash to find the most similar block for a given hash. const FlowBlock *matchWithOpcodes(BlendedBlockHash BlendedHash) const { @@ -321,30 +321,30 @@ class StaleMatcher { // Returns nullptr if there is not a 1:1 mapping of the yaml block pseudo // probe and binary pseudo probe. if (BlockPseudoProbes.size() == 0) { - if (opts::Verbosity >= 2) + if (opts::Verbosity >= 3) errs() << "BOLT-WARNING: no pseudo probes in profile block\n"; return nullptr; } if (BlockPseudoProbes.size() > 1) { - if (opts::Verbosity >= 2) + if (opts::Verbosity >= 3) errs() << "BOLT-WARNING: more than 1 pseudo probes in profile block\n"; return nullptr; } uint64_t Index = BlockPseudoProbes[0]->Index; if (Index > Blocks.size()) { - if (opts::Verbosity >= 2) + if (opts::Verbosity >= 3) errs() << "BOLT-WARNING: invalid index block pseudo probe index\n"; return nullptr; } auto It = IndexToBinaryPseudoProbes.find(Index); if (It == IndexToBinaryPseudoProbes.end()) { - if (opts::Verbosity >= 2) + if (opts::Verbosity >= 3) errs() << "BOLT-WARNING: no block pseudo probes found within binary " "block at index\n"; return nullptr; } if (It->second.size() > 1) { - if (opts::Verbosity >= 2) + if (opts::Verbosity >= 3) errs() << "BOLT-WARNING: more than 1 block pseudo probes in binary " "block at index\n"; return nullptr; >From 29347109ada65c82fef3aa0803b18c413d9c4e6b Mon Sep 17 00:00:00 2001 From: shawbyoung <shawbyo...@gmail.com> Date: Tue, 23 Jul 2024 15:48:14 -0700 Subject: [PATCH 06/19] More loggin Created using spr 1.3.4 --- bolt/lib/Profile/StaleProfileMatching.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/bolt/lib/Profile/StaleProfileMatching.cpp b/bolt/lib/Profile/StaleProfileMatching.cpp index 2d1a73bd60e8f..3762d91ea9489 100644 --- a/bolt/lib/Profile/StaleProfileMatching.cpp +++ b/bolt/lib/Profile/StaleProfileMatching.cpp @@ -238,11 +238,17 @@ class StaleMatcher { return Hash1.InstrHash == Hash2.InstrHash; } + /// Returns true if a profiled block was matched with its pseudo probe. bool isPseudoProbeMatch(BlendedBlockHash YamlBBHash) { return MatchedWithPseudoProbes.find(YamlBBHash.combine()) != MatchedWithPseudoProbes.end(); } + /// Returns the number of blocks matched with pseudo probes. + size_t getNumBlocksMatchedWithPseudoProbes() const { + return MatchedWithPseudoProbes.size(); + } + private: using HashBlockPairType = std::pair<BlendedBlockHash, FlowBlock *>; std::unordered_map<uint16_t, std::vector<HashBlockPairType>> OpHashToBlocks; @@ -303,7 +309,7 @@ class StaleMatcher { // Searches for the pseudo probe attached to the matched function's block, // ignoring pseudo probes attached to function calls and inlined functions' // blocks. - if (opts::Verbosity >= 2) + if (opts::Verbosity >= 3) outs() << "BOLT-INFO: attempting to match block with pseudo probes\n"; std::vector<const yaml::bolt::PseudoProbeInfo *> BlockPseudoProbes; @@ -672,6 +678,11 @@ size_t matchWeightsByHashes( BC.Stats.StaleSampleCount += YamlBB.ExecCount; } + if (opts::Verbosity >= 2) + outs() << "BOLT-INFO: " + << StaleMatcher.getNumBlocksMatchedWithPseudoProbes() + << " blocks matched with pseudo probes\n"; + // Match jumps from the profile to the jumps from CFG std::vector<uint64_t> OutWeight(Func.Blocks.size(), 0); std::vector<uint64_t> InWeight(Func.Blocks.size(), 0); >From b74fc8b2f200b776dcf0e51d505e4e43267ef938 Mon Sep 17 00:00:00 2001 From: shawbyoung <shawbyo...@gmail.com> Date: Tue, 23 Jul 2024 16:03:21 -0700 Subject: [PATCH 07/19] Logging blocks matched with opcodes Created using spr 1.3.4 --- bolt/lib/Profile/StaleProfileMatching.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/bolt/lib/Profile/StaleProfileMatching.cpp b/bolt/lib/Profile/StaleProfileMatching.cpp index 3762d91ea9489..b31bddd47edf9 100644 --- a/bolt/lib/Profile/StaleProfileMatching.cpp +++ b/bolt/lib/Profile/StaleProfileMatching.cpp @@ -224,6 +224,8 @@ class StaleMatcher { matchBlock(BlendedBlockHash BlendedHash, uint64_t CallHash, const std::vector<yaml::bolt::PseudoProbeInfo> &PseudoProbes) { const FlowBlock *BestBlock = matchWithOpcodes(BlendedHash); + if (BestBlock) + ++MatchedWithOpcodes; BestBlock = BestBlock ? BestBlock : matchWithCalls(BlendedHash, CallHash); return BestBlock || !YamlBFGUID ? BestBlock @@ -247,7 +249,10 @@ class StaleMatcher { /// Returns the number of blocks matched with pseudo probes. size_t getNumBlocksMatchedWithPseudoProbes() const { return MatchedWithPseudoProbes.size(); - } + } + + /// Returns the number of blocks matched with opcodes. + size_t getNumBlocksMatchedWithOpcodes() const { return MatchedWithOpcodes; } private: using HashBlockPairType = std::pair<BlendedBlockHash, FlowBlock *>; @@ -259,9 +264,8 @@ class StaleMatcher { BinaryPseudoProbeToBlock; std::unordered_set<uint64_t> MatchedWithPseudoProbes; std::vector<const FlowBlock *> Blocks; - // If the pseudo probe checksums of the profiled and binary functions are - // equal, then the YamlBF's GUID is defined and used to match blocks. uint64_t YamlBFGUID{0}; + uint64_t MatchedWithOpcodes{0}; // Uses OpcodeHash to find the most similar block for a given hash. const FlowBlock *matchWithOpcodes(BlendedBlockHash BlendedHash) const { @@ -678,10 +682,13 @@ size_t matchWeightsByHashes( BC.Stats.StaleSampleCount += YamlBB.ExecCount; } - if (opts::Verbosity >= 2) - outs() << "BOLT-INFO: " - << StaleMatcher.getNumBlocksMatchedWithPseudoProbes() - << " blocks matched with pseudo probes\n"; + if (opts::Verbosity >= 2) { + outs() << "BOLT-INFO: " + << StaleMatcher.getNumBlocksMatchedWithPseudoProbes() + << " blocks matched with pseudo probes\n" + << "BOLT-INFO: " << StaleMatcher.getNumBlocksMatchedWithOpcodes() + << " blocks matched with opcodes\n"; + } // Match jumps from the profile to the jumps from CFG std::vector<uint64_t> OutWeight(Func.Blocks.size(), 0); >From c38fb98fb287d881ce8162fde0522d60b43da56f Mon Sep 17 00:00:00 2001 From: shawbyoung <shawbyo...@gmail.com> Date: Tue, 23 Jul 2024 16:10:09 -0700 Subject: [PATCH 08/19] Updated test Created using spr 1.3.4 --- bolt/lib/Profile/StaleProfileMatching.cpp | 4 ++-- bolt/test/X86/match-blocks-with-pseudo-probes.test | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bolt/lib/Profile/StaleProfileMatching.cpp b/bolt/lib/Profile/StaleProfileMatching.cpp index b31bddd47edf9..c621c29a0db83 100644 --- a/bolt/lib/Profile/StaleProfileMatching.cpp +++ b/bolt/lib/Profile/StaleProfileMatching.cpp @@ -684,9 +684,9 @@ size_t matchWeightsByHashes( if (opts::Verbosity >= 2) { outs() << "BOLT-INFO: " - << StaleMatcher.getNumBlocksMatchedWithPseudoProbes() + << Matcher.getNumBlocksMatchedWithPseudoProbes() << " blocks matched with pseudo probes\n" - << "BOLT-INFO: " << StaleMatcher.getNumBlocksMatchedWithOpcodes() + << "BOLT-INFO: " << Matcher.getNumBlocksMatchedWithOpcodes() << " blocks matched with opcodes\n"; } diff --git a/bolt/test/X86/match-blocks-with-pseudo-probes.test b/bolt/test/X86/match-blocks-with-pseudo-probes.test index 6dc01eb492eae..83f9c20f31ba6 100644 --- a/bolt/test/X86/match-blocks-with-pseudo-probes.test +++ b/bolt/test/X86/match-blocks-with-pseudo-probes.test @@ -7,7 +7,7 @@ # RUN: llvm-bolt %t.exe -o %t.out --data %t/yaml -v=2 \ # RUN: --print-cfg --funcs=main --profile-ignore-hash=0 --infer-stale-profile 2>&1 | FileCheck %s -# CHECK: BOLT-INFO: matched 0 functions with similar names +# CHECK: BOLT-INFO: inference found a pseudo probe match for 100.00% of basic blocks (1 out of 1 stale) responsible for -nan% samples (0 out of 0 stale) #--- main.s .text >From b2a3ca7fd532828ae7320da6f888f20a1717bb92 Mon Sep 17 00:00:00 2001 From: shawbyoung <shawbyo...@gmail.com> Date: Tue, 23 Jul 2024 16:14:34 -0700 Subject: [PATCH 09/19] Name changes in prep for inlined block pseudo probe block matching Created using spr 1.3.4 --- bolt/lib/Profile/StaleProfileMatching.cpp | 35 +++++++++++------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/bolt/lib/Profile/StaleProfileMatching.cpp b/bolt/lib/Profile/StaleProfileMatching.cpp index c621c29a0db83..4410fddaf0b21 100644 --- a/bolt/lib/Profile/StaleProfileMatching.cpp +++ b/bolt/lib/Profile/StaleProfileMatching.cpp @@ -198,9 +198,9 @@ class StaleMatcher { const std::vector<uint64_t> &CallHashes, const std::unordered_map<uint64_t, std::vector<const MCDecodedPseudoProbe *>> - &IndexToBinaryPseudoProbes, + &IndexToBBPseudoProbes, const std::unordered_map<const MCDecodedPseudoProbe *, FlowBlock *> - &BinaryPseudoProbeToBlock, + &BBPseudoProbeToBlock, const uint64_t YamlBFGUID) { assert(Blocks.size() == Hashes.size() && Hashes.size() == CallHashes.size() && @@ -214,8 +214,8 @@ class StaleMatcher { std::make_pair(Hashes[I], Block)); this->Blocks.push_back(Block); } - this->IndexToBinaryPseudoProbes = IndexToBinaryPseudoProbes; - this->BinaryPseudoProbeToBlock = BinaryPseudoProbeToBlock; + this->IndexToBBPseudoProbes = IndexToBBPseudoProbes; + this->BBPseudoProbeToBlock = BBPseudoProbeToBlock; this->YamlBFGUID = YamlBFGUID; } @@ -259,9 +259,9 @@ class StaleMatcher { std::unordered_map<uint16_t, std::vector<HashBlockPairType>> OpHashToBlocks; std::unordered_map<uint64_t, std::vector<HashBlockPairType>> CallHashToBlocks; std::unordered_map<uint64_t, std::vector<const MCDecodedPseudoProbe *>> - IndexToBinaryPseudoProbes; + IndexToBBPseudoProbes; std::unordered_map<const MCDecodedPseudoProbe *, FlowBlock *> - BinaryPseudoProbeToBlock; + BBPseudoProbeToBlock; std::unordered_set<uint64_t> MatchedWithPseudoProbes; std::vector<const FlowBlock *> Blocks; uint64_t YamlBFGUID{0}; @@ -346,8 +346,8 @@ class StaleMatcher { errs() << "BOLT-WARNING: invalid index block pseudo probe index\n"; return nullptr; } - auto It = IndexToBinaryPseudoProbes.find(Index); - if (It == IndexToBinaryPseudoProbes.end()) { + auto It = IndexToBBPseudoProbes.find(Index); + if (It == IndexToBBPseudoProbes.end()) { if (opts::Verbosity >= 3) errs() << "BOLT-WARNING: no block pseudo probes found within binary " "block at index\n"; @@ -360,8 +360,8 @@ class StaleMatcher { return nullptr; } const MCDecodedPseudoProbe *BinaryPseudoProbe = It->second[0]; - auto BinaryPseudoProbeIt = BinaryPseudoProbeToBlock.find(BinaryPseudoProbe); - assert(BinaryPseudoProbeIt != BinaryPseudoProbeToBlock.end() && + auto BinaryPseudoProbeIt = BBPseudoProbeToBlock.find(BinaryPseudoProbe); + assert(BinaryPseudoProbeIt != BBPseudoProbeToBlock.end() && "All binary pseudo probes should belong a binary basic block"); MatchedWithPseudoProbes.insert(BlendedHash.combine()); @@ -560,9 +560,9 @@ size_t matchWeightsByHashes( std::vector<FlowBlock *> Blocks; std::vector<BlendedBlockHash> BlendedHashes; std::unordered_map<uint64_t, std::vector<const MCDecodedPseudoProbe *>> - IndexToBinaryPseudoProbes; + IndexToBBPseudoProbes; std::unordered_map<const MCDecodedPseudoProbe *, FlowBlock *> - BinaryPseudoProbeToBlock; + BBPseudoProbeToBlock; const MCPseudoProbeDecoder *PseudoProbeDecoder = BC.getPseudoProbeDecoder(); for (uint64_t I = 0; I < BlockOrder.size(); I++) { const BinaryBasicBlock *BB = BlockOrder[I]; @@ -598,8 +598,8 @@ size_t matchWeightsByHashes( continue; if (Probe.getType() != static_cast<uint8_t>(PseudoProbeType::Block)) continue; - IndexToBinaryPseudoProbes[Probe.getIndex()].push_back(&Probe); - BinaryPseudoProbeToBlock[&Probe] = Blocks[I]; + IndexToBBPseudoProbes[Probe.getIndex()].push_back(&Probe); + BBPseudoProbeToBlock[&Probe] = Blocks[I]; } } } @@ -624,8 +624,8 @@ size_t matchWeightsByHashes( : 0; StaleMatcher Matcher; - Matcher.init(Blocks, BlendedHashes, CallHashes, IndexToBinaryPseudoProbes, - BinaryPseudoProbeToBlock, YamlBFGUID); + Matcher.init(Blocks, BlendedHashes, CallHashes, IndexToBBPseudoProbes, + BBPseudoProbeToBlock, YamlBFGUID); // Index in yaml profile => corresponding (matched) block DenseMap<uint64_t, const FlowBlock *> MatchedBlocks; @@ -683,8 +683,7 @@ size_t matchWeightsByHashes( } if (opts::Verbosity >= 2) { - outs() << "BOLT-INFO: " - << Matcher.getNumBlocksMatchedWithPseudoProbes() + outs() << "BOLT-INFO: " << Matcher.getNumBlocksMatchedWithPseudoProbes() << " blocks matched with pseudo probes\n" << "BOLT-INFO: " << Matcher.getNumBlocksMatchedWithOpcodes() << " blocks matched with opcodes\n"; >From 2eb7bf2cff7c974a3327879fd46df7348fdb43e3 Mon Sep 17 00:00:00 2001 From: shawbyoung <shawbyo...@gmail.com> Date: Tue, 23 Jul 2024 17:16:19 -0700 Subject: [PATCH 10/19] Rm unnecessary Blocks vec in StaleMatcher Created using spr 1.3.4 --- bolt/lib/Profile/StaleProfileMatching.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/bolt/lib/Profile/StaleProfileMatching.cpp b/bolt/lib/Profile/StaleProfileMatching.cpp index 4410fddaf0b21..6ee14ef0194bd 100644 --- a/bolt/lib/Profile/StaleProfileMatching.cpp +++ b/bolt/lib/Profile/StaleProfileMatching.cpp @@ -212,7 +212,6 @@ class StaleMatcher { if (CallHashes[I]) CallHashToBlocks[CallHashes[I]].push_back( std::make_pair(Hashes[I], Block)); - this->Blocks.push_back(Block); } this->IndexToBBPseudoProbes = IndexToBBPseudoProbes; this->BBPseudoProbeToBlock = BBPseudoProbeToBlock; @@ -263,7 +262,6 @@ class StaleMatcher { std::unordered_map<const MCDecodedPseudoProbe *, FlowBlock *> BBPseudoProbeToBlock; std::unordered_set<uint64_t> MatchedWithPseudoProbes; - std::vector<const FlowBlock *> Blocks; uint64_t YamlBFGUID{0}; uint64_t MatchedWithOpcodes{0}; @@ -341,11 +339,6 @@ class StaleMatcher { return nullptr; } uint64_t Index = BlockPseudoProbes[0]->Index; - if (Index > Blocks.size()) { - if (opts::Verbosity >= 3) - errs() << "BOLT-WARNING: invalid index block pseudo probe index\n"; - return nullptr; - } auto It = IndexToBBPseudoProbes.find(Index); if (It == IndexToBBPseudoProbes.end()) { if (opts::Verbosity >= 3) >From 212bd005b53b85596ffe84012546247db99e898f Mon Sep 17 00:00:00 2001 From: shawbyoung <shawbyo...@gmail.com> Date: Tue, 23 Jul 2024 17:28:01 -0700 Subject: [PATCH 11/19] Improved matched block counting Created using spr 1.3.4 --- bolt/lib/Profile/StaleProfileMatching.cpp | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/bolt/lib/Profile/StaleProfileMatching.cpp b/bolt/lib/Profile/StaleProfileMatching.cpp index 6ee14ef0194bd..06557b3c3a388 100644 --- a/bolt/lib/Profile/StaleProfileMatching.cpp +++ b/bolt/lib/Profile/StaleProfileMatching.cpp @@ -223,12 +223,19 @@ class StaleMatcher { matchBlock(BlendedBlockHash BlendedHash, uint64_t CallHash, const std::vector<yaml::bolt::PseudoProbeInfo> &PseudoProbes) { const FlowBlock *BestBlock = matchWithOpcodes(BlendedHash); - if (BestBlock) + if (BestBlock) { ++MatchedWithOpcodes; - BestBlock = BestBlock ? BestBlock : matchWithCalls(BlendedHash, CallHash); - return BestBlock || !YamlBFGUID - ? BestBlock - : matchWithPseudoProbes(BlendedHash, PseudoProbes); + return BestBlock; + } + BestBlock = matchWithCalls(BlendedHash, CallHash); + if (BestBlock) { + return BestBlock; + } + BestBlock = matchWithPseudoProbes(BlendedHash, PseudoProbes); + if (BestBlock) { + MatchedWithPseudoProbes.insert(BlendedHash.combine()); + } + return BestBlock; } /// Returns true if the two basic blocks (in the binary and in the profile) @@ -307,7 +314,7 @@ class StaleMatcher { // block. const FlowBlock *matchWithPseudoProbes( BlendedBlockHash BlendedHash, - const std::vector<yaml::bolt::PseudoProbeInfo> &PseudoProbes) { + const std::vector<yaml::bolt::PseudoProbeInfo> &PseudoProbes) const { // Searches for the pseudo probe attached to the matched function's block, // ignoring pseudo probes attached to function calls and inlined functions' // blocks. @@ -357,7 +364,6 @@ class StaleMatcher { assert(BinaryPseudoProbeIt != BBPseudoProbeToBlock.end() && "All binary pseudo probes should belong a binary basic block"); - MatchedWithPseudoProbes.insert(BlendedHash.combine()); return BinaryPseudoProbeIt->second; } }; >From eb6dfb973126a245aea21fae5369e06d628ddcdd Mon Sep 17 00:00:00 2001 From: shawbyoung <shawbyo...@gmail.com> Date: Tue, 23 Jul 2024 17:33:55 -0700 Subject: [PATCH 12/19] Removed comment from test Created using spr 1.3.4 --- bolt/lib/Profile/StaleProfileMatching.cpp | 6 +++--- bolt/test/X86/match-blocks-with-pseudo-probes.test | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bolt/lib/Profile/StaleProfileMatching.cpp b/bolt/lib/Profile/StaleProfileMatching.cpp index 06557b3c3a388..f3e19e8fb100d 100644 --- a/bolt/lib/Profile/StaleProfileMatching.cpp +++ b/bolt/lib/Profile/StaleProfileMatching.cpp @@ -252,14 +252,14 @@ class StaleMatcher { MatchedWithPseudoProbes.end(); } + /// Returns the number of blocks matched with opcodes. + size_t getNumBlocksMatchedWithOpcodes() const { return MatchedWithOpcodes; } + /// Returns the number of blocks matched with pseudo probes. size_t getNumBlocksMatchedWithPseudoProbes() const { return MatchedWithPseudoProbes.size(); } - /// Returns the number of blocks matched with opcodes. - size_t getNumBlocksMatchedWithOpcodes() const { return MatchedWithOpcodes; } - private: using HashBlockPairType = std::pair<BlendedBlockHash, FlowBlock *>; std::unordered_map<uint16_t, std::vector<HashBlockPairType>> OpHashToBlocks; diff --git a/bolt/test/X86/match-blocks-with-pseudo-probes.test b/bolt/test/X86/match-blocks-with-pseudo-probes.test index 83f9c20f31ba6..4a6f2f1cf129a 100644 --- a/bolt/test/X86/match-blocks-with-pseudo-probes.test +++ b/bolt/test/X86/match-blocks-with-pseudo-probes.test @@ -53,7 +53,7 @@ functions: exec: 1 nblocks: 6 guid: 0xDB956436E78DD5FA - pseudo_probe_desc_hash: 4294967295 #lookup in code in a second + pseudo_probe_desc_hash: 4294967295 blocks: - bid: 1 hash: 0x0000000000000001 >From 16b5cfbbbb37820b00ad07b086481c46aefd0142 Mon Sep 17 00:00:00 2001 From: shawbyoung <shawbyo...@gmail.com> Date: Tue, 23 Jul 2024 17:48:12 -0700 Subject: [PATCH 13/19] Added comments and check for null YamlBFGUID in StaleMatcher before PseudoProbe matching Created using spr 1.3.4 --- bolt/lib/Profile/StaleProfileMatching.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/bolt/lib/Profile/StaleProfileMatching.cpp b/bolt/lib/Profile/StaleProfileMatching.cpp index f3e19e8fb100d..b74c1c5071815 100644 --- a/bolt/lib/Profile/StaleProfileMatching.cpp +++ b/bolt/lib/Profile/StaleProfileMatching.cpp @@ -218,7 +218,8 @@ class StaleMatcher { this->YamlBFGUID = YamlBFGUID; } - /// Find the most similar block for a given hash. + /// Find the most similar flow block for a profile block given its hashes and + /// pseudo probe information. const FlowBlock * matchBlock(BlendedBlockHash BlendedHash, uint64_t CallHash, const std::vector<yaml::bolt::PseudoProbeInfo> &PseudoProbes) { @@ -315,6 +316,8 @@ class StaleMatcher { const FlowBlock *matchWithPseudoProbes( BlendedBlockHash BlendedHash, const std::vector<yaml::bolt::PseudoProbeInfo> &PseudoProbes) const { + if (!YamlBFGUID) + return nullptr; // Searches for the pseudo probe attached to the matched function's block, // ignoring pseudo probes attached to function calls and inlined functions' // blocks. @@ -582,6 +585,7 @@ size_t matchWeightsByHashes( Blocks.push_back(&Func.Blocks[I + 1]); BlendedBlockHash BlendedHash(BB->getHash()); BlendedHashes.push_back(BlendedHash); + // Collects pseudo probes attached to the BB for use in the StaleMatcher. if (PseudoProbeDecoder) { const AddressProbesMap &ProbeMap = PseudoProbeDecoder->getAddress2ProbesMap(); @@ -607,6 +611,10 @@ size_t matchWeightsByHashes( << Twine::utohexstr(BB->getHash()) << "\n"); } + // Sets the YamlBFGUID in the StaleMatcher such that if either the profiled or + // binary function dne or they are not equal, to zero, as not to perform + // pseudo probe block matching. Otherwise, the YamlBF's GUID is used for + // pseudo probe block matching. uint64_t BFPseudoProbeDescHash = 0; if (BF.getGUID() != 0) { assert(PseudoProbeDecoder && >From 799f20cf7ed8dfc30d89beadd90d91758cdc9485 Mon Sep 17 00:00:00 2001 From: shawbyoung <shawbyo...@gmail.com> Date: Wed, 24 Jul 2024 07:42:26 -0700 Subject: [PATCH 14/19] Omitting braces in one line if Created using spr 1.3.4 --- bolt/lib/Profile/StaleProfileMatching.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bolt/lib/Profile/StaleProfileMatching.cpp b/bolt/lib/Profile/StaleProfileMatching.cpp index b74c1c5071815..e2fd85373485b 100644 --- a/bolt/lib/Profile/StaleProfileMatching.cpp +++ b/bolt/lib/Profile/StaleProfileMatching.cpp @@ -229,9 +229,8 @@ class StaleMatcher { return BestBlock; } BestBlock = matchWithCalls(BlendedHash, CallHash); - if (BestBlock) { + if (BestBlock) return BestBlock; - } BestBlock = matchWithPseudoProbes(BlendedHash, PseudoProbes); if (BestBlock) { MatchedWithPseudoProbes.insert(BlendedHash.combine()); >From 33f1b2ad7809786449b328e3eca93bb9e46694f4 Mon Sep 17 00:00:00 2001 From: shawbyoung <shawbyo...@gmail.com> Date: Wed, 24 Jul 2024 09:06:37 -0700 Subject: [PATCH 15/19] Omit unnecessary braces Created using spr 1.3.4 --- bolt/lib/Profile/StaleProfileMatching.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bolt/lib/Profile/StaleProfileMatching.cpp b/bolt/lib/Profile/StaleProfileMatching.cpp index b5ddef210d5e9..26cbd8250ce58 100644 --- a/bolt/lib/Profile/StaleProfileMatching.cpp +++ b/bolt/lib/Profile/StaleProfileMatching.cpp @@ -233,9 +233,8 @@ class StaleMatcher { if (BestBlock) return BestBlock; BestBlock = matchWithPseudoProbes(BlendedHash, PseudoProbes); - if (BestBlock) { + if (BestBlock) MatchedWithPseudoProbes.insert(BlendedHash.combine()); - } return BestBlock; } >From 9889f8903c85d1eae4a1cd536bda03d6959c8ba4 Mon Sep 17 00:00:00 2001 From: shawbyoung <shawbyo...@gmail.com> Date: Wed, 24 Jul 2024 09:51:22 -0700 Subject: [PATCH 16/19] Change initialization of index -> probe and probe -> block mappings Created using spr 1.3.4 --- bolt/lib/Profile/StaleProfileMatching.cpp | 81 ++++++++++++----------- 1 file changed, 41 insertions(+), 40 deletions(-) diff --git a/bolt/lib/Profile/StaleProfileMatching.cpp b/bolt/lib/Profile/StaleProfileMatching.cpp index 26cbd8250ce58..6e7525b66aaae 100644 --- a/bolt/lib/Profile/StaleProfileMatching.cpp +++ b/bolt/lib/Profile/StaleProfileMatching.cpp @@ -193,16 +193,12 @@ struct BlendedBlockHash { /// release. class StaleMatcher { public: + StaleMatcher(const uint64_t YamlBFGUID) : YamlBFGUID(YamlBFGUID) {} + /// Initialize stale matcher. void init(const std::vector<FlowBlock *> &Blocks, const std::vector<BlendedBlockHash> &Hashes, - const std::vector<uint64_t> &CallHashes, - const std::unordered_map<uint64_t, - std::vector<const MCDecodedPseudoProbe *>> - &IndexToBBPseudoProbes, - const std::unordered_map<const MCDecodedPseudoProbe *, FlowBlock *> - &BBPseudoProbeToBlock, - const uint64_t YamlBFGUID) { + const std::vector<uint64_t> &CallHashes) { assert(Blocks.size() == Hashes.size() && Hashes.size() == CallHashes.size() && "incorrect matcher initialization"); @@ -214,9 +210,17 @@ class StaleMatcher { CallHashToBlocks[CallHashes[I]].push_back( std::make_pair(Hashes[I], Block)); } - this->IndexToBBPseudoProbes = IndexToBBPseudoProbes; - this->BBPseudoProbeToBlock = BBPseudoProbeToBlock; - this->YamlBFGUID = YamlBFGUID; + } + + /// Creates a mapping from a pseudo probe index to block pseudo probe in the + /// binary. + void mapIndexToProbe(uint64_t Index, const MCDecodedPseudoProbe *Probe) { + IndexToBBPseudoProbes[Index].push_back(Probe); + } + + /// Creates a mapping from a pseudo probe to a flow block. + void mapProbeToBB(const MCDecodedPseudoProbe *Probe, FlowBlock *Block) { + BBPseudoProbeToBlock[Probe] = Block; } /// Find the most similar flow block for a profile block given its hashes and @@ -269,7 +273,7 @@ class StaleMatcher { std::unordered_map<const MCDecodedPseudoProbe *, FlowBlock *> BBPseudoProbeToBlock; std::unordered_set<uint64_t> MatchedWithPseudoProbes; - uint64_t YamlBFGUID{0}; + const uint64_t YamlBFGUID{0}; uint64_t MatchedWithOpcodes{0}; // Uses OpcodeHash to find the most similar block for a given hash. @@ -557,14 +561,32 @@ size_t matchWeightsByHashes( assert(Func.Blocks.size() == BlockOrder.size() + 2); + // Sets the YamlBFGUID in the StaleMatcher such that if either the profiled or + // binary function dne or they are not equal, to zero, as not to perform + // pseudo probe block matching. Otherwise, the YamlBF's GUID is used for + // pseudo probe block matching. + const MCPseudoProbeDecoder *PseudoProbeDecoder = + opts::ProfileUsePseudoProbes ? BC.getPseudoProbeDecoder() : nullptr; + uint64_t BFPseudoProbeDescHash = 0; + if (opts::ProfileUsePseudoProbes && BF.getGUID() != 0) { + assert(PseudoProbeDecoder && + "If BF has pseudo probe, BC should have a pseudo probe decoder"); + auto &GUID2FuncDescMap = PseudoProbeDecoder->getGUID2FuncDescMap(); + auto It = GUID2FuncDescMap.find(BF.getGUID()); + if (It != GUID2FuncDescMap.end()) + BFPseudoProbeDescHash = It->second.FuncHash; + } + uint64_t YamlBFGUID = + BFPseudoProbeDescHash && YamlBF.PseudoProbeDescHash && + BFPseudoProbeDescHash == YamlBF.PseudoProbeDescHash + ? static_cast<uint64_t>(YamlBF.GUID) + : 0; + + StaleMatcher Matcher(YamlBFGUID); std::vector<uint64_t> CallHashes; std::vector<FlowBlock *> Blocks; std::vector<BlendedBlockHash> BlendedHashes; - std::unordered_map<uint64_t, std::vector<const MCDecodedPseudoProbe *>> - IndexToBBPseudoProbes; - std::unordered_map<const MCDecodedPseudoProbe *, FlowBlock *> - BBPseudoProbeToBlock; - const MCPseudoProbeDecoder *PseudoProbeDecoder = BC.getPseudoProbeDecoder(); + for (uint64_t I = 0; I < BlockOrder.size(); I++) { const BinaryBasicBlock *BB = BlockOrder[I]; assert(BB->getHash() != 0 && "empty hash of BinaryBasicBlock"); @@ -600,8 +622,8 @@ size_t matchWeightsByHashes( continue; if (Probe.getType() != static_cast<uint8_t>(PseudoProbeType::Block)) continue; - IndexToBBPseudoProbes[Probe.getIndex()].push_back(&Probe); - BBPseudoProbeToBlock[&Probe] = Blocks[I]; + Matcher.mapIndexToProbe(Probe.getIndex(), &Probe); + Matcher.mapProbeToBB(&Probe, Blocks[I]); } } } @@ -610,28 +632,7 @@ size_t matchWeightsByHashes( << Twine::utohexstr(BB->getHash()) << "\n"); } - // Sets the YamlBFGUID in the StaleMatcher such that if either the profiled or - // binary function dne or they are not equal, to zero, as not to perform - // pseudo probe block matching. Otherwise, the YamlBF's GUID is used for - // pseudo probe block matching. - uint64_t BFPseudoProbeDescHash = 0; - if (opts::ProfileUsePseudoProbes && BF.getGUID() != 0) { - assert(PseudoProbeDecoder && - "If BF has pseudo probe, BC should have a pseudo probe decoder"); - auto &GUID2FuncDescMap = PseudoProbeDecoder->getGUID2FuncDescMap(); - auto It = GUID2FuncDescMap.find(BF.getGUID()); - if (It != GUID2FuncDescMap.end()) - BFPseudoProbeDescHash = It->second.FuncHash; - } - uint64_t YamlBFGUID = - BFPseudoProbeDescHash && YamlBF.PseudoProbeDescHash && - BFPseudoProbeDescHash == YamlBF.PseudoProbeDescHash - ? static_cast<uint64_t>(YamlBF.GUID) - : 0; - - StaleMatcher Matcher; - Matcher.init(Blocks, BlendedHashes, CallHashes, IndexToBBPseudoProbes, - BBPseudoProbeToBlock, YamlBFGUID); + Matcher.init(Blocks, BlendedHashes, CallHashes); // Index in yaml profile => corresponding (matched) block DenseMap<uint64_t, const FlowBlock *> MatchedBlocks; >From 022c517af0278979b92b48d75503b4278880d040 Mon Sep 17 00:00:00 2001 From: shawbyoung <shawbyo...@gmail.com> Date: Wed, 24 Jul 2024 09:54:02 -0700 Subject: [PATCH 17/19] Formatting Created using spr 1.3.4 --- bolt/lib/Profile/StaleProfileMatching.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/bolt/lib/Profile/StaleProfileMatching.cpp b/bolt/lib/Profile/StaleProfileMatching.cpp index 6e7525b66aaae..37140a7dd1e57 100644 --- a/bolt/lib/Profile/StaleProfileMatching.cpp +++ b/bolt/lib/Profile/StaleProfileMatching.cpp @@ -586,7 +586,6 @@ size_t matchWeightsByHashes( std::vector<uint64_t> CallHashes; std::vector<FlowBlock *> Blocks; std::vector<BlendedBlockHash> BlendedHashes; - for (uint64_t I = 0; I < BlockOrder.size(); I++) { const BinaryBasicBlock *BB = BlockOrder[I]; assert(BB->getHash() != 0 && "empty hash of BinaryBasicBlock"); @@ -631,7 +630,6 @@ size_t matchWeightsByHashes( LLVM_DEBUG(dbgs() << "BB with index " << I << " has hash = " << Twine::utohexstr(BB->getHash()) << "\n"); } - Matcher.init(Blocks, BlendedHashes, CallHashes); // Index in yaml profile => corresponding (matched) block >From 5109893be3eaf62e756e4837b6a49b9aa4b0824b Mon Sep 17 00:00:00 2001 From: shawbyoung <shawbyo...@gmail.com> Date: Wed, 24 Jul 2024 10:12:25 -0700 Subject: [PATCH 18/19] Comments Created using spr 1.3.4 --- bolt/lib/Profile/StaleProfileMatching.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/bolt/lib/Profile/StaleProfileMatching.cpp b/bolt/lib/Profile/StaleProfileMatching.cpp index 37140a7dd1e57..ba271cdbb2dc0 100644 --- a/bolt/lib/Profile/StaleProfileMatching.cpp +++ b/bolt/lib/Profile/StaleProfileMatching.cpp @@ -212,8 +212,7 @@ class StaleMatcher { } } - /// Creates a mapping from a pseudo probe index to block pseudo probe in the - /// binary. + /// Creates a mapping from a pseudo probe index to pseudo probe. void mapIndexToProbe(uint64_t Index, const MCDecodedPseudoProbe *Probe) { IndexToBBPseudoProbes[Index].push_back(Probe); } @@ -321,12 +320,13 @@ class StaleMatcher { const std::vector<yaml::bolt::PseudoProbeInfo> &PseudoProbes) const { if (!YamlBFGUID) return nullptr; - // Searches for the pseudo probe attached to the matched function's block, - // ignoring pseudo probes attached to function calls and inlined functions' - // blocks. + if (opts::Verbosity >= 3) outs() << "BOLT-INFO: attempting to match block with pseudo probes\n"; + // Searches for the pseudo probe attached to the matched function's block, + // ignoring pseudo probes attached to function calls and inlined functions' + // blocks. std::vector<const yaml::bolt::PseudoProbeInfo *> BlockPseudoProbes; for (const auto &PseudoProbe : PseudoProbes) { // Ensures that pseudo probe information belongs to the appropriate >From 5bf42207453830f9690895d9dd4efa78365c7bb1 Mon Sep 17 00:00:00 2001 From: shawbyoung <shawbyo...@gmail.com> Date: Wed, 24 Jul 2024 16:09:05 -0700 Subject: [PATCH 19/19] Changed std ADTs to LLVM Created using spr 1.3.4 --- bolt/lib/Profile/StaleProfileMatching.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/bolt/lib/Profile/StaleProfileMatching.cpp b/bolt/lib/Profile/StaleProfileMatching.cpp index ba271cdbb2dc0..65eb3b0a419ce 100644 --- a/bolt/lib/Profile/StaleProfileMatching.cpp +++ b/bolt/lib/Profile/StaleProfileMatching.cpp @@ -267,11 +267,10 @@ class StaleMatcher { using HashBlockPairType = std::pair<BlendedBlockHash, FlowBlock *>; std::unordered_map<uint16_t, std::vector<HashBlockPairType>> OpHashToBlocks; std::unordered_map<uint64_t, std::vector<HashBlockPairType>> CallHashToBlocks; - std::unordered_map<uint64_t, std::vector<const MCDecodedPseudoProbe *>> + DenseMap<uint64_t, std::vector<const MCDecodedPseudoProbe *>> IndexToBBPseudoProbes; - std::unordered_map<const MCDecodedPseudoProbe *, FlowBlock *> - BBPseudoProbeToBlock; - std::unordered_set<uint64_t> MatchedWithPseudoProbes; + DenseMap<const MCDecodedPseudoProbe *, FlowBlock *> BBPseudoProbeToBlock; + DenseSet<uint64_t> MatchedWithPseudoProbes; const uint64_t YamlBFGUID{0}; uint64_t MatchedWithOpcodes{0}; @@ -327,7 +326,7 @@ class StaleMatcher { // Searches for the pseudo probe attached to the matched function's block, // ignoring pseudo probes attached to function calls and inlined functions' // blocks. - std::vector<const yaml::bolt::PseudoProbeInfo *> BlockPseudoProbes; + SmallVector<const yaml::bolt::PseudoProbeInfo *> BlockPseudoProbes; for (const auto &PseudoProbe : PseudoProbes) { // Ensures that pseudo probe information belongs to the appropriate // function and not an inlined function. _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits