[lld] [llvm] [LLD][COFF] Add more `--time-trace` tags for ThinLTO linking (PR #156471)
Alexandre Ganea via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 3 05:52:22 PDT 2025
https://github.com/aganea updated https://github.com/llvm/llvm-project/pull/156471
>From bfb0de66f9c61b6eb992c4a3284d9c0799718efd Mon Sep 17 00:00:00 2001
From: Alexandre Ganea <aganea at havenstudios.com>
Date: Mon, 1 Sep 2025 18:47:49 -0400
Subject: [PATCH 1/2] [LLD][COFF] Add more `--time-trace` tags for ThinLTO
linking
---
lld/COFF/SymbolTable.cpp | 8 +-
llvm/lib/Bitcode/Reader/MetadataLoader.cpp | 2 +
llvm/lib/IR/AutoUpgrade.cpp | 2 +
llvm/lib/IR/DebugInfo.cpp | 2 +
llvm/lib/IR/Module.cpp | 2 +
llvm/lib/IR/Verifier.cpp | 12 +-
llvm/lib/LTO/LTO.cpp | 45 ++--
llvm/lib/LTO/LTOBackend.cpp | 17 +-
llvm/lib/Transforms/IPO/FunctionImport.cpp | 195 ++++++++++--------
.../lib/Transforms/IPO/WholeProgramDevirt.cpp | 2 +
.../Transforms/Utils/FunctionImportUtils.cpp | 3 +
11 files changed, 172 insertions(+), 118 deletions(-)
diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp
index 0a88807c00dd5..335f3d65a078f 100644
--- a/lld/COFF/SymbolTable.cpp
+++ b/lld/COFF/SymbolTable.cpp
@@ -1440,8 +1440,12 @@ void SymbolTable::compileBitcodeFiles() {
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);
+ }
+ llvm::TimeTraceScope compileScope("LTO compile");
for (InputFile *newObj : lto->compile()) {
ObjFile *obj = cast<ObjFile>(newObj);
obj->parse();
diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
index 738e47b8b16c4..a5cedadd30981 100644
--- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
+++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
@@ -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");
diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp
index 7ea9c6dff13b8..8034b3ffe273e 100644
--- a/llvm/lib/IR/AutoUpgrade.cpp
+++ b/llvm/lib/IR/AutoUpgrade.cpp
@@ -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.
diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp
index b468d929b0280..166521a276643 100644
--- a/llvm/lib/IR/DebugInfo.cpp
+++ b/llvm/lib/IR/DebugInfo.cpp
@@ -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())) {
diff --git a/llvm/lib/IR/Module.cpp b/llvm/lib/IR/Module.cpp
index 70d364176062f..30b5e48652b28 100644
--- a/llvm/lib/IR/Module.cpp
+++ b/llvm/lib/IR/Module.cpp
@@ -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();
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index da05ff166122f..52f41747f8b9b 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -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 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
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!");
@@ -408,8 +410,10 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
// out-of-date dominator tree and makes it significantly more complex to run
// this code outside of a pass manager.
// FIXME: It's really gross that we have to cast away constness here.
- if (!F.empty())
+ if (!F.empty()) {
+ llvm::TimeTraceScope domScope("Dominator Tree Builder");
DT.recalculate(const_cast<Function &>(F));
+ }
for (const BasicBlock &BB : F) {
if (!BB.empty() && BB.back().isTerminator())
@@ -431,7 +435,10 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
Broken = false;
// FIXME: We strip const here because the inst visitor strips const.
- visit(const_cast<Function &>(F));
+ {
+ llvm::TimeTraceScope domScope("Verifier visit");
+ visit(const_cast<Function &>(F));
+ }
verifySiblingFuncletUnwinds();
if (ConvergenceVerifyHelper.sawTokens())
@@ -2832,6 +2839,7 @@ static Instruction *getSuccPad(Instruction *Terminator) {
}
void Verifier::verifySiblingFuncletUnwinds() {
+ llvm::TimeTraceScope domScope("Verifier verify sibling funclet unwinds");
SmallPtrSet<Instruction *, 8> Visited;
SmallPtrSet<Instruction *, 8> Active;
for (const auto &Pair : SiblingFuncletInfo) {
diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp
index 35d24c17bbd93..424c6e251fb8c 100644
--- a/llvm/lib/LTO/LTO.cpp
+++ b/llvm/lib/LTO/LTO.cpp
@@ -631,6 +631,7 @@ LTO::~LTO() = default;
void LTO::addModuleToGlobalRes(ArrayRef<InputFile::Symbol> Syms,
ArrayRef<SymbolResolution> Res,
unsigned Partition, bool InSummary) {
+ llvm::TimeTraceScope importScope("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 importScope("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 importScope("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 importScope("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 importScope("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 importScope("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 importScope("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 @@ class InProcessThinBackend : public CGThinBackend {
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 @@ class InProcessThinBackend : public CGThinBackend {
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 @@ class FirstRoundThinBackend : public InProcessThinBackend {
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 @@ class FirstRoundThinBackend : public InProcessThinBackend {
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 @@ class SecondRoundThinBackend : public InProcessThinBackend {
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 @@ class SecondRoundThinBackend : public InProcessThinBackend {
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,13 +1927,9 @@ 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(""));
- auto TimeTraceScopeExit = llvm::make_scope_exit([]() {
- if (llvm::timeTraceProfilerEnabled())
- llvm::timeTraceProfilerEnd();
- });
if (ThinLTO.ModuleMap.empty())
return Error::success();
@@ -2069,11 +2077,6 @@ Error LTO::runThinLTO(AddStreamFn AddStream, FileCache Cache,
generateParamAccessSummary(ThinLTO.CombinedIndex);
- if (llvm::timeTraceProfilerEnabled())
- llvm::timeTraceProfilerEnd();
-
- TimeTraceScopeExit.release();
-
auto &ModuleMap =
ThinLTO.ModulesToCompile ? *ThinLTO.ModulesToCompile : ThinLTO.ModuleMap;
diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp
index 5e8cd12fe040b..402e4a5c6a8bd 100644
--- a/llvm/lib/LTO/LTOBackend.cpp
+++ b/llvm/lib/LTO/LTOBackend.cpp
@@ -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 importScope("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);
diff --git a/llvm/lib/Transforms/IPO/FunctionImport.cpp b/llvm/lib/Transforms/IPO/FunctionImport.cpp
index 7bcb20de46ff6..96b274e2f45a9 100644
--- a/llvm/lib/Transforms/IPO/FunctionImport.cpp
+++ b/llvm/lib/Transforms/IPO/FunctionImport.cpp
@@ -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("Dead symbols");
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_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())}));
+ {
+ llvm::TimeTraceScope findGlobalsScope("Find globals");
+ 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);
}
- 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);
+ {
+ 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);
+ }
}
}
- 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::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 (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 = 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);
}
}
diff --git a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
index cb98ed838f5d7..402eeea0402f8 100644
--- a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
+++ b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
@@ -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 importScope("Update public type test calls");
Function *PublicTypeTestFunc =
Intrinsic::getDeclarationIfExists(&M, Intrinsic::public_type_test);
if (!PublicTypeTestFunc)
diff --git a/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp b/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp
index 3bbe875bbe9e5..1a9e16be6989e 100644
--- a/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp
+++ b/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp
@@ -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();
>From 076d4756f9b9e7d76e88068f53dd683edebd41ea Mon Sep 17 00:00:00 2001
From: Alexandre Ganea <aganea at havenstudios.com>
Date: Wed, 3 Sep 2025 08:51:53 -0400
Subject: [PATCH 2/2] Remove some unneeded tags
---
llvm/lib/IR/Verifier.cpp | 11 +++--------
1 file changed, 3 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 52f41747f8b9b..4729b36b94ab8 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -410,10 +410,8 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
// out-of-date dominator tree and makes it significantly more complex to run
// this code outside of a pass manager.
// FIXME: It's really gross that we have to cast away constness here.
- if (!F.empty()) {
- llvm::TimeTraceScope domScope("Dominator Tree Builder");
+ if (!F.empty())
DT.recalculate(const_cast<Function &>(F));
- }
for (const BasicBlock &BB : F) {
if (!BB.empty() && BB.back().isTerminator())
@@ -435,10 +433,7 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
Broken = false;
// FIXME: We strip const here because the inst visitor strips const.
- {
- llvm::TimeTraceScope domScope("Verifier visit");
- visit(const_cast<Function &>(F));
- }
+ visit(const_cast<Function &>(F));
verifySiblingFuncletUnwinds();
if (ConvergenceVerifyHelper.sawTokens())
@@ -2839,7 +2834,7 @@ static Instruction *getSuccPad(Instruction *Terminator) {
}
void Verifier::verifySiblingFuncletUnwinds() {
- llvm::TimeTraceScope domScope("Verifier verify sibling funclet unwinds");
+ llvm::TimeTraceScope timeTraceScope("Verifier verify sibling funclet unwinds");
SmallPtrSet<Instruction *, 8> Visited;
SmallPtrSet<Instruction *, 8> Active;
for (const auto &Pair : SiblingFuncletInfo) {
More information about the llvm-commits
mailing list