re PR middle-end/68067 (Wrong constant folding)
authorRichard Biener <rguenther@suse.de>
Wed, 28 Oct 2015 10:01:23 +0000 (10:01 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Wed, 28 Oct 2015 10:01:23 +0000 (10:01 +0000)
2015-10-28  Richard Biener  <rguenther@suse.de>

PR middle-end/68067
* fold-const.c (negate_expr_p): We cannot negate plus or minus
if overflow is not wrapping.  Likewise multiplication unless
one operand is constant and not power of two.
(fold_negate_expr): Adjust accordingly.

* gcc.dg/torture/pr68067-1.c: New testcase.
* gcc.dg/torture/pr68067-2.c: Likewise.

From-SVN: r229479

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr68067-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/pr68067-2.c [new file with mode: 0644]

index 463e6012d0015738e3d3c02229ed23a8f1f42345..af9963f9688fce6a1d776ab8bc989198abd97620 100644 (file)
@@ -1,3 +1,11 @@
+2015-10-28  Richard Biener  <rguenther@suse.de>
+
+       PR middle-end/68067
+       * fold-const.c (negate_expr_p): We cannot negate plus or minus
+       if overflow is not wrapping.  Likewise multiplication unless
+       one operand is constant and not power of two.
+       (fold_negate_expr): Adjust accordingly.
+
 2015-10-27  Nathan Sidwell  <nathan@codesourcery.com>
 
        * omp-low.c (struct omp_context): Remove gwv_below, gwv_this
index e8ff1de13b65234d160275bcb9d0d41445a7c058..61801cbefee5ac0823733fc673d01b4c3609e515 100644 (file)
@@ -443,7 +443,9 @@ negate_expr_p (tree t)
 
     case PLUS_EXPR:
       if (HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type))
-         || HONOR_SIGNED_ZEROS (element_mode (type)))
+         || HONOR_SIGNED_ZEROS (element_mode (type))
+         || (INTEGRAL_TYPE_P (type)
+             && ! TYPE_OVERFLOW_WRAPS (type)))
        return false;
       /* -(A + B) -> (-B) - A.  */
       if (negate_expr_p (TREE_OPERAND (t, 1))
@@ -457,12 +459,23 @@ negate_expr_p (tree t)
       /* We can't turn -(A-B) into B-A when we honor signed zeros.  */
       return !HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type))
             && !HONOR_SIGNED_ZEROS (element_mode (type))
+            && (! INTEGRAL_TYPE_P (type)
+                || TYPE_OVERFLOW_WRAPS (type))
             && reorder_operands_p (TREE_OPERAND (t, 0),
                                    TREE_OPERAND (t, 1));
 
     case MULT_EXPR:
-      if (TYPE_UNSIGNED (TREE_TYPE (t)))
-        break;
+      if (TYPE_UNSIGNED (type))
+       break;
+      /* INT_MIN/n * n doesn't overflow while negating one operand it does
+         if n is a power of two.  */
+      if (INTEGRAL_TYPE_P (TREE_TYPE (t))
+         && ! TYPE_OVERFLOW_WRAPS (TREE_TYPE (t))
+         && ! ((TREE_CODE (TREE_OPERAND (t, 0)) == INTEGER_CST
+                && ! integer_pow2p (TREE_OPERAND (t, 0)))
+               || (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST
+                   && ! integer_pow2p (TREE_OPERAND (t, 1)))))
+       break;
 
       /* Fall through.  */
 
index 59633302423e9b01c5769d0ca6484823cbd6d686..9d7a47c6b3b9bbdf123ff4e4e50677310918c6b6 100644 (file)
@@ -1,3 +1,9 @@
+2015-10-28  Richard Biener  <rguenther@suse.de>
+
+       PR middle-end/68067
+       * gcc.dg/torture/pr68067-1.c: New testcase.
+       * gcc.dg/torture/pr68067-2.c: Likewise.
+
 2015-10-28  Segher Boessenkool  <segher@kernel.crashing.org>
 
        * gcc.target/powerpc/p8vector-builtin-8.c: Add "target int128".
diff --git a/gcc/testsuite/gcc.dg/torture/pr68067-1.c b/gcc/testsuite/gcc.dg/torture/pr68067-1.c
new file mode 100644 (file)
index 0000000..a7b6aa0
--- /dev/null
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+
+int main()
+{
+  int a = -1;
+  static int b = -2147483647 - 1;
+  static int c = 0;
+  int t = a - (b - c);
+  if (t != 2147483647)
+    __builtin_abort();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr68067-2.c b/gcc/testsuite/gcc.dg/torture/pr68067-2.c
new file mode 100644 (file)
index 0000000..38a459b
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+
+int main()
+{
+  int a = -1;
+  static int b = -2147483647 - 1;
+  static int c = 0;
+  int t = a - (b + c*-2);
+  if (t != 2147483647)
+    __builtin_abort();
+  return 0;
+}
+