Skip to content

Commit 9b007a1

Browse files
authored
[BOLT] Expose pseudo probe function checksum and GUID (#99389)
Add a BinaryFunction field for pseudo probe function GUID. Populate it during pseudo probe section parsing, and emit it in YAML profile (both regular and BAT), along with function checksum. To be used for stale function matching. Test Plan: update pseudoprobe-decoding-inline.test
1 parent 3023b15 commit 9b007a1

File tree

8 files changed

+92
-4
lines changed

8 files changed

+92
-4
lines changed

bolt/include/bolt/Core/BinaryContext.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "llvm/MC/MCContext.h"
3333
#include "llvm/MC/MCObjectFileInfo.h"
3434
#include "llvm/MC/MCObjectWriter.h"
35+
#include "llvm/MC/MCPseudoProbe.h"
3536
#include "llvm/MC/MCSectionELF.h"
3637
#include "llvm/MC/MCSectionMachO.h"
3738
#include "llvm/MC/MCStreamer.h"
@@ -246,6 +247,9 @@ class BinaryContext {
246247
/// DWP Context.
247248
std::shared_ptr<DWARFContext> DWPContext;
248249

250+
/// Decoded pseudo probes.
251+
std::shared_ptr<MCPseudoProbeDecoder> PseudoProbeDecoder;
252+
249253
/// A map of DWO Ids to CUs.
250254
using DWOIdToCUMapType = std::unordered_map<uint64_t, DWARFUnit *>;
251255
DWOIdToCUMapType DWOCUs;
@@ -377,6 +381,15 @@ class BinaryContext {
377381
RtLibrary = std::move(Lib);
378382
}
379383

384+
const MCPseudoProbeDecoder *getPseudoProbeDecoder() const {
385+
return PseudoProbeDecoder.get();
386+
}
387+
388+
void setPseudoProbeDecoder(std::shared_ptr<MCPseudoProbeDecoder> Decoder) {
389+
assert(!PseudoProbeDecoder && "Cannot set pseudo probe decoder twice.");
390+
PseudoProbeDecoder = Decoder;
391+
}
392+
380393
/// Return BinaryFunction containing a given \p Address or nullptr if
381394
/// no registered function contains the \p Address.
382395
///

bolt/include/bolt/Core/BinaryFunction.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,9 @@ class BinaryFunction {
416416
/// different parameters by every pass.
417417
mutable uint64_t Hash{0};
418418

419+
/// Function GUID assigned externally.
420+
uint64_t GUID{0};
421+
419422
/// For PLT functions it contains a symbol associated with a function
420423
/// reference. It is nullptr for non-PLT functions.
421424
const MCSymbol *PLTSymbol{nullptr};
@@ -2256,6 +2259,11 @@ class BinaryFunction {
22562259
/// Returns the last computed hash value of the function.
22572260
size_t getHash() const { return Hash; }
22582261

2262+
/// Returns the function GUID.
2263+
uint64_t getGUID() const { return GUID; }
2264+
2265+
void setGUID(uint64_t Id) { GUID = Id; }
2266+
22592267
using OperandHashFuncTy =
22602268
function_ref<typename std::string(const MCOperand &)>;
22612269

bolt/include/bolt/Profile/ProfileYAMLMapping.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,8 @@ struct BinaryFunctionProfile {
151151
llvm::yaml::Hex64 Hash{0};
152152
uint64_t ExecCount{0};
153153
std::vector<BinaryBasicBlockProfile> Blocks;
154+
llvm::yaml::Hex64 GUID{0};
155+
llvm::yaml::Hex64 PseudoProbeDescHash{0};
154156
bool Used{false};
155157
};
156158
} // end namespace bolt
@@ -164,6 +166,9 @@ template <> struct MappingTraits<bolt::BinaryFunctionProfile> {
164166
YamlIO.mapRequired("nblocks", BFP.NumBasicBlocks);
165167
YamlIO.mapOptional("blocks", BFP.Blocks,
166168
std::vector<bolt::BinaryBasicBlockProfile>());
169+
YamlIO.mapOptional("guid", BFP.GUID, (uint64_t)0);
170+
YamlIO.mapOptional("pseudo_probe_desc_hash", BFP.PseudoProbeDescHash,
171+
(uint64_t)0);
167172
}
168173
};
169174

bolt/lib/Profile/DataAggregator.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2298,6 +2298,8 @@ std::error_code DataAggregator::writeBATYAML(BinaryContext &BC,
22982298

22992299
yaml::bolt::BinaryProfile BP;
23002300

2301+
const MCPseudoProbeDecoder *PseudoProbeDecoder = BC.getPseudoProbeDecoder();
2302+
23012303
// Fill out the header info.
23022304
BP.Header.Version = 1;
23032305
BP.Header.FileName = std::string(BC.getFilename());
@@ -2398,6 +2400,13 @@ std::error_code DataAggregator::writeBATYAML(BinaryContext &BC,
23982400
const unsigned BlockIndex = BlockMap.getBBIndex(BI.To.Offset);
23992401
YamlBF.Blocks[BlockIndex].ExecCount += BI.Branches;
24002402
}
2403+
if (PseudoProbeDecoder) {
2404+
if ((YamlBF.GUID = BF->getGUID())) {
2405+
const MCPseudoProbeFuncDesc *FuncDesc =
2406+
PseudoProbeDecoder->getFuncDescForGUID(YamlBF.GUID);
2407+
YamlBF.PseudoProbeDescHash = FuncDesc->FuncHash;
2408+
}
2409+
}
24012410
// Drop blocks without a hash, won't be useful for stale matching.
24022411
llvm::erase_if(YamlBF.Blocks,
24032412
[](const yaml::bolt::BinaryBasicBlockProfile &YamlBB) {

bolt/lib/Profile/YAMLProfileWriter.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ YAMLProfileWriter::convert(const BinaryFunction &BF, bool UseDFS,
5757
const BoltAddressTranslation *BAT) {
5858
yaml::bolt::BinaryFunctionProfile YamlBF;
5959
const BinaryContext &BC = BF.getBinaryContext();
60+
const MCPseudoProbeDecoder *PseudoProbeDecoder = BC.getPseudoProbeDecoder();
6061

6162
const uint16_t LBRProfile = BF.getProfileFlags() & BinaryFunction::PF_LBR;
6263

@@ -69,6 +70,13 @@ YAMLProfileWriter::convert(const BinaryFunction &BF, bool UseDFS,
6970
YamlBF.Hash = BF.getHash();
7071
YamlBF.NumBasicBlocks = BF.size();
7172
YamlBF.ExecCount = BF.getKnownExecutionCount();
73+
if (PseudoProbeDecoder) {
74+
if ((YamlBF.GUID = BF.getGUID())) {
75+
const MCPseudoProbeFuncDesc *FuncDesc =
76+
PseudoProbeDecoder->getFuncDescForGUID(YamlBF.GUID);
77+
YamlBF.PseudoProbeDescHash = FuncDesc->FuncHash;
78+
}
79+
}
7280

7381
BinaryFunction::BasicBlockOrderType Order;
7482
llvm::copy(UseDFS ? BF.dfs() : BF.getLayout().blocks(),

bolt/lib/Rewrite/PseudoProbeRewriter.cpp

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "llvm/Support/CommandLine.h"
2020
#include "llvm/Support/Debug.h"
2121
#include "llvm/Support/LEB128.h"
22+
#include <memory>
2223

2324
#undef DEBUG_TYPE
2425
#define DEBUG_TYPE "pseudo-probe-rewriter"
@@ -72,23 +73,35 @@ class PseudoProbeRewriter final : public MetadataRewriter {
7273
void parsePseudoProbe();
7374

7475
/// PseudoProbe decoder
75-
MCPseudoProbeDecoder ProbeDecoder;
76+
std::shared_ptr<MCPseudoProbeDecoder> ProbeDecoderPtr;
7677

7778
public:
7879
PseudoProbeRewriter(BinaryContext &BC)
79-
: MetadataRewriter("pseudo-probe-rewriter", BC) {}
80+
: MetadataRewriter("pseudo-probe-rewriter", BC),
81+
ProbeDecoderPtr(std::make_shared<MCPseudoProbeDecoder>()) {
82+
BC.setPseudoProbeDecoder(ProbeDecoderPtr);
83+
}
8084

85+
Error preCFGInitializer() override;
8186
Error postEmitFinalizer() override;
87+
88+
~PseudoProbeRewriter() override { ProbeDecoderPtr.reset(); }
8289
};
8390

84-
Error PseudoProbeRewriter::postEmitFinalizer() {
91+
Error PseudoProbeRewriter::preCFGInitializer() {
8592
parsePseudoProbe();
93+
94+
return Error::success();
95+
}
96+
97+
Error PseudoProbeRewriter::postEmitFinalizer() {
8698
updatePseudoProbes();
8799

88100
return Error::success();
89101
}
90102

91103
void PseudoProbeRewriter::parsePseudoProbe() {
104+
MCPseudoProbeDecoder &ProbeDecoder(*ProbeDecoderPtr);
92105
PseudoProbeDescSection = BC.getUniqueSectionByName(".pseudo_probe_desc");
93106
PseudoProbeSection = BC.getUniqueSectionByName(".pseudo_probe");
94107

@@ -138,9 +151,18 @@ void PseudoProbeRewriter::parsePseudoProbe() {
138151
ProbeDecoder.printGUID2FuncDescMap(outs());
139152
ProbeDecoder.printProbesForAllAddresses(outs());
140153
}
154+
155+
for (const auto &[GUID, FuncDesc] : ProbeDecoder.getGUID2FuncDescMap()) {
156+
if (!FuncStartAddrs.contains(GUID))
157+
continue;
158+
BinaryFunction *BF = BC.getBinaryFunctionAtAddress(FuncStartAddrs[GUID]);
159+
assert(BF);
160+
BF->setGUID(GUID);
161+
}
141162
}
142163

143164
void PseudoProbeRewriter::updatePseudoProbes() {
165+
MCPseudoProbeDecoder &ProbeDecoder(*ProbeDecoderPtr);
144166
// check if there is pseudo probe section decoded
145167
if (ProbeDecoder.getAddress2ProbesMap().empty())
146168
return;
@@ -241,6 +263,7 @@ void PseudoProbeRewriter::updatePseudoProbes() {
241263
}
242264

243265
void PseudoProbeRewriter::encodePseudoProbes() {
266+
MCPseudoProbeDecoder &ProbeDecoder(*ProbeDecoderPtr);
244267
// Buffer for new pseudo probes section
245268
SmallString<8> Contents;
246269
MCDecodedPseudoProbe *LastProbe = nullptr;

bolt/lib/Rewrite/RewriteInstance.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,7 @@ Error RewriteInstance::run() {
669669
opts::ProfileFormat == opts::ProfileFormatKind::PF_YAML) {
670670
selectFunctionsToProcess();
671671
disassembleFunctions();
672+
processMetadataPreCFG();
672673
buildFunctionsCFG();
673674
}
674675
processProfileData();

bolt/test/X86/pseudoprobe-decoding-inline.test

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,26 @@
11
# REQUIRES: system-linux
2-
# RUN: llvm-bolt %S/../../../llvm/test/tools/llvm-profgen/Inputs/inline-cs-pseudoprobe.perfbin --print-pseudo-probes=all -o %t.bolt 2>&1 | FileCheck %s
2+
# RUN: llvm-bolt %S/../../../llvm/test/tools/llvm-profgen/Inputs/inline-cs-pseudoprobe.perfbin --print-pseudo-probes=all -o %t.bolt --lite=0 --enable-bat 2>&1 | FileCheck %s
3+
4+
# PREAGG: B X:0 #foo# 1 0
5+
# PREAGG: B X:0 #bar# 1 0
6+
# PREAGG: B X:0 #main# 1 0
7+
## Check pseudo-probes in regular YAML profile (non-BOLTed binary)
8+
# RUN: link_fdata %s %S/../../../llvm/test/tools/llvm-profgen/Inputs/inline-cs-pseudoprobe.perfbin %t.preagg PREAGG
9+
# RUN: perf2bolt %S/../../../llvm/test/tools/llvm-profgen/Inputs/inline-cs-pseudoprobe.perfbin -p %t.preagg --pa -w %t.yaml -o %t.fdata
10+
# RUN: FileCheck --input-file %t.yaml %s --check-prefix CHECK-YAML
11+
## Check pseudo-probes in BAT YAML profile (BOLTed binary)
12+
# RUN: link_fdata %s %t.bolt %t.preagg2 PREAGG
13+
# RUN: perf2bolt %t.bolt -p %t.preagg2 --pa -w %t.yaml2 -o %t.fdata2
14+
# RUN: FileCheck --input-file %t.yaml2 %s --check-prefix CHECK-YAML
15+
# CHECK-YAML: name: bar
16+
# CHECK-YAML: guid: 0xE413754A191DB537
17+
# CHECK-YAML: pseudo_probe_desc_hash: 0x10E852DA94
18+
# CHECK-YAML: name: foo
19+
# CHECK-YAML: guid: 0x5CF8C24CDB18BDAC
20+
# CHECK-YAML: pseudo_probe_desc_hash: 0x200205A19C5B4
21+
# CHECK-YAML: name: main
22+
# CHECK-YAML: guid: 0xDB956436E78DD5FA
23+
# CHECK-YAML: pseudo_probe_desc_hash: 0x10000FFFFFFFF
324

425
CHECK: Report of decoding input pseudo probe binaries
526

0 commit comments

Comments
 (0)