On 10/30/2017 01:35 PM, Nathan Sidwell wrote:
On 10/26/2017 04:11 AM, marxin wrote:
Human readable format is quite useful in my opinion. There's example:
-: 1:unsigned
14.00K: 2:loop (unsigned n, int value)
My first thought is 'why 2 decimal places'? That seems excessive. Zero surely
suffices?
Hi.
Agree.
Question is do we want to do it by default, or a new option is fine?
Note that all external tools using gcov should use intermediate format
which is obviously unchanged.
I don't think other tools do it by default.
Works for me/
+ [@option{-j}|@option{--human-numbers}]
man ls:
-h, --human-readable
with -l and/or -s, print human readable sizes (e.g., 1K 234M 2G)
Sadly '-h' is help (IIRC). but we could at least copy the long form.
Yep, copied.
+ const char *units[] = {"", "K", "M", "G", "Y", "P", "E", "Z"};
Those aren't right KMGTPEZY
http://www.npl.co.uk/reference/measurement-units/si-prefixes/
Ha, SI units. Last time I heart about it was at grammar school during Physics
classes ;)
Following that.
+ for (unsigned i = 0; i < sizeof (units); i++)
+ {
+ if (v < 1000.0f)
+ {
+ sprintf (buffer, "%3.2f%s", v, units[i]);
+ return buffer;
+ }
+
+ v /= 1000.0f;
+ }
that's going to fail on certain roundings. You're doing multiple divisions by
1000, which itself will have roundings. But more importantly, numbers after
scaling like 999.999 will round to 1000, and you probably don't want that.
This kind of formatting is tricky. My inclination is to keep it in the integer
domain. Determine a scaling factor. Divide once by that and then explicitly
round to nearest even[*] with a check for the 999.9 case. Then print as an
unsigned.
Done that.
Is the patch fine to be installed?
Martin
nathan
[*] I presume you're familiar with RNE? That's probably overkill and plain RN
would be adequate.
>From b14bed2b376dc60eb35c07c5521007d16b137c78 Mon Sep 17 00:00:00 2001
From: marxin <mli...@suse.cz>
Date: Thu, 26 Oct 2017 10:11:16 +0200
Subject: [PATCH 4/8] GCOV: add -j argument (human readable format).
Human readable format is quite useful in my opinion. There's example:
-: 4:unsigned
14k: 5:loop (unsigned n, int value) /* count(14k) */
-: 6:{
21M: 7: for (unsigned i = 0; i < n - 1; i++)
-: 8: {
21M: 9: value += i; /* count(21M) */
-: 10: }
-: 11:
14k: 12: return value;
-: 13:}
-: 14:
1: 15:int main(int argc, char **argv)
-: 16:{
1: 17: unsigned sum = 0;
7k: 18: for (unsigned i = 0; i < 7 * 1000; i++)
-: 19: {
7k: 20: sum += loop (1000, sum);
7k: 21: sum += loop (2000, sum); /* count(7k) */
-: 22: }
-: 23:
1: 24: return 0; /* count(1) */
-: 25:}
-: 26:
gcc/ChangeLog:
2017-10-23 Martin Liska <mli...@suse.cz>
* doc/gcov.texi: Document new option.
* gcov.c (print_usage): Likewise print it.
(process_args): Support the argument.
(format_count): New function.
(format_gcov): Use the function.
gcc/testsuite/ChangeLog:
2017-10-23 Martin Liska <mli...@suse.cz>
* g++.dg/gcov/loop.C: New test.
* lib/gcov.exp: Support human readable format for counts.
---
gcc/doc/gcov.texi | 5 +++++
gcc/gcov.c | 45 ++++++++++++++++++++++++++++++++++++++--
gcc/testsuite/g++.dg/gcov/loop.C | 27 ++++++++++++++++++++++++
gcc/testsuite/lib/gcov.exp | 2 +-
4 files changed, 76 insertions(+), 3 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/gcov/loop.C
diff --git a/gcc/doc/gcov.texi b/gcc/doc/gcov.texi
index e186ac6e1ea..5c4ba8a51a7 100644
--- a/gcc/doc/gcov.texi
+++ b/gcc/doc/gcov.texi
@@ -125,6 +125,7 @@ gcov [@option{-v}|@option{--version}] [@option{-h}|@option{--help}]
[@option{-d}|@option{--display-progress}]
[@option{-f}|@option{--function-summaries}]
[@option{-i}|@option{--intermediate-format}]
+ [@option{-j}|@option{--human-readable}]
[@option{-k}|@option{--use-colors}]
[@option{-l}|@option{--long-file-names}]
[@option{-m}|@option{--demangled-names}]
@@ -186,6 +187,10 @@ be used by @command{lcov} or other tools. The output is a single
The format of the intermediate @file{.gcov} file is plain text with
one entry per line
+@item -j
+@itemx --human-readable
+Write counts in human readable format (like 24k).
+
@smallexample
file:@var{source_file_name}
function:@var{line_number},@var{execution_count},@var{function_name}
diff --git a/gcc/gcov.c b/gcc/gcov.c
index f9334f96eb3..ff246c104e4 100644
--- a/gcc/gcov.c
+++ b/gcc/gcov.c
@@ -44,6 +44,7 @@ along with Gcov; see the file COPYING3. If not see
#include "color-macros.h"
#include <getopt.h>
+#include <math.h>
#include "md5.h"
@@ -393,6 +394,10 @@ static int flag_use_colors = 0;
static int flag_all_blocks = 0;
+/* Output human readable numbers. */
+
+static int flag_human_readable_numbers = 0;
+
/* Output summary info for each function. */
static int flag_function_summary = 0;
@@ -710,6 +715,7 @@ print_usage (int error_p)
fnotice (file, " -f, --function-summaries Output summaries for each function\n");
fnotice (file, " -h, --help Print this help, then exit\n");
fnotice (file, " -i, --intermediate-format Output .gcov file in intermediate text format\n");
+ fnotice (file, " -j, --human-readable Output human readable numbers\n");
fnotice (file, " -k, --use-colors Emit colored output\n");
fnotice (file, " -l, --long-file-names Use long output file names for included\n\
source files\n");
@@ -752,6 +758,7 @@ static const struct option options[] =
{ "branch-probabilities", no_argument, NULL, 'b' },
{ "branch-counts", no_argument, NULL, 'c' },
{ "intermediate-format", no_argument, NULL, 'i' },
+ { "human-readable", no_argument, NULL, 'j' },
{ "no-output", no_argument, NULL, 'n' },
{ "long-file-names", no_argument, NULL, 'l' },
{ "function-summaries", no_argument, NULL, 'f' },
@@ -775,7 +782,7 @@ process_args (int argc, char **argv)
{
int opt;
- const char *opts = "abcdfhiklmno:prs:uvwx";
+ const char *opts = "abcdfhijklmno:prs:uvwx";
while ((opt = getopt_long (argc, argv, opts, options, NULL)) != -1)
{
switch (opt)
@@ -798,6 +805,9 @@ process_args (int argc, char **argv)
case 'l':
flag_long_names = 1;
break;
+ case 'j':
+ flag_human_readable_numbers = 1;
+ break;
case 'k':
flag_use_colors = 1;
break;
@@ -1938,6 +1948,37 @@ add_branch_counts (coverage_t *coverage, const arc_t *arc)
}
}
+/* Format COUNT, if flag_human_readable_numbers is set, return it human
+ readable format. */
+
+static char const *
+format_count (gcov_type count)
+{
+ static char buffer[64];
+ float v = count;
+ const char *units = " kMGTPEZY";
+
+ if (count < 1000 || !flag_human_readable_numbers)
+ {
+ sprintf (buffer, "%" PRId64, count);
+ return buffer;
+ }
+
+ gcov_type divisor = 1;
+ for (unsigned i = 0; i < strlen (units); i++)
+ {
+ if (v < (1000 * divisor))
+ {
+ gcov_type r = (gcov_type)roundf (v / divisor);
+ sprintf (buffer, "%" PRId64 "%c", r, units[i]);
+ return buffer;
+ }
+ divisor *= 1000;
+ }
+
+ gcc_unreachable ();
+}
+
/* Format a GCOV_TYPE integer as either a percent ratio, or absolute
count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
If DP is zero, no decimal point is printed. Only print 100% when
@@ -1985,7 +2026,7 @@ format_gcov (gcov_type top, gcov_type bottom, int dp)
}
}
else
- sprintf (buffer, "%" PRId64, (int64_t)top);
+ return format_count (top);
return buffer;
}
diff --git a/gcc/testsuite/g++.dg/gcov/loop.C b/gcc/testsuite/g++.dg/gcov/loop.C
new file mode 100644
index 00000000000..7f3be5587af
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gcov/loop.C
@@ -0,0 +1,27 @@
+/* { dg-options "-fprofile-arcs -ftest-coverage" } */
+/* { dg-do run { target native } } */
+
+unsigned
+loop (unsigned n, int value) /* count(14k) */
+{
+ for (unsigned i = 0; i < n - 1; i++)
+ {
+ value += i; /* count(21M) */
+ }
+
+ return value;
+}
+
+int main(int argc, char **argv)
+{
+ unsigned sum = 0;
+ for (unsigned i = 0; i < 7 * 1000; i++)
+ {
+ sum += loop (1000, sum);
+ sum += loop (2000, sum); /* count(7k) */
+ }
+
+ return 0; /* count(1) */
+}
+
+/* { dg-final { run-gcov branches { -abj loop.C } } } */
diff --git a/gcc/testsuite/lib/gcov.exp b/gcc/testsuite/lib/gcov.exp
index 18adc71351a..ede01e70212 100644
--- a/gcc/testsuite/lib/gcov.exp
+++ b/gcc/testsuite/lib/gcov.exp
@@ -59,7 +59,7 @@ proc verify-lines { testname testcase file } {
while { [gets $fd line] >= 0 } {
# We want to match both "-" and "#####" as count as well as numbers,
# since we want to detect lines that shouldn't be marked as covered.
- if [regexp "^ *(\[^:]*): *(\[0-9\\-#]+):.*count\\((\[0-9\\-#=]+)\\)(.*)" \
+ if [regexp "^ *(\[^:]*): *(\[0-9\\-#]+):.*count\\((\[0-9\\-#=\\.kMGTPEZY]+)\\)(.*)" \
"$line" all is n shouldbe rest] {
if [regexp "^ *{(.*)}" $rest all xfailed] {
switch [dg-process-target $xfailed] {
--
2.14.3