llvm-cov: Added edge struct for traversal in block.
authorYuchen Wu <yuchenericwu@hotmail.com>
Tue, 3 Dec 2013 00:24:44 +0000 (00:24 +0000)
committerYuchen Wu <yuchenericwu@hotmail.com>
Tue, 3 Dec 2013 00:24:44 +0000 (00:24 +0000)
Added GCOVEdge which are simple structs owned by the GCOVFunction that
stores the source and destination GCOVBlocks, as well as the counts.
Changed GCOVBlocks so that it stores a vector of source GCOVEdges and a
vector of destination GCOVEdges, rather than just the block number.

Storing the block number was only useful for knowing the number of edges
and for debug info. Using a struct is useful for traversing the edges,
especially back edges which may be needed later.

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

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

index 9649a1dad3b71a7905da8370a915339f52f4cf04..ee81229ff8d26208b4a39d5a34ac3ba226176723 100644 (file)
@@ -205,6 +205,14 @@ private:
   uint32_t ProgramCount;
 };
 
+struct GCOVEdge {
+  GCOVEdge(GCOVBlock *S, GCOVBlock *D): Src(S), Dst(D), Count(0) {}
+
+  GCOVBlock *Src;
+  GCOVBlock *Dst;
+  uint64_t Count;
+};
+
 /// GCOVFunction - Collects function information.
 class GCOVFunction {
 public:
@@ -221,25 +229,43 @@ private:
   StringRef Name;
   StringRef Filename;
   SmallVector<GCOVBlock *, 16> Blocks;
+  SmallVector<GCOVEdge *, 16> Edges;
 };
 
 /// GCOVBlock - Collects block information.
 class GCOVBlock {
 public:
+  typedef SmallVectorImpl<GCOVEdge *>::const_iterator EdgeIterator;
+
   GCOVBlock(GCOVFunction &P, uint32_t N) :
-    Parent(P), Number(N), Counter(0), Edges(), Lines() {}
+    Parent(P), Number(N), Counter(0), SrcEdges(), DstEdges(), Lines() {}
   ~GCOVBlock();
-  void addEdge(uint32_t N) { Edges.push_back(N); }
+  void addSrcEdge(GCOVEdge *Edge) {
+    assert(Edge->Dst == this); // up to caller to ensure edge is valid
+    SrcEdges.push_back(Edge);
+  }
+  void addDstEdge(GCOVEdge *Edge) {
+    assert(Edge->Src == this); // up to caller to ensure edge is valid
+    DstEdges.push_back(Edge);
+  }
   void addLine(uint32_t N) { Lines.push_back(N); }
-  void addCount(uint64_t N) { Counter += N; }
-  size_t getNumEdges() const { return Edges.size(); }
+  void addCount(size_t DstEdgeNo, uint64_t N);
+  size_t getNumSrcEdges() const { return SrcEdges.size(); }
+  size_t getNumDstEdges() const { return DstEdges.size(); }
+
+  EdgeIterator src_begin() const { return SrcEdges.begin(); }
+  EdgeIterator src_end() const { return SrcEdges.end(); }
+  EdgeIterator dst_begin() const { return DstEdges.begin(); }
+  EdgeIterator dst_end() const { return DstEdges.end(); }
+
   void dump() const;
   void collectLineCounts(FileInfo &FI);
 private:
   GCOVFunction &Parent;
   uint32_t Number;
   uint64_t Counter;
-  SmallVector<uint32_t, 16> Edges;
+  SmallVector<GCOVEdge *, 16> SrcEdges;
+  SmallVector<GCOVEdge *, 16> DstEdges;
   SmallVector<uint32_t, 16> Lines;
 };
 
index 3b0dee4016f81ba011e26dc3a2d1ab03338d1658..ebf10927fc9a2105c9f29e6d342d23ac26bd57ce 100644 (file)
@@ -112,6 +112,7 @@ void GCOVFile::collectLineCounts(FileInfo &FI) {
 /// ~GCOVFunction - Delete GCOVFunction and its content.
 GCOVFunction::~GCOVFunction() {
   DeleteContainerPointers(Blocks);
+  DeleteContainerPointers(Edges);
 }
 
 /// readGCNO - Read a function from the GCNO buffer. Return false if an error
@@ -154,7 +155,10 @@ bool GCOVFunction::readGCNO(GCOVBuffer &Buff, GCOV::GCOVFormat Format) {
     for (uint32_t i = 0, e = EdgeCount; i != e; ++i) {
       uint32_t Dst;
       if (!Buff.readInt(Dst)) return false;
-      Blocks[BlockNo]->addEdge(Dst);
+      GCOVEdge *Edge = new GCOVEdge(Blocks[BlockNo], Blocks[Dst]);
+      Edges.push_back(Edge);
+      Blocks[BlockNo]->addDstEdge(Edge);
+      Blocks[Dst]->addSrcEdge(Edge);
       if (!Buff.readInt(Dummy)) return false; // Edge flag
     }
   }
@@ -208,26 +212,29 @@ bool GCOVFunction::readGCDA(GCOVBuffer &Buff, GCOV::GCOVFormat Format) {
     errs() << "Arc tag not found.\n";
     return false;
   }
+
   uint32_t Count;
   if (!Buff.readInt(Count)) return false;
   Count /= 2;
 
   // 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; Count > 0; ++Line) {
-    if (Line >= Blocks.size()) {
+  for (uint32_t BlockNo = 0; Count > 0; ++BlockNo) {
+    // The last block is always reserved for exit block
+    if (BlockNo >= Blocks.size()-1) {
       errs() << "Unexpected number of edges.\n";
       return false;
     }
-    GCOVBlock &Block = *Blocks[Line];
-    for (size_t Edge = 0, End = Block.getNumEdges(); Edge < End; ++Edge) {
+    GCOVBlock &Block = *Blocks[BlockNo];
+    for (size_t EdgeNo = 0, End = Block.getNumDstEdges(); EdgeNo < End;
+           ++EdgeNo) {
       if (Count == 0) {
         errs() << "Unexpected number of edges.\n";
         return false;
       }
       uint64_t ArcCount;
       if (!Buff.readInt64(ArcCount)) return false;
-      Block.addCount(ArcCount);
+      Block.addCount(EdgeNo, ArcCount);
       --Count;
     }
   }
@@ -255,10 +262,21 @@ void GCOVFunction::collectLineCounts(FileInfo &FI) {
 
 /// ~GCOVBlock - Delete GCOVBlock and its content.
 GCOVBlock::~GCOVBlock() {
-  Edges.clear();
+  SrcEdges.clear();
+  DstEdges.clear();
   Lines.clear();
 }
 
+/// addCount - Add to block counter while storing the edge count. If the
+/// destination has no outgoing edges, also update that block's count too.
+void GCOVBlock::addCount(size_t DstEdgeNo, uint64_t N) {
+  assert(DstEdgeNo < DstEdges.size()); // up to caller to ensure EdgeNo is valid
+  DstEdges[DstEdgeNo]->Count = N;
+  Counter += N;
+  if (!DstEdges[DstEdgeNo]->Dst->getNumDstEdges())
+    DstEdges[DstEdgeNo]->Dst->Counter += N;
+}
+
 /// collectLineCounts - Collect line counts. This must be used after
 /// reading .gcno and .gcda files.
 void GCOVBlock::collectLineCounts(FileInfo &FI) {
@@ -270,11 +288,20 @@ void GCOVBlock::collectLineCounts(FileInfo &FI) {
 /// dump - Dump GCOVBlock content to dbgs() for debugging purposes.
 void GCOVBlock::dump() const {
   dbgs() << "Block : " << Number << " Counter : " << Counter << "\n";
-  if (!Edges.empty()) {
-    dbgs() << "\tEdges : ";
-    for (SmallVectorImpl<uint32_t>::const_iterator I = Edges.begin(), E = Edges.end();
-         I != E; ++I)
-      dbgs() << (*I) << ",";
+  if (!SrcEdges.empty()) {
+    dbgs() << "\tSource Edges : ";
+    for (EdgeIterator I = SrcEdges.begin(), E = SrcEdges.end(); I != E; ++I) {
+      const GCOVEdge *Edge = *I;
+      dbgs() << Edge->Src->Number << " (" << Edge->Count << "), ";
+    }
+    dbgs() << "\n";
+  }
+  if (!DstEdges.empty()) {
+    dbgs() << "\tDestination Edges : ";
+    for (EdgeIterator I = DstEdges.begin(), E = DstEdges.end(); I != E; ++I) {
+      const GCOVEdge *Edge = *I;
+      dbgs() << Edge->Dst->Number << " (" << Edge->Count << "), ";
+    }
     dbgs() << "\n";
   }
   if (!Lines.empty()) {