re PR tree-optimization/85529 (wrong code at -O2 and -O3 on x86_64-linux-gnu)
authorJakub Jelinek <jakub@redhat.com>
Fri, 27 Apr 2018 07:09:51 +0000 (09:09 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 27 Apr 2018 07:09:51 +0000 (09:09 +0200)
PR tree-optimization/85529
* tree-ssa-reassoc.c (optimize_range_tests_var_bound): Add FIRST_BB
argument.  Don't call get_nonzero_bits if opcode is ERROR_MARK_NODE,
rhs2 def stmt's bb is dominated by first_bb and it isn't an obvious
zero extension or masking of the MSB bit.
(optimize_range_tests): Add FIRST_BB argument, pass it through
to optimize_range_tests_var_bound.
(maybe_optimize_range_tests, reassociate_bb): Adjust
optimize_range_tests callers.

* gcc.c-torture/execute/pr85529-1.c: New test.
* gcc.c-torture/execute/pr85529-2.c: New test.
* gcc.dg/pr85529.c: New test.

From-SVN: r259696

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr85529-1.c [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/execute/pr85529-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr85529.c [new file with mode: 0644]
gcc/tree-ssa-reassoc.c

index 617fc36..723f85b 100644 (file)
@@ -1,3 +1,15 @@
+2018-04-27  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/85529
+       * tree-ssa-reassoc.c (optimize_range_tests_var_bound): Add FIRST_BB
+       argument.  Don't call get_nonzero_bits if opcode is ERROR_MARK_NODE,
+       rhs2 def stmt's bb is dominated by first_bb and it isn't an obvious
+       zero extension or masking of the MSB bit.
+       (optimize_range_tests): Add FIRST_BB argument, pass it through
+       to optimize_range_tests_var_bound.
+       (maybe_optimize_range_tests, reassociate_bb): Adjust
+       optimize_range_tests callers.
+
 2018-04-26  Richard Biener  <rguenther@suse.de>
            Jakub Jelinek  <jakub@redhat.com>
 
index 9720593..fd71303 100644 (file)
@@ -1,3 +1,10 @@
+2018-04-27  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/85529
+       * gcc.c-torture/execute/pr85529-1.c: New test.
+       * gcc.c-torture/execute/pr85529-2.c: New test.
+       * gcc.dg/pr85529.c: New test.
+
 2018-04-26  Maciej W. Rozycki  <macro@mips.com>
 
        * gcc.target/mips/data-sym-pool.c (dg-options): Match `ld' and
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr85529-1.c b/gcc/testsuite/gcc.c-torture/execute/pr85529-1.c
new file mode 100644 (file)
index 0000000..83d5cdd
--- /dev/null
@@ -0,0 +1,28 @@
+/* PR tree-optimization/85529 */
+
+struct S { int a; };
+
+int b, c = 1, d, e, f;
+static int g;
+volatile struct S s;
+
+signed char
+foo (signed char i, int j)
+{
+  return i < 0 ? i : i << j;
+}
+
+int
+main ()
+{
+  signed char k = -83;
+  if (!d)
+    goto L;
+  k = e || f;
+L:
+  for (; b < 1; b++)
+    s.a != (k < foo (k, 2) && (c = k = g));
+  if (c != 1)
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr85529-2.c b/gcc/testsuite/gcc.c-torture/execute/pr85529-2.c
new file mode 100644 (file)
index 0000000..5de3084
--- /dev/null
@@ -0,0 +1,25 @@
+/* PR tree-optimization/85529 */
+
+__attribute__((noipa)) int
+foo (int x)
+{
+  x &= 63;
+  x -= 50;
+  x |= 1;
+  if (x < 0)
+    return 1;
+  int y = x >> 2;
+  if (x >= y)
+    return 1;
+  return 0;
+}
+
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 63; i++)
+    if (foo (i) != 1)
+      __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr85529.c b/gcc/testsuite/gcc.dg/pr85529.c
new file mode 100644 (file)
index 0000000..0b73228
--- /dev/null
@@ -0,0 +1,27 @@
+/* PR tree-optimization/85529 */
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-ssa-phiopt" } */
+
+__attribute__((noinline, noclone)) int
+foo (int x)
+{
+  x &= 31;
+  x -= 25;
+  x *= 2;
+  if (x < 0)
+    return 1;
+  int y = x >> 2;
+  if (x >= y)
+    return 1;
+  return 0;
+}
+
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 63; i++)
+    if (foo (i) != 1)
+      __builtin_abort ();
+  return 0;
+}
index 0e59bb5..38bae77 100644 (file)
@@ -3035,7 +3035,8 @@ optimize_range_tests_cmp_bitwise (enum tree_code opcode, int first, int length,
 static bool
 optimize_range_tests_var_bound (enum tree_code opcode, int first, int length,
                                vec<operand_entry *> *ops,
-                               struct range_entry *ranges)
+                               struct range_entry *ranges,
+                               basic_block first_bb)
 {
   int i;
   bool any_changes = false;
@@ -3143,6 +3144,60 @@ optimize_range_tests_var_bound (enum tree_code opcode, int first, int length,
       if (idx == NULL)
        continue;
 
+      /* maybe_optimize_range_tests allows statements without side-effects
+        in the basic blocks as long as they are consumed in the same bb.
+        Make sure rhs2's def stmt is not among them, otherwise we can't
+        use safely get_nonzero_bits on it.  E.g. in:
+         # RANGE [-83, 1] NONZERO 173
+         # k_32 = PHI <k_47(13), k_12(9)>
+        ...
+         if (k_32 >= 0)
+           goto <bb 5>; [26.46%]
+         else
+           goto <bb 9>; [73.54%]
+
+         <bb 5> [local count: 140323371]:
+         # RANGE [0, 1] NONZERO 1
+         _5 = (int) k_32;
+         # RANGE [0, 4] NONZERO 4
+         _21 = _5 << 2;
+         # RANGE [0, 4] NONZERO 4
+         iftmp.0_44 = (char) _21;
+         if (k_32 < iftmp.0_44)
+           goto <bb 6>; [84.48%]
+         else
+           goto <bb 9>; [15.52%]
+        the ranges on _5/_21/iftmp.0_44 are flow sensitive, assume that
+        k_32 >= 0.  If we'd optimize k_32 >= 0 to true and k_32 < iftmp.0_44
+        to (unsigned) k_32 < (unsigned) iftmp.0_44, then we would execute
+        those stmts even for negative k_32 and the value ranges would be no
+        longer guaranteed and so the optimization would be invalid.  */
+      if (opcode == ERROR_MARK)
+       {
+         gimple *g = SSA_NAME_DEF_STMT (rhs2);
+         basic_block bb2 = gimple_bb (g);
+         if (bb2
+             && bb2 != first_bb
+             && dominated_by_p (CDI_DOMINATORS, bb2, first_bb))
+           {
+             /* As an exception, handle a few common cases.  */
+             if (gimple_assign_cast_p (g)
+                 && INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (g)))
+                 && TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (g)))
+                 && (TYPE_PRECISION (TREE_TYPE (rhs2))
+                     > TYPE_PRECISION (TREE_TYPE (gimple_assign_rhs1 (g)))))
+               /* Zero-extension is always ok.  */ ;
+             else if (is_gimple_assign (g)
+                      && gimple_assign_rhs_code (g) == BIT_AND_EXPR
+                      && TREE_CODE (gimple_assign_rhs2 (g)) == INTEGER_CST
+                      && !wi::neg_p (wi::to_wide (gimple_assign_rhs2 (g))))
+               /* Masking with INTEGER_CST with MSB clear is always ok
+                  too.  */ ;
+             else
+               continue;
+           }
+       }
+
       wide_int nz = get_nonzero_bits (rhs2);
       if (wi::neg_p (nz))
        continue;
@@ -3269,11 +3324,12 @@ optimize_range_tests_var_bound (enum tree_code opcode, int first, int length,
    maybe_optimize_range_tests for inter-bb range optimization.
    In that case if oe->op is NULL, oe->id is bb->index whose
    GIMPLE_COND is && or ||ed into the test, and oe->rank says
-   the actual opcode.  */
+   the actual opcode.
+   FIRST_BB is the first basic block if OPCODE is ERROR_MARK.  */
 
 static bool
 optimize_range_tests (enum tree_code opcode,
-                     vec<operand_entry *> *ops)
+                     vec<operand_entry *> *ops, basic_block first_bb)
 {
   unsigned int length = ops->length (), i, j, first;
   operand_entry *oe;
@@ -3353,7 +3409,7 @@ optimize_range_tests (enum tree_code opcode,
   any_changes |= optimize_range_tests_cmp_bitwise (opcode, first, length,
                                                   ops, ranges);
   any_changes |= optimize_range_tests_var_bound (opcode, first, length, ops,
-                                                ranges);
+                                                ranges, first_bb);
 
   if (any_changes && opcode != ERROR_MARK)
     {
@@ -4100,7 +4156,7 @@ maybe_optimize_range_tests (gimple *stmt)
        break;
     }
   if (ops.length () > 1)
-    any_changes = optimize_range_tests (ERROR_MARK, &ops);
+    any_changes = optimize_range_tests (ERROR_MARK, &ops, first_bb);
   if (any_changes)
     {
       unsigned int idx, max_idx = 0;
@@ -5855,7 +5911,7 @@ reassociate_bb (basic_block bb)
                  if (is_vector)
                    optimize_vec_cond_expr (rhs_code, &ops);
                  else
-                   optimize_range_tests (rhs_code, &ops);
+                   optimize_range_tests (rhs_code, &ops, NULL);
                }
 
              if (rhs_code == MULT_EXPR && !is_vector)