[llvm-branch-commits] [llvm] llvm-cov: Show `FileCoverageSummary` with `getCoverageForFile()` (PR #121192)

NAKAMURA Takumi via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Dec 27 01:10:28 PST 2024


https://github.com/chapuni created https://github.com/llvm/llvm-project/pull/121192

`FunctionCoverageSummary::get()` is removed since it was used only from `SingleFileReport`. "Merge" facilities with `std::max` are removed as well for now. They will be re-introduced later.

For file indices, show also files that have no functions but any other `CoverageInfo`.

Fixes #119282 

Depends on: #121188, #121191

>From c1678ea160892c7b0912d9521866073a6b2ff839 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Fri, 27 Dec 2024 16:11:10 +0900
Subject: [PATCH] llvm-cov: Use `getCoverageForFile()`

---
 .../ProfileData/Coverage/CoverageMapping.h    |  4 +-
 .../ProfileData/Coverage/CoverageMapping.cpp  |  6 ++-
 .../test/tools/llvm-cov/branch-templates.test |  4 +-
 .../tools/llvm-cov/coverage_watermark.test    | 22 ++++----
 llvm/test/tools/llvm-cov/zeroFunctionFile.c   |  3 +-
 llvm/tools/llvm-cov/CoverageReport.cpp        | 42 +++++++++++----
 llvm/tools/llvm-cov/CoverageSummaryInfo.cpp   | 26 ----------
 llvm/tools/llvm-cov/CoverageSummaryInfo.h     | 51 +++++--------------
 .../tools/llvm-cov/SourceCoverageViewHTML.cpp | 16 ++++--
 9 files changed, 79 insertions(+), 95 deletions(-)

diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index c51733b46a1894..64416fdba1b247 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -1012,7 +1012,9 @@ class CoverageMapping {
   /// The given filename must be the name as recorded in the coverage
   /// information. That is, only names returned from getUniqueSourceFiles will
   /// yield a result.
-  CoverageData getCoverageForFile(StringRef Filename) const;
+  CoverageData getCoverageForFile(
+      StringRef Filename,
+      const DenseSet<const FunctionRecord *> &FilteredOutFunctions = {}) const;
 
   /// Get the coverage for a particular function.
   CoverageData getCoverageForFunction(const FunctionRecord &Function) const;
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index feededcd7d1eb5..e7780b465186df 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -1422,7 +1422,9 @@ static bool isExpansion(const CountedRegion &R, unsigned FileID) {
   return R.Kind == CounterMappingRegion::ExpansionRegion && R.FileID == FileID;
 }
 
-CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const {
+CoverageData CoverageMapping::getCoverageForFile(
+    StringRef Filename,
+    const DenseSet<const FunctionRecord *> &FilteredOutFunctions) const {
   assert(SingleByteCoverage);
   MergeableCoverageData FileCoverage(*SingleByteCoverage, Filename);
 
@@ -1432,6 +1434,8 @@ CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const {
       getImpreciseRecordIndicesForFilename(Filename);
   for (unsigned RecordIndex : RecordIndices) {
     const FunctionRecord &Function = Functions[RecordIndex];
+    if (FilteredOutFunctions.count(&Function))
+      continue;
     auto MainFileID = findMainViewFileID(Filename, Function);
     auto FileIDs = gatherFileIDs(Filename, Function);
     FileCoverage.addFunctionRegions(
diff --git a/llvm/test/tools/llvm-cov/branch-templates.test b/llvm/test/tools/llvm-cov/branch-templates.test
index d5535022239f5f..594a3ca533678b 100644
--- a/llvm/test/tools/llvm-cov/branch-templates.test
+++ b/llvm/test/tools/llvm-cov/branch-templates.test
@@ -26,6 +26,6 @@
 
 // REPORTFILE:      Filename                 Regions    Missed Regions     Cover   Functions  Missed Functions  Executed       Lines      Missed Lines     Cover    Branches   Missed Branches     Cover
 // REPORTFILE-NEXT: ---
-// REPORTFILE-NEXT: branch-templates.cpp          12                 3    75.00%           2                 0   100.00%          17                 4    76.47%           8                 4    50.00%
+// REPORTFILE-NEXT: branch-templates.cpp          12                 2    83.33%           2                 0   100.00%          17                 3    82.35%          12                 6    50.00%
 // REPORTFILE-NEXT: ---
-// REPORTFILE-NEXT: TOTAL                         12                 3    75.00%           2                 0   100.00%          17                 4    76.47%           8                 4    50.00%
+// REPORTFILE-NEXT: TOTAL                         12                 2    83.33%           2                 0   100.00%          17                 3    82.35%          12                 6    50.00%
diff --git a/llvm/test/tools/llvm-cov/coverage_watermark.test b/llvm/test/tools/llvm-cov/coverage_watermark.test
index 5c48b4f0fb4bf4..818baa470bc38d 100644
--- a/llvm/test/tools/llvm-cov/coverage_watermark.test
+++ b/llvm/test/tools/llvm-cov/coverage_watermark.test
@@ -18,15 +18,15 @@ ORIGIN: <td class='column-entry-green'>
 ORIGIN: 100.00% (2/2)
 ORIGIN: <td class='column-entry-green'>
 ORIGIN: 100.00% (3/3)
-ORIGIN: <td class='column-entry-red'>
-ORIGIN: 75.00% (9/12)
-ORIGIN: <td class='column-entry-red'>
-ORIGIN: 66.67% (4/6)
+ORIGIN: <td class='column-entry-yellow'>
+ORIGIN: 83.33% (10/12)
+ORIGIN: <td class='column-entry-yellow'>
+ORIGIN: 83.33% (5/6)
 ORIGIN: <td class='column-entry-gray'>
 ORIGIN: - (0/0)
 ORIGIN: </tr>
 
-RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %S/Inputs/templateInstantiations.profdata -format html -show-region-summary -show-instantiation-summary -o %t.html.dir -path-equivalence=/tmp,%S -coverage-watermark 80,70 %S/showTemplateInstantiations.cpp
+RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %S/Inputs/templateInstantiations.profdata -format html -show-region-summary -show-instantiation-summary -o %t.html.dir -path-equivalence=/tmp,%S -coverage-watermark 90,70 %S/showTemplateInstantiations.cpp
 RUN: FileCheck -check-prefix=DOWNGRADE1 %s -input-file %t.html.dir/index.html
 
 DOWNGRADE:1 Totals
@@ -35,9 +35,9 @@ DOWNGRADE1: 100.00% (2/2)
 DOWNGRADE1: <td class='column-entry-green'>
 DOWNGRADE1: 100.00% (3/3)
 DOWNGRADE1: <td class='column-entry-yellow'>
-DOWNGRADE1: 75.00% (9/12)
-DOWNGRADE1: <td class='column-entry-red'>
-DOWNGRADE1: 66.67% (4/6)
+DOWNGRADE1: 83.33% (10/12)
+DOWNGRADE1: <td class='column-entry-yellow'>
+DOWNGRADE1: 83.33% (5/6)
 DOWNGRADE1: <td class='column-entry-gray'>
 DOWNGRADE1: - (0/0)
 DOWNGRADE1: </tr>
@@ -51,9 +51,9 @@ DOWNGRADE2: 100.00% (2/2)
 DOWNGRADE2: <td class='column-entry-green'>
 DOWNGRADE2: 100.00% (3/3)
 DOWNGRADE2: <td class='column-entry-green'>
-DOWNGRADE2: 75.00% (9/12)
-DOWNGRADE2: <td class='column-entry-yellow'>
-DOWNGRADE2: 66.67% (4/6)
+DOWNGRADE2: 83.33% (10/12)
+DOWNGRADE2: <td class='column-entry-green'>
+DOWNGRADE2: 83.33% (5/6)
 DOWNGRADE1: <td class='column-entry-gray'>
 DOWNGRADE1: - (0/0)
 DOWNGRADE1: </tr>
diff --git a/llvm/test/tools/llvm-cov/zeroFunctionFile.c b/llvm/test/tools/llvm-cov/zeroFunctionFile.c
index f463007fe7f60f..28caa5ac241650 100644
--- a/llvm/test/tools/llvm-cov/zeroFunctionFile.c
+++ b/llvm/test/tools/llvm-cov/zeroFunctionFile.c
@@ -16,5 +16,4 @@ int main() {
 // RUN: llvm-cov show -j 1 %S/Inputs/zeroFunctionFile.covmapping -format html -instr-profile %t.profdata -o %t.dir
 // RUN: FileCheck %s -input-file=%t.dir/index.html -check-prefix=HTML
 // HTML-NO: 0.00% (0/0)
-// HTML: Files which contain no functions
-// HTML: zeroFunctionFile.h
+// HTML-NOT: Files which contain no functions
diff --git a/llvm/tools/llvm-cov/CoverageReport.cpp b/llvm/tools/llvm-cov/CoverageReport.cpp
index 00aea4039bfdeb..0046b968756dd0 100644
--- a/llvm/tools/llvm-cov/CoverageReport.cpp
+++ b/llvm/tools/llvm-cov/CoverageReport.cpp
@@ -446,27 +446,47 @@ void CoverageReport::prepareSingleFileReport(const StringRef Filename,
     const coverage::CoverageMapping *Coverage,
     const CoverageViewOptions &Options, const unsigned LCP,
     FileCoverageSummary *FileReport, const CoverageFilter *Filters) {
+  DenseSet<const coverage::FunctionRecord *> FilteredOutFunctions;
+  assert(FileReport->empty());
   for (const auto &Group : Coverage->getInstantiationGroups(Filename)) {
-    std::vector<FunctionCoverageSummary> InstantiationSummaries;
+    bool Updated = false;
     for (const coverage::FunctionRecord *F : Group.getInstantiations()) {
-      if (!Filters->matches(*Coverage, *F))
+      if (!Filters->matches(*Coverage, *F)) {
+        FilteredOutFunctions.insert(F);
         continue;
-      auto InstantiationSummary = FunctionCoverageSummary::get(*Coverage, *F);
-      FileReport->addInstantiation(InstantiationSummary);
-      InstantiationSummaries.push_back(InstantiationSummary);
+      }
+      FileReport->InstantiationCoverage.addFunction(
+          /*Covered=*/F->ExecutionCount > 0);
+      Updated = true;
     }
-    if (InstantiationSummaries.empty())
+    if (!Updated)
       continue;
 
-    auto GroupSummary =
-        FunctionCoverageSummary::get(Group, InstantiationSummaries);
+    if (Options.Debug) {
+      std::string Name;
+      if (Group.hasName()) {
+        Name = std::string(Group.getName());
+      } else {
+        llvm::raw_string_ostream OS(Name);
+        OS << "Definition at line " << Group.getLine() << ", column "
+           << Group.getColumn();
+      }
 
-    if (Options.Debug)
-      outs() << "InstantiationGroup: " << GroupSummary.Name << " with "
+      outs() << "InstantiationGroup: " << Name << " with "
              << "size = " << Group.size() << "\n";
+    }
 
-    FileReport->addFunction(GroupSummary);
+    FileReport->FunctionCoverage.addFunction(
+        /*Covered=*/Group.getTotalExecutionCount() > 0);
   }
+
+  auto FileCoverage =
+      Coverage->getCoverageForFile(Filename, FilteredOutFunctions);
+  if (FileCoverage.empty())
+    return;
+
+  *static_cast<CoverageDataSummary *>(FileReport) +=
+      CoverageDataSummary(FileCoverage);
 }
 
 std::vector<FileCoverageSummary> CoverageReport::prepareFileReports(
diff --git a/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp b/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp
index 86d11266ecdd7c..745a92103bccc9 100644
--- a/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp
+++ b/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp
@@ -110,29 +110,3 @@ FunctionCoverageSummary::get(const CoverageMapping &CM,
 
   return Summary;
 }
-
-FunctionCoverageSummary
-FunctionCoverageSummary::get(const InstantiationGroup &Group,
-                             ArrayRef<FunctionCoverageSummary> Summaries) {
-  std::string Name;
-  if (Group.hasName()) {
-    Name = std::string(Group.getName());
-  } else {
-    llvm::raw_string_ostream OS(Name);
-    OS << "Definition at line " << Group.getLine() << ", column "
-       << Group.getColumn();
-  }
-
-  FunctionCoverageSummary Summary(Name, Group.getTotalExecutionCount());
-  Summary.RegionCoverage = Summaries[0].RegionCoverage;
-  Summary.LineCoverage = Summaries[0].LineCoverage;
-  Summary.BranchCoverage = Summaries[0].BranchCoverage;
-  Summary.MCDCCoverage = Summaries[0].MCDCCoverage;
-  for (const auto &FCS : Summaries.drop_front()) {
-    Summary.RegionCoverage.merge(FCS.RegionCoverage);
-    Summary.LineCoverage.merge(FCS.LineCoverage);
-    Summary.BranchCoverage.merge(FCS.BranchCoverage);
-    Summary.MCDCCoverage.merge(FCS.MCDCCoverage);
-  }
-  return Summary;
-}
diff --git a/llvm/tools/llvm-cov/CoverageSummaryInfo.h b/llvm/tools/llvm-cov/CoverageSummaryInfo.h
index 42398ee06100e2..09ceba5de72719 100644
--- a/llvm/tools/llvm-cov/CoverageSummaryInfo.h
+++ b/llvm/tools/llvm-cov/CoverageSummaryInfo.h
@@ -41,11 +41,6 @@ class RegionCoverageInfo {
     return *this;
   }
 
-  void merge(const RegionCoverageInfo &RHS) {
-    Covered = std::max(Covered, RHS.Covered);
-    NumRegions = std::max(NumRegions, RHS.NumRegions);
-  }
-
   size_t getCovered() const { return Covered; }
 
   size_t getNumRegions() const { return NumRegions; }
@@ -82,11 +77,6 @@ class LineCoverageInfo {
     return *this;
   }
 
-  void merge(const LineCoverageInfo &RHS) {
-    Covered = std::max(Covered, RHS.Covered);
-    NumLines = std::max(NumLines, RHS.NumLines);
-  }
-
   size_t getCovered() const { return Covered; }
 
   size_t getNumLines() const { return NumLines; }
@@ -123,11 +113,6 @@ class BranchCoverageInfo {
     return *this;
   }
 
-  void merge(const BranchCoverageInfo &RHS) {
-    Covered = std::max(Covered, RHS.Covered);
-    NumBranches = std::max(NumBranches, RHS.NumBranches);
-  }
-
   size_t getCovered() const { return Covered; }
 
   size_t getNumBranches() const { return NumBranches; }
@@ -164,11 +149,6 @@ class MCDCCoverageInfo {
     return *this;
   }
 
-  void merge(const MCDCCoverageInfo &RHS) {
-    CoveredPairs = std::max(CoveredPairs, RHS.CoveredPairs);
-    NumPairs = std::max(NumPairs, RHS.NumPairs);
-  }
-
   size_t getCoveredPairs() const { return CoveredPairs; }
 
   size_t getNumPairs() const { return NumPairs; }
@@ -232,6 +212,13 @@ struct CoverageDataSummary {
   CoverageDataSummary() = default;
   CoverageDataSummary(const coverage::CoverageData &CD);
 
+  bool empty() const {
+    return (RegionCoverage.getNumRegions() == 0 &&
+            LineCoverage.getNumLines() == 0 &&
+            BranchCoverage.getNumBranches() == 0 &&
+            MCDCCoverage.getNumPairs() == 0);
+  }
+
   auto &operator+=(const CoverageDataSummary &RHS) {
     RegionCoverage += RHS.RegionCoverage;
     LineCoverage += RHS.LineCoverage;
@@ -253,12 +240,6 @@ struct FunctionCoverageSummary : CoverageDataSummary {
   /// mapping record.
   static FunctionCoverageSummary get(const coverage::CoverageMapping &CM,
                                      const coverage::FunctionRecord &Function);
-
-  /// Compute the code coverage summary for an instantiation group \p Group,
-  /// given a list of summaries for each instantiation in \p Summaries.
-  static FunctionCoverageSummary
-  get(const coverage::InstantiationGroup &Group,
-      ArrayRef<FunctionCoverageSummary> Summaries);
 };
 
 /// A summary of file's code coverage.
@@ -270,24 +251,18 @@ struct FileCoverageSummary : CoverageDataSummary {
   FileCoverageSummary() = default;
   FileCoverageSummary(StringRef Name) : Name(Name) {}
 
+  bool empty() const {
+    return (CoverageDataSummary::empty() &&
+            FunctionCoverage.getNumFunctions() == 0 &&
+            InstantiationCoverage.getNumFunctions() == 0);
+  }
+
   FileCoverageSummary &operator+=(const FileCoverageSummary &RHS) {
     *static_cast<CoverageDataSummary *>(this) += RHS;
     FunctionCoverage += RHS.FunctionCoverage;
     InstantiationCoverage += RHS.InstantiationCoverage;
     return *this;
   }
-
-  void addFunction(const FunctionCoverageSummary &Function) {
-    RegionCoverage += Function.RegionCoverage;
-    LineCoverage += Function.LineCoverage;
-    BranchCoverage += Function.BranchCoverage;
-    MCDCCoverage += Function.MCDCCoverage;
-    FunctionCoverage.addFunction(/*Covered=*/Function.ExecutionCount > 0);
-  }
-
-  void addInstantiation(const FunctionCoverageSummary &Function) {
-    InstantiationCoverage.addFunction(/*Covered=*/Function.ExecutionCount > 0);
-  }
 };
 
 /// A cache for demangled symbols.
diff --git a/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp b/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
index c94d3853fc0143..cb0ea6e0cdafc3 100644
--- a/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
+++ b/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
@@ -23,6 +23,16 @@ using namespace llvm;
 
 namespace {
 
+template <class SummaryTy>
+bool IsSummaryEmpty(const SummaryTy &Report, const CoverageViewOptions &Opts) {
+  return !(Report.FunctionCoverage.getNumFunctions() ||
+           (Opts.ShowInstantiationSummary &&
+            Report.InstantiationCoverage.getNumFunctions()) ||
+           (Opts.ShowRegionSummary && Report.RegionCoverage.getNumRegions()) ||
+           (Opts.ShowBranchSummary && Report.BranchCoverage.getNumBranches()) ||
+           (Opts.ShowMCDCSummary && Report.MCDCCoverage.getNumPairs()));
+}
+
 // Return a string with the special characters in \p Str escaped.
 std::string escape(StringRef Str, const CoverageViewOptions &Opts) {
   std::string TabExpandedResult;
@@ -666,7 +676,7 @@ Error CoveragePrinterHTML::createIndexFile(
       Coverage, Totals, SourceFiles, Opts, Filters);
   bool EmptyFiles = false;
   for (unsigned I = 0, E = FileReports.size(); I < E; ++I) {
-    if (FileReports[I].FunctionCoverage.getNumFunctions())
+    if (!IsSummaryEmpty(FileReports[I], Opts))
       emitFileSummary(OSRef, SourceFiles[I], FileReports[I]);
     else
       EmptyFiles = true;
@@ -734,7 +744,7 @@ struct CoveragePrinterHTMLDirectory::Reporter : public DirectoryCoverageReport {
     // Make directories at the top of the table.
     for (auto &&SubDir : SubDirs) {
       auto &Report = SubDir.second.first;
-      if (!Report.FunctionCoverage.getNumFunctions())
+      if (IsSummaryEmpty(Report, Printer.Opts))
         EmptyFiles.push_back(&Report);
       else
         emitTableRow(OSRef, Options, buildRelLinkToFile(Report.Name), Report,
@@ -743,7 +753,7 @@ struct CoveragePrinterHTMLDirectory::Reporter : public DirectoryCoverageReport {
 
     for (auto &&SubFile : SubFiles) {
       auto &Report = SubFile.second;
-      if (!Report.FunctionCoverage.getNumFunctions())
+      if (IsSummaryEmpty(Report, Printer.Opts))
         EmptyFiles.push_back(&Report);
       else
         emitTableRow(OSRef, Options, buildRelLinkToFile(Report.Name), Report,



More information about the llvm-branch-commits mailing list