[LLD][COFF] Add more --time-trace tags for ThinLTO linking (#156471)
In order to better see what's going on during ThinLTO linking, this PR adds more profile tags when using `--time-trace` on a `lld-link.exe` invocation. After PR, linking `clang.exe`: <img width="3839" height="2026" alt="Capture d’écran 2025-09-02 082021" src="https://github.com/user-attachments/assets/bf0c85ba-2f85-4bbf-a5c1-800039b56910" /> Linking a custom (Unreal Engine game) binary gives a completly different picture, probably because of using Unity files, and the sheer amount of input files (here, providing over 60 GB of .OBJs/.LIBs). <img width="1940" height="1008" alt="Capture d’écran 2025-09-02 102048" src="https://github.com/user-attachments/assets/60b28630-7995-45ce-9e8c-13f3cb5312e0" />
This commit is contained in:
parent
a549e73cad
commit
5cda2424c8
@ -26,6 +26,7 @@
|
||||
#include "llvm/Support/Caching.h"
|
||||
#include "llvm/Support/CodeGen.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/TimeProfiler.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
@ -176,6 +177,7 @@ void BitcodeCompiler::add(BitcodeFile &f) {
|
||||
// Merge all the bitcode files we have seen, codegen the result
|
||||
// and return the resulting objects.
|
||||
std::vector<InputFile *> BitcodeCompiler::compile() {
|
||||
llvm::TimeTraceScope timeScope("Bitcode compile");
|
||||
unsigned maxTasks = ltoObj->getMaxTasks();
|
||||
buf.resize(maxTasks);
|
||||
files.resize(maxTasks);
|
||||
|
||||
@ -1437,11 +1437,13 @@ void SymbolTable::compileBitcodeFiles() {
|
||||
if (bitcodeFileInstances.empty())
|
||||
return;
|
||||
|
||||
llvm::TimeTraceScope timeScope("Compile bitcode");
|
||||
ScopedTimer t(ctx.ltoTimer);
|
||||
lto.reset(new BitcodeCompiler(ctx));
|
||||
for (BitcodeFile *f : bitcodeFileInstances)
|
||||
lto->add(*f);
|
||||
{
|
||||
llvm::TimeTraceScope addScope("Add bitcode file instances");
|
||||
for (BitcodeFile *f : bitcodeFileInstances)
|
||||
lto->add(*f);
|
||||
}
|
||||
for (InputFile *newObj : lto->compile()) {
|
||||
ObjFile *obj = cast<ObjFile>(newObj);
|
||||
obj->parse();
|
||||
|
||||
@ -43,6 +43,7 @@
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/TimeProfiler.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
@ -1052,6 +1053,7 @@ void MetadataLoader::MetadataLoaderImpl::callMDTypeCallback(Metadata **Val,
|
||||
/// Parse a METADATA_BLOCK. If ModuleLevel is true then we are parsing
|
||||
/// module level metadata.
|
||||
Error MetadataLoader::MetadataLoaderImpl::parseMetadata(bool ModuleLevel) {
|
||||
llvm::TimeTraceScope timeScope("Parse metadata");
|
||||
if (!ModuleLevel && MetadataList.hasFwdRefs())
|
||||
return error("Invalid metadata: fwd refs into function blocks");
|
||||
|
||||
|
||||
@ -48,6 +48,7 @@
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/NVPTXAddrSpace.h"
|
||||
#include "llvm/Support/Regex.h"
|
||||
#include "llvm/Support/TimeProfiler.h"
|
||||
#include "llvm/TargetParser/Triple.h"
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
@ -5256,6 +5257,7 @@ bool llvm::UpgradeDebugInfo(Module &M) {
|
||||
if (DisableAutoUpgradeDebugInfo)
|
||||
return false;
|
||||
|
||||
llvm::TimeTraceScope timeScope("Upgrade debug info");
|
||||
// We need to get metadata before the module is verified (i.e., getModuleFlag
|
||||
// makes assumptions that we haven't verified yet). Carefully extract the flag
|
||||
// from the metadata.
|
||||
|
||||
@ -36,6 +36,7 @@
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/IR/PassManager.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/TimeProfiler.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <optional>
|
||||
@ -563,6 +564,7 @@ bool llvm::stripDebugInfo(Function &F) {
|
||||
}
|
||||
|
||||
bool llvm::StripDebugInfo(Module &M) {
|
||||
llvm::TimeTraceScope timeScope("Strip debug info");
|
||||
bool Changed = false;
|
||||
|
||||
for (NamedMDNode &NMD : llvm::make_early_inc_range(M.named_metadata())) {
|
||||
|
||||
@ -44,6 +44,7 @@
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/RandomNumberGenerator.h"
|
||||
#include "llvm/Support/TimeProfiler.h"
|
||||
#include "llvm/Support/VersionTuple.h"
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
@ -478,6 +479,7 @@ Error Module::materializeAll() {
|
||||
}
|
||||
|
||||
Error Module::materializeMetadata() {
|
||||
llvm::TimeTraceScope timeScope("Materialize metadata");
|
||||
if (!Materializer)
|
||||
return Error::success();
|
||||
return Materializer->materializeMetadata();
|
||||
|
||||
@ -119,6 +119,7 @@
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/ModRef.h"
|
||||
#include "llvm/Support/TimeProfiler.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
@ -399,6 +400,7 @@ public:
|
||||
bool hasBrokenDebugInfo() const { return BrokenDebugInfo; }
|
||||
|
||||
bool verify(const Function &F) {
|
||||
llvm::TimeTraceScope timeScope("Verifier");
|
||||
assert(F.getParent() == &M &&
|
||||
"An instance of this class only works with a specific module!");
|
||||
|
||||
@ -2822,6 +2824,7 @@ static Instruction *getSuccPad(Instruction *Terminator) {
|
||||
}
|
||||
|
||||
void Verifier::verifySiblingFuncletUnwinds() {
|
||||
llvm::TimeTraceScope timeScope("Verifier verify sibling funclet unwinds");
|
||||
SmallPtrSet<Instruction *, 8> Visited;
|
||||
SmallPtrSet<Instruction *, 8> Active;
|
||||
for (const auto &Pair : SiblingFuncletInfo) {
|
||||
|
||||
@ -631,6 +631,7 @@ LTO::~LTO() = default;
|
||||
void LTO::addModuleToGlobalRes(ArrayRef<InputFile::Symbol> Syms,
|
||||
ArrayRef<SymbolResolution> Res,
|
||||
unsigned Partition, bool InSummary) {
|
||||
llvm::TimeTraceScope timeScope("LTO add module to global resolution");
|
||||
auto *ResI = Res.begin();
|
||||
auto *ResE = Res.end();
|
||||
(void)ResE;
|
||||
@ -731,6 +732,7 @@ static void writeToResolutionFile(raw_ostream &OS, InputFile *Input,
|
||||
|
||||
Error LTO::add(std::unique_ptr<InputFile> Input,
|
||||
ArrayRef<SymbolResolution> Res) {
|
||||
llvm::TimeTraceScope timeScope("LTO add input", Input->getName());
|
||||
assert(!CalledGetMaxTasks);
|
||||
|
||||
if (Conf.ResolutionFile)
|
||||
@ -756,6 +758,7 @@ Error LTO::add(std::unique_ptr<InputFile> Input,
|
||||
Expected<ArrayRef<SymbolResolution>>
|
||||
LTO::addModule(InputFile &Input, ArrayRef<SymbolResolution> InputRes,
|
||||
unsigned ModI, ArrayRef<SymbolResolution> Res) {
|
||||
llvm::TimeTraceScope timeScope("LTO add module", Input.getName());
|
||||
Expected<BitcodeLTOInfo> LTOInfo = Input.Mods[ModI].getLTOInfo();
|
||||
if (!LTOInfo)
|
||||
return LTOInfo.takeError();
|
||||
@ -850,6 +853,7 @@ Expected<
|
||||
LTO::addRegularLTO(InputFile &Input, ArrayRef<SymbolResolution> InputRes,
|
||||
BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
|
||||
ArrayRef<SymbolResolution> Res) {
|
||||
llvm::TimeTraceScope timeScope("LTO add regular LTO");
|
||||
RegularLTOState::AddedModule Mod;
|
||||
Expected<std::unique_ptr<Module>> MOrErr =
|
||||
BM.getLazyModule(RegularLTO.Ctx, /*ShouldLazyLoadMetadata*/ true,
|
||||
@ -1024,6 +1028,7 @@ LTO::addRegularLTO(InputFile &Input, ArrayRef<SymbolResolution> InputRes,
|
||||
|
||||
Error LTO::linkRegularLTO(RegularLTOState::AddedModule Mod,
|
||||
bool LivenessFromIndex) {
|
||||
llvm::TimeTraceScope timeScope("LTO link regular LTO");
|
||||
std::vector<GlobalValue *> Keep;
|
||||
for (GlobalValue *GV : Mod.Keep) {
|
||||
if (LivenessFromIndex && !ThinLTO.CombinedIndex.isGUIDLive(GV->getGUID())) {
|
||||
@ -1063,6 +1068,7 @@ Error LTO::linkRegularLTO(RegularLTOState::AddedModule Mod,
|
||||
Expected<ArrayRef<SymbolResolution>>
|
||||
LTO::addThinLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
|
||||
ArrayRef<SymbolResolution> Res) {
|
||||
llvm::TimeTraceScope timeScope("LTO add thin LTO");
|
||||
ArrayRef<SymbolResolution> ResTmp = Res;
|
||||
for (const InputFile::Symbol &Sym : Syms) {
|
||||
assert(!ResTmp.empty());
|
||||
@ -1252,6 +1258,7 @@ Error LTO::run(AddStreamFn AddStream, FileCache Cache) {
|
||||
|
||||
void lto::updateMemProfAttributes(Module &Mod,
|
||||
const ModuleSummaryIndex &Index) {
|
||||
llvm::TimeTraceScope timeScope("LTO update memprof attributes");
|
||||
if (Index.withSupportsHotColdNew())
|
||||
return;
|
||||
|
||||
@ -1282,6 +1289,7 @@ void lto::updateMemProfAttributes(Module &Mod,
|
||||
}
|
||||
|
||||
Error LTO::runRegularLTO(AddStreamFn AddStream) {
|
||||
llvm::TimeTraceScope timeScope("Run regular LTO");
|
||||
// Setup optimization remarks.
|
||||
auto DiagFileOrErr = lto::setupLLVMOptimizationRemarks(
|
||||
RegularLTO.CombinedModule->getContext(), Conf.RemarksFilename,
|
||||
@ -1294,10 +1302,12 @@ Error LTO::runRegularLTO(AddStreamFn AddStream) {
|
||||
|
||||
// Finalize linking of regular LTO modules containing summaries now that
|
||||
// we have computed liveness information.
|
||||
for (auto &M : RegularLTO.ModsWithSummaries)
|
||||
if (Error Err = linkRegularLTO(std::move(M),
|
||||
/*LivenessFromIndex=*/true))
|
||||
return Err;
|
||||
{
|
||||
llvm::TimeTraceScope timeScope("Link regular LTO");
|
||||
for (auto &M : RegularLTO.ModsWithSummaries)
|
||||
if (Error Err = linkRegularLTO(std::move(M), /*LivenessFromIndex=*/true))
|
||||
return Err;
|
||||
}
|
||||
|
||||
// Ensure we don't have inconsistently split LTO units with type tests.
|
||||
// FIXME: this checks both LTO and ThinLTO. It happens to work as we take
|
||||
@ -1526,6 +1536,9 @@ public:
|
||||
const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
|
||||
const GVSummaryMapTy &DefinedGlobals,
|
||||
MapVector<StringRef, BitcodeModule> &ModuleMap) {
|
||||
auto ModuleID = BM.getModuleIdentifier();
|
||||
llvm::TimeTraceScope timeScope("Run ThinLTO backend thread (in-process)",
|
||||
ModuleID);
|
||||
auto RunThinBackend = [&](AddStreamFn AddStream) {
|
||||
LTOLLVMContext BackendContext(Conf);
|
||||
Expected<std::unique_ptr<Module>> MOrErr = BM.parseModule(BackendContext);
|
||||
@ -1536,9 +1549,6 @@ public:
|
||||
ImportList, DefinedGlobals, &ModuleMap,
|
||||
Conf.CodeGenOnly);
|
||||
};
|
||||
|
||||
auto ModuleID = BM.getModuleIdentifier();
|
||||
|
||||
if (ShouldEmitIndexFiles) {
|
||||
if (auto E = emitFiles(ImportList, ModuleID, ModuleID.str()))
|
||||
return E;
|
||||
@ -1639,6 +1649,9 @@ public:
|
||||
const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
|
||||
const GVSummaryMapTy &DefinedGlobals,
|
||||
MapVector<StringRef, BitcodeModule> &ModuleMap) override {
|
||||
auto ModuleID = BM.getModuleIdentifier();
|
||||
llvm::TimeTraceScope timeScope("Run ThinLTO backend thread (first round)",
|
||||
ModuleID);
|
||||
auto RunThinBackend = [&](AddStreamFn CGAddStream,
|
||||
AddStreamFn IRAddStream) {
|
||||
LTOLLVMContext BackendContext(Conf);
|
||||
@ -1650,8 +1663,6 @@ public:
|
||||
ImportList, DefinedGlobals, &ModuleMap,
|
||||
Conf.CodeGenOnly, IRAddStream);
|
||||
};
|
||||
|
||||
auto ModuleID = BM.getModuleIdentifier();
|
||||
// Like InProcessThinBackend, we produce index files as needed for
|
||||
// FirstRoundThinBackend. However, these files are not generated for
|
||||
// SecondRoundThinBackend.
|
||||
@ -1735,6 +1746,9 @@ public:
|
||||
const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
|
||||
const GVSummaryMapTy &DefinedGlobals,
|
||||
MapVector<StringRef, BitcodeModule> &ModuleMap) override {
|
||||
auto ModuleID = BM.getModuleIdentifier();
|
||||
llvm::TimeTraceScope timeScope("Run ThinLTO backend thread (second round)",
|
||||
ModuleID);
|
||||
auto RunThinBackend = [&](AddStreamFn AddStream) {
|
||||
LTOLLVMContext BackendContext(Conf);
|
||||
std::unique_ptr<Module> LoadedModule =
|
||||
@ -1744,8 +1758,6 @@ public:
|
||||
ImportList, DefinedGlobals, &ModuleMap,
|
||||
/*CodeGenOnly=*/true);
|
||||
};
|
||||
|
||||
auto ModuleID = BM.getModuleIdentifier();
|
||||
if (!Cache.isValid() || !CombinedIndex.modulePaths().count(ModuleID) ||
|
||||
all_of(CombinedIndex.getModuleHash(ModuleID),
|
||||
[](uint32_t V) { return V == 0; }))
|
||||
@ -1915,6 +1927,7 @@ ThinBackend lto::createWriteIndexesThinBackend(
|
||||
|
||||
Error LTO::runThinLTO(AddStreamFn AddStream, FileCache Cache,
|
||||
const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols) {
|
||||
llvm::TimeTraceScope timeScope("Run ThinLTO");
|
||||
LLVM_DEBUG(dbgs() << "Running ThinLTO\n");
|
||||
ThinLTO.CombinedIndex.releaseTemporaryMemory();
|
||||
timeTraceProfilerBegin("ThinLink", StringRef(""));
|
||||
|
||||
@ -366,6 +366,7 @@ bool lto::opt(const Config &Conf, TargetMachine *TM, unsigned Task, Module &Mod,
|
||||
bool IsThinLTO, ModuleSummaryIndex *ExportSummary,
|
||||
const ModuleSummaryIndex *ImportSummary,
|
||||
const std::vector<uint8_t> &CmdArgs) {
|
||||
llvm::TimeTraceScope timeScope("opt");
|
||||
if (EmbedBitcode == LTOBitcodeEmbedding::EmbedPostMergePreOptimized) {
|
||||
// FIXME: the motivation for capturing post-merge bitcode and command line
|
||||
// is replicating the compilation environment from bitcode, without needing
|
||||
@ -399,6 +400,7 @@ bool lto::opt(const Config &Conf, TargetMachine *TM, unsigned Task, Module &Mod,
|
||||
static void codegen(const Config &Conf, TargetMachine *TM,
|
||||
AddStreamFn AddStream, unsigned Task, Module &Mod,
|
||||
const ModuleSummaryIndex &CombinedIndex) {
|
||||
llvm::TimeTraceScope timeScope("codegen");
|
||||
if (Conf.PreCodeGenModuleHook && !Conf.PreCodeGenModuleHook(Task, Mod))
|
||||
return;
|
||||
|
||||
@ -552,6 +554,7 @@ Error lto::finalizeOptimizationRemarks(
|
||||
Error lto::backend(const Config &C, AddStreamFn AddStream,
|
||||
unsigned ParallelCodeGenParallelismLevel, Module &Mod,
|
||||
ModuleSummaryIndex &CombinedIndex) {
|
||||
llvm::TimeTraceScope timeScope("LTO backend");
|
||||
Expected<const Target *> TOrErr = initAndLookupTarget(C, Mod);
|
||||
if (!TOrErr)
|
||||
return TOrErr.takeError();
|
||||
@ -577,6 +580,7 @@ Error lto::backend(const Config &C, AddStreamFn AddStream,
|
||||
|
||||
static void dropDeadSymbols(Module &Mod, const GVSummaryMapTy &DefinedGlobals,
|
||||
const ModuleSummaryIndex &Index) {
|
||||
llvm::TimeTraceScope timeScope("Drop dead symbols");
|
||||
std::vector<GlobalValue*> DeadGVs;
|
||||
for (auto &GV : Mod.global_values())
|
||||
if (GlobalValueSummary *GVS = DefinedGlobals.lookup(GV.getGUID()))
|
||||
@ -603,6 +607,7 @@ Error lto::thinBackend(const Config &Conf, unsigned Task, AddStreamFn AddStream,
|
||||
MapVector<StringRef, BitcodeModule> *ModuleMap,
|
||||
bool CodeGenOnly, AddStreamFn IRAddStream,
|
||||
const std::vector<uint8_t> &CmdArgs) {
|
||||
llvm::TimeTraceScope timeScope("Thin backend", Mod.getModuleIdentifier());
|
||||
Expected<const Target *> TOrErr = initAndLookupTarget(Conf, Mod);
|
||||
if (!TOrErr)
|
||||
return TOrErr.takeError();
|
||||
@ -679,6 +684,7 @@ Error lto::thinBackend(const Config &Conf, unsigned Task, AddStreamFn AddStream,
|
||||
return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
|
||||
|
||||
auto ModuleLoader = [&](StringRef Identifier) {
|
||||
llvm::TimeTraceScope moduleLoaderScope("Module loader", Identifier);
|
||||
assert(Mod.getContext().isODRUniquingDebugTypes() &&
|
||||
"ODR Type uniquing should be enabled on the context");
|
||||
if (ModuleMap) {
|
||||
@ -712,10 +718,13 @@ Error lto::thinBackend(const Config &Conf, unsigned Task, AddStreamFn AddStream,
|
||||
return MOrErr;
|
||||
};
|
||||
|
||||
FunctionImporter Importer(CombinedIndex, ModuleLoader,
|
||||
ClearDSOLocalOnDeclarations);
|
||||
if (Error Err = Importer.importFunctions(Mod, ImportList).takeError())
|
||||
return Err;
|
||||
{
|
||||
llvm::TimeTraceScope importScope("Import functions");
|
||||
FunctionImporter Importer(CombinedIndex, ModuleLoader,
|
||||
ClearDSOLocalOnDeclarations);
|
||||
if (Error Err = Importer.importFunctions(Mod, ImportList).takeError())
|
||||
return Err;
|
||||
}
|
||||
|
||||
// Do this after any importing so that imported code is updated.
|
||||
updateMemProfAttributes(Mod, CombinedIndex);
|
||||
|
||||
@ -40,6 +40,7 @@
|
||||
#include "llvm/Support/JSON.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/SourceMgr.h"
|
||||
#include "llvm/Support/TimeProfiler.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Transforms/IPO/Internalize.h"
|
||||
#include "llvm/Transforms/Utils/Cloning.h"
|
||||
@ -1550,6 +1551,7 @@ void llvm::computeDeadSymbolsWithConstProp(
|
||||
const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols,
|
||||
function_ref<PrevailingType(GlobalValue::GUID)> isPrevailing,
|
||||
bool ImportEnabled) {
|
||||
llvm::TimeTraceScope timeScope("Drop dead symbols and propagate attributes");
|
||||
computeDeadSymbolsAndUpdateIndirectCalls(Index, GUIDPreservedSymbols,
|
||||
isPrevailing);
|
||||
if (ImportEnabled)
|
||||
@ -1664,6 +1666,7 @@ bool llvm::convertToDeclaration(GlobalValue &GV) {
|
||||
void llvm::thinLTOFinalizeInModule(Module &TheModule,
|
||||
const GVSummaryMapTy &DefinedGlobals,
|
||||
bool PropagateAttrs) {
|
||||
llvm::TimeTraceScope timeScope("ThinLTO finalize in module");
|
||||
DenseSet<Comdat *> NonPrevailingComdats;
|
||||
auto FinalizeInModule = [&](GlobalValue &GV, bool Propagate = false) {
|
||||
// See if the global summary analysis computed a new resolved linkage.
|
||||
@ -1791,6 +1794,7 @@ void llvm::thinLTOFinalizeInModule(Module &TheModule,
|
||||
/// Run internalization on \p TheModule based on symmary analysis.
|
||||
void llvm::thinLTOInternalizeModule(Module &TheModule,
|
||||
const GVSummaryMapTy &DefinedGlobals) {
|
||||
llvm::TimeTraceScope timeScope("ThinLTO internalize module");
|
||||
// Declare a callback for the internalize pass that will ask for every
|
||||
// candidate GlobalValue if it can be internalized or not.
|
||||
auto MustPreserveGV = [&](const GlobalValue &GV) -> bool {
|
||||
@ -1885,6 +1889,7 @@ Expected<bool> FunctionImporter::importFunctions(
|
||||
|
||||
// Do the actual import of functions now, one Module at a time
|
||||
for (const auto &ModName : ImportList.getSourceModules()) {
|
||||
llvm::TimeTraceScope timeScope("Import", ModName);
|
||||
// Get the module for the import
|
||||
Expected<std::unique_ptr<Module>> SrcModuleOrErr = ModuleLoader(ModName);
|
||||
if (!SrcModuleOrErr)
|
||||
@ -1900,102 +1905,114 @@ Expected<bool> FunctionImporter::importFunctions(
|
||||
|
||||
// Find the globals to import
|
||||
SetVector<GlobalValue *> GlobalsToImport;
|
||||
for (Function &F : *SrcModule) {
|
||||
if (!F.hasName())
|
||||
continue;
|
||||
auto GUID = F.getGUID();
|
||||
auto MaybeImportType = ImportList.getImportType(ModName, GUID);
|
||||
bool ImportDefinition = MaybeImportType == GlobalValueSummary::Definition;
|
||||
{
|
||||
llvm::TimeTraceScope functionsScope("Functions");
|
||||
for (Function &F : *SrcModule) {
|
||||
if (!F.hasName())
|
||||
continue;
|
||||
auto GUID = F.getGUID();
|
||||
auto MaybeImportType = ImportList.getImportType(ModName, GUID);
|
||||
bool ImportDefinition =
|
||||
MaybeImportType == GlobalValueSummary::Definition;
|
||||
|
||||
LLVM_DEBUG(dbgs() << (MaybeImportType ? "Is" : "Not")
|
||||
<< " importing function"
|
||||
<< (ImportDefinition
|
||||
? " definition "
|
||||
: (MaybeImportType ? " declaration " : " "))
|
||||
<< GUID << " " << F.getName() << " from "
|
||||
<< SrcModule->getSourceFileName() << "\n");
|
||||
if (ImportDefinition) {
|
||||
if (Error Err = F.materialize())
|
||||
return std::move(Err);
|
||||
// MemProf should match function's definition and summary,
|
||||
// 'thinlto_src_module' is needed.
|
||||
if (EnableImportMetadata || EnableMemProfContextDisambiguation) {
|
||||
// Add 'thinlto_src_module' and 'thinlto_src_file' metadata for
|
||||
// statistics and debugging.
|
||||
F.setMetadata(
|
||||
"thinlto_src_module",
|
||||
MDNode::get(DestModule.getContext(),
|
||||
{MDString::get(DestModule.getContext(),
|
||||
SrcModule->getModuleIdentifier())}));
|
||||
F.setMetadata(
|
||||
"thinlto_src_file",
|
||||
MDNode::get(DestModule.getContext(),
|
||||
{MDString::get(DestModule.getContext(),
|
||||
SrcModule->getSourceFileName())}));
|
||||
}
|
||||
GlobalsToImport.insert(&F);
|
||||
}
|
||||
}
|
||||
for (GlobalVariable &GV : SrcModule->globals()) {
|
||||
if (!GV.hasName())
|
||||
continue;
|
||||
auto GUID = GV.getGUID();
|
||||
auto MaybeImportType = ImportList.getImportType(ModName, GUID);
|
||||
bool ImportDefinition = MaybeImportType == GlobalValueSummary::Definition;
|
||||
|
||||
LLVM_DEBUG(dbgs() << (MaybeImportType ? "Is" : "Not")
|
||||
<< " importing global"
|
||||
<< (ImportDefinition
|
||||
? " definition "
|
||||
: (MaybeImportType ? " declaration " : " "))
|
||||
<< GUID << " " << GV.getName() << " from "
|
||||
<< SrcModule->getSourceFileName() << "\n");
|
||||
if (ImportDefinition) {
|
||||
if (Error Err = GV.materialize())
|
||||
return std::move(Err);
|
||||
ImportedGVCount += GlobalsToImport.insert(&GV);
|
||||
}
|
||||
}
|
||||
for (GlobalAlias &GA : SrcModule->aliases()) {
|
||||
if (!GA.hasName() || isa<GlobalIFunc>(GA.getAliaseeObject()))
|
||||
continue;
|
||||
auto GUID = GA.getGUID();
|
||||
auto MaybeImportType = ImportList.getImportType(ModName, GUID);
|
||||
bool ImportDefinition = MaybeImportType == GlobalValueSummary::Definition;
|
||||
|
||||
LLVM_DEBUG(dbgs() << (MaybeImportType ? "Is" : "Not")
|
||||
<< " importing alias"
|
||||
<< (ImportDefinition
|
||||
? " definition "
|
||||
: (MaybeImportType ? " declaration " : " "))
|
||||
<< GUID << " " << GA.getName() << " from "
|
||||
<< SrcModule->getSourceFileName() << "\n");
|
||||
if (ImportDefinition) {
|
||||
if (Error Err = GA.materialize())
|
||||
return std::move(Err);
|
||||
// Import alias as a copy of its aliasee.
|
||||
GlobalObject *GO = GA.getAliaseeObject();
|
||||
if (Error Err = GO->materialize())
|
||||
return std::move(Err);
|
||||
auto *Fn = replaceAliasWithAliasee(SrcModule.get(), &GA);
|
||||
LLVM_DEBUG(dbgs() << "Is importing aliasee fn " << GO->getGUID() << " "
|
||||
<< GO->getName() << " from "
|
||||
LLVM_DEBUG(dbgs() << (MaybeImportType ? "Is" : "Not")
|
||||
<< " importing function"
|
||||
<< (ImportDefinition
|
||||
? " definition "
|
||||
: (MaybeImportType ? " declaration " : " "))
|
||||
<< GUID << " " << F.getName() << " from "
|
||||
<< SrcModule->getSourceFileName() << "\n");
|
||||
if (EnableImportMetadata || EnableMemProfContextDisambiguation) {
|
||||
// Add 'thinlto_src_module' and 'thinlto_src_file' metadata for
|
||||
// statistics and debugging.
|
||||
Fn->setMetadata(
|
||||
"thinlto_src_module",
|
||||
MDNode::get(DestModule.getContext(),
|
||||
{MDString::get(DestModule.getContext(),
|
||||
SrcModule->getModuleIdentifier())}));
|
||||
Fn->setMetadata(
|
||||
"thinlto_src_file",
|
||||
MDNode::get(DestModule.getContext(),
|
||||
{MDString::get(DestModule.getContext(),
|
||||
SrcModule->getSourceFileName())}));
|
||||
if (ImportDefinition) {
|
||||
if (Error Err = F.materialize())
|
||||
return std::move(Err);
|
||||
// MemProf should match function's definition and summary,
|
||||
// 'thinlto_src_module' is needed.
|
||||
if (EnableImportMetadata || EnableMemProfContextDisambiguation) {
|
||||
// Add 'thinlto_src_module' and 'thinlto_src_file' metadata for
|
||||
// statistics and debugging.
|
||||
F.setMetadata(
|
||||
"thinlto_src_module",
|
||||
MDNode::get(DestModule.getContext(),
|
||||
{MDString::get(DestModule.getContext(),
|
||||
SrcModule->getModuleIdentifier())}));
|
||||
F.setMetadata(
|
||||
"thinlto_src_file",
|
||||
MDNode::get(DestModule.getContext(),
|
||||
{MDString::get(DestModule.getContext(),
|
||||
SrcModule->getSourceFileName())}));
|
||||
}
|
||||
GlobalsToImport.insert(&F);
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
llvm::TimeTraceScope globalsScope("Globals");
|
||||
for (GlobalVariable &GV : SrcModule->globals()) {
|
||||
if (!GV.hasName())
|
||||
continue;
|
||||
auto GUID = GV.getGUID();
|
||||
auto MaybeImportType = ImportList.getImportType(ModName, GUID);
|
||||
bool ImportDefinition =
|
||||
MaybeImportType == GlobalValueSummary::Definition;
|
||||
|
||||
LLVM_DEBUG(dbgs() << (MaybeImportType ? "Is" : "Not")
|
||||
<< " importing global"
|
||||
<< (ImportDefinition
|
||||
? " definition "
|
||||
: (MaybeImportType ? " declaration " : " "))
|
||||
<< GUID << " " << GV.getName() << " from "
|
||||
<< SrcModule->getSourceFileName() << "\n");
|
||||
if (ImportDefinition) {
|
||||
if (Error Err = GV.materialize())
|
||||
return std::move(Err);
|
||||
ImportedGVCount += GlobalsToImport.insert(&GV);
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
llvm::TimeTraceScope aliasesScope("Aliases");
|
||||
for (GlobalAlias &GA : SrcModule->aliases()) {
|
||||
if (!GA.hasName() || isa<GlobalIFunc>(GA.getAliaseeObject()))
|
||||
continue;
|
||||
auto GUID = GA.getGUID();
|
||||
auto MaybeImportType = ImportList.getImportType(ModName, GUID);
|
||||
bool ImportDefinition =
|
||||
MaybeImportType == GlobalValueSummary::Definition;
|
||||
|
||||
LLVM_DEBUG(dbgs() << (MaybeImportType ? "Is" : "Not")
|
||||
<< " importing alias"
|
||||
<< (ImportDefinition
|
||||
? " definition "
|
||||
: (MaybeImportType ? " declaration " : " "))
|
||||
<< GUID << " " << GA.getName() << " from "
|
||||
<< SrcModule->getSourceFileName() << "\n");
|
||||
if (ImportDefinition) {
|
||||
if (Error Err = GA.materialize())
|
||||
return std::move(Err);
|
||||
// Import alias as a copy of its aliasee.
|
||||
GlobalObject *GO = GA.getAliaseeObject();
|
||||
if (Error Err = GO->materialize())
|
||||
return std::move(Err);
|
||||
auto *Fn = replaceAliasWithAliasee(SrcModule.get(), &GA);
|
||||
LLVM_DEBUG(dbgs() << "Is importing aliasee fn " << GO->getGUID()
|
||||
<< " " << GO->getName() << " from "
|
||||
<< SrcModule->getSourceFileName() << "\n");
|
||||
if (EnableImportMetadata || EnableMemProfContextDisambiguation) {
|
||||
// Add 'thinlto_src_module' and 'thinlto_src_file' metadata for
|
||||
// statistics and debugging.
|
||||
Fn->setMetadata(
|
||||
"thinlto_src_module",
|
||||
MDNode::get(DestModule.getContext(),
|
||||
{MDString::get(DestModule.getContext(),
|
||||
SrcModule->getModuleIdentifier())}));
|
||||
Fn->setMetadata(
|
||||
"thinlto_src_file",
|
||||
MDNode::get(DestModule.getContext(),
|
||||
{MDString::get(DestModule.getContext(),
|
||||
SrcModule->getSourceFileName())}));
|
||||
}
|
||||
GlobalsToImport.insert(Fn);
|
||||
}
|
||||
GlobalsToImport.insert(Fn);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -90,6 +90,7 @@
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/GlobPattern.h"
|
||||
#include "llvm/Support/TimeProfiler.h"
|
||||
#include "llvm/TargetParser/Triple.h"
|
||||
#include "llvm/Transforms/IPO.h"
|
||||
#include "llvm/Transforms/IPO/FunctionAttrs.h"
|
||||
@ -869,6 +870,7 @@ void llvm::updateVCallVisibilityInModule(
|
||||
|
||||
void llvm::updatePublicTypeTestCalls(Module &M,
|
||||
bool WholeProgramVisibilityEnabledInLTO) {
|
||||
llvm::TimeTraceScope timeScope("Update public type test calls");
|
||||
Function *PublicTypeTestFunc =
|
||||
Intrinsic::getDeclarationIfExists(&M, Intrinsic::public_type_test);
|
||||
if (!PublicTypeTestFunc)
|
||||
|
||||
@ -13,6 +13,8 @@
|
||||
|
||||
#include "llvm/Transforms/Utils/FunctionImportUtils.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/TimeProfiler.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
/// Uses the "source_filename" instead of a Module hash ID for the suffix of
|
||||
@ -370,6 +372,7 @@ void FunctionImportGlobalProcessing::run() { processGlobalsForThinLTO(); }
|
||||
void llvm::renameModuleForThinLTO(Module &M, const ModuleSummaryIndex &Index,
|
||||
bool ClearDSOLocalOnDeclarations,
|
||||
SetVector<GlobalValue *> *GlobalsToImport) {
|
||||
llvm::TimeTraceScope timeScope("Rename module for ThinLTO");
|
||||
FunctionImportGlobalProcessing ThinLTOProcessing(M, Index, GlobalsToImport,
|
||||
ClearDSOLocalOnDeclarations);
|
||||
ThinLTOProcessing.run();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user