Fixed llvm-cov to count edges instead of blocks.
authorYuchen Wu <yuchenericwu@hotmail.com>
Thu, 24 Oct 2013 01:51:04 +0000 (01:51 +0000)
committerYuchen Wu <yuchenericwu@hotmail.com>
Thu, 24 Oct 2013 01:51:04 +0000 (01:51 +0000)
This was a fundamental flaw in llvm-cov where it treated the values in
the GCDA files as block counts instead of edge counts. This created
incorrect line counts when branching was present. Instead, the edge
counts should be summed to obtain the correct block count.

The fix was tested using custom test files as well as single source
files from the test-suite directory. The behaviour can be verified by
reading the GCOV documentation that describes the GCDA spec ("ARC_COUNTS
gives the counter values for those arcs that are instrumented") and the
header description provided by GCOVProfiling.cpp ("instruments the code
that runs to records (sic) the edges between blocks that run and emit a
complementary "gcda" file on exit").

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

include/llvm/Support/GCOV.h
lib/IR/GCOV.cpp

index f1e7998bc4bcded83776e515d700d455b4f618ff..4bcd0ed0c394944be578d25f518db2685d539e5a 100644 (file)
@@ -191,7 +191,8 @@ public:
   ~GCOVBlock();
   void addEdge(uint32_t N) { Edges.push_back(N); }
   void addLine(StringRef Filename, uint32_t LineNo);
-  void addCount(uint64_t N) { Counter = N; }
+  void addCount(uint64_t N) { Counter += N; }
+  size_t getNumEdges() { return Edges.size(); }
   void dump();
   void collectLineCounts(FileInfo &FI);
 private:
@@ -217,7 +218,7 @@ typedef DenseMap<uint32_t, uint64_t> LineCounts;
 class FileInfo {
 public:
   void addLineCount(StringRef Filename, uint32_t Line, uint64_t Count) {
-    LineInfo[Filename][Line-1] = Count;
+    LineInfo[Filename][Line-1] += Count;
   }
   void print(StringRef gcnoFile, StringRef gcdaFile);
 private:
index 68b91e6dc9a28f702ddf736aa33cec33d362f2da..908523a3a66515ad3609816904465245c57d2530 100644 (file)
@@ -103,9 +103,18 @@ bool GCOVFunction::read(GCOVBuffer &Buff, GCOV::GCOVFormat Format) {
 
   if (Format == GCOV::GCDA_402 || Format == GCOV::GCDA_404) {
     Buff.readArcTag();
+    uint32_t i = 0;
     uint32_t Count = Buff.readInt() / 2;
-    for (unsigned i = 0, e = Count; i != e; ++i) {
-      Blocks[i]->addCount(Buff.readInt64());
+
+    // This for loop adds the counts for each block. A second nested loop is
+    // required to combine the edge counts that are contained in the GCDA file.
+    for (uint32_t Line = 0; i < Count; ++Line) {
+      GCOVBlock &Block = *Blocks[Line];
+      for (size_t Edge = 0, End = Block.getNumEdges(); Edge < End; ++Edge) {
+        assert(i < Count && "Unexpected number of Edges!");
+        Block.addCount(Buff.readInt64());
+        ++i;
+      }
     }
     return true;
   }