diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -1144,7 +1144,7 @@ return; } - lld::threadsEnabled = args.hasFlag(OPT_threads, OPT_threads_no, true); + lld::enabledThreads = args.hasFlag(OPT_threads, OPT_threads_no, true) ? 0 : 1; if (args.hasArg(OPT_show_timing)) config->showTiming = true; diff --git a/lld/Common/Filesystem.cpp b/lld/Common/Filesystem.cpp --- a/lld/Common/Filesystem.cpp +++ b/lld/Common/Filesystem.cpp @@ -43,7 +43,7 @@ #if defined(_WIN32) sys::fs::remove(path); #else - if (!threadsEnabled || !sys::fs::exists(path) || + if (enabledThreads == 1 || !sys::fs::exists(path) || !sys::fs::is_regular_file(path)) return; diff --git a/lld/Common/Threads.cpp b/lld/Common/Threads.cpp --- a/lld/Common/Threads.cpp +++ b/lld/Common/Threads.cpp @@ -8,4 +8,4 @@ #include "lld/Common/Threads.h" -bool lld::threadsEnabled = true; +int lld::enabledThreads = 0; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -860,7 +860,7 @@ 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); + enabledThreads = args::getInteger(args, OPT_threads, 0); config->allowMultipleDefinition = args.hasFlag(OPT_allow_multiple_definition, diff --git a/lld/ELF/ICF.cpp b/lld/ELF/ICF.cpp --- a/lld/ELF/ICF.cpp +++ b/lld/ELF/ICF.cpp @@ -400,7 +400,7 @@ 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 (enabledThreads == 1 || sections.size() < 1024) { forEachClassRange(0, sections.size(), fn); ++cnt; return; diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -350,9 +350,8 @@ 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. 0 (default) means all of " + "concurrent threads supported">; 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">; diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -2747,10 +2747,9 @@ // 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( - hardware_concurrency().compute_thread_count(), numShards); + size_t concurrency = hardware_concurrency().compute_thread_count(); + if (enabledThreads != 0) + concurrency = std::min(concurrency, enabledThreads); // A sharded map to uniquify symbols by name. std::vector> map(numShards); @@ -3194,7 +3193,7 @@ // Concurrency level. Must be a power of 2 to avoid expensive modulo // operations in the following tight loop. size_t concurrency = 1; - if (threadsEnabled) + if (enabledThreads) concurrency = std::min( hardware_concurrency().compute_thread_count(), numShards); diff --git a/lld/include/lld/Common/Threads.h b/lld/include/lld/Common/Threads.h --- a/lld/include/lld/Common/Threads.h +++ b/lld/include/lld/Common/Threads.h @@ -63,10 +63,12 @@ namespace lld { -extern bool threadsEnabled; +// Number of threads. 0 means all of concurrent threads supported. +extern int enabledThreads; template void parallelForEach(R &&range, FuncTy fn) { - if (threadsEnabled) + // TODO Make llvm::parallel::par support different numbers of threads. + if (enabledThreads != 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 +76,14 @@ inline void parallelForEachN(size_t begin, size_t end, llvm::function_ref fn) { - if (threadsEnabled) + if (enabledThreads != 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 (enabledThreads != 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/ELF/build-id.s b/lld/test/ELF/build-id.s --- 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 --threads=0 # 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 --threads=0 # 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 --threads=0 # 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 --threads=0 # 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 --threads=0 # 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/wasm/Driver.cpp b/lld/wasm/Driver.cpp --- a/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp @@ -365,7 +365,7 @@ config->thinLTOJobs = args::getInteger(args, OPT_thinlto_jobs, -1u); errorHandler().verbose = args.hasArg(OPT_verbose); LLVM_DEBUG(errorHandler().verbose = true); - threadsEnabled = args.hasFlag(OPT_threads, OPT_no_threads, true); + enabledThreads = args::getInteger(args, OPT_threads, 0); config->initialMemory = args::getInteger(args, OPT_initial_memory, 0); config->globalBase = args::getInteger(args, OPT_global_base, 1024); diff --git a/lld/wasm/Options.td b/lld/wasm/Options.td --- a/lld/wasm/Options.td +++ b/lld/wasm/Options.td @@ -64,9 +64,6 @@ 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,8 @@ 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. 0 (default) means all of " + "concurrent threads supported">; def trace: F<"trace">, HelpText<"Print the names of the input files">;