diff mbox

Fix PR81227

Message ID alpine.LSU.2.20.1706281352250.23185@zhemvz.fhfr.qr
State New
Headers show

Commit Message

Richard Biener June 28, 2017, 11:57 a.m. UTC
The following avoids generating TREE_OVERFLOW constants from VRPs
avoidance (sic!) of them when generating MAX - 1 for symbolic 1-bit
ranges with -fwrapv.  The issue is that all constant folding is
agnostic of TREE_OVERFLOW_WRAPS but looks at TYPE_UNSIGNED only
and thus negation of signed -1 is overflowing even with -fwrapv but the 
negate_expr_p predicate says otherwise resulting in a + -1(OVF)
generated from a - -1.

I didn't feel like (had a dejavu with bad outcome) changing the
condition when to mark results with TREE_OVERFLOW and instead made
the predicates in negate_expr_p consistent with "overflow".

Bootstrapped and tested on x86_64-unknown-linux-gnu.

Richard.

2017-06-28  Richard Biener  <rguenther@suse.de>

	PR middle-end/81227
	* fold-const.c (negate_expr_p): Use TYPE_UNSIGNED, not
	TYPE_OVERFLOW_WRAPS.
	* match.pd (negate_expr_p): Likewise.
	* tree-ssa-reassoc.c (optimize_range_tests_diff): Use
	fold_build2, not fold_binary.

	* gcc.dg/pr81227.c: New testcase.
diff mbox

Patch

Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c	(revision 249729)
+++ gcc/fold-const.c	(working copy)
@@ -383,7 +383,7 @@  negate_expr_p (tree t)
   switch (TREE_CODE (t))
     {
     case INTEGER_CST:
-      if (INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_WRAPS (type))
+      if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type))
 	return true;
 
       /* Check that -CST will not overflow type.  */
Index: gcc/match.pd
===================================================================
--- gcc/match.pd	(revision 249729)
+++ gcc/match.pd	(working copy)
@@ -913,7 +913,7 @@  DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 (match negate_expr_p
  INTEGER_CST
  (if ((INTEGRAL_TYPE_P (type)
-       && TYPE_OVERFLOW_WRAPS (type))
+       && TYPE_UNSIGNED (type))
       || (!TYPE_OVERFLOW_SANITIZED (type)
 	  && may_negate_without_overflow_p (t)))))
 (match negate_expr_p
Index: gcc/testsuite/gcc.dg/pr81227.c
===================================================================
--- gcc/testsuite/gcc.dg/pr81227.c	(revision 0)
+++ gcc/testsuite/gcc.dg/pr81227.c	(working copy)
@@ -0,0 +1,22 @@ 
+/* Copy of gcc.c-torture/compile/pr80443.c  */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fwrapv" } */
+
+struct S { int a : 1; } b, c;
+signed char d, e, f;
+
+void
+foo ()
+{ 
+  while (f)
+    { 
+      signed char g = b.a;
+      if (g)
+	b.a = ~(1 + (d || c.a));
+      if (b.a < g && b.a)
+	g = 0;
+      if (b.a > c.a)
+	b.a = g;
+      c.a = e;
+    }
+}
Index: gcc/tree-ssa-reassoc.c
===================================================================
--- gcc/tree-ssa-reassoc.c	(revision 249729)
+++ gcc/tree-ssa-reassoc.c	(working copy)
@@ -2561,7 +2561,7 @@  optimize_range_tests_diff (enum tree_cod
   tem2 = fold_convert (type, tem2);
   lowi = fold_convert (type, lowi);
   mask = fold_build1 (BIT_NOT_EXPR, type, tem1);
-  tem1 = fold_binary (MINUS_EXPR, type,
+  tem1 = fold_build2 (MINUS_EXPR, type,
 		      fold_convert (type, rangei->exp), lowi);
   tem1 = fold_build2 (BIT_AND_EXPR, type, tem1, mask);
   lowj = build_int_cst (type, 0);