GCOV: add cache for streamed locations.
authorMartin Liska <mliska@suse.cz>
Tue, 31 Jul 2018 10:34:36 +0000 (12:34 +0200)
committerMartin Liska <marxin@gcc.gnu.org>
Tue, 31 Jul 2018 10:34:36 +0000 (10:34 +0000)
2018-07-31  Martin Liska  <mliska@suse.cz>

        PR gcov-profile/85338
        PR gcov-profile/85350
        PR gcov-profile/85372
        * profile.c (struct location_triplet): New.
(struct location_triplet_hash): Likewise.
(output_location): Do not output a BB that
        is already recorded for a line.
(branch_prob): Use streamed_locations.
2018-07-31  Martin Liska  <mliska@suse.cz>

        PR gcov-profile/85338
        PR gcov-profile/85350
        PR gcov-profile/85372
* gcc.misc-tests/gcov-pr85338.c: New test.
* gcc.misc-tests/gcov-pr85350.c: New test.
* gcc.misc-tests/gcov-pr85372.c: New test.

From-SVN: r263113

gcc/ChangeLog
gcc/profile.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.misc-tests/gcov-pr85338.c [new file with mode: 0644]
gcc/testsuite/gcc.misc-tests/gcov-pr85350.c [new file with mode: 0644]
gcc/testsuite/gcc.misc-tests/gcov-pr85372.c [new file with mode: 0644]

index b55f7a3f19bcda707735bfe6627aaf337b7d6972..ca678154c6439aae018acf25b43091c67176682d 100644 (file)
@@ -1,3 +1,14 @@
+2018-07-31  Martin Liska  <mliska@suse.cz>
+
+        PR gcov-profile/85338
+        PR gcov-profile/85350
+        PR gcov-profile/85372
+        * profile.c (struct location_triplet): New.
+       (struct location_triplet_hash): Likewise.
+       (output_location): Do not output a BB that
+        is already recorded for a line.
+       (branch_prob): Use streamed_locations.
+
 2018-07-31  Martin Liska  <mliska@suse.cz>
 
         PR gcov-profile/85370
index 00f37b657a4d988341ff80708921b1c8486ec8bc..cb51e0d4c51feba9942528f5e3ff8ba92c8c1976 100644 (file)
@@ -919,17 +919,90 @@ compute_value_histograms (histogram_values values, unsigned cfg_checksum,
     free (histogram_counts[t]);
 }
 
+/* Location triplet which records a location.  */
+struct location_triplet
+{
+  const char *filename;
+  int lineno;
+  int bb_index;
+};
+
+/* Traits class for streamed_locations hash set below.  */
+
+struct location_triplet_hash : typed_noop_remove <location_triplet>
+{
+  typedef location_triplet value_type;
+  typedef location_triplet compare_type;
+
+  static hashval_t
+  hash (const location_triplet &ref)
+  {
+    inchash::hash hstate (0);
+    if (ref.filename)
+      hstate.add_int (strlen (ref.filename));
+    hstate.add_int (ref.lineno);
+    hstate.add_int (ref.bb_index);
+    return hstate.end ();
+  }
+
+  static bool
+  equal (const location_triplet &ref1, const location_triplet &ref2)
+  {
+    return ref1.lineno == ref2.lineno
+      && ref1.bb_index == ref2.bb_index
+      && ref1.filename != NULL
+      && ref2.filename != NULL
+      && strcmp (ref1.filename, ref2.filename) == 0;
+  }
+
+  static void
+  mark_deleted (location_triplet &ref)
+  {
+    ref.lineno = -1;
+  }
+
+  static void
+  mark_empty (location_triplet &ref)
+  {
+    ref.lineno = -2;
+  }
+
+  static bool
+  is_deleted (const location_triplet &ref)
+  {
+    return ref.lineno == -1;
+  }
+
+  static bool
+  is_empty (const location_triplet &ref)
+  {
+    return ref.lineno == -2;
+  }
+};
+
+
+
+
 /* When passed NULL as file_name, initialize.
    When passed something else, output the necessary commands to change
    line to LINE and offset to FILE_NAME.  */
 static void
-output_location (char const *file_name, int line,
+output_location (hash_set<location_triplet_hash> *streamed_locations,
+                char const *file_name, int line,
                 gcov_position_t *offset, basic_block bb)
 {
   static char const *prev_file_name;
   static int prev_line;
   bool name_differs, line_differs;
 
+  location_triplet triplet;
+  triplet.filename = file_name;
+  triplet.lineno = line;
+  triplet.bb_index = bb ? bb->index : 0;
+
+  if (streamed_locations->add (triplet))
+    return;
+
   if (!file_name)
     {
       prev_file_name = NULL;
@@ -1018,6 +1091,8 @@ branch_prob (void)
   flow_call_edges_add (NULL);
   add_noreturn_fake_exit_edges ();
 
+  hash_set <location_triplet_hash> streamed_locations;
+
   /* We can't handle cyclic regions constructed using abnormal edges.
      To avoid these we replace every source of abnormal edge by a fake
      edge from entry node and every destination by fake edge to exit.
@@ -1254,7 +1329,7 @@ branch_prob (void)
 
       /* Line numbers.  */
       /* Initialize the output.  */
-      output_location (NULL, 0, NULL, NULL);
+      output_location (&streamed_locations, NULL, 0, NULL, NULL);
 
       hash_set<int_hash <location_t, 0, 2> > seen_locations;
 
@@ -1268,8 +1343,8 @@ branch_prob (void)
              location_t loc = DECL_SOURCE_LOCATION (current_function_decl);
              seen_locations.add (loc);
              expanded_location curr_location = expand_location (loc);
-             output_location (curr_location.file, curr_location.line,
-                              &offset, bb);
+             output_location (&streamed_locations, curr_location.file,
+                              curr_location.line, &offset, bb);
            }
 
          for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
@@ -1279,8 +1354,8 @@ branch_prob (void)
              if (!RESERVED_LOCATION_P (loc))
                {
                  seen_locations.add (loc);
-                 output_location (gimple_filename (stmt), gimple_lineno (stmt),
-                                  &offset, bb);
+                 output_location (&streamed_locations, gimple_filename (stmt),
+                                  gimple_lineno (stmt), &offset, bb);
                }
            }
 
@@ -1294,8 +1369,8 @@ branch_prob (void)
              && !seen_locations.contains (loc))
            {
              expanded_location curr_location = expand_location (loc);
-             output_location (curr_location.file, curr_location.line,
-                              &offset, bb);
+             output_location (&streamed_locations, curr_location.file,
+                              curr_location.line, &offset, bb);
            }
 
          if (offset)
index f726e24f3afb652c47bb817e317159ee401ec415..eaa6b19848743e7b3a4ba83aa93cbdee41ccb585 100644 (file)
@@ -1,3 +1,12 @@
+2018-07-31  Martin Liska  <mliska@suse.cz>
+
+        PR gcov-profile/85338
+        PR gcov-profile/85350
+        PR gcov-profile/85372
+       * gcc.misc-tests/gcov-pr85338.c: New test.
+       * gcc.misc-tests/gcov-pr85350.c: New test.
+       * gcc.misc-tests/gcov-pr85372.c: New test.
+
 2018-07-31  Martin Liska  <mliska@suse.cz>
 
         PR gcov-profile/83813
diff --git a/gcc/testsuite/gcc.misc-tests/gcov-pr85338.c b/gcc/testsuite/gcc.misc-tests/gcov-pr85338.c
new file mode 100644 (file)
index 0000000..d1e16d2
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-options "-fprofile-arcs -ftest-coverage" } */
+/* { dg-do run { target native } } */
+
+void Test(long long Val, int Amt)
+{
+  __builtin_printf("  lshr: 0x%llx \t\t shl: 0x%llx\n", Val >> Amt, Val << Amt);  /* count(1) */
+  __builtin_printf("  lshr: 0x%llx\t\tshl: 0x%llx\n",  /* count(1) */
+    Val >> Amt, Val << Amt);
+  __builtin_printf("  lshr: 0x%llx \t\t shl: 0x%llx\n",  /* count(1) */
+    (unsigned long long)Val >> Amt, Val << Amt);
+}
+
+int main()
+{
+  Test(10, 4);
+
+  return 0;
+}
+
+
+/* { dg-final { run-gcov gcov-pr85338.c } } */
diff --git a/gcc/testsuite/gcc.misc-tests/gcov-pr85350.c b/gcc/testsuite/gcc.misc-tests/gcov-pr85350.c
new file mode 100644 (file)
index 0000000..0383b81
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-options "-fprofile-arcs -ftest-coverage" } */
+/* { dg-do run { target native } } */
+
+int main (void)
+{
+  const int t = 2; /* count(1) */
+  struct s1 {  /* count(1) */
+    int x;
+    int g[t];
+  };
+
+  struct s2 {
+    int x;
+    int g[2];
+  };
+
+  __builtin_printf("Sucess!\n");
+  return 0;
+}
+
+/* { dg-final { run-gcov gcov-pr85350.c } } */
diff --git a/gcc/testsuite/gcc.misc-tests/gcov-pr85372.c b/gcc/testsuite/gcc.misc-tests/gcov-pr85372.c
new file mode 100644 (file)
index 0000000..7c90e68
--- /dev/null
@@ -0,0 +1,28 @@
+/* { dg-options "-fprofile-arcs -ftest-coverage" } */
+/* { dg-do run { target native } } */
+/* { dg-require-effective-target indirect_jumps } */
+
+void *buf[5];
+
+void fjmp (void) {
+  __builtin_longjmp (buf, 1);
+}
+
+int main(void)
+{
+  int last = 0;
+
+  if (__builtin_setjmp (buf) == 0) {   /* count(2) */
+    __builtin_printf("True  branch\n");
+    while (1) {
+      last = 1;        /* count(1) */
+      fjmp (); /* count(1) */
+    }
+  } else {
+    __builtin_printf("False branch\n");
+  }
+
+  return 0;
+}
+
+/* { dg-final { run-gcov gcov-pr85372.c } } */