Support N values in libgcov for single value counter type.
authorMartin Liska <mliska@suse.cz>
Wed, 3 Jul 2019 12:42:02 +0000 (14:42 +0200)
committerMartin Liska <marxin@gcc.gnu.org>
Wed, 3 Jul 2019 12:42:02 +0000 (12:42 +0000)
2019-07-03  Martin Liska  <mliska@suse.cz>

* gcc.dg/tree-prof/val-prof-2.c: Update scanned pattern
as we do now better.
2019-07-03  Martin Liska  <mliska@suse.cz>

* libgcov-merge.c (merge_single_value_set): Support N values.
* libgcov-profiler.c (__gcov_one_value_profiler_body): Likewise.

From-SVN: r273004

gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-prof/val-prof-2.c
libgcc/ChangeLog
libgcc/libgcov-merge.c
libgcc/libgcov-profiler.c

index 656b589..0214647 100644 (file)
@@ -1,3 +1,8 @@
+2019-07-03  Martin Liska  <mliska@suse.cz>
+
+       * gcc.dg/tree-prof/val-prof-2.c: Update scanned pattern
+       as we do now better.
+
 2019-07-03  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gnat.dg/specs/debug1.ads: New test.
index 8cb3c64..b3bbadf 100644 (file)
@@ -25,8 +25,5 @@ main ()
   return 0;
 }
 /* autofdo does not do value profiling so far */
-/* { dg-final-use-not-autofdo { scan-ipa-dump "Transformation done: mod power of 2" "profile" } } */
-/* This is part of code checking that n is power of 2, so we are sure that the transformation
-   didn't get optimized out.  */
-/* { dg-final-use-not-autofdo { scan-tree-dump "n_\[0-9\]* \\+ (4294967295|0x0*ffffffff)" "optimized"} } */
+/* { dg-final-use-not-autofdo { scan-ipa-dump "Transformation done: div/mod by constant 256" "profile" } } */
 /* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
index d69e55e..90183dc 100644 (file)
@@ -1,3 +1,8 @@
+2019-07-03  Martin Liska  <mliska@suse.cz>
+
+       * libgcov-merge.c (merge_single_value_set): Support N values.
+       * libgcov-profiler.c (__gcov_one_value_profiler_body): Likewise.
+
 2019-06-27  Ilia Diachkov  <ilia.diachkov@optimitech.com>
 
        * Makefile.in (USE_TM_CLONE_REGISTRY): New.
index f778cc4..8436700 100644 (file)
@@ -89,49 +89,53 @@ __gcov_merge_time_profile (gcov_type *counters, unsigned n_counters)
 static void
 merge_single_value_set (gcov_type *counters)
 {
-  unsigned j;
-  gcov_type value, counter;
-
   /* First value is number of total executions of the profiler.  */
   gcov_type all = gcov_get_counter_ignore_scaling (-1);
   counters[0] += all;
   ++counters;
 
+  /* Read all part values.  */
+  gcov_type read_counters[2 * GCOV_DISK_SINGLE_VALUES];
+
   for (unsigned i = 0; i < GCOV_DISK_SINGLE_VALUES; i++)
     {
-      value = gcov_get_counter_target ();
-      counter = gcov_get_counter_ignore_scaling (-1);
+      read_counters[2 * i] = gcov_get_counter_target ();
+      read_counters[2 * i + 1] = gcov_get_counter_ignore_scaling (-1);
+    }
 
-      if (counter == -1)
-       {
-         counters[1] = -1;
-         /* We can't return as we need to read all counters.  */
-         continue;
-       }
-      else if (counter == 0 || counters[1] == -1)
-       {
-         /* We can't return as we need to read all counters.  */
-         continue;
-       }
+  if (read_counters[1] == -1)
+    {
+      counters[1] = -1;
+      return;
+    }
+
+  for (unsigned i = 0; i < GCOV_DISK_SINGLE_VALUES; i++)
+    {
+      if (read_counters[2 * i + 1] == 0)
+       return;
 
+      unsigned j;
       for (j = 0; j < GCOV_DISK_SINGLE_VALUES; j++)
        {
-         if (counters[2 * j] == value)
+         if (counters[2 * j] == read_counters[2 * i])
            {
-             counters[2 * j + 1] += counter;
+             counters[2 * j + 1] += read_counters[2 * i + 1];
              break;
            }
          else if (counters[2 * j + 1] == 0)
            {
-             counters[2 * j] = value;
-             counters[2 * j + 1] = counter;
+             counters[2 * j] += read_counters[2 * i];
+             counters[2 * j + 1] += read_counters[2 * i + 1];
              break;
            }
        }
 
-      /* We haven't found a free slot for the value, mark overflow.  */
+      /* We haven't found a slot, bail out.  */
       if (j == GCOV_DISK_SINGLE_VALUES)
-       counters[1] = -1;
+       {
+         counters[1] = -1;
+         return;
+       }
     }
 }
 
index 9ba65b9..04d6f9c 100644 (file)
@@ -118,20 +118,44 @@ static inline void
 __gcov_one_value_profiler_body (gcov_type *counters, gcov_type value,
                                int use_atomic)
 {
-  if (value == counters[1])
-    counters[2]++;
-  else if (counters[2] == 0)
+  if (use_atomic)
+    __atomic_fetch_add (&counters[0], 1, __ATOMIC_RELAXED);
+  else
+    counters[0]++;
+
+  ++counters;
+
+  /* We have GCOV_DISK_SINGLE_VALUES as we can keep multiple values
+     next to each other.  */
+  unsigned sindex = 0;
+
+  for (unsigned i = 0; i < GCOV_DISK_SINGLE_VALUES; i++)
     {
-      counters[2] = 1;
-      counters[1] = value;
+      if (value == counters[2 * i])
+       {
+         if (use_atomic)
+           __atomic_fetch_add (&counters[2 * i + 1], 1, __ATOMIC_RELAXED);
+         else
+           counters[2 * i + 1]++;
+         return;
+       }
+      else if (counters[2 * i + 1] == 0)
+       {
+         /* We found an empty slot.  */
+         counters[2 * i] = value;
+         counters[2 * i + 1] = 1;
+         return;
+       }
+
+      if (counters[2 * i + 1] < counters[2 * sindex + 1])
+       sindex = i;
     }
-  else
-    counters[2]--;
 
+  /* We haven't found an empty slot, then decrement the smallest.  */
   if (use_atomic)
-    __atomic_fetch_add (&counters[0], 1, __ATOMIC_RELAXED);
+    __atomic_fetch_sub (&counters[2 * sindex + 1], 1, __ATOMIC_RELAXED);
   else
-    counters[0]++;
+    counters[2 * sindex + 1]--;
 }
 
 #ifdef L_gcov_one_value_profiler_v2