diff mbox series

Fix PR85574

Message ID alpine.LSU.2.20.1805040921060.24704@zhemvz.fhfr.qr
State New
Headers show
Series Fix PR85574 | expand

Commit Message

Richard Biener May 4, 2018, 7:23 a.m. UTC
The PR correctly notices that we cannot transform -((a-b)/c) to
(b-a)/c if a-b == b-a == INT_MIN because we are then changing
the results sign if c != 1.  Thus the following patch restricts
this transform/predicate further.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

2018-05-04  Richard Biener  <rguenther@suse.de>

	PR middle-end/85574
	* fold-const.c (negate_expr_p): Restrict negation of operand
	zero of a division to when we know that can happen without
	overflow.
	(fold_negate_expr_1): Likewise.

	* gcc.dg/torture/pr85574.c: New testcase.
	* gcc.dg/torture/pr57656.c: Use dg-additional-options.
diff mbox series

Patch

Index: gcc/testsuite/gcc.dg/torture/pr85574.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr85574.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/torture/pr85574.c	(working copy)
@@ -0,0 +1,4 @@ 
+/* { dg-do run } */
+/* { dg-additional-options "-fwrapv" } */
+
+#include "pr57656.c"
Index: gcc/testsuite/gcc.dg/torture/pr57656.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr57656.c	(revision 259879)
+++ gcc/testsuite/gcc.dg/torture/pr57656.c	(working copy)
@@ -1,5 +1,5 @@ 
 /* { dg-do run } */
-/* { dg-options "-fstrict-overflow" } */
+/* { dg-additional-options "-fstrict-overflow" } */
 
 int main (void)
 {
Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c	(revision 259879)
+++ gcc/fold-const.c	(working copy)
@@ -474,12 +474,15 @@  negate_expr_p (tree t)
     case EXACT_DIV_EXPR:
       if (TYPE_UNSIGNED (type))
 	break;
-      if (negate_expr_p (TREE_OPERAND (t, 0)))
+      /* In general we can't negate A in A / B, because if A is INT_MIN and
+         B is not 1 we change the sign of the result.  */
+      if (TREE_CODE (TREE_OPERAND (t, 0)) == INTEGER_CST
+	  && negate_expr_p (TREE_OPERAND (t, 0)))
 	return true;
       /* In general we can't negate B in A / B, because if A is INT_MIN and
 	 B is 1, we may turn this into INT_MIN / -1 which is undefined
 	 and actually traps on some architectures.  */
-      if (! INTEGRAL_TYPE_P (TREE_TYPE (t))
+      if (! ANY_INTEGRAL_TYPE_P (TREE_TYPE (t))
 	  || TYPE_OVERFLOW_WRAPS (TREE_TYPE (t))
 	  || (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST
 	      && ! integer_onep (TREE_OPERAND (t, 1))))
@@ -652,14 +655,17 @@  fold_negate_expr_1 (location_t loc, tree
     case EXACT_DIV_EXPR:
       if (TYPE_UNSIGNED (type))
 	break;
-      if (negate_expr_p (TREE_OPERAND (t, 0)))
+      /* In general we can't negate A in A / B, because if A is INT_MIN and
+	 B is not 1 we change the sign of the result.  */
+      if (TREE_CODE (TREE_OPERAND (t, 0)) == INTEGER_CST
+	  && negate_expr_p (TREE_OPERAND (t, 0)))
 	return fold_build2_loc (loc, TREE_CODE (t), type,
 				negate_expr (TREE_OPERAND (t, 0)),
 				TREE_OPERAND (t, 1));
       /* In general we can't negate B in A / B, because if A is INT_MIN and
 	 B is 1, we may turn this into INT_MIN / -1 which is undefined
 	 and actually traps on some architectures.  */
-      if ((! INTEGRAL_TYPE_P (TREE_TYPE (t))
+      if ((! ANY_INTEGRAL_TYPE_P (TREE_TYPE (t))
 	   || TYPE_OVERFLOW_WRAPS (TREE_TYPE (t))
 	   || (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST
 	       && ! integer_onep (TREE_OPERAND (t, 1))))