PATCH: fix .bbg info for gcov for computed gotos, C++

Janis Johnson janis@us.ibm.com
Mon Jul 9 09:30:00 GMT 2001


This patch fixes some problems with test coverage information that is
used by gcov.

  1. It excludes from the total count of arcs in the .bbg file those
     that are ignored and not actually written to the file.  This
     problem caused gcov to abort when the source file contained
     computed gotos.

     This is probably the same as in PR 1824, submitted by Brad Lucier.

  2. It excludes from the arcs recorded in the .bbg file those that
     are not on the spanning tree but that are fake edges and so will
     not result in instrumented edges.  This problem caused gcov to
     abort sometimes when the file contained exception handling code.

     This is probably the the problem described by David Faitelson on
     July 4, 2001:
        http://gcc.gnu.org/ml/gcc-bugs/2001-07/msg00115.html

  3. It sets the 0x2 flag bit in the .bbg file according to EDGE_FAKE
     rather than EDGE_ABNORMAL, thereby allowing gcov to once again
     report information about calls.

  4. It reports counts of ignored edges to the rtl dump file.

  5. It adds a test case for use of gcov with computed gotos, which
     checks that gcov can be used but doesn't check counts for the use
     of computed gotos, since they are apparently not supported on
     every platform.  There is no test case for the C++ problems because
     there is not yet support for C++ gcov tests.

This patch does not affect generated code, just the information written
to the .bbg file.

There are remaining problems with profiling and gcov with C++ code
as demonstrated by the Stepanov benchmark, for which some of the branch
percentages are reported as negative.  I'll file a problem report.

I can't do full bootstraps on either i686-pc-linux-gnu or
ia64-unknown-linux right now, but I bootstrapped and tested without cgj
on i686-pc-linux-gnu and bootstrapped and tested with a 3.0 version of
the patch with the 20010702 3.0 snapshot on both systems.  Let me know
if you'd like the 3.0 version also.

Janis

2001-07-09  Janis Johnson <janis@us.ibm.com>

	* gcc/profile.c: Fix .bbg info for computed gotos, C++.

--- gcc/profile.c.orig	Wed Jun 27 10:40:58 2001
+++ gcc/profile.c	Fri Jul  6 17:12:46 2001
@@ -100,6 +100,7 @@
 
 static int total_num_blocks;
 static int total_num_edges;
+static int total_num_edges_ignored;
 static int total_num_edges_instrumented;
 static int total_num_blocks_created;
 static int total_num_passes;
@@ -539,7 +540,7 @@
 branch_prob ()
 {
   int i;
-  int num_edges;
+  int num_edges, ignored_edges;
   struct edge_info *edge_infos;
   struct edge_list *el;
 
@@ -626,6 +627,7 @@
   edge_infos = (struct edge_info *)
     xcalloc (num_edges, sizeof (struct edge_info));
 
+  ignored_edges = 0;
   for (i = 0 ; i < num_edges ; i++)
     {
       edge e = INDEX_EDGE (el, i);
@@ -635,17 +637,12 @@
       /* Mark edges we've replaced by fake edges above as ignored.  */
       if ((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL))
 	  && e->src != ENTRY_BLOCK_PTR && e->dest != EXIT_BLOCK_PTR)
-	EDGE_INFO (e)->ignore = 1;
+        {
+	  EDGE_INFO (e)->ignore = 1;
+	  ignored_edges++;
+        }
     }
 
-  total_num_blocks += n_basic_blocks + 2;
-  if (rtl_dump_file)
-    fprintf (rtl_dump_file, "%d basic blocks\n", n_basic_blocks);
-
-  total_num_edges += num_edges;
-  if (rtl_dump_file)
-    fprintf (rtl_dump_file, "%d edges\n", num_edges);
-
 #ifdef ENABLE_CHECKING
   verify_flow_info ();
 #endif
@@ -722,6 +719,31 @@
 
   find_spanning_tree (el);
 
+  /* Fake edges that are not on the tree will not be instrumented, so
+     mark them ignored. */
+  for (i = 0; i < num_edges; i++)
+    {
+      edge e = INDEX_EDGE (el, i);
+      struct edge_info *inf = EDGE_INFO (e);
+      if ((e->flags & EDGE_FAKE) && !inf->ignore && !inf->on_tree)
+        {
+          inf->ignore = 1;
+          ignored_edges++;
+        }
+    }
+
+  total_num_blocks += n_basic_blocks + 2;
+  if (rtl_dump_file)
+    fprintf (rtl_dump_file, "%d basic blocks\n", n_basic_blocks);
+
+  total_num_edges += num_edges;
+  if (rtl_dump_file)
+    fprintf (rtl_dump_file, "%d edges\n", num_edges);
+
+  total_num_edges_ignored += ignored_edges;
+  if (rtl_dump_file)
+    fprintf (rtl_dump_file, "%d ignored edges\n", ignored_edges);
+
   /* Create a .bbg file from which gcov can reconstruct the basic block
      graph.  First output the number of basic blocks, and then for every
      edge output the source and target basic block numbers.
@@ -733,7 +755,7 @@
 
       /* The plus 2 stands for entry and exit block.  */
       __write_long (n_basic_blocks + 2, bbg_file, 4);
-      __write_long (num_edges + 1, bbg_file, 4);
+      __write_long (num_edges - ignored_edges + 1, bbg_file, 4);
 
       for (i = 0; i < n_basic_blocks + 1; i++)
 	{
@@ -754,7 +776,7 @@
 		  flag_bits = 0;
 		  if (i->on_tree)
 		    flag_bits |= 0x1;
-		  if (e->flags & EDGE_ABNORMAL)
+		  if (e->flags & EDGE_FAKE)
 		    flag_bits |= 0x2;
 		  if (e->flags & EDGE_FALLTHRU)
 		    flag_bits |= 0x4;
@@ -950,6 +972,7 @@
 
   total_num_blocks = 0;
   total_num_edges = 0;
+  total_num_edges_ignored = 0;
   total_num_edges_instrumented = 0;
   total_num_blocks_created = 0;
   total_num_passes = 0;
@@ -995,6 +1018,8 @@
       fprintf (rtl_dump_file, "Total number of blocks: %d\n",
 	       total_num_blocks);
       fprintf (rtl_dump_file, "Total number of edges: %d\n", total_num_edges);
+      fprintf (rtl_dump_file, "Total number of ignored edges: %d\n",
+	       total_num_edges_ignored);
       fprintf (rtl_dump_file, "Total number of instrumented edges: %d\n",
 	       total_num_edges_instrumented);
       fprintf (rtl_dump_file, "Total number of blocks created: %d\n",
--- gcc/testsuite/gcc.misc-tests/gcov-3.c.orig	Tue Jul  3 13:46:17 2001
+++ gcc/testsuite/gcc.misc-tests/gcov-3.c	Thu Jul  5 12:29:16 2001
@@ -0,0 +1,45 @@
+/* Test Gcov with computed gotos.
+   This is the same as test gcc.c-torture/execute/980526-1.c */
+
+/* { dg-options "-fprofile-arcs -ftest-coverage" } */
+/* { dg-do run { target native } } */
+
+int expect_do1 = 1, expect_do2 = 2;
+ 
+static int doit(int x){
+  __label__ lbl1;
+  __label__ lbl2;
+  static int jtab_init = 0;
+  static void *jtab[2];
+ 
+  if(!jtab_init) {
+    jtab[0] = &&lbl1;
+    jtab[1] = &&lbl2;
+    jtab_init = 1;
+  }
+  goto *jtab[x];
+lbl1:
+  return 1;
+lbl2:
+  return 2;
+}
+ 
+static void do1(void) {
+  if (doit(0) != expect_do1)
+    abort ();
+}
+ 
+static void do2(void){
+  if (doit(1) != expect_do2)
+    abort ();
+}
+ 
+int main(void){			/* count(1) */
+#ifndef NO_LABEL_VALUES
+  do1();
+  do2();
+#endif
+  exit(0);			/* count(1) */
+}
+
+/* { dg-final { run-gcov gcov-3.c } } */



More information about the Gcc-patches mailing list