llvm-cov: Use the number of executed functions for the function coverage metric.
authorAlex Lorenz <arphaman@gmail.com>
Tue, 30 Sep 2014 12:45:13 +0000 (12:45 +0000)
committerAlex Lorenz <arphaman@gmail.com>
Tue, 30 Sep 2014 12:45:13 +0000 (12:45 +0000)
This commit fixes llvm-cov's function coverage metric by using the number of executed functions instead of the number of fully covered functions.

Differential Revision: http://reviews.llvm.org/D5196

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@218672 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/ProfileData/CoverageMapping.h
lib/ProfileData/CoverageMapping.cpp
test/tools/llvm-cov/Inputs/report.covmapping [new file with mode: 0644]
test/tools/llvm-cov/Inputs/report.profdata [new file with mode: 0644]
test/tools/llvm-cov/report.cpp [new file with mode: 0644]
tools/llvm-cov/CoverageReport.cpp
tools/llvm-cov/CoverageSummary.cpp
tools/llvm-cov/CoverageSummaryInfo.cpp
tools/llvm-cov/CoverageSummaryInfo.h

index 15445b5..617afd4 100644 (file)
@@ -228,9 +228,13 @@ struct FunctionRecord {
   std::vector<std::string> Filenames;
   /// \brief Regions in the function along with their counts.
   std::vector<CountedRegion> CountedRegions;
+  /// \brief The number of times this function was executed.
+  uint64_t ExecutionCount;
 
-  FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames)
-      : Name(Name), Filenames(Filenames.begin(), Filenames.end()) {}
+  FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames,
+                 uint64_t ExecutionCount)
+      : Name(Name), Filenames(Filenames.begin(), Filenames.end()),
+        ExecutionCount(ExecutionCount) {}
 };
 
 /// \brief Coverage information for a macro expansion or #included file.
index 06a950c..1152563 100644 (file)
@@ -167,7 +167,9 @@ CoverageMapping::load(ObjectFileCoverageMappingReader &CoverageReader,
       continue;
     }
 
-    FunctionRecord Function(Record.FunctionName, Record.Filenames);
+    assert(Counts.size() != 0 && "Function's counts are empty");
+    FunctionRecord Function(Record.FunctionName, Record.Filenames,
+                            Counts.front());
     CounterMappingContext Ctx(Record.Expressions, Counts);
     for (const auto &Region : Record.MappingRegions) {
       ErrorOr<int64_t> ExecutionCount = Ctx.evaluate(Region.Count);
diff --git a/test/tools/llvm-cov/Inputs/report.covmapping b/test/tools/llvm-cov/Inputs/report.covmapping
new file mode 100644 (file)
index 0000000..32d84bc
Binary files /dev/null and b/test/tools/llvm-cov/Inputs/report.covmapping differ
diff --git a/test/tools/llvm-cov/Inputs/report.profdata b/test/tools/llvm-cov/Inputs/report.profdata
new file mode 100644 (file)
index 0000000..aa47be0
Binary files /dev/null and b/test/tools/llvm-cov/Inputs/report.profdata differ
diff --git a/test/tools/llvm-cov/report.cpp b/test/tools/llvm-cov/report.cpp
new file mode 100644 (file)
index 0000000..297322a
--- /dev/null
@@ -0,0 +1,24 @@
+// RUN: llvm-cov report %S/Inputs/report.covmapping -instr-profile %S/Inputs/report.profdata -no-colors 2>&1 | FileCheck %s
+
+// CHECK: Filename                    Regions    Miss   Cover Functions  Executed
+// CHECK: TOTAL                             5       2  60.00%         4    75.00%
+
+void foo(bool cond) {
+  if (cond) {
+  }
+}
+
+void bar() {
+}
+
+void func() {
+}
+
+int main() {
+  foo(false);
+  bar();
+  return 0;
+}
+
+// llvm-cov doesn't work on big endian yet
+// XFAIL: powerpc64-, s390x, mips-, mips64-, sparc
index 2efa8e0..94071b7 100644 (file)
@@ -85,7 +85,7 @@ static Column column(StringRef Str, unsigned Width, const T &Value) {
   return Column(Str, Width).set(Value);
 }
 
-static const unsigned FileReportColumns[] = {25, 10, 8, 8, 10, 8};
+static const unsigned FileReportColumns[] = {25, 10, 8, 8, 10, 10};
 static const unsigned FunctionReportColumns[] = {25, 10, 8, 8, 10, 8, 8};
 
 /// \brief Prints a horizontal divider which spans across the given columns.
@@ -178,8 +178,8 @@ void CoverageReport::renderFunctionReports(raw_ostream &OS) {
       render(Function, OS);
     renderDivider(FunctionReportColumns, OS);
     OS << "\n";
-    render(FunctionCoverageSummary("TOTAL", File.RegionCoverage,
-                                   File.LineCoverage),
+    render(FunctionCoverageSummary("TOTAL", /*ExecutionCount=*/0,
+                                   File.RegionCoverage, File.LineCoverage),
            OS);
   }
 }
@@ -190,7 +190,8 @@ void CoverageReport::renderFileReports(raw_ostream &OS) {
      << column("Miss", FileReportColumns[2], Column::RightAlignment)
      << column("Cover", FileReportColumns[3], Column::RightAlignment)
      << column("Functions", FileReportColumns[4], Column::RightAlignment)
-     << column("Cover", FileReportColumns[5], Column::RightAlignment) << "\n";
+     << column("Executed", FileReportColumns[5], Column::RightAlignment)
+     << "\n";
   renderDivider(FileReportColumns, OS);
   OS << "\n";
   for (const auto &File : Summary.getFileSummaries())
index 8df3beb..785e902 100644 (file)
@@ -72,7 +72,7 @@ CoverageSummary::createSummaries(ArrayRef<coverage::FunctionRecord> Functions) {
 FileCoverageSummary CoverageSummary::getCombinedFileSummaries() {
   size_t NumRegions = 0, CoveredRegions = 0;
   size_t NumLines = 0, NonCodeLines = 0, CoveredLines = 0;
-  size_t NumFunctionsCovered = 0, NumFunctions = 0;
+  size_t NumFunctionsExecuted = 0, NumFunctions = 0;
   for (const auto &File : FileSummaries) {
     NumRegions += File.RegionCoverage.NumRegions;
     CoveredRegions += File.RegionCoverage.Covered;
@@ -81,12 +81,12 @@ FileCoverageSummary CoverageSummary::getCombinedFileSummaries() {
     NonCodeLines += File.LineCoverage.NonCodeLines;
     CoveredLines += File.LineCoverage.Covered;
 
-    NumFunctionsCovered += File.FunctionCoverage.FullyCovered;
+    NumFunctionsExecuted += File.FunctionCoverage.Executed;
     NumFunctions += File.FunctionCoverage.NumFunctions;
   }
   return FileCoverageSummary(
       "TOTAL", RegionCoverageInfo(CoveredRegions, NumRegions),
       LineCoverageInfo(CoveredLines, NonCodeLines, NumLines),
-      FunctionCoverageInfo(NumFunctionsCovered, NumFunctions),
+      FunctionCoverageInfo(NumFunctionsExecuted, NumFunctions),
       None);
 }
index 334bc73..dd78ace 100644 (file)
@@ -65,7 +65,8 @@ FunctionCoverageSummary::get(const coverage::FunctionRecord &Function) {
     NumLines += LineCount;
   }
   return FunctionCoverageSummary(
-      Function.Name, RegionCoverageInfo(CoveredRegions, NumCodeRegions),
+      Function.Name, Function.ExecutionCount,
+      RegionCoverageInfo(CoveredRegions, NumCodeRegions),
       LineCoverageInfo(CoveredLines, 0, NumLines));
 }
 
@@ -74,7 +75,7 @@ FileCoverageSummary::get(StringRef Name,
                          ArrayRef<FunctionCoverageSummary> FunctionSummaries) {
   size_t NumRegions = 0, CoveredRegions = 0;
   size_t NumLines = 0, NonCodeLines = 0, CoveredLines = 0;
-  size_t NumFunctionsCovered = 0;
+  size_t NumFunctionsExecuted = 0;
   for (const auto &Func : FunctionSummaries) {
     CoveredRegions += Func.RegionCoverage.Covered;
     NumRegions += Func.RegionCoverage.NumRegions;
@@ -83,13 +84,13 @@ FileCoverageSummary::get(StringRef Name,
     NonCodeLines += Func.LineCoverage.NonCodeLines;
     NumLines += Func.LineCoverage.NumLines;
 
-    if (Func.RegionCoverage.isFullyCovered())
-      ++NumFunctionsCovered;
+    if (Func.ExecutionCount != 0)
+      ++NumFunctionsExecuted;
   }
 
   return FileCoverageSummary(
       Name, RegionCoverageInfo(CoveredRegions, NumRegions),
       LineCoverageInfo(CoveredLines, NonCodeLines, NumLines),
-      FunctionCoverageInfo(NumFunctionsCovered, FunctionSummaries.size()),
+      FunctionCoverageInfo(NumFunctionsExecuted, FunctionSummaries.size()),
       FunctionSummaries);
 }
index 18b2704..0036032 100644 (file)
@@ -69,33 +69,34 @@ struct LineCoverageInfo {
 
 /// \brief Provides information about function coverage for a file.
 struct FunctionCoverageInfo {
-  /// \brief The number of functions that have full
-  /// region coverage.
-  size_t FullyCovered;
+  /// \brief The number of functions that were executed.
+  size_t Executed;
 
   /// \brief The total number of functions in this file.
   size_t NumFunctions;
 
-  FunctionCoverageInfo(size_t FullyCovered, size_t NumFunctions)
-      : FullyCovered(FullyCovered), NumFunctions(NumFunctions) {}
+  FunctionCoverageInfo(size_t Executed, size_t NumFunctions)
+      : Executed(Executed), NumFunctions(NumFunctions) {}
 
-  bool isFullyCovered() const { return FullyCovered == NumFunctions; }
+  bool isFullyCovered() const { return Executed == NumFunctions; }
 
   double getPercentCovered() const {
-    return double(FullyCovered) / double(NumFunctions) * 100.0;
+    return double(Executed) / double(NumFunctions) * 100.0;
   }
 };
 
 /// \brief A summary of function's code coverage.
 struct FunctionCoverageSummary {
   StringRef Name;
+  uint64_t ExecutionCount;
   RegionCoverageInfo RegionCoverage;
   LineCoverageInfo LineCoverage;
 
-  FunctionCoverageSummary(StringRef Name,
+  FunctionCoverageSummary(StringRef Name, uint64_t ExecutionCount,
                           const RegionCoverageInfo &RegionCoverage,
                           const LineCoverageInfo &LineCoverage)
-      : Name(Name), RegionCoverage(RegionCoverage), LineCoverage(LineCoverage) {
+      : Name(Name), ExecutionCount(ExecutionCount),
+        RegionCoverage(RegionCoverage), LineCoverage(LineCoverage) {
   }
 
   /// \brief Compute the code coverage summary for the given function coverage