Index: llvm/include/llvm/Support/Threading.h =================================================================== --- llvm/include/llvm/Support/Threading.h +++ llvm/include/llvm/Support/Threading.h @@ -157,6 +157,10 @@ // std::thread per core. bool UseHyperThreads = true; + // If set, will constrain 'ThreadsRequested' to the number of hardware + // threads, or hardware cores. + bool Limit = false; + /// Retrieves the max available threads for the current strategy. This /// accounts for affinity masks and takes advantage of all CPU sockets. unsigned compute_thread_count() const; Index: llvm/lib/Support/Threading.cpp =================================================================== --- llvm/lib/Support/Threading.cpp +++ llvm/lib/Support/Threading.cpp @@ -84,14 +84,15 @@ int computeHostNumHardwareThreads(); unsigned llvm::ThreadPoolStrategy::compute_thread_count() const { - if (ThreadsRequested > 0) - return ThreadsRequested; - int MaxThreadCount = UseHyperThreads ? computeHostNumHardwareThreads() : sys::getHostNumPhysicalCores(); if (MaxThreadCount <= 0) MaxThreadCount = 1; - return MaxThreadCount; + if (ThreadsRequested == 0) + return MaxThreadCount; + if (!Limit) + return ThreadsRequested; + return std::min((unsigned)MaxThreadCount, ThreadsRequested); } namespace { Index: llvm/tools/dsymutil/dsymutil.cpp =================================================================== --- llvm/tools/dsymutil/dsymutil.cpp +++ llvm/tools/dsymutil/dsymutil.cpp @@ -547,10 +547,14 @@ // Shared a single binary holder for all the link steps. BinaryHolder BinHolder; - unsigned ThreadCount = Options.LinkOpts.Threads; - if (!ThreadCount) - ThreadCount = DebugMapPtrsOrErr->size(); - ThreadPool Threads(hardware_concurrency(ThreadCount)); + ThreadPoolStrategy S = hardware_concurrency(Options.LinkOpts.Threads); + if (Options.LinkOpts.Threads == 0) { + // If NumThreads is not specified, create one thread for each input, up to + // the number of hardware cores. + S.ThreadsRequested = DebugMapPtrsOrErr->size(); + S.Limit = true; + } + ThreadPool Threads(S); // If there is more than one link to execute, we need to generate // temporary files. Index: llvm/tools/llvm-cov/CodeCoverage.cpp =================================================================== --- llvm/tools/llvm-cov/CodeCoverage.cpp +++ llvm/tools/llvm-cov/CodeCoverage.cpp @@ -943,19 +943,21 @@ (SourceFiles.size() != 1) || ViewOpts.hasOutputDirectory() || (ViewOpts.Format == CoverageViewOptions::OutputFormat::HTML); - auto NumThreads = ViewOpts.NumThreads; - - // If NumThreads is not specified, auto-detect a good default. - if (NumThreads == 0) - NumThreads = SourceFiles.size(); + ThreadPoolStrategy S = hardware_concurrency(ViewOpts.NumThreads); + if (ViewOpts.NumThreads == 0) { + // If NumThreads is not specified, create one thread for each input, up to + // the number of hardware cores. + S = heavyweight_hardware_concurrency(SourceFiles.size()); + S.Limit = true; + } - if (!ViewOpts.hasOutputDirectory() || NumThreads == 1) { + if (!ViewOpts.hasOutputDirectory() || S.ThreadsRequested == 1) { for (const std::string &SourceFile : SourceFiles) writeSourceFileView(SourceFile, Coverage.get(), Printer.get(), ShowFilenames); } else { // In -output-dir mode, it's safe to use multiple threads to print files. - ThreadPool Pool(heavyweight_hardware_concurrency(NumThreads)); + ThreadPool Pool(S); for (const std::string &SourceFile : SourceFiles) Pool.async(&CodeCoverageTool::writeSourceFileView, this, SourceFile, Coverage.get(), Printer.get(), ShowFilenames); Index: llvm/tools/llvm-cov/CoverageExporterJson.cpp =================================================================== --- llvm/tools/llvm-cov/CoverageExporterJson.cpp +++ llvm/tools/llvm-cov/CoverageExporterJson.cpp @@ -163,10 +163,14 @@ ArrayRef SourceFiles, ArrayRef FileReports, const CoverageViewOptions &Options) { - auto NumThreads = Options.NumThreads; - if (NumThreads == 0) - NumThreads = SourceFiles.size(); - ThreadPool Pool(heavyweight_hardware_concurrency(NumThreads)); + ThreadPoolStrategy S = hardware_concurrency(Options.NumThreads); + if (Options.NumThreads == 0) { + // If NumThreads is not specified, create one thread for each input, up to + // the number of hardware cores. + S = heavyweight_hardware_concurrency(SourceFiles.size()); + S.Limit = true; + } + ThreadPool Pool(S); json::Array FileArray; std::mutex FileArrayMutex; Index: llvm/tools/llvm-cov/CoverageReport.cpp =================================================================== --- llvm/tools/llvm-cov/CoverageReport.cpp +++ llvm/tools/llvm-cov/CoverageReport.cpp @@ -352,12 +352,15 @@ ArrayRef Files, const CoverageViewOptions &Options, const CoverageFilter &Filters) { unsigned LCP = getRedundantPrefixLen(Files); - auto NumThreads = Options.NumThreads; - // If NumThreads is not specified, auto-detect a good default. - if (NumThreads == 0) - NumThreads = Files.size(); - ThreadPool Pool(heavyweight_hardware_concurrency(NumThreads)); + ThreadPoolStrategy S = hardware_concurrency(Options.NumThreads); + if (Options.NumThreads == 0) { + // If NumThreads is not specified, create one thread for each input, up to + // the number of hardware cores. + S = heavyweight_hardware_concurrency(SourceFiles.size()); + S.Limit = true; + } + ThreadPool Pool(S); std::vector FileReports; FileReports.reserve(Files.size());