[lld] eb4663d - [lld][COFF][ELF][WebAssembly] Replace --[no-]threads /threads[:no] with --threads={1,2,...} /threads:{1,2,...}

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 31 08:46:35 PDT 2020


Author: Fangrui Song
Date: 2020-03-31T08:46:12-07:00
New Revision: eb4663d8c6add351d758748383f1a9fc231e5e64

URL: https://github.com/llvm/llvm-project/commit/eb4663d8c6add351d758748383f1a9fc231e5e64
DIFF: https://github.com/llvm/llvm-project/commit/eb4663d8c6add351d758748383f1a9fc231e5e64.diff

LOG: [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

Added: 
    lld/test/ELF/threads.s
    lld/test/wasm/threads.s

Modified: 
    lld/COFF/Driver.cpp
    lld/COFF/Options.td
    lld/Common/CMakeLists.txt
    lld/Common/Filesystem.cpp
    lld/ELF/Driver.cpp
    lld/ELF/ICF.cpp
    lld/ELF/Options.td
    lld/ELF/SyntheticSections.cpp
    lld/docs/ld.lld.1
    lld/include/lld/Common/Threads.h
    lld/test/COFF/pdb-globals.test
    lld/test/ELF/build-id.s
    lld/test/ELF/lto/thinlto.ll
    lld/test/wasm/lto/thinlto.ll
    lld/wasm/Driver.cpp
    lld/wasm/Options.td
    llvm/include/llvm/Support/Parallel.h
    llvm/lib/Support/Parallel.cpp
    llvm/utils/gn/secondary/lld/Common/BUILD.gn

Removed: 
    lld/Common/Threads.cpp


################################################################################
diff  --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index 7d99f798a322..931b8cf601a7 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -1144,7 +1144,17 @@ void LinkerDriver::link(ArrayRef<const char *> 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 72fe9ce8c118..f8fe6f9efc19 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 7d5ad654925e..53649032bd98 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 75e88dbce1ab..d75c462d244d 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 af04972a3760..000000000000
--- 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 95276cd33420..c31cbcc8a54d 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 cdc4a15ea691..4b1ecadde5ab 100644
--- a/lld/ELF/ICF.cpp
+++ b/lld/ELF/ICF.cpp
@@ -400,7 +400,7 @@ template <class ELFT>
 void ICF<ELFT>::forEachClass(llvm::function_ref<void(size_t, size_t)> 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 e1c489c4a1e3..47210b6ac122 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -350,9 +350,10 @@ defm target2:
   Eq<"target2", "Interpret R_ARM_TARGET2 as <type>, where <type> is one of rel, abs, or got-rel">,
   MetaVarName<"<type>">;
 
-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 2388b08dd20b..48339099dc27 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -2746,12 +2746,11 @@ createSymbols(ArrayRef<std::vector<GdbIndexSection::NameAttrEntry>> 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<size_t>(
-        PowerOf2Floor(hardware_concurrency().compute_thread_count()),
-        numShards);
+  constexpr size_t numShards = 32;
+  size_t concurrency = PowerOf2Floor(
+      std::min<size_t>(hardware_concurrency(parallel::strategy.ThreadsRequested)
+                           .compute_thread_count(),
+                       numShards));
 
   // A sharded map to uniquify symbols by name.
   std::vector<DenseMap<CachedHashStringRef, size_t>> 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<size_t>(
-        PowerOf2Floor(hardware_concurrency().compute_thread_count()),
-        numShards);
+  size_t concurrency = PowerOf2Floor(
+      std::min<size_t>(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 238ac28a599c..7af9a16e83f9 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 7834130fdf72..1090961b18cd 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 <typename R, class FuncTy> 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 <typename R, class FuncTy> void parallelForEach(R &&range, FuncTy fn) {
 
 inline void parallelForEachN(size_t begin, size_t end,
                              llvm::function_ref<void(size_t)> 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 <typename R, class FuncTy> 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 00909fa317bb..169a16907633 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 32966b8a378b..b693a088a266 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 bf9062be7c10..50e31d1e6232 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 000000000000..6d4b36924031
--- /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 460452905597..da42469f2deb 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 000000000000..e02f5e620805
--- /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 b38e980004ad..d0b01d5ccef0 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<std::string>>(std::vector<std::string>());

diff  --git a/lld/wasm/Options.td b/lld/wasm/Options.td
index d0275cf5cd49..0910a74660f3 100644
--- a/lld/wasm/Options.td
+++ b/lld/wasm/Options.td
@@ -64,9 +64,6 @@ def L: JoinedOrSeparate<["-"], "L">, MetaVarName<"<dir>">,
 
 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 3c0ed2c11127..e9d04bfb279f 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 <algorithm>
 #include <condition_variable>
@@ -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 0272a53beb39..7f6ce82763d6 100644
--- a/llvm/lib/Support/Parallel.cpp
+++ b/llvm/lib/Support/Parallel.cpp
@@ -20,6 +20,8 @@
 #include <thread>
 #include <vector>
 
+llvm::ThreadPoolStrategy llvm::parallel::strategy;
+
 namespace llvm {
 namespace parallel {
 namespace detail {
@@ -78,6 +80,9 @@ class ThreadPoolExecutor : public Executor {
         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<ThreadPoolExecutor, object_creator<ThreadPoolExecutor>,
+
+  static ManagedStatic<ThreadPoolExecutor, ThreadPoolExecutor::Creator,
                        ThreadPoolExecutor::Deleter>
       ManagedExec;
   static std::unique_ptr<ThreadPoolExecutor> Exec(&(*ManagedExec));

diff  --git a/llvm/utils/gn/secondary/lld/Common/BUILD.gn b/llvm/utils/gn/secondary/lld/Common/BUILD.gn
index 02f91cde6745..125cad30a32e 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",
   ]


        


More information about the llvm-commits mailing list