From eb4663d8c6add351d758748383f1a9fc231e5e64 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 17 Mar 2020 12:40:19 -0700 Subject: [PATCH] [lld][COFF][ELF][WebAssembly] Replace --[no-]threads /threads[:no] with --threads={1,2,...} /threads:{1,2,...} --no-threads is a name copied from gold. gold has --no-thread, --thread-count and several other --thread-count-*. There are needs to customize the number of threads (running several lld processes concurrently or customizing the number of LTO threads). Having a single --threads=N is a straightforward replacement of gold's --no-threads + --thread-count. --no-threads is used rarely. So just delete --no-threads instead of keeping it for compatibility for a while. If --threads= is specified (ELF,wasm; COFF /threads: is similar), --thinlto-jobs= defaults to --threads=, otherwise all available hardware threads are used. There is currently no way to override a --threads={1,2,...}. It is still a debate whether we should use --threads=all. Reviewed By: rnk, aganea Differential Revision: https://reviews.llvm.org/D76885 --- lld/COFF/Driver.cpp | 12 +++++++++++- lld/COFF/Options.td | 6 +++--- lld/Common/CMakeLists.txt | 1 - lld/Common/Filesystem.cpp | 2 +- lld/Common/Threads.cpp | 11 ----------- lld/ELF/Driver.cpp | 16 ++++++++++++++-- lld/ELF/ICF.cpp | 2 +- lld/ELF/Options.td | 10 ++++++---- lld/ELF/SyntheticSections.cpp | 20 +++++++++----------- lld/docs/ld.lld.1 | 11 ++++++----- lld/include/lld/Common/Threads.h | 8 +++----- lld/test/COFF/pdb-globals.test | 4 ++-- lld/test/ELF/build-id.s | 18 +++++++++--------- lld/test/ELF/lto/thinlto.ll | 12 ++++++++++++ lld/test/ELF/threads.s | 11 +++++++++++ lld/test/wasm/lto/thinlto.ll | 12 ++++++++++++ lld/test/wasm/threads.s | 12 ++++++++++++ lld/wasm/Driver.cpp | 16 ++++++++++++++-- lld/wasm/Options.td | 10 +++++----- llvm/include/llvm/Support/Parallel.h | 6 ++++++ llvm/lib/Support/Parallel.cpp | 8 +++++++- llvm/utils/gn/secondary/lld/Common/BUILD.gn | 1 - 22 files changed, 144 insertions(+), 65 deletions(-) delete mode 100644 lld/Common/Threads.cpp create mode 100644 lld/test/ELF/threads.s create mode 100644 lld/test/wasm/threads.s diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index 7d99f798..931b8cf 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -1144,7 +1144,17 @@ void LinkerDriver::link(ArrayRef argsArr) { return; } - lld::threadsEnabled = args.hasFlag(OPT_threads, OPT_threads_no, true); + // /threads: takes a positive integer and provides the default value for + // /opt:lldltojobs=. + if (auto *arg = args.getLastArg(OPT_threads)) { + StringRef v(arg->getValue()); + unsigned threads = 0; + if (!llvm::to_integer(v, threads, 0) || threads == 0) + error(arg->getSpelling() + ": expected a positive integer, but got '" + + arg->getValue() + "'"); + parallel::strategy = hardware_concurrency(threads); + config->thinLTOJobs = v.str(); + } if (args.hasArg(OPT_show_timing)) config->showTiming = true; diff --git a/lld/COFF/Options.td b/lld/COFF/Options.td index 72fe9ce..f8fe6f9 100644 --- a/lld/COFF/Options.td +++ b/lld/COFF/Options.td @@ -219,9 +219,9 @@ def lto_obj_path : P< "output native object for merged LTO unit to this path">; def dash_dash_version : Flag<["--"], "version">, HelpText<"Print version information">; -defm threads: B<"threads", - "Run the linker multi-threaded (default)", - "Do not run the linker multi-threaded">; +def threads + : P<"threads", "Number of threads. '1' disables multi-threading. By " + "default all available hardware threads are used">; // Flags for debugging def lldmap : F<"lldmap">; diff --git a/lld/Common/CMakeLists.txt b/lld/Common/CMakeLists.txt index 7d5ad65..5364903 100644 --- a/lld/Common/CMakeLists.txt +++ b/lld/Common/CMakeLists.txt @@ -36,7 +36,6 @@ add_lld_library(lldCommon Reproduce.cpp Strings.cpp TargetOptionsCommandFlags.cpp - Threads.cpp Timer.cpp VCSVersion.inc Version.cpp diff --git a/lld/Common/Filesystem.cpp b/lld/Common/Filesystem.cpp index 75e88db..d75c462 100644 --- a/lld/Common/Filesystem.cpp +++ b/lld/Common/Filesystem.cpp @@ -43,7 +43,7 @@ void lld::unlinkAsync(StringRef path) { #if defined(_WIN32) sys::fs::remove(path); #else - if (!threadsEnabled || !sys::fs::exists(path) || + if (parallel::strategy.ThreadsRequested == 1 || !sys::fs::exists(path) || !sys::fs::is_regular_file(path)) return; diff --git a/lld/Common/Threads.cpp b/lld/Common/Threads.cpp deleted file mode 100644 index af04972..0000000 --- a/lld/Common/Threads.cpp +++ /dev/null @@ -1,11 +0,0 @@ -//===- Threads.cpp --------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "lld/Common/Threads.h" - -bool lld::threadsEnabled = true; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 95276cd..c31cbcc 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -860,7 +860,6 @@ static void readConfigs(opt::InputArgList &args) { args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false); errorHandler().vsDiagnostics = args.hasArg(OPT_visual_studio_diagnostics_format, false); - threadsEnabled = args.hasFlag(OPT_threads, OPT_no_threads, true); config->allowMultipleDefinition = args.hasFlag(OPT_allow_multiple_definition, @@ -974,7 +973,6 @@ static void readConfigs(opt::InputArgList &args) { config->thinLTOIndexOnly = args.hasArg(OPT_thinlto_index_only) || args.hasArg(OPT_thinlto_index_only_eq); config->thinLTOIndexOnlyArg = args.getLastArgValue(OPT_thinlto_index_only_eq); - config->thinLTOJobs = args.getLastArgValue(OPT_thinlto_jobs); config->thinLTOObjectSuffixReplace = getOldNewOptions(args, OPT_thinlto_object_suffix_replace_eq); config->thinLTOPrefixReplace = @@ -1036,6 +1034,20 @@ static void readConfigs(opt::InputArgList &args) { for (auto *arg : args.filtered(OPT_mllvm)) parseClangOption(arg->getValue(), arg->getSpelling()); + // --threads= takes a positive integer and provides the default value for + // --thinlto-jobs=. + if (auto *arg = args.getLastArg(OPT_threads)) { + StringRef v(arg->getValue()); + unsigned threads = 0; + if (!llvm::to_integer(v, threads, 0) || threads == 0) + error(arg->getSpelling() + ": expected a positive integer, but got '" + + arg->getValue() + "'"); + parallel::strategy = hardware_concurrency(threads); + config->thinLTOJobs = v; + } + if (auto *arg = args.getLastArg(OPT_thinlto_jobs)) + config->thinLTOJobs = arg->getValue(); + if (config->ltoo > 3) error("invalid optimization level for LTO: " + Twine(config->ltoo)); if (config->ltoPartitions == 0) diff --git a/lld/ELF/ICF.cpp b/lld/ELF/ICF.cpp index cdc4a15..4b1ecad 100644 --- a/lld/ELF/ICF.cpp +++ b/lld/ELF/ICF.cpp @@ -400,7 +400,7 @@ template void ICF::forEachClass(llvm::function_ref fn) { // If threading is disabled or the number of sections are // too small to use threading, call Fn sequentially. - if (!threadsEnabled || sections.size() < 1024) { + if (parallel::strategy.ThreadsRequested == 1 || sections.size() < 1024) { forEachClassRange(0, sections.size(), fn); ++cnt; return; diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td index e1c489c..47210b6 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -350,9 +350,10 @@ defm target2: Eq<"target2", "Interpret R_ARM_TARGET2 as , where is one of rel, abs, or got-rel">, MetaVarName<"">; -defm threads: B<"threads", - "Run the linker multi-threaded (default)", - "Do not run the linker multi-threaded">; +defm threads + : Eq<"threads", + "Number of threads. '1' disables multi-threading. By default all " + "available hardware threads are used">; 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">; @@ -509,7 +510,8 @@ defm thinlto_cache_policy: Eq<"thinlto-cache-policy", "Pruning policy for the Th def thinlto_emit_imports_files: F<"thinlto-emit-imports-files">; def thinlto_index_only: F<"thinlto-index-only">; def thinlto_index_only_eq: J<"thinlto-index-only=">; -def thinlto_jobs: J<"thinlto-jobs=">, HelpText<"Number of ThinLTO jobs">; +def thinlto_jobs: J<"thinlto-jobs=">, + HelpText<"Number of ThinLTO jobs. Default to --threads=">; def thinlto_object_suffix_replace_eq: J<"thinlto-object-suffix-replace=">; def thinlto_prefix_replace_eq: J<"thinlto-prefix-replace=">; diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 2388b08..4833909 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -2746,12 +2746,11 @@ createSymbols(ArrayRef> nameAttrs, // The number of symbols we will handle in this function is of the order // of millions for very large executables, so we use multi-threading to // speed it up. - size_t numShards = 32; - size_t concurrency = 1; - if (threadsEnabled) - concurrency = std::min( - PowerOf2Floor(hardware_concurrency().compute_thread_count()), - numShards); + constexpr size_t numShards = 32; + size_t concurrency = PowerOf2Floor( + std::min(hardware_concurrency(parallel::strategy.ThreadsRequested) + .compute_thread_count(), + numShards)); // A sharded map to uniquify symbols by name. std::vector> map(numShards); @@ -3194,11 +3193,10 @@ void MergeNoTailSection::finalizeContents() { // Concurrency level. Must be a power of 2 to avoid expensive modulo // operations in the following tight loop. - size_t concurrency = 1; - if (threadsEnabled) - concurrency = std::min( - PowerOf2Floor(hardware_concurrency().compute_thread_count()), - numShards); + size_t concurrency = PowerOf2Floor( + std::min(hardware_concurrency(parallel::strategy.ThreadsRequested) + .compute_thread_count(), + numShards)); // Add section pieces to the builders. parallelForEachN(0, concurrency, [&](size_t threadId) { diff --git a/lld/docs/ld.lld.1 b/lld/docs/ld.lld.1 index 238ac28..7af9a16 100644 --- a/lld/docs/ld.lld.1 +++ b/lld/docs/ld.lld.1 @@ -302,8 +302,6 @@ Page align sections. Do not set the text data sections to be writable, page align sections. .It Fl -no-rosegment Do not put read-only non-executable sections in their own segment. -.It Fl -no-threads -Do not run the linker multi-threaded. .It Fl -no-undefined-version Report version scripts that refer undefined symbols. .It Fl -no-undefined @@ -525,9 +523,12 @@ Path to ThinLTO cached object file directory. Pruning policy for the ThinLTO cache. .It Fl -thinlto-jobs Ns = Ns Ar value Number of ThinLTO jobs. -.It Fl -threads -Run the linker multi-threaded. -This option is enabled by default. +.It Fl -threads Ns = Ns Ar N +Number of threads. +.Cm all +(default) means all of concurrent threads supported. +.Cm 1 +disables multi-threading. .It Fl -trace Print the names of the input files. .It Fl -trace-symbol Ns = Ns Ar symbol , Fl y Ar symbol diff --git a/lld/include/lld/Common/Threads.h b/lld/include/lld/Common/Threads.h index 7834130..1090961 100644 --- a/lld/include/lld/Common/Threads.h +++ b/lld/include/lld/Common/Threads.h @@ -63,10 +63,8 @@ namespace lld { -extern bool threadsEnabled; - template void parallelForEach(R &&range, FuncTy fn) { - if (threadsEnabled) + if (llvm::parallel::strategy.ThreadsRequested != 1) for_each(llvm::parallel::par, std::begin(range), std::end(range), fn); else for_each(llvm::parallel::seq, std::begin(range), std::end(range), fn); @@ -74,14 +72,14 @@ template void parallelForEach(R &&range, FuncTy fn) { inline void parallelForEachN(size_t begin, size_t end, llvm::function_ref fn) { - if (threadsEnabled) + if (llvm::parallel::strategy.ThreadsRequested != 1) for_each_n(llvm::parallel::par, begin, end, fn); else for_each_n(llvm::parallel::seq, begin, end, fn); } template void parallelSort(R &&range, FuncTy fn) { - if (threadsEnabled) + if (llvm::parallel::strategy.ThreadsRequested != 1) sort(llvm::parallel::par, std::begin(range), std::end(range), fn); else sort(llvm::parallel::seq, std::begin(range), std::end(range), fn); diff --git a/lld/test/COFF/pdb-globals.test b/lld/test/COFF/pdb-globals.test index 00909fa..169a169 100644 --- a/lld/test/COFF/pdb-globals.test +++ b/lld/test/COFF/pdb-globals.test @@ -2,9 +2,9 @@ RUN: yaml2obj %S/Inputs/pdb-globals.yaml > %t.obj RUN: lld-link /debug /nodefaultlib /entry:main /out:%t.exe /pdb:%t.pdb %t.obj RUN: llvm-pdbutil dump -symbols -globals %t.pdb | FileCheck %s -RUN: lld-link /debug /nodefaultlib /entry:main /out:%t.exe /pdb:%t.pdb %t.obj /threads +RUN: lld-link /debug /nodefaultlib /entry:main /out:%t.exe /pdb:%t.pdb %t.obj /threads:1 RUN: llvm-pdbutil dump -symbols -globals %t.pdb | FileCheck %s -RUN: lld-link /debug /nodefaultlib /entry:main /out:%t.exe /pdb:%t.pdb %t.obj /threads:no +RUN: lld-link /debug /nodefaultlib /entry:main /out:%t.exe /pdb:%t.pdb %t.obj /threads:2 RUN: llvm-pdbutil dump -symbols -globals %t.pdb | FileCheck %s # Test that we correctly distribute symbols between the globals and module diff --git a/lld/test/ELF/build-id.s b/lld/test/ELF/build-id.s index 32966b8..b693a08 100644 --- a/lld/test/ELF/build-id.s +++ b/lld/test/ELF/build-id.s @@ -5,26 +5,26 @@ # RUN: ld.lld --build-id %t -o %t2 # RUN: llvm-readobj -S %t2 | FileCheck -check-prefix=ALIGN %s -# RUN: ld.lld --build-id %t -o %t2 -threads +# RUN: ld.lld --build-id %t -o %t2 # RUN: llvm-objdump -s %t2 | FileCheck --check-prefix=DEFAULT %s -# RUN: ld.lld --build-id=fast %t -o %t2 -threads +# RUN: ld.lld --build-id=fast %t -o %t2 # RUN: llvm-objdump -s %t2 | FileCheck --check-prefix=DEFAULT %s -# RUN: ld.lld --build-id %t -o %t2 -no-threads +# RUN: ld.lld --build-id %t -o %t2 --threads=1 # RUN: llvm-objdump -s %t2 | FileCheck --check-prefix=DEFAULT %s -# RUN: ld.lld --build-id=md5 %t -o %t2 -threads +# RUN: ld.lld --build-id=md5 %t -o %t2 # RUN: llvm-objdump -s %t2 | FileCheck --check-prefix=MD5 %s -# RUN: ld.lld --build-id=md5 %t -o %t2 -no-threads +# RUN: ld.lld --build-id=md5 %t -o %t2 --threads=1 # RUN: llvm-objdump -s %t2 | FileCheck --check-prefix=MD5 %s -# RUN: ld.lld --build-id=sha1 %t -o %t2 -threads +# RUN: ld.lld --build-id=sha1 %t -o %t2 # RUN: llvm-objdump -s %t2 | FileCheck --check-prefix=SHA1 %s -# RUN: ld.lld --build-id=sha1 %t -o %t2 -no-threads +# RUN: ld.lld --build-id=sha1 %t -o %t2 --threads=1 # RUN: llvm-objdump -s %t2 | FileCheck --check-prefix=SHA1 %s -# RUN: ld.lld --build-id=tree %t -o %t2 -threads +# RUN: ld.lld --build-id=tree %t -o %t2 # RUN: llvm-objdump -s %t2 | FileCheck --check-prefix=SHA1 %s -# RUN: ld.lld --build-id=tree %t -o %t2 -no-threads +# RUN: ld.lld --build-id=tree %t -o %t2 --threads=1 # RUN: llvm-objdump -s %t2 | FileCheck --check-prefix=SHA1 %s # RUN: ld.lld --build-id=uuid %t -o %t2 diff --git a/lld/test/ELF/lto/thinlto.ll b/lld/test/ELF/lto/thinlto.ll index bf9062be..50e31d1 100644 --- a/lld/test/ELF/lto/thinlto.ll +++ b/lld/test/ELF/lto/thinlto.ll @@ -22,6 +22,18 @@ ; RUN: llvm-nm %t31.lto.o | FileCheck %s --check-prefix=NM1 ; RUN: llvm-nm %t32.lto.o | FileCheck %s --check-prefix=NM2 +;; --thinlto-jobs= defaults to --threads=. +; RUN: rm -f %t31.lto.o %t32.lto.o +; RUN: ld.lld -save-temps --threads=2 -shared %t1.o %t2.o -o %t3 +; RUN: llvm-nm %t31.lto.o | FileCheck %s --check-prefix=NM1 +; RUN: llvm-nm %t32.lto.o | FileCheck %s --check-prefix=NM2 + +;; --thinlto-jobs= overrides --threads=. +; RUN: rm -f %t31.lto.o %t32.lto.o +; RUN: ld.lld -save-temps --threads=1 --plugin-opt=jobs=2 -shared %t1.o %t2.o -o %t3 +; RUN: llvm-nm %t31.lto.o | FileCheck %s --check-prefix=NM1 +; RUN: llvm-nm %t32.lto.o | FileCheck %s --check-prefix=NM2 + ; Test with all threads, on all cores, on all CPU sockets ; RUN: rm -f %t31.lto.o %t32.lto.o ; RUN: ld.lld -save-temps --thinlto-jobs=all -shared %t1.o %t2.o -o %t3 diff --git a/lld/test/ELF/threads.s b/lld/test/ELF/threads.s new file mode 100644 index 0000000..6d4b369 --- /dev/null +++ b/lld/test/ELF/threads.s @@ -0,0 +1,11 @@ +# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o + +## A positive integer is allowed. +# RUN: ld.lld --threads=1 %t.o -o /dev/null +# RUN: ld.lld --threads=2 %t.o -o /dev/null + +# RUN: not ld.lld --threads=all %t.o -o /dev/null 2>&1 | FileCheck %s -DN=all +# RUN: not ld.lld --threads=0 %t.o -o /dev/null 2>&1 | FileCheck %s -DN=0 +# RUN: not ld.lld --threads=-1 %t.o -o /dev/null 2>&1 | FileCheck %s -DN=-1 + +# CHECK: error: --threads: expected a positive integer, but got '[[N]]' diff --git a/lld/test/wasm/lto/thinlto.ll b/lld/test/wasm/lto/thinlto.ll index 4604529..da42469 100644 --- a/lld/test/wasm/lto/thinlto.ll +++ b/lld/test/wasm/lto/thinlto.ll @@ -14,6 +14,18 @@ ; RUN: llvm-nm %t31.lto.o | FileCheck %s --check-prefix=NM1 ; RUN: llvm-nm %t32.lto.o | FileCheck %s --check-prefix=NM2 +;; --thinlto-jobs= defaults to --threads=. +; RUN: rm -f %t31.lto.o %t32.lto.o +; RUN: wasm-ld -r -save-temps --threads=2 %t1.o %t2.o -o %t3 +; RUN: llvm-nm %t31.lto.o | FileCheck %s --check-prefix=NM1 +; RUN: llvm-nm %t32.lto.o | FileCheck %s --check-prefix=NM2 + +;; --thinlto-jobs= overrides --threads=. +; RUN: rm -f %t31.lto.o %t32.lto.o +; RUN: wasm-ld -r -save-temps --threads=1 --thinlto-jobs=2 %t1.o %t2.o -o %t3 +; RUN: llvm-nm %t31.lto.o | FileCheck %s --check-prefix=NM1 +; RUN: llvm-nm %t32.lto.o | FileCheck %s --check-prefix=NM2 + ; Test with all threads, on all cores, on all CPU sockets ; RUN: rm -f %t31.lto.o %t32.lto.o ; RUN: wasm-ld -r -save-temps --thinlto-jobs=all %t1.o %t2.o -o %t3 diff --git a/lld/test/wasm/threads.s b/lld/test/wasm/threads.s new file mode 100644 index 0000000..e02f5e6 --- /dev/null +++ b/lld/test/wasm/threads.s @@ -0,0 +1,12 @@ +# RUN: llvm-mc -filetype=obj -triple=wasm32 %s -o %t.o + +## A positive integer is allowed. +# RUN: wasm-ld --no-entry %t.o -o /dev/null +# RUN: wasm-ld --no-entry --threads=1 %t.o -o /dev/null +# RUN: wasm-ld --no-entry --threads=2 %t.o -o /dev/null + +# RUN: not wasm-ld --threads=all %t.o -o /dev/null 2>&1 | FileCheck %s -DN=all +# RUN: not wasm-ld --threads=0 %t.o -o /dev/null 2>&1 | FileCheck %s -DN=0 +# RUN: not wasm-ld --threads=-1 %t.o -o /dev/null 2>&1 | FileCheck %s -DN=-1 + +# CHECK: error: --threads: expected a positive integer, but got '[[N]]' diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp index b38e980..d0b01d5 100644 --- a/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp @@ -362,10 +362,8 @@ static void readConfigs(opt::InputArgList &args) { config->thinLTOCachePolicy = CHECK( parseCachePruningPolicy(args.getLastArgValue(OPT_thinlto_cache_policy)), "--thinlto-cache-policy: invalid cache policy"); - config->thinLTOJobs = args.getLastArgValue(OPT_thinlto_jobs); errorHandler().verbose = args.hasArg(OPT_verbose); LLVM_DEBUG(errorHandler().verbose = true); - threadsEnabled = args.hasFlag(OPT_threads, OPT_no_threads, true); config->initialMemory = args::getInteger(args, OPT_initial_memory, 0); config->globalBase = args::getInteger(args, OPT_global_base, 1024); @@ -377,6 +375,20 @@ static void readConfigs(opt::InputArgList &args) { config->exportDynamic = args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, config->shared); + // --threads= takes a positive integer and provides the default value for + // --thinlto-jobs=. + if (auto *arg = args.getLastArg(OPT_threads)) { + StringRef v(arg->getValue()); + unsigned threads = 0; + if (!llvm::to_integer(v, threads, 0) || threads == 0) + error(arg->getSpelling() + ": expected a positive integer, but got '" + + arg->getValue() + "'"); + parallel::strategy = hardware_concurrency(threads); + config->thinLTOJobs = v; + } + if (auto *arg = args.getLastArg(OPT_thinlto_jobs)) + config->thinLTOJobs = arg->getValue(); + if (auto *arg = args.getLastArg(OPT_features)) { config->features = llvm::Optional>(std::vector()); diff --git a/lld/wasm/Options.td b/lld/wasm/Options.td index d0275cf..0910a74 100644 --- a/lld/wasm/Options.td +++ b/lld/wasm/Options.td @@ -64,9 +64,6 @@ def L: JoinedOrSeparate<["-"], "L">, MetaVarName<"">, def mllvm: S<"mllvm">, HelpText<"Options to pass to LLVM">; -def no_threads: F<"no-threads">, - HelpText<"Do not run the linker multi-threaded">; - def no_color_diagnostics: F<"no-color-diagnostics">, HelpText<"Do not use colors in diagnostics">; @@ -98,7 +95,9 @@ def strip_all: F<"strip-all">, HelpText<"Strip all symbols">; def strip_debug: F<"strip-debug">, HelpText<"Strip debugging information">; -def threads: F<"threads">, HelpText<"Run the linker multi-threaded">; +defm threads + : Eq<"threads", "Number of threads. '1' disables multi-threading. By " + "default all available hardware threads are used">; def trace: F<"trace">, HelpText<"Print the names of the input files">; @@ -198,4 +197,5 @@ def save_temps: F<"save-temps">; def thinlto_cache_dir: J<"thinlto-cache-dir=">, HelpText<"Path to ThinLTO cached object file directory">; defm thinlto_cache_policy: Eq<"thinlto-cache-policy", "Pruning policy for the ThinLTO cache">; -def thinlto_jobs: J<"thinlto-jobs=">, HelpText<"Number of ThinLTO jobs">; +def thinlto_jobs: J<"thinlto-jobs=">, + HelpText<"Number of ThinLTO jobs. Default to --threads=">; diff --git a/llvm/include/llvm/Support/Parallel.h b/llvm/include/llvm/Support/Parallel.h index 3c0ed2c..e9d04bf 100644 --- a/llvm/include/llvm/Support/Parallel.h +++ b/llvm/include/llvm/Support/Parallel.h @@ -12,6 +12,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/Config/llvm-config.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/Threading.h" #include #include @@ -33,6 +34,11 @@ struct is_execution_policy constexpr sequential_execution_policy seq{}; constexpr parallel_execution_policy par{}; +// Strategy for the default executor used by the parallel routines provided by +// this file. It defaults to using all hardware threads and should be +// initialized before the first use of parallel routines. +extern ThreadPoolStrategy strategy; + namespace detail { #if LLVM_ENABLE_THREADS diff --git a/llvm/lib/Support/Parallel.cpp b/llvm/lib/Support/Parallel.cpp index 0272a53..7f6ce82 100644 --- a/llvm/lib/Support/Parallel.cpp +++ b/llvm/lib/Support/Parallel.cpp @@ -20,6 +20,8 @@ #include #include +llvm::ThreadPoolStrategy llvm::parallel::strategy; + namespace llvm { namespace parallel { namespace detail { @@ -78,6 +80,9 @@ public: T.join(); } + struct Creator { + static void *call() { return new ThreadPoolExecutor(strategy); } + }; struct Deleter { static void call(void *Ptr) { ((ThreadPoolExecutor *)Ptr)->stop(); } }; @@ -131,7 +136,8 @@ Executor *Executor::getDefaultExecutor() { // are more frequent with the debug static runtime. // // This also prevents intermittent deadlocks on exit with the MinGW runtime. - static ManagedStatic, + + static ManagedStatic ManagedExec; static std::unique_ptr Exec(&(*ManagedExec)); diff --git a/llvm/utils/gn/secondary/lld/Common/BUILD.gn b/llvm/utils/gn/secondary/lld/Common/BUILD.gn index 02f91cd..125cad3 100644 --- a/llvm/utils/gn/secondary/lld/Common/BUILD.gn +++ b/llvm/utils/gn/secondary/lld/Common/BUILD.gn @@ -39,7 +39,6 @@ static_library("Common") { "Reproduce.cpp", "Strings.cpp", "TargetOptionsCommandFlags.cpp", - "Threads.cpp", "Timer.cpp", "Version.cpp", ] -- 2.7.4