[lld-macho] Add more TimeTraceScopes
I added just enough to allow us to see a top-level breakdown of time taken. This
is the result of loading the time-trace output into `chrome:://tracing`:
https://gist.githubusercontent.com/int3/236c723cbb4b6fa3b2d340bb6395c797/raw/ef5e8234f3fdf609bf93b50f54f4e0d9bd439403/tracing.png
Reviewed By: oontvoo
Differential Revision: https://reviews.llvm.org/D99311
GitOrigin-RevId: 4bcaafeb0e82ca268d9038e106339d4d92e98eec
diff --git a/MachO/Config.h b/MachO/Config.h
index 6114401..60c20a3 100644
--- a/MachO/Config.h
+++ b/MachO/Config.h
@@ -85,7 +85,7 @@
uint32_t headerPad;
uint32_t dylibCompatibilityVersion = 0;
uint32_t dylibCurrentVersion = 0;
- uint32_t timeTraceGranularity;
+ uint32_t timeTraceGranularity = 0;
std::string progName;
llvm::StringRef installName;
llvm::StringRef mapFile;
diff --git a/MachO/Driver.cpp b/MachO/Driver.cpp
index 392adef..57ff369 100644
--- a/MachO/Driver.cpp
+++ b/MachO/Driver.cpp
@@ -496,6 +496,7 @@
}
static void compileBitcodeFiles() {
+ TimeTraceScope timeScope("LTO");
auto *lto = make<BitcodeCompiler>();
for (InputFile *file : inputFiles)
if (auto *bitcodeFile = dyn_cast<BitcodeFile>(file))
@@ -510,6 +511,7 @@
// all InputFiles have been loaded.) As a result, later operations won't see
// any CommonSymbols.
static void replaceCommonSymbols() {
+ TimeTraceScope timeScope("Replace common symbols");
for (macho::Symbol *sym : symtab->getSymbols()) {
auto *common = dyn_cast<CommonSymbol>(sym);
if (common == nullptr)
@@ -772,6 +774,44 @@
}
}
+void createFiles(const InputArgList &args) {
+ TimeTraceScope timeScope("Load input files");
+ // This loop should be reserved for options whose exact ordering matters.
+ // Other options should be handled via filtered() and/or getLastArg().
+ for (const Arg *arg : args) {
+ const Option &opt = arg->getOption();
+ warnIfDeprecatedOption(opt);
+ warnIfUnimplementedOption(opt);
+
+ switch (opt.getID()) {
+ case OPT_INPUT:
+ addFile(arg->getValue(), false);
+ break;
+ case OPT_weak_library:
+ if (auto *dylibFile =
+ dyn_cast_or_null<DylibFile>(addFile(arg->getValue(), false)))
+ dylibFile->forceWeakImport = true;
+ break;
+ case OPT_filelist:
+ addFileList(arg->getValue());
+ break;
+ case OPT_force_load:
+ addFile(arg->getValue(), true);
+ break;
+ case OPT_l:
+ case OPT_weak_l:
+ addLibrary(arg->getValue(), opt.getID() == OPT_weak_l);
+ break;
+ case OPT_framework:
+ case OPT_weak_framework:
+ addFramework(arg->getValue(), opt.getID() == OPT_weak_framework);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
bool macho::link(ArrayRef<const char *> argsArr, bool canExitEarly,
raw_ostream &stdoutOS, raw_ostream &stderrOS) {
lld::stdoutOS = &stdoutOS;
@@ -952,44 +992,10 @@
timeTraceProfilerInitialize(config->timeTraceGranularity, config->progName);
{
- llvm::TimeTraceScope timeScope("Link", StringRef("ExecuteLinker"));
+ TimeTraceScope timeScope("Link", StringRef("ExecuteLinker"));
initLLVM(); // must be run before any call to addFile()
-
- // This loop should be reserved for options whose exact ordering matters.
- // Other options should be handled via filtered() and/or getLastArg().
- for (const Arg *arg : args) {
- const Option &opt = arg->getOption();
- warnIfDeprecatedOption(opt);
- warnIfUnimplementedOption(opt);
-
- switch (opt.getID()) {
- case OPT_INPUT:
- addFile(arg->getValue(), false);
- break;
- case OPT_weak_library:
- if (auto *dylibFile =
- dyn_cast_or_null<DylibFile>(addFile(arg->getValue(), false)))
- dylibFile->forceWeakImport = true;
- break;
- case OPT_filelist:
- addFileList(arg->getValue());
- break;
- case OPT_force_load:
- addFile(arg->getValue(), true);
- break;
- case OPT_l:
- case OPT_weak_l:
- addLibrary(arg->getValue(), opt.getID() == OPT_weak_l);
- break;
- case OPT_framework:
- case OPT_weak_framework:
- addFramework(arg->getValue(), opt.getID() == OPT_weak_framework);
- break;
- default:
- break;
- }
- }
+ createFiles(args);
config->isPic = config->outputType == MH_DYLIB ||
config->outputType == MH_BUNDLE || isPie(args);
@@ -1060,12 +1066,15 @@
inputFiles.insert(make<OpaqueFile>(*buffer, segName, sectName));
}
- // Initialize InputSections.
- for (const InputFile *file : inputFiles) {
- for (const SubsectionMap &map : file->subsections) {
- for (const auto &p : map) {
- InputSection *isec = p.second;
- inputSections.push_back(isec);
+ {
+ TimeTraceScope timeScope("Gathering input sections");
+ // Gather all InputSections into one vector.
+ for (const InputFile *file : inputFiles) {
+ for (const SubsectionMap &map : file->subsections) {
+ for (const auto &p : map) {
+ InputSection *isec = p.second;
+ inputSections.push_back(isec);
+ }
}
}
}
diff --git a/MachO/MapFile.cpp b/MachO/MapFile.cpp
index e089136..a10516f 100644
--- a/MachO/MapFile.cpp
+++ b/MachO/MapFile.cpp
@@ -33,6 +33,7 @@
#include "Symbols.h"
#include "Target.h"
#include "llvm/Support/Parallel.h"
+#include "llvm/Support/TimeProfiler.h"
using namespace llvm;
using namespace llvm::sys;
@@ -93,6 +94,8 @@
if (config->mapFile.empty())
return;
+ TimeTraceScope timeScope("Write map file");
+
// Open a map file for writing.
std::error_code ec;
raw_fd_ostream os(config->mapFile, ec, sys::fs::OF_None);
diff --git a/MachO/Writer.cpp b/MachO/Writer.cpp
index 4070a20..9a28ade 100644
--- a/MachO/Writer.cpp
+++ b/MachO/Writer.cpp
@@ -27,6 +27,7 @@
#include "llvm/Support/LEB128.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/TimeProfiler.h"
#include "llvm/Support/xxhash.h"
#include <algorithm>
@@ -56,6 +57,7 @@
void writeSections();
void writeUuid();
void writeCodeSignature();
+ void writeOutputFile();
void run();
@@ -502,6 +504,7 @@
}
void Writer::scanRelocations() {
+ TimeTraceScope timeScope("Scan relocations");
for (InputSection *isec : inputSections) {
if (isec->segname == segment_names::ld) {
prepareCompactUnwind(isec);
@@ -534,6 +537,7 @@
}
void Writer::scanSymbols() {
+ TimeTraceScope timeScope("Scan symbols");
for (const macho::Symbol *sym : symtab->getSymbols()) {
if (const auto *defined = dyn_cast<Defined>(sym)) {
if (defined->overridesWeakDef)
@@ -737,6 +741,8 @@
// segments, output sections within each segment, and input sections within each
// output segment.
static void sortSegmentsAndSections() {
+ TimeTraceScope timeScope("Sort segments and sections");
+
llvm::stable_sort(outputSegments,
compareByOrder<OutputSegment *>(segmentOrder));
@@ -777,6 +783,7 @@
}
void Writer::createOutputSections() {
+ TimeTraceScope timeScope("Create output sections");
// First, create hidden sections
stringTableSection = make<StringTableSection>();
unwindInfoSection = make<UnwindInfoSection>(); // TODO(gkm): only when no -r
@@ -834,6 +841,7 @@
}
void Writer::finalizeAddressses() {
+ TimeTraceScope timeScope("Finalize addresses");
// Ensure that segments (and the sections they contain) are allocated
// addresses in ascending order, which dyld requires.
//
@@ -848,6 +856,7 @@
}
void Writer::finalizeLinkEditSegment() {
+ TimeTraceScope timeScope("Finalize __LINKEDIT segment");
// Fill __LINKEDIT contents.
in.rebase->finalizeContents();
in.binding->finalizeContents();
@@ -904,6 +913,7 @@
}
void Writer::writeUuid() {
+ TimeTraceScope timeScope("Computing UUID");
uint64_t digest =
xxHash64({buffer->getBufferStart(), buffer->getBufferEnd()});
uuidCommand->writeUuid(digest);
@@ -914,6 +924,19 @@
codeSignatureSection->writeHashes(buffer->getBufferStart());
}
+void Writer::writeOutputFile() {
+ TimeTraceScope timeScope("Write output file");
+ openFile();
+ if (errorCount())
+ return;
+ writeSections();
+ writeUuid();
+ writeCodeSignature();
+
+ if (auto e = buffer->commit())
+ error("failed to write to the output file: " + toString(std::move(e)));
+}
+
void Writer::run() {
prepareBranchTarget(config->entry);
scanRelocations();
@@ -927,15 +950,7 @@
finalizeAddressses();
finalizeLinkEditSegment();
writeMapFile();
- openFile();
- if (errorCount())
- return;
- writeSections();
- writeUuid();
- writeCodeSignature();
-
- if (auto e = buffer->commit())
- error("failed to write to the output file: " + toString(std::move(e)));
+ writeOutputFile();
}
void macho::writeResult() { Writer().run(); }