[NFC][LTO] Move isPreservedName out of IRSymtab into LTO's Symbol as isLibcall (#177046)

This resolves the FIXME in IRSymtab and cleans up the semantics of the
IRSymtab. The list of preserved symbols really shouldn't be seen as a
property of the IR symbol table, since it's an LTO-specific concern, and
it's very tenuous to claim that this information is actually present in
the bitcode file to be exposed through its symbol table.

Instead, this PR moves this logic into LTO's view of the symbol, which
allows consumers to determine preserved-ness themselves. This was broken
out of #164916; this prevents that PR from introducing a circular
dependency, but it still seems like an independently good idea by virtue
of the above.
This commit is contained in:
Daniel Thornburgh 2026-01-21 11:32:33 -08:00 committed by GitHub
parent 1d5e0408c9
commit 567fe2bbca
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 31 additions and 19 deletions

View File

@ -25,6 +25,7 @@
#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/RuntimeLibcalls.h"
#include "llvm/LTO/LTO.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/COFF.h"
@ -1395,6 +1396,8 @@ void BitcodeFile::parse() {
// FIXME: Check nodeduplicate
comdat[i] =
symtab.addComdat(this, saver.save(obj->getComdatTable()[i].first));
Triple tt(obj->getTargetTriple());
RTLIB::RuntimeLibcallsInfo libcalls(tt);
for (const lto::InputFile::Symbol &objSym : obj->symbols()) {
StringRef symName = saver.save(objSym.getName());
int comdatIndex = objSym.getComdatIndex();
@ -1444,7 +1447,7 @@ void BitcodeFile::parse() {
symtab.addRegular(this, symName, nullptr, fakeSC, 0, objSym.isWeak());
}
symbols.push_back(sym);
if (objSym.isUsed())
if (objSym.isUsed() || objSym.isLibcall(libcalls))
symtab.ctx.config.gcroot.push_back(sym);
}
directives = saver.save(obj->getCOFFLinkerOpts());

View File

@ -16,6 +16,7 @@
#define LLVM_LTO_LTO_H
#include "llvm/IR/LLVMRemarkStreamer.h"
#include "llvm/IR/RuntimeLibcalls.h"
#include "llvm/Support/Compiler.h"
#include <memory>
@ -167,6 +168,12 @@ public:
using irsymtab::Symbol::getSectionName;
using irsymtab::Symbol::isExecutable;
using irsymtab::Symbol::isUsed;
// Returns whether this symbol is a library call that LTO code generation
// may emit references to. Such symbols must be considered external, as
// removing them or modifying their interfaces would invalidate the code
// generator's knowledge about them.
bool isLibcall(const RTLIB::RuntimeLibcallsInfo &Libcalls) const;
};
/// A range over the symbols in this InputFile.
@ -583,7 +590,7 @@ private:
void addModuleToGlobalRes(ArrayRef<InputFile::Symbol> Syms,
ArrayRef<SymbolResolution> Res, unsigned Partition,
bool InSummary);
bool InSummary, const Triple &TT);
// These functions take a range of symbol resolutions and consume the
// resolutions used by a single input module. Functions return ranges refering

View File

@ -597,6 +597,11 @@ Expected<std::unique_ptr<InputFile>> InputFile::create(MemoryBufferRef Object) {
return std::move(File);
}
bool InputFile::Symbol::isLibcall(
const RTLIB::RuntimeLibcallsInfo &Libcalls) const {
return Libcalls.getSupportedLibcallImpl(IRName) != RTLIB::Unsupported;
}
StringRef InputFile::getName() const {
return Mods[0].getModuleIdentifier();
}
@ -642,11 +647,13 @@ LTO::~LTO() = default;
// their partitions.
void LTO::addModuleToGlobalRes(ArrayRef<InputFile::Symbol> Syms,
ArrayRef<SymbolResolution> Res,
unsigned Partition, bool InSummary) {
unsigned Partition, bool InSummary,
const Triple &TT) {
llvm::TimeTraceScope timeScope("LTO add module to global resolution");
auto *ResI = Res.begin();
auto *ResE = Res.end();
(void)ResE;
RTLIB::RuntimeLibcallsInfo Libcalls(TT);
for (const InputFile::Symbol &Sym : Syms) {
assert(ResI != ResE);
SymbolResolution Res = *ResI++;
@ -689,11 +696,14 @@ void LTO::addModuleToGlobalRes(ArrayRef<InputFile::Symbol> Syms,
GlobalRes.VisibleOutsideSummary = true;
}
bool IsLibcall = Sym.isLibcall(Libcalls);
// Set the partition to external if we know it is re-defined by the linker
// with -defsym or -wrap options, used elsewhere, e.g. it is visible to a
// regular object, is referenced from llvm.compiler.used/llvm.used, or was
// already recorded as being referenced from a different partition.
if (Res.LinkerRedefined || Res.VisibleToRegularObj || Sym.isUsed() ||
IsLibcall ||
(GlobalRes.Partition != GlobalResolution::Unknown &&
GlobalRes.Partition != Partition)) {
GlobalRes.Partition = GlobalResolution::External;
@ -704,7 +714,7 @@ void LTO::addModuleToGlobalRes(ArrayRef<InputFile::Symbol> Syms,
// Flag as visible outside of summary if visible from a regular object or
// from a module that does not have a summary.
GlobalRes.VisibleOutsideSummary |=
(Res.VisibleToRegularObj || Sym.isUsed() || !InSummary);
(Res.VisibleToRegularObj || Sym.isUsed() || IsLibcall || !InSummary);
GlobalRes.ExportDynamic |= Res.ExportDynamic;
}
@ -811,7 +821,7 @@ LTO::addModule(InputFile &Input, ArrayRef<SymbolResolution> InputRes,
auto ModSyms = Input.module_symbols(ModI);
addModuleToGlobalRes(ModSyms, Res,
IsThinLTO ? ThinLTO.ModuleMap.size() + 1 : 0,
LTOInfo->HasSummary);
LTOInfo->HasSummary, Triple(Input.getTargetTriple()));
if (IsThinLTO)
return addThinLTO(BM, ModSyms, Res);

View File

@ -290,11 +290,12 @@ static void optimizeModule(Module &TheModule, TargetMachine &TM,
static void
addUsedSymbolToPreservedGUID(const lto::InputFile &File,
DenseSet<GlobalValue::GUID> &PreservedGUID) {
for (const auto &Sym : File.symbols()) {
if (Sym.isUsed())
Triple TT(File.getTargetTriple());
RTLIB::RuntimeLibcallsInfo Libcalls(TT);
for (const auto &Sym : File.symbols())
if (Sym.isUsed() || Sym.isLibcall(Libcalls))
PreservedGUID.insert(
GlobalValue::getGUIDAssumingExternalLinkage(Sym.getIRName()));
}
}
// Convert the PreservedSymbols map from "Name" based to "GUID" based.

View File

@ -22,7 +22,6 @@
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/RuntimeLibcalls.h"
#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Object/ModuleSymbolTable.h"
#include "llvm/Object/SymbolicFile.h"
@ -74,16 +73,12 @@ struct Builder {
// so this provides somewhere to store any strings that we create.
Builder(SmallVector<char, 0> &Symtab, StringTableBuilder &StrtabBuilder,
BumpPtrAllocator &Alloc, const Triple &TT)
: Symtab(Symtab), StrtabBuilder(StrtabBuilder), Saver(Alloc), TT(TT),
Libcalls(TT) {}
: Symtab(Symtab), StrtabBuilder(StrtabBuilder), Saver(Alloc), TT(TT) {}
DenseMap<const Comdat *, int> ComdatMap;
Mangler Mang;
const Triple &TT;
// FIXME: This shouldn't be here.
RTLIB::RuntimeLibcallsInfo Libcalls;
std::vector<storage::Comdat> Comdats;
std::vector<storage::Module> Mods;
std::vector<storage::Symbol> Syms;
@ -94,10 +89,6 @@ struct Builder {
std::vector<storage::Str> DependentLibraries;
bool isPreservedName(StringRef Name) {
return Libcalls.getSupportedLibcallImpl(Name) != RTLIB::Unsupported;
}
void setStr(storage::Str &S, StringRef Value) {
S.Offset = StrtabBuilder.add(Value);
S.Size = Value.size();
@ -269,7 +260,7 @@ Error Builder::addSymbol(const ModuleSymbolTable &Msymtab,
StringRef GVName = GV->getName();
setStr(Sym.IRName, GVName);
if (Used.count(GV) || isPreservedName(GVName))
if (Used.count(GV))
Sym.Flags |= 1 << storage::Symbol::FB_used;
if (GV->isThreadLocal())
Sym.Flags |= 1 << storage::Symbol::FB_tls;