Skip to content

Commit a66ce58

Browse files
authored
[BOLT] Drop suffixes in parsePseudoProbe GUID assignment (#106243)
Pseudo probe function records contain GUIDs assigned by the compiler using an IR function name. Thus suffixes added later (e.g. `.llvm.` for internal symbols, `.destroy`/`.resume` for coroutine fragments, and `.cold`/`.warm` for split fragments) cause GUID mismatch. Address that by dropping those suffixes using `getCommonName` which is a parametrized form of `getLTOCommonName`.
1 parent 4618b67 commit a66ce58

File tree

3 files changed

+45
-12
lines changed

3 files changed

+45
-12
lines changed

bolt/include/bolt/Utils/Utils.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ std::string getEscapedName(const StringRef &Name);
4141
/// Return the unescaped name
4242
std::string getUnescapedName(const StringRef &Name);
4343

44+
/// Return a common part for a given \p Name wrt a given \p Suffixes list.
45+
/// Preserve the suffix if \p KeepSuffix is set, only dropping characters
46+
/// following it, otherwise drop the suffix as well.
47+
std::optional<StringRef> getCommonName(const StringRef Name, bool KeepSuffix,
48+
ArrayRef<StringRef> Suffixes);
4449
/// LTO-generated function names take a form:
4550
///
4651
/// <function_name>.lto_priv.<decimal_number>/...

bolt/lib/Rewrite/PseudoProbeRewriter.cpp

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "bolt/Rewrite/MetadataRewriter.h"
1515
#include "bolt/Rewrite/MetadataRewriters.h"
1616
#include "bolt/Utils/CommandLineOpts.h"
17+
#include "bolt/Utils/Utils.h"
1718
#include "llvm/IR/Function.h"
1819
#include "llvm/MC/MCPseudoProbe.h"
1920
#include "llvm/Support/CommandLine.h"
@@ -133,10 +134,19 @@ void PseudoProbeRewriter::parsePseudoProbe() {
133134

134135
MCPseudoProbeDecoder::Uint64Set GuidFilter;
135136
MCPseudoProbeDecoder::Uint64Map FuncStartAddrs;
137+
SmallVector<StringRef, 0> Suffixes(
138+
{".destroy", ".resume", ".llvm.", ".cold", ".warm"});
136139
for (const BinaryFunction *F : BC.getAllBinaryFunctions()) {
137140
for (const MCSymbol *Sym : F->getSymbols()) {
138-
FuncStartAddrs[Function::getGUID(NameResolver::restore(Sym->getName()))] =
139-
F->getAddress();
141+
StringRef SymName = Sym->getName();
142+
for (auto Name : {std::optional(NameResolver::restore(SymName)),
143+
getCommonName(SymName, false, Suffixes)}) {
144+
if (!Name)
145+
continue;
146+
SymName = *Name;
147+
uint64_t GUID = Function::getGUID(SymName);
148+
FuncStartAddrs[GUID] = F->getAddress();
149+
}
140150
}
141151
}
142152
Contents = PseudoProbeSection->getContents();
@@ -155,13 +165,25 @@ void PseudoProbeRewriter::parsePseudoProbe() {
155165
ProbeDecoder.printProbesForAllAddresses(outs());
156166
}
157167

158-
for (const auto &FuncDesc : ProbeDecoder.getGUID2FuncDescMap()) {
159-
uint64_t GUID = FuncDesc.FuncGUID;
160-
if (!FuncStartAddrs.contains(GUID))
161-
continue;
162-
BinaryFunction *BF = BC.getBinaryFunctionAtAddress(FuncStartAddrs[GUID]);
163-
assert(BF);
164-
BF->setGUID(GUID);
168+
const GUIDProbeFunctionMap &GUID2Func = ProbeDecoder.getGUID2FuncDescMap();
169+
// Checks GUID in GUID2Func and returns it if it's present or null otherwise.
170+
auto checkGUID = [&](StringRef SymName) -> uint64_t {
171+
uint64_t GUID = Function::getGUID(SymName);
172+
if (GUID2Func.find(GUID) == GUID2Func.end())
173+
return 0;
174+
return GUID;
175+
};
176+
for (BinaryFunction *F : BC.getAllBinaryFunctions()) {
177+
for (const MCSymbol *Sym : F->getSymbols()) {
178+
StringRef SymName = NameResolver::restore(Sym->getName());
179+
uint64_t GUID = checkGUID(SymName);
180+
std::optional<StringRef> CommonName =
181+
getCommonName(SymName, false, Suffixes);
182+
if (!GUID && CommonName)
183+
GUID = checkGUID(*CommonName);
184+
if (GUID)
185+
F->setGUID(GUID);
186+
}
165187
}
166188
}
167189

bolt/lib/Utils/Utils.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,21 @@ std::string getUnescapedName(const StringRef &Name) {
6666
return Output;
6767
}
6868

69-
std::optional<StringRef> getLTOCommonName(const StringRef Name) {
70-
for (StringRef Suffix : {".__uniq.", ".lto_priv.", ".constprop.", ".llvm."}) {
69+
std::optional<StringRef> getCommonName(const StringRef Name, bool KeepSuffix,
70+
ArrayRef<StringRef> Suffixes) {
71+
for (StringRef Suffix : Suffixes) {
7172
size_t LTOSuffixPos = Name.find(Suffix);
7273
if (LTOSuffixPos != StringRef::npos)
73-
return Name.substr(0, LTOSuffixPos + Suffix.size());
74+
return Name.substr(0, LTOSuffixPos + (KeepSuffix ? Suffix.size() : 0));
7475
}
7576
return std::nullopt;
7677
}
7778

79+
std::optional<StringRef> getLTOCommonName(const StringRef Name) {
80+
return getCommonName(Name, true,
81+
{".__uniq.", ".lto_priv.", ".constprop.", ".llvm."});
82+
}
83+
7884
std::optional<uint8_t> readDWARFExpressionTargetReg(StringRef ExprBytes) {
7985
uint8_t Opcode = ExprBytes[0];
8086
if (Opcode == dwarf::DW_CFA_def_cfa_expression)

0 commit comments

Comments
 (0)