Index: tools/llvm-cov/CodeCoverage.cpp =================================================================== --- tools/llvm-cov/CodeCoverage.cpp +++ tools/llvm-cov/CodeCoverage.cpp @@ -32,8 +32,8 @@ #include "llvm/Support/Process.h" #include "llvm/Support/Program.h" #include "llvm/Support/ScopedPrinter.h" -#include "llvm/Support/Threading.h" #include "llvm/Support/ThreadPool.h" +#include "llvm/Support/Threading.h" #include "llvm/Support/ToolOutputFile.h" #include @@ -826,6 +826,7 @@ ViewOpts.ShowOutputDirectory = ShowOutputDirectory; ViewOpts.TabSize = TabSize; ViewOpts.ProjectTitle = ProjectTitle; + ViewOpts.NumThreads = NumThreads; if (ViewOpts.hasOutputDirectory()) { if (auto E = sys::fs::create_directories(ViewOpts.ShowOutputDirectory)) { Index: tools/llvm-cov/CoverageReport.h =================================================================== --- tools/llvm-cov/CoverageReport.h +++ tools/llvm-cov/CoverageReport.h @@ -44,6 +44,14 @@ const CoverageViewOptions &Options, const CoverageFilter &Filters = CoverageFiltersMatchAll()); + static void + prepareSingleFileReport(const StringRef &Filename, + const coverage::CoverageMapping *Coverage, + const CoverageViewOptions &Options, + const unsigned LCP, + FileCoverageSummary *FileReport, + const CoverageFilter &Filters); + /// Render file reports for every unique file in the coverage mapping. void renderFileReports(raw_ostream &OS) const; Index: tools/llvm-cov/CoverageReport.cpp =================================================================== --- tools/llvm-cov/CoverageReport.cpp +++ tools/llvm-cov/CoverageReport.cpp @@ -16,6 +16,8 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/Support/Format.h" #include "llvm/Support/Path.h" +#include "llvm/Support/ThreadPool.h" +#include "llvm/Support/Threading.h" #include using namespace llvm; @@ -319,42 +321,60 @@ } } +void CoverageReport::prepareSingleFileReport(const StringRef &Filename, + const coverage::CoverageMapping *Coverage, + const CoverageViewOptions &Options, const unsigned LCP, + FileCoverageSummary *FileReport, const CoverageFilter &Filters) { + for (const auto &Group : Coverage->getInstantiationGroups(Filename)) { + std::vector InstantiationSummaries; + for (const coverage::FunctionRecord *F : Group.getInstantiations()) { + if (!Filters.matches(*Coverage, *F)) + continue; + auto InstantiationSummary = FunctionCoverageSummary::get(*Coverage, *F); + FileReport->addInstantiation(InstantiationSummary); + InstantiationSummaries.push_back(InstantiationSummary); + } + if (InstantiationSummaries.empty()) + continue; + + auto GroupSummary = + FunctionCoverageSummary::get(Group, InstantiationSummaries); + + if (Options.Debug) + outs() << "InstantiationGroup: " << GroupSummary.Name << " with " + << "size = " << Group.size() << "\n"; + + FileReport->addFunction(GroupSummary); + } +} + std::vector CoverageReport::prepareFileReports( const coverage::CoverageMapping &Coverage, FileCoverageSummary &Totals, ArrayRef Files, const CoverageViewOptions &Options, const CoverageFilter &Filters) { - std::vector FileReports; unsigned LCP = getRedundantPrefixLen(Files); + auto NumThreads = Options.NumThreads; - for (StringRef Filename : Files) { - FileCoverageSummary Summary(Filename.drop_front(LCP)); - - for (const auto &Group : Coverage.getInstantiationGroups(Filename)) { - std::vector InstantiationSummaries; - for (const coverage::FunctionRecord *F : Group.getInstantiations()) { - if (!Filters.matches(Coverage, *F)) - continue; - auto InstantiationSummary = FunctionCoverageSummary::get(Coverage, *F); - Summary.addInstantiation(InstantiationSummary); - Totals.addInstantiation(InstantiationSummary); - InstantiationSummaries.push_back(InstantiationSummary); - } - if (InstantiationSummaries.empty()) - continue; - - auto GroupSummary = - FunctionCoverageSummary::get(Group, InstantiationSummaries); + // If NumThreads is not specified, auto-detect a good default. + if (NumThreads == 0) + NumThreads = + std::max(1U, std::min(llvm::heavyweight_hardware_concurrency(), + unsigned(Files.size()))); - if (Options.Debug) - outs() << "InstantiationGroup: " << GroupSummary.Name << " with " - << "size = " << Group.size() << "\n"; + ThreadPool Pool(NumThreads); - Summary.addFunction(GroupSummary); - Totals.addFunction(GroupSummary); - } + std::vector FileReports; + FileReports.reserve(Files.size()); - FileReports.push_back(Summary); + for (StringRef Filename : Files) { + FileReports.emplace_back(Filename.drop_front(LCP)); + Pool.async(&CoverageReport::prepareSingleFileReport, Filename, + &Coverage, Options, LCP, &FileReports.back(), Filters); } + Pool.wait(); + + for (const auto &FileReport : FileReports) + Totals += FileReport; return FileReports; } Index: tools/llvm-cov/CoverageSummaryInfo.h =================================================================== --- tools/llvm-cov/CoverageSummaryInfo.h +++ tools/llvm-cov/CoverageSummaryInfo.h @@ -116,6 +116,12 @@ FunctionCoverageInfo(size_t Executed, size_t NumFunctions) : Executed(Executed), NumFunctions(NumFunctions) {} + FunctionCoverageInfo &operator+=(const FunctionCoverageInfo &RHS) { + Executed += RHS.Executed; + NumFunctions += RHS.NumFunctions; + return *this; + } + void addFunction(bool Covered) { if (Covered) ++Executed; @@ -176,6 +182,14 @@ : Name(Name), RegionCoverage(), LineCoverage(), FunctionCoverage(), InstantiationCoverage() {} + FileCoverageSummary &operator+=(const FileCoverageSummary &RHS) { + RegionCoverage += RHS.RegionCoverage; + LineCoverage += RHS.LineCoverage; + FunctionCoverage += RHS.FunctionCoverage; + InstantiationCoverage += RHS.InstantiationCoverage; + return *this; + } + void addFunction(const FunctionCoverageSummary &Function) { RegionCoverage += Function.RegionCoverage; LineCoverage += Function.LineCoverage; Index: tools/llvm-cov/CoverageViewOptions.h =================================================================== --- tools/llvm-cov/CoverageViewOptions.h +++ tools/llvm-cov/CoverageViewOptions.h @@ -39,6 +39,7 @@ uint32_t TabSize; std::string ProjectTitle; std::string CreatedTimeStr; + unsigned NumThreads; /// \brief Change the output's stream color if the colors are enabled. ColoredRawOstream colored_ostream(raw_ostream &OS,