[lld][COFF][ELF][WebAssembly] Replace --[no-]threads /threads[:no] with --threads...
authorFangrui Song <maskray@google.com>
Tue, 17 Mar 2020 19:40:19 +0000 (12:40 -0700)
committerFangrui Song <maskray@google.com>
Tue, 31 Mar 2020 15:46:12 +0000 (08:46 -0700)
--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

22 files changed:
lld/COFF/Driver.cpp
lld/COFF/Options.td
lld/Common/CMakeLists.txt
lld/Common/Filesystem.cpp
lld/Common/Threads.cpp [deleted file]
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/ELF/threads.s [new file with mode: 0644]
lld/test/wasm/lto/thinlto.ll
lld/test/wasm/threads.s [new file with mode: 0644]
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

index 7d99f79..931b8cf 100644 (file)
@@ -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;
index 72fe9ce..f8fe6f9 100644 (file)
@@ -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">;
index 7d5ad65..5364903 100644 (file)
@@ -36,7 +36,6 @@ add_lld_library(lldCommon
   Reproduce.cpp
   Strings.cpp
   TargetOptionsCommandFlags.cpp
-  Threads.cpp
   Timer.cpp
   VCSVersion.inc
   Version.cpp
index 75e88db..d75c462 100644 (file)
@@ -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 (file)
index af04972..0000000
+++ /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;
index 95276cd..c31cbcc 100644 (file)
@@ -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)
index cdc4a15..4b1ecad 100644 (file)
@@ -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;
index e1c489c..47210b6 100644 (file)
@@ -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=">;
 
index 2388b08..4833909 100644 (file)
@@ -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) {
index 238ac28..7af9a16 100644 (file)
@@ -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
index 7834130..1090961 100644 (file)
 
 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);
index 00909fa..169a169 100644 (file)
@@ -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
index 32966b8..b693a08 100644 (file)
@@ -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
index bf9062b..50e31d1 100644 (file)
 ; 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 (file)
index 0000000..6d4b369
--- /dev/null
@@ -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]]'
index 4604529..da42469 100644 (file)
 ; 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 (file)
index 0000000..e02f5e6
--- /dev/null
@@ -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]]'
index b38e980..d0b01d5 100644 (file)
@@ -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>());
index d0275cf..0910a74 100644 (file)
@@ -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=">;
index 3c0ed2c..e9d04bf 100644 (file)
@@ -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
index 0272a53..7f6ce82 100644 (file)
@@ -20,6 +20,8 @@
 #include <thread>
 #include <vector>
 
+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<ThreadPoolExecutor, object_creator<ThreadPoolExecutor>,
+
+  static ManagedStatic<ThreadPoolExecutor, ThreadPoolExecutor::Creator,
                        ThreadPoolExecutor::Deleter>
       ManagedExec;
   static std::unique_ptr<ThreadPoolExecutor> Exec(&(*ManagedExec));
index 02f91cd..125cad3 100644 (file)
@@ -39,7 +39,6 @@ static_library("Common") {
     "Reproduce.cpp",
     "Strings.cpp",
     "TargetOptionsCommandFlags.cpp",
-    "Threads.cpp",
     "Timer.cpp",
     "Version.cpp",
   ]