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  <rguent...@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.

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);

Reply via email to