Index: tools/llvm-cov/CodeCoverage.cpp =================================================================== --- tools/llvm-cov/CodeCoverage.cpp +++ tools/llvm-cov/CodeCoverage.cpp @@ -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, FileCoverageSummary *Totals, + const CoverageViewOptions &Options, const unsigned LCP, + FileCoverageSummary *FileReportsChunk, + const CoverageFilter &Filters = CoverageFiltersMatchAll()); + +// static std::unique_ptr CoveragePtr; + /// 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 @@ -17,6 +17,8 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/Format.h" #include "llvm/Support/Path.h" +#include "llvm/Support/Threading.h" +#include "llvm/Support/ThreadPool.h" #include using namespace llvm; @@ -320,42 +322,67 @@ } } -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); +//std::unique_ptr CoverageReport::CoveragePtr = nullptr; - for (StringRef Filename : Files) { - FileCoverageSummary Summary(Filename.drop_front(LCP)); +void CoverageReport::prepareSingleFileReport(const StringRef &Filename, + const coverage::CoverageMapping *Coverage, FileCoverageSummary *Totals, + const CoverageViewOptions &Options, const unsigned LCP, + FileCoverageSummary *FileReportsChunk, + const CoverageFilter &Filters) { + FileReportsChunk->Name = 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()) + 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); + FileReportsChunk->addInstantiation(InstantiationSummary); + Totals->addInstantiation(InstantiationSummary); + InstantiationSummaries.push_back(InstantiationSummary); + } + if (InstantiationSummaries.empty()) + continue; - auto GroupSummary = - FunctionCoverageSummary::get(Group, InstantiationSummaries); + auto GroupSummary = + FunctionCoverageSummary::get(Group, InstantiationSummaries); - if (Options.Debug) - outs() << "InstantiationGroup: " << GroupSummary.Name << " with " - << "size = " << Group.size() << "\n"; + if (Options.Debug) + outs() << "InstantiationGroup: " << GroupSummary.Name << " with " + << "size = " << Group.size() << "\n"; - Summary.addFunction(GroupSummary); - Totals.addFunction(GroupSummary); - } + FileReportsChunk->addFunction(GroupSummary); + Totals->addFunction(GroupSummary); + } +} + +std::vector CoverageReport::prepareFileReports( + const coverage::CoverageMapping &Coverage, FileCoverageSummary &Totals, + ArrayRef Files, const CoverageViewOptions &Options, + const CoverageFilter &Filters) { + unsigned LCP = getRedundantPrefixLen(Files); + auto NumThreads = Options.NumThreads; - FileReports.push_back(Summary); + // 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()))); + + ThreadPool Pool(NumThreads); + std::vector PartialTotals(NumThreads); + std::vector FileReports(Files.size()); + size_t Index = 0; + for (StringRef Filename : Files) { + Pool.async(&CoverageReport::prepareSingleFileReport, Filename, + &Coverage, &PartialTotals[Index % NumThreads], + Options, LCP, &FileReports[Index], Filters); + ++Index; } + Pool.wait(); + + for (const auto& TotalsPart : PartialTotals) + Totals += TotalsPart; 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; @@ -172,10 +178,24 @@ FunctionCoverageInfo FunctionCoverage; FunctionCoverageInfo InstantiationCoverage; + FileCoverageSummary() + : Name(), RegionCoverage(), LineCoverage(), FunctionCoverage(), + InstantiationCoverage() {} + FileCoverageSummary(StringRef Name) : Name(Name), RegionCoverage(), LineCoverage(), FunctionCoverage(), InstantiationCoverage() {} + FileCoverageSummary &operator+=(const FileCoverageSummary &RHS) { + assert((RHS.Name.empty() || RHS.Name == LHS.Name) && + "Addition of file coverage summary from different files."); + 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,