Output branches and calls in gcov function summaries

Message ID 20240227163543.2101976-1-j@lambda.is
State New
Headers
Series Output branches and calls in gcov function summaries |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Testing passed
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_gcc_check--master-arm success Testing passed
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 success Testing passed

Commit Message

Jørgen Kvalsvik Feb. 27, 2024, 4:35 p.m. UTC
  The gcov function summaries only output the covered lines, not the
branches and calls. Since the function summaries is an opt-in it
probably makes sense to also include branch coverage. Simply adds the
branch- and call information to the function-summaries output.

$ gcc --coverage hello.c -o hello
$ ./hello

Before:
    $ gcov -f hello
    Function 'main'
    Lines executed:100.00% of 4

    Function 'fn'
    Lines executed:100.00% of 7

    File 'hello.c'
    Lines executed:100.00% of 11
    Creating 'hello.c.gcov'

After:
    $ gcov -f hello
    Function 'main'
    Lines executed:100.00% of 3
    No branches
    Calls executed:100.00% of 1

    Function 'fn'
    Lines executed:100.00% of 7
    Branches executed:100.00% of 4
    Taken at least once:50.00% of 4
    No calls

    File 'hello.c'
    Lines executed:100.00% of 10
    Creating 'hello.c.gcov'

    Lines executed:100.00% of 10

gcc/ChangeLog:

	* gcov.cc (generate_results): Count branches.
	(function_summary): Output branch count.
---
 gcc/gcov.cc | 32 +++++++++++++++++++++++++++++---
 1 file changed, 29 insertions(+), 3 deletions(-)

---

I am unsure if it is intentional for the function-summaries to be line
only, but I did find it a bit odd, so I submit this patch for feedback.
If this is ok we could also look into refactoring the summaries
slightly, to bring together the printing function- and file summaries.

---
  

Patch

diff --git a/gcc/gcov.cc b/gcc/gcov.cc
index 2fad6aa7ede..4b9aafa543c 100644
--- a/gcc/gcov.cc
+++ b/gcc/gcov.cc
@@ -1530,11 +1530,18 @@  generate_results (const char *file_name)
       memset (&coverage, 0, sizeof (coverage));
       coverage.name = fn->get_name ();
       add_line_counts (flag_function_summary ? &coverage : NULL, fn);
-      if (flag_function_summary)
+
+      if (!flag_function_summary)
+	continue;
+
+      for (const block_info& block : fn->blocks)
 	{
-	  function_summary (&coverage);
-	  fnotice (stdout, "\n");
+	  for (arc_info *arc = block.succ; arc; arc = arc->succ_next)
+	    add_branch_counts (&coverage, arc);
 	}
+
+      function_summary (&coverage);
+      fnotice (stdout, "\n");
     }
 
   name_map needle;
@@ -2528,6 +2535,25 @@  function_summary (const coverage_info *coverage)
 {
   fnotice (stdout, "%s '%s'\n", "Function", coverage->name);
   executed_summary (coverage->lines, coverage->lines_executed);
+
+  if (coverage->branches)
+    {
+      fnotice (stdout, "Branches executed:%s of %d\n",
+	       format_gcov (coverage->branches_executed, coverage->branches, 2),
+	       coverage->branches);
+      fnotice (stdout, "Taken at least once:%s of %d\n",
+	       format_gcov (coverage->branches_taken, coverage->branches, 2),
+			    coverage->branches);
+    }
+  else
+    fnotice (stdout, "No branches\n");
+
+  if (coverage->calls)
+    fnotice (stdout, "Calls executed:%s of %d\n",
+	     format_gcov (coverage->calls_executed, coverage->calls, 2),
+	     coverage->calls);
+  else
+    fnotice (stdout, "No calls\n");
 }
 
 /* Output summary info for a file.  */