[BOLT][NFCI] Use FileSymbols for local symbol disambiguation (#89088)

Remove SymbolToFileName mapping from every local symbol to its
containing FILE symbol name, and reuse FileSymbols to disambiguate
local symbols instead.

Also removes the check for `ld-temp.o` file symbol which was added to
prevent LTO build mode from affecting the disambiguated name. This may
cause incompatibility when using the profile collected on a binary built
in a different mode than the input binary.

Addresses #90661.

Speeds up discover file objects by 5-10% for large binaries:
- binary with ~1.2M symbols: 12.6422s -> 12.0297s
- binary with ~4.5M symbols: 48.8851s -> 43.7315s
This commit is contained in:
Amir Ayupov
2025-06-20 14:29:32 -07:00
committed by GitHub
parent 5886f0a183
commit f0d32575a1

View File

@@ -780,14 +780,6 @@ void RewriteInstance::discoverFileObjects() {
// For local symbols we want to keep track of associated FILE symbol name for
// disambiguation by combined name.
StringRef FileSymbolName;
bool SeenFileName = false;
struct SymbolRefHash {
size_t operator()(SymbolRef const &S) const {
return std::hash<decltype(DataRefImpl::p)>{}(S.getRawDataRefImpl().p);
}
};
std::unordered_map<SymbolRef, StringRef, SymbolRefHash> SymbolToFileName;
for (const ELFSymbolRef &Symbol : InputFile->symbols()) {
Expected<StringRef> NameOrError = Symbol.getName();
if (NameOrError && NameOrError->starts_with("__asan_init")) {
@@ -806,21 +798,8 @@ void RewriteInstance::discoverFileObjects() {
if (cantFail(Symbol.getFlags()) & SymbolRef::SF_Undefined)
continue;
if (cantFail(Symbol.getType()) == SymbolRef::ST_File) {
if (cantFail(Symbol.getType()) == SymbolRef::ST_File)
FileSymbols.emplace_back(Symbol);
StringRef Name =
cantFail(std::move(NameOrError), "cannot get symbol name for file");
// Ignore Clang LTO artificial FILE symbol as it is not always generated,
// and this uncertainty is causing havoc in function name matching.
if (Name == "ld-temp.o")
continue;
FileSymbolName = Name;
SeenFileName = true;
continue;
}
if (!FileSymbolName.empty() &&
!(cantFail(Symbol.getFlags()) & SymbolRef::SF_Global))
SymbolToFileName[Symbol] = FileSymbolName;
}
// Sort symbols in the file by value. Ignore symbols from non-allocatable
@@ -1028,14 +1007,14 @@ void RewriteInstance::discoverFileObjects() {
// The <id> field is used for disambiguation of local symbols since there
// could be identical function names coming from identical file names
// (e.g. from different directories).
std::string AltPrefix;
auto SFI = SymbolToFileName.find(Symbol);
if (SymbolType == SymbolRef::ST_Function && SFI != SymbolToFileName.end())
AltPrefix = Name + "/" + std::string(SFI->second);
auto SFI = llvm::upper_bound(FileSymbols, ELFSymbolRef(Symbol));
if (SymbolType == SymbolRef::ST_Function && SFI != FileSymbols.begin()) {
StringRef FileSymbolName = cantFail(SFI[-1].getName());
if (!FileSymbolName.empty())
AlternativeName = NR.uniquify(Name + "/" + FileSymbolName.str());
}
UniqueName = NR.uniquify(Name);
if (!AltPrefix.empty())
AlternativeName = NR.uniquify(AltPrefix);
}
uint64_t SymbolSize = ELFSymbolRef(Symbol).getSize();
@@ -1294,7 +1273,7 @@ void RewriteInstance::discoverFileObjects() {
FDE->getAddressRange());
}
BC->setHasSymbolsWithFileName(SeenFileName);
BC->setHasSymbolsWithFileName(FileSymbols.size());
// Now that all the functions were created - adjust their boundaries.
adjustFunctionBoundaries();