The option prints TOP N counters in a stable format
usage for comparison (diff).

Will install the patch if there are no objections.

Patch can bootstrap on x86_64-linux-gnu and survives regression tests.

Martin

gcc/ChangeLog:

        * doc/gcov-dump.texi: Document the new option.
        * gcov-dump.cc (main): Parse the new option.
        (print_usage): Show the option.
        (tag_counters): Sort key:value pairs of TOP N counter.
---
 gcc/doc/gcov-dump.texi |  5 ++++
 gcc/gcov-dump.cc       | 61 +++++++++++++++++++++++++++++++++++++-----
 2 files changed, 59 insertions(+), 7 deletions(-)

diff --git a/gcc/doc/gcov-dump.texi b/gcc/doc/gcov-dump.texi
index 4f4e355dd28..0491ab17bc1 100644
--- a/gcc/doc/gcov-dump.texi
+++ b/gcc/doc/gcov-dump.texi
@@ -62,6 +62,7 @@ gcov-dump [@option{-v}|@option{--version}]
      [@option{-l}|@option{--long}]
      [@option{-p}|@option{--positions}]
      [@option{-r}|@option{--raw}]
+     [@option{-s}|@option{--stable}]
      @var{gcovfiles}
 @c man end
 @end ignore
@@ -85,6 +86,10 @@ Dump positions of records.
 @itemx --raw
 Print content records in raw format.
 
+@item -s
+@itemx --stable
+Print content in stable format usable for comparison.
+
 @item -v
 @itemx --version
 Display the @command{gcov-dump} version number (on the standard output),
diff --git a/gcc/gcov-dump.cc b/gcc/gcov-dump.cc
index 0804c794e9e..85b1be8859e 100644
--- a/gcc/gcov-dump.cc
+++ b/gcc/gcov-dump.cc
@@ -28,6 +28,10 @@ along with Gcov; see the file COPYING3.  If not see
 #include "gcov-io.h"
 #include "gcov-io.cc"
 
+#include <vector>
+
+using namespace std;
+
 static void dump_gcov_file (const char *);
 static void print_prefix (const char *, unsigned, gcov_position_t);
 static void print_usage (void);
@@ -50,6 +54,7 @@ typedef struct tag_format
 static int flag_dump_contents = 0;
 static int flag_dump_positions = 0;
 static int flag_dump_raw = 0;
+static int flag_dump_stable = 0;
 
 static const struct option options[] =
 {
@@ -57,7 +62,9 @@ static const struct option options[] =
   { "version",              no_argument,       NULL, 'v' },
   { "long",                 no_argument,       NULL, 'l' },
   { "positions",           no_argument,       NULL, 'o' },
-  { 0, 0, 0, 0 }
+  { "raw",                 no_argument,       NULL, 'r' },
+  { "stable",              no_argument,       NULL, 's' },
+  {}
 };
 
 #define VALUE_PADDING_PREFIX "              "
@@ -96,7 +103,7 @@ main (int argc ATTRIBUTE_UNUSED, char **argv)
 
   diagnostic_initialize (global_dc, 0);
 
-  while ((opt = getopt_long (argc, argv, "hlprvw", options, NULL)) != -1)
+  while ((opt = getopt_long (argc, argv, "hlprsvw", options, NULL)) != -1)
     {
       switch (opt)
        {
@@ -115,6 +122,9 @@ main (int argc ATTRIBUTE_UNUSED, char **argv)
        case 'r':
          flag_dump_raw = 1;
          break;
+       case 's':
+         flag_dump_stable = 1;
+         break;
        default:
          fprintf (stderr, "unknown flag `%c'\n", opt);
        }
@@ -134,6 +144,8 @@ print_usage (void)
   printf ("  -l, --long           Dump record contents too\n");
   printf ("  -p, --positions      Dump record positions\n");
   printf ("  -r, --raw            Print content records in raw format\n");
+  printf ("  -s, --stable         Print content in stable "
+         "format usable for comparison\n");
   printf ("  -v, --version        Print version number\n");
   printf ("\nFor bug reporting instructions, please see:\n%s.\n",
           bug_report_url);
@@ -439,16 +451,52 @@ tag_counters (const char *filename ATTRIBUTE_UNUSED,
   int n_counts = GCOV_TAG_COUNTER_NUM (length);
   bool has_zeros = n_counts < 0;
   n_counts = abs (n_counts);
+  unsigned counter_idx = GCOV_COUNTER_FOR_TAG (tag);
 
   printf (" %s %u counts%s",
-         counter_names[GCOV_COUNTER_FOR_TAG (tag)], n_counts,
+         counter_names[counter_idx], n_counts,
          has_zeros ? " (all zero)" : "");
   if (flag_dump_contents)
     {
+      vector<gcov_type> counters;
       for (int ix = 0; ix != n_counts; ix++)
+       counters.push_back (has_zeros ? 0 : gcov_read_counter ());
+
+      /* Make stable sort for TOP N counters.  */
+      if (flag_dump_stable)
+       if (counter_idx == GCOV_COUNTER_V_INDIR
+           || counter_idx == GCOV_COUNTER_V_TOPN)
+         {
+           unsigned start = 0;
+           while (start < counters.size ())
+             {
+               unsigned n = counters[start + 1];
+
+               /* Use bubble sort.  */
+               for (unsigned i = 1; i <= n; ++i)
+                 for (unsigned j = i; j <= n; ++j)
+                   {
+                     gcov_type key1 = counters[start + 2 * i];
+                     gcov_type value1 = counters[start + 2 * i + 1];
+                     gcov_type key2 = counters[start + 2 * j];
+                     gcov_type value2 = counters[start + 2 * j + 1];
+
+                     if (value1 < value2 || (value1 == value2 && key1 < key2))
+                       {
+                         std::swap (counters[start + 2 * i],
+                                    counters[start + 2 * j]);
+                         std::swap (counters[start + 2 * i + 1],
+                                    counters[start + 2 * j + 1]);
+                       }
+                   }
+               start += 2 * (n + 1);
+             }
+           if (start != counters.size ())
+             abort ();
+         }
+
+      for (unsigned ix = 0; ix < counters.size (); ++ix)
        {
-         gcov_type count;
-
          if (flag_dump_raw)
            {
              if (ix == 0)
@@ -461,8 +509,7 @@ tag_counters (const char *filename ATTRIBUTE_UNUSED,
              printf (VALUE_PADDING_PREFIX VALUE_PREFIX, ix);
            }
 
-         count = has_zeros ? 0 : gcov_read_counter ();
-         printf ("%" PRId64 " ", count);
+         printf ("%" PRId64 " ", counters[ix]);
        }
     }
 }
-- 
2.37.1

Reply via email to