[PATCH] Fix PR68067
Richard Biener
rguenther@suse.de
Tue Oct 27 12:50:00 GMT 2015
The following patch adjusts negate_expr_p to account for the fact
that we can't generally change a - (b - c) to (c - b) + a because
-INF - 0 is ok while 0 - -INF not. Similarly for a - (b + c).
While creating testcases I noticed that MULT_EXPR handling is bogus
as well as with -INF/2 * 2 neither operand can be negated safely.
I believe the division case is also still wrong but I refrained
from touching it with this patch.
Bootstrapped and tested on x86_64-unknown-linux-gnu.
Richard.
2015-10-27 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.
Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c (revision 229404)
+++ gcc/fold-const.c (working copy)
@@ -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: gcc/testsuite/gcc.dg/torture/pr68067-1.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr68067-1.c (revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr68067-1.c (working copy)
@@ -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;
+}
Index: gcc/testsuite/gcc.dg/torture/pr68067-2.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr68067-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr68067-2.c (working copy)
@@ -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;
+}
+
More information about the Gcc-patches
mailing list