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