re PR debug/81278 (-fcompare-debug failure (length))
authorJakub Jelinek <jakub@redhat.com>
Tue, 4 Jul 2017 18:51:02 +0000 (20:51 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 4 Jul 2017 18:51:02 +0000 (20:51 +0200)
PR debug/81278
* tree-vrp.c (compare_assert_loc): Turn into a function template
with stable template parameter.  Only test if a->e is NULL,
!a->e == !b->e has been verified already.  Use e == NULL or
e != NULL instead of e or ! e tests.  If stable is true, don't use
iterative_hash_expr, on the other side allow a or b or both NULL
and sort the NULLs last.
(process_assert_insertions): Sort using compare_assert_loc<false>
instead of compare_assert_loc, later sort using
compare_assert_loc<true> before calling process_assert_insertions_for
in a loop.  Use break instead of continue once seen NULL pointer.

From-SVN: r249975

gcc/ChangeLog
gcc/tree-vrp.c

index 46dd0898becfd748c817cdeba1146b60f4c1cdf2..d57f764b42de35dd3576ee91088ca4933d518416 100644 (file)
@@ -1,3 +1,17 @@
+2017-07-04  Jakub Jelinek  <jakub@redhat.com>
+
+       PR debug/81278
+       * tree-vrp.c (compare_assert_loc): Turn into a function template
+       with stable template parameter.  Only test if a->e is NULL,
+       !a->e == !b->e has been verified already.  Use e == NULL or
+       e != NULL instead of e or ! e tests.  If stable is true, don't use
+       iterative_hash_expr, on the other side allow a or b or both NULL
+       and sort the NULLs last.
+       (process_assert_insertions): Sort using compare_assert_loc<false>
+       instead of compare_assert_loc, later sort using
+       compare_assert_loc<true> before calling process_assert_insertions_for
+       in a loop.  Use break instead of continue once seen NULL pointer.
+
 2017-07-04  Thomas Preud'homme  <thomas.preudhomme@arm.com>
 
        * config/arm/driver-arm.c (arm_cpu_table): Add entry for ARM
index 9ca3924ea89c21645152347aabea48e606f60121..28205f197518969badc634248bd2b759c83cd4a8 100644 (file)
@@ -6393,20 +6393,37 @@ process_assert_insertions_for (tree name, assert_locus *loc)
   gcc_unreachable ();
 }
 
-/* Qsort helper for sorting assert locations.  */
+/* Qsort helper for sorting assert locations.  If stable is true, don't
+   use iterative_hash_expr because it can be unstable for -fcompare-debug,
+   on the other side some pointers might be NULL.  */
 
+template <bool stable>
 static int
 compare_assert_loc (const void *pa, const void *pb)
 {
   assert_locus * const a = *(assert_locus * const *)pa;
   assert_locus * const b = *(assert_locus * const *)pb;
-  if (! a->e && b->e)
+
+  /* If stable, some asserts might be optimized away already, sort
+     them last.  */
+  if (stable)
+    {
+      if (a == NULL)
+       return b != NULL;
+      else if (b == NULL)
+       return -1;
+    }
+
+  if (a->e == NULL && b->e != NULL)
     return 1;
-  else if (a->e && ! b->e)
+  else if (a->e != NULL && b->e == NULL)
     return -1;
 
+  /* After the above checks, we know that (a->e == NULL) == (b->e == NULL),
+     no need to test both a->e and b->e.  */
+
   /* Sort after destination index.  */
-  if (! a->e && ! b->e)
+  if (a->e == NULL)
     ;
   else if (a->e->dest->index > b->e->dest->index)
     return 1;
@@ -6419,11 +6436,27 @@ compare_assert_loc (const void *pa, const void *pb)
   else if (a->comp_code < b->comp_code)
     return -1;
 
+  hashval_t ha, hb;
+
+  /* E.g. if a->val is ADDR_EXPR of a VAR_DECL, iterative_hash_expr
+     uses DECL_UID of the VAR_DECL, so sorting might differ between
+     -g and -g0.  When doing the removal of redundant assert exprs
+     and commonization to successors, this does not matter, but for
+     the final sort needs to be stable.  */
+  if (stable)
+    {
+      ha = 0;
+      hb = 0;
+    }
+  else
+    {
+      ha = iterative_hash_expr (a->expr, iterative_hash_expr (a->val, 0));
+      hb = iterative_hash_expr (b->expr, iterative_hash_expr (b->val, 0));
+    }
+
   /* Break the tie using hashing and source/bb index.  */
-  hashval_t ha = iterative_hash_expr (a->expr, iterative_hash_expr (a->val, 0));
-  hashval_t hb = iterative_hash_expr (b->expr, iterative_hash_expr (b->val, 0));
   if (ha == hb)
-    return (a->e && b->e
+    return (a->e != NULL
            ? a->e->src->index - b->e->src->index
            : a->bb->index - b->bb->index);
   return ha - hb;
@@ -6452,7 +6485,7 @@ process_assert_insertions (void)
       auto_vec<assert_locus *, 16> asserts;
       for (; loc; loc = loc->next)
        asserts.safe_push (loc);
-      asserts.qsort (compare_assert_loc);
+      asserts.qsort (compare_assert_loc<false>);
 
       /* Push down common asserts to successors and remove redundant ones.  */
       unsigned ecnt = 0;
@@ -6506,11 +6539,14 @@ process_assert_insertions (void)
            }
        }
 
+      /* The asserts vector sorting above might be unstable for
+        -fcompare-debug, sort again to ensure a stable sort.  */
+      asserts.qsort (compare_assert_loc<true>);
       for (unsigned j = 0; j < asserts.length (); ++j)
        {
          loc = asserts[j];
          if (! loc)
-           continue;
+           break;
          update_edges_p |= process_assert_insertions_for (ssa_name (i), loc);
          num_asserts++;
          free (loc);