Make gcno more precise about BBs really belonging to a line (PR gcov-profile/79891).
authorMartin Liska <mliska@suse.cz>
Fri, 28 Apr 2017 12:51:05 +0000 (14:51 +0200)
committerMartin Liska <marxin@gcc.gnu.org>
Fri, 28 Apr 2017 12:51:05 +0000 (12:51 +0000)
2017-04-28  Martin Liska  <mliska@suse.cz>

PR gcov-profile/79891
* gcov.c (add_line_counts): Assign BBs to lines just if the BB
is marked by compiler as living on a line.
(get_cycles_count): Remove usage of the union.
(output_intermediate_file): Likewise.
(find_source): Fix GNU coding style.
(accumulate_line_counts): Remove old non-all block mode.
(output_lines): Remove usage of the union.
* profile.c (output_location): Include all BBs, even if
belonging to a same line (and file) as a previous BB.
2017-04-28  Martin Liska  <mliska@suse.cz>

PR gcov-profile/79891
* gcc.misc-tests/gcov-17.c: New test.
* gcc.misc-tests/gcov-18.c: New test.

From-SVN: r247374

gcc/ChangeLog
gcc/gcov.c
gcc/profile.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.misc-tests/gcov-17.c [new file with mode: 0644]
gcc/testsuite/gcc.misc-tests/gcov-18.c [new file with mode: 0644]

index 86e70e7814bc3e81e2d125bea40c58809164e704..63b6276c07d9dc8b8eec3a0120c683aa99af718c 100644 (file)
@@ -1,3 +1,16 @@
+2017-04-28  Martin Liska  <mliska@suse.cz>
+
+       PR gcov-profile/79891
+       * gcov.c (add_line_counts): Assign BBs to lines just if the BB
+       is marked by compiler as living on a line.
+       (get_cycles_count): Remove usage of the union.
+       (output_intermediate_file): Likewise.
+       (find_source): Fix GNU coding style.
+       (accumulate_line_counts): Remove old non-all block mode.
+       (output_lines): Remove usage of the union.
+       * profile.c (output_location): Include all BBs, even if
+       belonging to a same line (and file) as a previous BB.
+
 2017-04-28  Martin Liska  <mliska@suse.cz>
 
        * gcov.c (process_args): Handle new argument 'w'.
index c8a26b988e3144260a5c5444f2a2baaf5495b411..b25464e730ea39bad7e82797d7738c43495884f2 100644 (file)
@@ -238,14 +238,9 @@ typedef struct line_info
   bool has_block (block_t *needle);
 
   gcov_type count;        /* execution count */
-  union
-  {
-    arc_t *branches;      /* branches from blocks that end on this
-                             line. Used for branch-counts when not
-                             all-blocks mode.  */
-    block_t *blocks;       /* blocks which start on this line.  Used
-                             in all-blocks mode.  */
-  } u;
+  arc_t *branches;        /* branches from blocks that end on this line.  */
+  block_t *blocks;        /* blocks which start on this line.
+                             Used in all-blocks mode.  */
   unsigned exists : 1;
   unsigned unexceptional : 1;
 } line_t;
@@ -253,7 +248,7 @@ typedef struct line_info
 bool
 line_t::has_block (block_t *needle)
 {
-  for (block_t *n = u.blocks; n; n = n->chain)
+  for (block_t *n = blocks; n; n = n->chain)
     if (n == needle)
       return true;
 
@@ -608,7 +603,7 @@ get_cycles_count (line_t &linfo, bool handle_negative_cycles = true)
 
   loop_type result = NO_LOOP;
   gcov_type count = 0;
-  for (block_t *block = linfo.u.blocks; block; block = block->chain)
+  for (block_t *block = linfo.blocks; block; block = block->chain)
     {
       arc_vector_t path;
       block_vector_t blocked;
@@ -886,7 +881,7 @@ output_intermediate_file (FILE *gcov_file, source_t *src)
        fprintf (gcov_file, "lcount:%u,%s\n", line_num,
                 format_gcov (line->count, 0, -1));
       if (flag_branches)
-        for (arc = line->u.branches; arc; arc = arc->line_next)
+       for (arc = line->branches; arc; arc = arc->line_next)
           {
             if (!arc->is_unconditional && !arc->is_call_non_return)
               {
@@ -1279,7 +1274,7 @@ find_source (const char *file_name)
 
   /* Resort the name map.  */
   qsort (names, n_names, sizeof (*names), name_sort);
-  
+
  check_date:
   if (sources[idx].file_time > bbg_file_time)
     {
@@ -2239,13 +2234,11 @@ mangle_name (char const *base, char *ptr)
 static void
 add_line_counts (coverage_t *coverage, function_t *fn)
 {
-  unsigned ix;
-  line_t *line = NULL; /* This is propagated from one iteration to the
-                         next.  */
-
+  bool has_any_line = false;
   /* Scan each basic block.  */
-  for (ix = 0; ix != fn->blocks.size (); ix++)
+  for (unsigned ix = 0; ix != fn->blocks.size (); ix++)
     {
+      line_t *line = NULL;
       block_t *block = &fn->blocks[ix];
       if (block->count && ix && ix + 1 != fn->blocks.size ())
        fn->blocks_executed++;
@@ -2272,33 +2265,31 @@ add_line_counts (coverage_t *coverage, function_t *fn)
        }
       block->cycle.arc = NULL;
       block->cycle.ident = ~0U;
+      has_any_line = true;
 
       if (!ix || ix + 1 == fn->blocks.size ())
        /* Entry or exit block */;
-      else if (flag_all_blocks)
+      else if (line != NULL)
        {
-         line_t *block_line = line;
-
-         if (!block_line)
-           block_line = &sources[fn->src].lines[fn->line];
+         block->chain = line->blocks;
+         line->blocks = block;
 
-         block->chain = block_line->u.blocks;
-         block_line->u.blocks = block;
-       }
-      else if (flag_branches)
-       {
-         arc_t *arc;
-
-         for (arc = block->succ; arc; arc = arc->succ_next)
+         if (flag_branches)
            {
-             arc->line_next = line->u.branches;
-             line->u.branches = arc;
-             if (coverage && !arc->is_unconditional)
-               add_branch_counts (coverage, arc);
+             arc_t *arc;
+
+             for (arc = block->succ; arc; arc = arc->succ_next)
+               {
+                 arc->line_next = line->branches;
+                 line->branches = arc;
+                 if (coverage && !arc->is_unconditional)
+                   add_branch_counts (coverage, arc);
+               }
            }
        }
     }
-  if (!line)
+
+  if (!has_any_line)
     fnotice (stderr, "%s:no lines for '%s'\n", bbg_file_name, fn->name);
 }
 
@@ -2321,22 +2312,7 @@ accumulate_line_counts (source_t *src)
 
   for (ix = src->num_lines, line = src->lines; ix--; line++)
     {
-      if (!flag_all_blocks)
-       {
-         arc_t *arc, *arc_p, *arc_n;
-
-         /* Total and reverse the branch information.  */
-         for (arc = line->u.branches, arc_p = NULL; arc;
-              arc_p = arc, arc = arc_n)
-           {
-             arc_n = arc->line_next;
-             arc->line_next = arc_p;
-
-             add_branch_counts (&src->coverage, arc);
-           }
-         line->u.branches = arc_p;
-       }
-      else if (line->u.blocks)
+      if (line->blocks)
        {
          /* The user expects the line count to be the number of times
             a line has been executed. Simply summing the block count
@@ -2348,17 +2324,17 @@ accumulate_line_counts (source_t *src)
          gcov_type count = 0;
 
          /* Reverse the block information.  */
-         for (block = line->u.blocks, block_p = NULL; block;
+         for (block = line->blocks, block_p = NULL; block;
               block_p = block, block = block_n)
            {
              block_n = block->chain;
              block->chain = block_p;
              block->cycle.ident = ix;
            }
-         line->u.blocks = block_p;
+         line->blocks = block_p;
 
          /* Sum the entry arcs.  */
-         for (block = line->u.blocks; block; block = block->chain)
+         for (block = line->blocks; block; block = block->chain)
            {
              arc_t *arc;
 
@@ -2368,7 +2344,7 @@ accumulate_line_counts (source_t *src)
            }
 
          /* Cycle detection.  */
-         for (block = line->u.blocks; block; block = block->chain)
+         for (block = line->blocks; block; block = block->chain)
            {
              for (arc_t *arc = block->pred; arc; arc = arc->pred_next)
                if (!line->has_block (arc->src))
@@ -2554,7 +2530,7 @@ output_lines (FILE *gcov_file, const source_t *src)
          arc_t *arc;
          int ix, jx;
 
-         for (ix = jx = 0, block = line->u.blocks; block;
+         for (ix = jx = 0, block = line->blocks; block;
               block = block->chain)
            {
              if (!block->is_call_return)
@@ -2578,7 +2554,7 @@ output_lines (FILE *gcov_file, const source_t *src)
          int ix;
          arc_t *arc;
 
-         for (ix = 0, arc = line->u.branches; arc; arc = arc->line_next)
+         for (ix = 0, arc = line->branches; arc; arc = arc->line_next)
            ix += output_branch_count (gcov_file, ix, arc);
        }
     }
index c7eed0e3dfddf5811628a2032c208653245b96c3..3346af4e961ac77b34805c1dcc273b4ae4d2c6a7 100644 (file)
@@ -941,29 +941,26 @@ output_location (char const *file_name, int line,
   name_differs = !prev_file_name || filename_cmp (file_name, prev_file_name);
   line_differs = prev_line != line;
 
-  if (name_differs || line_differs)
+  if (!*offset)
     {
-      if (!*offset)
-       {
-         *offset = gcov_write_tag (GCOV_TAG_LINES);
-         gcov_write_unsigned (bb->index);
-         name_differs = line_differs=true;
-       }
+      *offset = gcov_write_tag (GCOV_TAG_LINES);
+      gcov_write_unsigned (bb->index);
+      name_differs = line_differs = true;
+    }
 
-      /* If this is a new source file, then output the
-        file's name to the .bb file.  */
-      if (name_differs)
-       {
-         prev_file_name = file_name;
-         gcov_write_unsigned (0);
-         gcov_write_string (prev_file_name);
-       }
-      if (line_differs)
-       {
-         gcov_write_unsigned (line);
-         prev_line = line;
-       }
-     }
+  /* If this is a new source file, then output the
+     file's name to the .bb file.  */
+  if (name_differs)
+    {
+      prev_file_name = file_name;
+      gcov_write_unsigned (0);
+      gcov_write_string (prev_file_name);
+    }
+  if (line_differs)
+    {
+      gcov_write_unsigned (line);
+      prev_line = line;
+    }
 }
 
 /* Instrument and/or analyze program behavior based on program the CFG.
index a33c19a5b76655a8a18a7f8e8df7309081e48620..cf3199b8ed5c96d9f8d819ccbe7cf60bdf7c6dc2 100644 (file)
@@ -1,3 +1,9 @@
+2017-04-28  Martin Liska  <mliska@suse.cz>
+
+       PR gcov-profile/79891
+       * gcc.misc-tests/gcov-17.c: New test.
+       * gcc.misc-tests/gcov-18.c: New test.
+
 2017-04-28  Tom de Vries  <tom@codesourcery.com>
 
        * g++.dg/parse/error2.C: Remove superfluous '{ target *-*-* }' in
diff --git a/gcc/testsuite/gcc.misc-tests/gcov-17.c b/gcc/testsuite/gcc.misc-tests/gcov-17.c
new file mode 100644 (file)
index 0000000..e388608
--- /dev/null
@@ -0,0 +1,51 @@
+/* Test gcov block mode.  Compiler generates following CFG:
+
+  <bb 3>:
+  if (false_var_4 != 0)
+    goto <bb 4>;
+  else
+    goto <bb 5>;
+
+  <bb 4>:
+  ret_6 = 111;
+  PROF_edge_counter_10 = __gcov0.UuT[0];
+  PROF_edge_counter_11 = PROF_edge_counter_10 + 1;
+  __gcov0.UuT[0] = PROF_edge_counter_11;
+
+  <bb 5>:
+  # ret_1 = PHI <ret_5(3), ret_6(4)>
+  goto <bb 7>;
+
+It's important not to include <bb 5> to any line as it's actually shared
+by both branches of the condition in <bb 3>.
+
+*/
+
+/* { dg-options "-fprofile-arcs -ftest-coverage" } */
+/* { dg-do run { target native } } */
+
+unsigned int
+UuT (void)
+{
+  unsigned int true_var = 1;
+  unsigned int false_var = 0;
+  unsigned int ret = 0;
+
+  if (true_var) /* count(1) */
+    {
+      if (false_var) /* count(1) */
+       ret = 111; /* count(#####) */
+    }
+  else
+    ret = 999; /* count(#####) */
+  return ret;
+}
+
+int
+main (int argc, char **argv)
+{
+  UuT ();
+  return 0;
+}
+
+/* { dg-final { run-gcov { -a gcov-17.c } } } */
diff --git a/gcc/testsuite/gcc.misc-tests/gcov-18.c b/gcc/testsuite/gcc.misc-tests/gcov-18.c
new file mode 100644 (file)
index 0000000..ae10178
--- /dev/null
@@ -0,0 +1,29 @@
+/* Test gcov block mode. As the example does jump to a statement
+   that is on a line with different ones, we must calculate such jump
+   just once.  */
+
+/* { dg-options "-fprofile-arcs -ftest-coverage" } */
+/* { dg-do run { target native } } */
+
+int a = 0;
+
+void foo() /* count(1) */
+{
+  a = 1;
+}
+
+void bar() /* count(1) */
+{
+  a++;
+}
+
+int main() /* count(1) */
+{
+  foo (); goto baz; lab: bar (); /* count(2) */
+
+  baz:
+    if (a == 1) /* count(2) */
+      goto lab; /* count(1) */
+}
+
+/* { dg-final { run-gcov { gcov-18.c } } } */