https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81227

--- Comment #2 from Richard Biener <rguenth at gcc dot gnu.org> ---
As input we get:

(gdb) p debug_tree (val1)
 <plus_expr 0x7ffff6d884b0
    type <integer_type 0x7ffff6d572a0 public QI
        size <integer_cst 0x7ffff6c3fdc8 constant 8>
        unit size <integer_cst 0x7ffff6c3fde0 constant 1>
        align 8 symtab 0 alias set -1 canonical type 0x7ffff6d572a0 precision 1
min <integer_cst 0x7ffff6d6a270 -1> max <integer_cst 0x7ffff6d6a288 0>>

    arg 0 <ssa_name 0x7ffff6c4ac18 type <integer_type 0x7ffff6d572a0>
        visited
        def_stmt _9 = b.a;
        version 9>
    arg 1 <integer_cst 0x7ffff6d6a738 type <integer_type 0x7ffff6d572a0>
constant public overflow -1>>

that's from trying to set a symbolic range where we try to build

              if (TYPE_PRECISION (TREE_TYPE (min)) == 1
                  && !TYPE_UNSIGNED (TREE_TYPE (min)))
                min = fold_build2 (MINUS_EXPR, TREE_TYPE (min), min,
                                   build_int_cst (TREE_TYPE (min), -1));

thus _9 - -1 but that's folded to _9 + -1(OVF) via

/* A - B -> A + (-B) if B is easily negatable.  */
(simplify
 (minus @0 negate_expr_p@1)
 (if (!FIXED_POINT_TYPE_P (type))
 (plus @0 (negate @1))))

and

(match negate_expr_p
 INTEGER_CST
 (if ((INTEGRAL_TYPE_P (type)
       && TYPE_OVERFLOW_WRAPS (type))
      || (!TYPE_OVERFLOW_SANITIZED (type)
          && may_negate_without_overflow_p (t)))))

uncovering the old issue that implementation defined "overflow" still causes
TREE_OVERFLOW to be set.  I suppose the above (copied from fold-const.c
negate_expr_p) should eventually not say that MSB only unsigned is easily
negated.

Or fold_negate_const should not do

    case INTEGER_CST:
      {
        bool overflow;
        wide_int val = wi::neg (arg0, &overflow);
        t = force_fit_type (type, val, 1,
                            (overflow | TREE_OVERFLOW (arg0))
                            && !TYPE_UNSIGNED (type));

but check && ! TYPE_OVERFLOW_WRAPS (type) here.  OTOH int_const_binop
looks at the sign of the type only as well.

IMHO simplifying and aligning fold-const.c and match.pd here w/o changing
when we set TREE_OVERFLOW makes sense:

Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c    (revision 249435)
+++ gcc/fold-const.c    (working copy)
@@ -383,9 +383,6 @@ negate_expr_p (tree t)
   switch (TREE_CODE (t))
     {
     case INTEGER_CST:
-      if (INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_WRAPS (type))
-       return true;
-
       /* Check that -CST will not overflow type.  */
       return may_negate_without_overflow_p (t);
     case BIT_NOT_EXPR:
Index: gcc/match.pd
===================================================================
--- gcc/match.pd        (revision 249435)
+++ gcc/match.pd        (working copy)
@@ -834,10 +834,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 /* A few cases of fold-const.c negate_expr_p predicate.  */
 (match negate_expr_p
  INTEGER_CST
- (if ((INTEGRAL_TYPE_P (type)
-       && TYPE_OVERFLOW_WRAPS (type))
-      || (!TYPE_OVERFLOW_SANITIZED (type)
-         && may_negate_without_overflow_p (t)))))
+ (if (may_negate_without_overflow_p (t))))
 (match negate_expr_p
  FIXED_CST)
 (match negate_expr_p

Reply via email to