InstrProf: Handle unknown functions if they consist only of zero-regions
authorJustin Bogner <mail@justinbogner.com>
Wed, 18 Feb 2015 18:40:46 +0000 (18:40 +0000)
committerJustin Bogner <mail@justinbogner.com>
Wed, 18 Feb 2015 18:40:46 +0000 (18:40 +0000)
This comes up when we generate coverage for a function but don't end
up emitting the function at all - dead static functions or inline
functions that aren't referenced in a particular TU, for example. In
these cases we'd like to show that the function was never called,
which is trivially true.

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

include/llvm/ProfileData/CoverageMapping.h
lib/ProfileData/CoverageMapping.cpp
unittests/ProfileData/CoverageMappingTest.cpp

index 147d17c3bd882a9e61113d8a1321caa9873473f6..4d393b3e948c24bc6fcbfd8923f574761a487091 100644 (file)
@@ -237,6 +237,8 @@ public:
                         ArrayRef<uint64_t> CounterValues = ArrayRef<uint64_t>())
       : Expressions(Expressions), CounterValues(CounterValues) {}
 
+  void setCounts(ArrayRef<uint64_t> Counts) { CounterValues = Counts; }
+
   void dump(const Counter &C, llvm::raw_ostream &OS) const;
   void dump(const Counter &C) const { dump(C, dbgs()); }
 
@@ -256,10 +258,14 @@ struct FunctionRecord {
   /// \brief The number of times this function was executed.
   uint64_t ExecutionCount;
 
-  FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames,
-                 uint64_t ExecutionCount)
-      : Name(Name), Filenames(Filenames.begin(), Filenames.end()),
-        ExecutionCount(ExecutionCount) {}
+  FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames)
+      : Name(Name), Filenames(Filenames.begin(), Filenames.end()) {}
+
+  void pushRegion(CounterMappingRegion Region, uint64_t Count) {
+    if (CountedRegions.empty())
+      ExecutionCount = Count;
+    CountedRegions.emplace_back(Region, Count);
+  }
 };
 
 /// \brief Iterator over Functions, optionally filtered to a single file.
index 3c615d5b784bbe6729b57d942b075ba0fdb03611..bef8605df48f2513bb4f875a1ee8496827e2336b 100644 (file)
@@ -184,25 +184,26 @@ CoverageMapping::load(CoverageMappingReader &CoverageReader,
 
   std::vector<uint64_t> Counts;
   for (const auto &Record : CoverageReader) {
+    CounterMappingContext Ctx(Record.Expressions);
+
     Counts.clear();
     if (std::error_code EC = ProfileReader.getFunctionCounts(
             Record.FunctionName, Record.FunctionHash, Counts)) {
-      if (EC != instrprof_error::hash_mismatch &&
-          EC != instrprof_error::unknown_function)
+      if (EC == instrprof_error::hash_mismatch) {
+        Coverage->MismatchedFunctionCount++;
+        continue;
+      } else if (EC != instrprof_error::unknown_function)
         return EC;
-      Coverage->MismatchedFunctionCount++;
-      continue;
-    }
+    } else
+      Ctx.setCounts(Counts);
 
-    assert(Counts.size() != 0 && "Function's counts are empty");
-    FunctionRecord Function(Record.FunctionName, Record.Filenames,
-                            Counts.front());
-    CounterMappingContext Ctx(Record.Expressions, Counts);
+    assert(!Record.MappingRegions.empty() && "Function has no regions");
+    FunctionRecord Function(Record.FunctionName, Record.Filenames);
     for (const auto &Region : Record.MappingRegions) {
       ErrorOr<int64_t> ExecutionCount = Ctx.evaluate(Region.Count);
       if (!ExecutionCount)
         break;
-      Function.CountedRegions.push_back(CountedRegion(Region, *ExecutionCount));
+      Function.pushRegion(Region, *ExecutionCount);
     }
     if (Function.CountedRegions.size() != Record.MappingRegions.size()) {
       Coverage->MismatchedFunctionCount++;
index d079b479216856874b211cdead2a60fefd7326c4..5e64843b6d6ac546c6689aff0903cb4208480741 100644 (file)
@@ -209,4 +209,17 @@ TEST_F(CoverageMappingTest, basic_coverage_iteration) {
   ASSERT_EQ(CoverageSegment(11, 11, false),   Segments[6]);
 }
 
+TEST_F(CoverageMappingTest, uncovered_function) {
+  readProfCounts();
+
+  addCMR(Counter::getZero(), "file1", 1, 2, 3, 4);
+  loadCoverageMapping("func", 0x1234);
+
+  CoverageData Data = LoadedCoverage->getCoverageForFile("file1");
+  std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
+  ASSERT_EQ(2U, Segments.size());
+  ASSERT_EQ(CoverageSegment(1, 2, 0, true), Segments[0]);
+  ASSERT_EQ(CoverageSegment(3, 4, false),   Segments[1]);
+}
+
 } // end anonymous namespace