[lld] af5ca40 - temporary
Rui Ueyama via llvm-commits
llvm-commits at lists.llvm.org
Thu Dec 12 22:17:03 PST 2019
Apologies, this is committed by accident. I'll roll this change back.
On Fri, Dec 13, 2019 at 3:16 PM Rui Ueyama via llvm-commits <
llvm-commits at lists.llvm.org> wrote:
>
> Author: Rui Ueyama
> Date: 2019-12-13T14:35:03+09:00
> New Revision: af5ca40b47b3e85c3add81ccdc0b787c4bc355ae
>
> URL:
> https://github.com/llvm/llvm-project/commit/af5ca40b47b3e85c3add81ccdc0b787c4bc355ae
> DIFF:
> https://github.com/llvm/llvm-project/commit/af5ca40b47b3e85c3add81ccdc0b787c4bc355ae.diff
>
> LOG: temporary
>
> Added:
> lld/test/ELF/check-time-trace.s
> lld/test/ELF/lto/thinlto-time-trace.ll
>
> Modified:
> lld/ELF/Config.h
> lld/ELF/Driver.cpp
> lld/ELF/ICF.cpp
> lld/ELF/LTO.cpp
> lld/ELF/MarkLive.cpp
> lld/ELF/Options.td
> lld/ELF/SyntheticSections.cpp
> lld/ELF/Writer.cpp
> llvm/include/llvm/LTO/Config.h
> llvm/lib/LTO/LTO.cpp
>
> Removed:
>
>
>
>
> ################################################################################
> diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
> index d7e715ebf357..6d804ee2bbe6 100644
> --- a/lld/ELF/Config.h
> +++ b/lld/ELF/Config.h
> @@ -191,6 +191,7 @@ struct Configuration {
> bool trace;
> bool thinLTOEmitImportsFiles;
> bool thinLTOIndexOnly;
> + bool timeTraceEnabled;
> bool tocOptimize;
> bool undefinedVersion;
> bool useAndroidRelrTags = false;
> @@ -240,6 +241,7 @@ struct Configuration {
> unsigned ltoo;
> unsigned optimize;
> unsigned thinLTOJobs;
> + unsigned timeTraceGranularity;
> int32_t splitStackAdjustSize;
>
> // The following config options do not directly correspond to any
>
> diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
> index c721e872e12e..cc4cefc6ed97 100644
> --- a/lld/ELF/Driver.cpp
> +++ b/lld/ELF/Driver.cpp
> @@ -56,6 +56,7 @@
> #include "llvm/Support/Path.h"
> #include "llvm/Support/TarWriter.h"
> #include "llvm/Support/TargetSelect.h"
> +#include "llvm/Support/TimeProfiler.h"
> #include "llvm/Support/raw_ostream.h"
> #include <cstdlib>
> #include <utility>
> @@ -490,6 +491,10 @@ void LinkerDriver::main(ArrayRef<const char *>
> argsArr) {
> if (args.hasArg(OPT_version))
> return;
>
> + // Initialize time trace.
> + if (config->timeTraceEnabled)
> + timeTraceProfilerInitialize(config->timeTraceGranularity,
> config->progName);
> +
> initLLVM();
> createFiles(args);
> if (errorCount())
> @@ -509,19 +514,34 @@ void LinkerDriver::main(ArrayRef<const char *>
> argsArr) {
> switch (config->ekind) {
> case ELF32LEKind:
> link<ELF32LE>(args);
> - return;
> + break;
> case ELF32BEKind:
> link<ELF32BE>(args);
> - return;
> + break;
> case ELF64LEKind:
> link<ELF64LE>(args);
> - return;
> + break;
> case ELF64BEKind:
> link<ELF64BE>(args);
> - return;
> + break;
> default:
> llvm_unreachable("unknown Config->EKind");
> }
> +
> + if (config->timeTraceEnabled) {
> + std::string path = args.getLastArgValue(OPT_time_trace_file_eq);
> + if (path.empty())
> + path = (config->outputFile + ".time-trace").str();
> +
> + std::error_code ec;
> + raw_fd_ostream os(path, errorCode, sys::fs::F_Text);
> + if (ec) {
> + error("cannot open " + path + ": " + ec.message());
> + return;
> + }
> + timeTraceProfilerWrite(os);
> + timeTraceProfilerCleanup();
> + }
> }
>
> static std::string getRpath(opt::InputArgList &args) {
> @@ -953,6 +973,9 @@ static void readConfigs(opt::InputArgList &args) {
> getOldNewOptions(args, OPT_thinlto_object_suffix_replace_eq);
> config->thinLTOPrefixReplace =
> getOldNewOptions(args, OPT_thinlto_prefix_replace_eq);
> + config->timeTraceEnabled = args.hasArg(OPT_time_trace);
> + config->timeTraceGranularity =
> + args::getInteger(args, OPT_time_trace_granularity, 500);
> config->trace = args.hasArg(OPT_trace);
> config->undefined = args::getStrings(args, OPT_undefined);
> config->undefinedVersion =
> @@ -1597,6 +1620,7 @@ static Symbol *addUndefined(StringRef name) {
> // Because all bitcode files that the program consists of are passed to
> // the compiler at once, it can do a whole-program optimization.
> template <class ELFT> void LinkerDriver::compileBitcodeFiles() {
> + llvm::TimeTraceScope timeScope("LTO");
> // Compile bitcode files and replace bitcode symbols.
> lto.reset(new BitcodeCompiler);
> for (BitcodeFile *file : bitcodeFiles)
> @@ -1723,6 +1747,8 @@ template <class ELFT> static uint32_t
> getAndFeatures() {
> // Do actual linking. Note that when this function is called,
> // all linker scripts have already been parsed.
> template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
> + llvm::TimeTraceScope timeScope("ExecuteLinker");
> +
> // If a -hash-style option was not given, set to a default value,
> // which varies depending on the target.
> if (!args.hasArg(OPT_hash_style)) {
> @@ -1762,8 +1788,11 @@ template <class ELFT> void
> LinkerDriver::link(opt::InputArgList &args) {
> // symbols that we need to the symbol table. This process might
> // add files to the link, via autolinking, these files are always
> // appended to the Files vector.
> - for (size_t i = 0; i < files.size(); ++i)
> - parseFile(files[i]);
> + {
> + llvm::TimeTraceScope timeScope("Parse input files");
> + for (size_t i = 0; i < files.size(); ++i)
> + parseFile(files[i]);
> + }
>
> // Now that we have every file, we can decide if we will need a
> // dynamic symbol table.
> @@ -1981,11 +2010,15 @@ template <class ELFT> void
> LinkerDriver::link(opt::InputArgList &args) {
> // merging MergeInputSections into a single MergeSyntheticSection. From
> this
> // point onwards InputSectionDescription::sections should be used
> instead of
> // sectionBases.
> - for (BaseCommand *base : script->sectionCommands)
> - if (auto *sec = dyn_cast<OutputSection>(base))
> - sec->finalizeInputSections();
> - llvm::erase_if(inputSections,
> - [](InputSectionBase *s) { return
> isa<MergeInputSection>(s); });
> + {
> + llvm::TimeTraceScope timeScope("Merge input sections");
> + for (BaseCommand *base : script->sectionCommands)
> + if (auto *sec = dyn_cast<OutputSection>(base))
> + sec->finalizeInputSections();
> + llvm::erase_if(inputSections, [](InputSectionBase *s) {
> + return isa<MergeInputSection>(s);
> + });
> + }
>
> // Two input sections with
> diff erent output sections should not be folded.
> // ICF runs after processSectionCommands() so that we know the output
> sections.
>
> diff --git a/lld/ELF/ICF.cpp b/lld/ELF/ICF.cpp
> index 5e38066f45ba..7838a45557cc 100644
> --- a/lld/ELF/ICF.cpp
> +++ b/lld/ELF/ICF.cpp
> @@ -84,6 +84,7 @@
> #include "llvm/ADT/StringExtras.h"
> #include "llvm/BinaryFormat/ELF.h"
> #include "llvm/Object/ELF.h"
> +#include "llvm/Support/TimeProfiler.h"
> #include "llvm/Support/xxhash.h"
> #include <algorithm>
> #include <atomic>
> @@ -452,6 +453,7 @@ static void print(const Twine &s) {
>
> // The main function of ICF.
> template <class ELFT> void ICF<ELFT>::run() {
> + llvm::TimeTraceScope timeScope("ICF");
> // Compute isPreemptible early. We may add more symbols later, so this
> loop
> // cannot be merged with the later computeIsPreemptible() pass which is
> used
> // by scanRelocations().
>
> diff --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp
> index 524d552b0b84..3f677d86f13a 100644
> --- a/lld/ELF/LTO.cpp
> +++ b/lld/ELF/LTO.cpp
> @@ -108,6 +108,9 @@ static lto::Config createConfig() {
> c.DebugPassManager = config->ltoDebugPassManager;
> c.DwoDir = config->dwoDir;
>
> + c.TimeTraceEnabled = config->timeTraceEnabled;
> + c.TimeTraceGranularity = config->timeTraceGranularity;
> +
> c.CSIRProfile = config->ltoCSProfileFile;
> c.RunCSIRInstr = config->ltoCSProfileGenerate;
>
>
> diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp
> index bb0105c28928..b77fab9abb62 100644
> --- a/lld/ELF/MarkLive.cpp
> +++ b/lld/ELF/MarkLive.cpp
> @@ -31,6 +31,7 @@
> #include "lld/Common/Strings.h"
> #include "llvm/ADT/STLExtras.h"
> #include "llvm/Object/ELF.h"
> +#include "llvm/Support/TimeProfiler.h"
> #include <functional>
> #include <vector>
>
> @@ -323,6 +324,7 @@ template <class ELFT> void
> MarkLive<ELFT>::moveToMain() {
> // input sections. This function make some or all of them on
> // so that they are emitted to the output file.
> template <class ELFT> void markLive() {
> + llvm::TimeTraceScope timeScope("GC");
> // If -gc-sections is not given, no sections are removed.
> if (!config->gcSections) {
> for (InputSectionBase *sec : inputSections)
>
> diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
> index b86a670915c1..3ee1d17b31df 100644
> --- a/lld/ELF/Options.td
> +++ b/lld/ELF/Options.td
> @@ -358,6 +358,12 @@ defm threads: B<"threads",
> "Run the linker multi-threaded (default)",
> "Do not run the linker multi-threaded">;
>
> +def time_trace: F<"time-trace">, HelpText<"Record time trace">;
> +def time_trace_file_eq: J<"time-trace-file=">, HelpText<"Specify time
> trace output file">;
> +
> +defm time_trace_granularity: Eq<"time-trace-granularity",
> + "Minimum time granularity (in microseconds) traced by time profiler">;
> +
> defm toc_optimize : B<"toc-optimize",
> "(PowerPC64) Enable TOC related optimizations (default)",
> "(PowerPC64) Disable TOC related optimizations">;
>
> diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
> index d014da220817..e765d2a9465b 100644
> --- a/lld/ELF/SyntheticSections.cpp
> +++ b/lld/ELF/SyntheticSections.cpp
> @@ -36,6 +36,7 @@
> #include "llvm/Support/Endian.h"
> #include "llvm/Support/LEB128.h"
> #include "llvm/Support/MD5.h"
> +#include "llvm/Support/TimeProfiler.h"
> #include <cstdlib>
> #include <thread>
>
> @@ -3132,6 +3133,7 @@ MergeSyntheticSection
> *createMergeSynthetic(StringRef name, uint32_t type,
> }
>
> template <class ELFT> void splitSections() {
> + llvm::TimeTraceScope timeScope("Split sections");
> // splitIntoPieces needs to be called on each MergeInputSection
> // before calling finalizeContents().
> parallelForEach(inputSections, [](InputSectionBase *sec) {
>
> diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
> index 38009bdd9aa3..67fd2b9a8c53 100644
> --- a/lld/ELF/Writer.cpp
> +++ b/lld/ELF/Writer.cpp
> @@ -27,6 +27,7 @@
> #include "llvm/ADT/StringSwitch.h"
> #include "llvm/Support/RandomNumberGenerator.h"
> #include "llvm/Support/SHA1.h"
> +#include "llvm/Support/TimeProfiler.h"
> #include "llvm/Support/xxhash.h"
> #include <climits>
>
> @@ -139,7 +140,10 @@ static bool needsInterpSection() {
> script->needsInterpSection();
> }
>
> -template <class ELFT> void writeResult() { Writer<ELFT>().run(); }
> +template <class ELFT> void writeResult() {
> + llvm::TimeTraceScope timeScope("Write output file");
> + Writer<ELFT>().run();
> +}
>
> static void removeEmptyPTLoad(std::vector<PhdrEntry *> &phdrs) {
> llvm::erase_if(phdrs, [&](const PhdrEntry *p) {
>
> diff --git a/lld/test/ELF/check-time-trace.s
> b/lld/test/ELF/check-time-trace.s
> new file mode 100644
> index 000000000000..8144b2abefb5
> --- /dev/null
> +++ b/lld/test/ELF/check-time-trace.s
> @@ -0,0 +1,39 @@
> +# REQUIRES: x86
> +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
> +
> +# Test implicit trace file name
> +# RUN: ld.lld -time-trace -time-trace-granularity=0 -o %t1.elf %t.o
> +# RUN: cat %t1.elf.time-trace \
> +# RUN: | %python -c 'import json, sys;
> json.dump(json.loads(sys.stdin.read()), sys.stdout, sort_keys=True,
> indent=2)' \
> +# RUN: | FileCheck %s
> +
> +# Test specified trace file name
> +# RUN: ld.lld -time-trace -time-trace-file=%t2.json
> -time-trace-granularity=0 -o %t2.elf %t.o
> +# RUN: cat %t2.json \
> +# RUN: | %python -c 'import json, sys;
> json.dump(json.loads(sys.stdin.read()), sys.stdout, sort_keys=True,
> indent=2)' \
> +# RUN: | FileCheck %s
> +
> +# Test trace requested to stdout
> +# RUN: ld.lld -time-trace -time-trace-file=- -time-trace-granularity=0 -o
> %t3.elf %t.o \
> +# RUN: | %python -c 'import json, sys;
> json.dump(json.loads(sys.stdin.read()), sys.stdout, sort_keys=True,
> indent=2)' \
> +# RUN: | FileCheck %s
> +
> +# CHECK: "traceEvents": [
> +# Check one event has correct fields
> +# CHECK: "dur":
> +# CHECK-NEXT: "name":
> +# CHECK-NEXT: "ph":
> +# CHECK-NEXT: "pid":
> +# CHECK-NEXT: "tid":
> +# CHECK-NEXT: "ts":
> +
> +# Check there is an ExecuteLinker event
> +# CHECK: "name": "ExecuteLinker"
> +
> +# Check process_name entry field
> +# CHECK: "name": "ld.lld{{(.exe)?}}"
> +# CHECK: "name": "process_name"
> +
> +.globl _start
> +_start:
> + ret
>
> diff --git a/lld/test/ELF/lto/thinlto-time-trace.ll
> b/lld/test/ELF/lto/thinlto-time-trace.ll
> new file mode 100644
> index 000000000000..1b8335cbb9a9
> --- /dev/null
> +++ b/lld/test/ELF/lto/thinlto-time-trace.ll
> @@ -0,0 +1,43 @@
> +; REQUIRES: x86
> +
> +; Test ThinLTO with time trace
> +; RUN: opt -module-summary %s -o %t1.o
> +; RUN: opt -module-summary %p/Inputs/thinlto.ll -o %t2.o
> +
> +; Test single-threaded
> +; RUN: ld.lld --thinlto-jobs=1 -time-trace -time-trace-granularity=0
> -shared %t1.o %t2.o -o %t3.so
> +; RUN: cat %t3.so.time-trace \
> +; RUN: | %python -c 'import json, sys;
> json.dump(json.loads(sys.stdin.read()), sys.stdout, sort_keys=True,
> indent=2)' \
> +; RUN: | FileCheck %s
> +
> +; Test multi-threaded
> +; RUN: ld.lld -time-trace -time-trace-granularity=0 -shared %t1.o %t2.o
> -o %t4.so
> +; RUN: cat %t4.so.time-trace \
> +; RUN: | %python -c 'import json, sys;
> json.dump(json.loads(sys.stdin.read()), sys.stdout, sort_keys=True,
> indent=2)' \
> +; RUN: | FileCheck %s
> +
> +; CHECK: "traceEvents": [
> +; Check fields for an event are present
> +; CHECK: "args":
> +; CHECK-NEXT: "detail":
> +; CHECK: "dur":
> +; CHECK-NEXT: "name":
> +; CHECK-NEXT: "ph":
> +; CHECK-NEXT: "pid":
> +; CHECK-NEXT: "tid":
> +; CHECK-NEXT: "ts":
> +
> +; Check that an optimisation event is present
> +; CHECK: "name": "OptModule"
> +
> +target datalayout =
> "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
> +target triple = "x86_64-unknown-linux-gnu"
> +
> +declare void @g(...)
> +
> +define void @f() {
> +entry:
> + call void (...) @g()
> + ret void
> +}
> +
>
> diff --git a/llvm/include/llvm/LTO/Config.h
> b/llvm/include/llvm/LTO/Config.h
> index 754e3126f8a9..6db1235a692c 100644
> --- a/llvm/include/llvm/LTO/Config.h
> +++ b/llvm/include/llvm/LTO/Config.h
> @@ -117,6 +117,12 @@ struct Config {
> /// Statistics output file path.
> std::string StatsFile;
>
> + /// Time trace enabled
> + bool TimeTraceEnabled = false;
> +
> + /// Time trace granularity
> + unsigned TimeTraceGranularity = 500;
> +
> bool ShouldDiscardValueNames = true;
> DiagnosticHandlerFunction DiagHandler;
>
>
> diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp
> index 0d48090e4268..e2c8aa159896 100644
> --- a/llvm/lib/LTO/LTO.cpp
> +++ b/llvm/lib/LTO/LTO.cpp
> @@ -39,6 +39,7 @@
> #include "llvm/Support/TargetRegistry.h"
> #include "llvm/Support/ThreadPool.h"
> #include "llvm/Support/Threading.h"
> +#include "llvm/Support/TimeProfiler.h"
> #include "llvm/Support/VCSRevision.h"
> #include "llvm/Support/raw_ostream.h"
> #include "llvm/Target/TargetMachine.h"
> @@ -1133,6 +1134,9 @@ class InProcessThinBackend : public ThinBackendProc {
> &ResolvedODR,
> const GVSummaryMapTy &DefinedGlobals,
> MapVector<StringRef, BitcodeModule> &ModuleMap) {
> + if (Conf.TimeTraceEnabled)
> + timeTraceProfilerInitialize(Conf.TimeTraceGranularity,
> + "thin backend");
> Error E = runThinLTOBackendThread(
> AddStream, Cache, Task, BM, CombinedIndex, ImportList,
> ExportList,
> ResolvedODR, DefinedGlobals, ModuleMap);
> @@ -1143,6 +1147,8 @@ class InProcessThinBackend : public ThinBackendProc {
> else
> Err = std::move(E);
> }
> + if (timeTraceProfilerEnabled())
> + timeTraceProfilerFinishThread();
> },
> BM, std::ref(CombinedIndex), std::ref(ImportList),
> std::ref(ExportList),
> std::ref(ResolvedODR), std::ref(DefinedGlobals),
> std::ref(ModuleMap));
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20191213/93d506a7/attachment.html>
More information about the llvm-commits
mailing list