The following fixes fold_binary to not call negate_expr_p on arg[01]
as those have sign-changing nops stripped which gets us wrong answers
for negate_expr_p.  Instead of passing arg[01] we need to pass op[01]
(negate_expr_p and friends use STRIP_SIGN_NOPS themselves).

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

Richard.

2015-11-25  Richard Biener  <rguent...@suse.de>

        PR middle-end/68528
        * fold-const.c (fold_binary_loc): Do not call negate_expr_p
        on stripped operands.

        * gcc.dg/torture/pr68528.c: New testcase.

Index: gcc/fold-const.c
===================================================================
*** gcc/fold-const.c    (revision 230857)
--- gcc/fold-const.c    (working copy)
*************** fold_binary_loc (location_t loc,
*** 9681,9693 ****
      case MINUS_EXPR:
        /* (-A) - B -> (-B) - A  where B is easily negated and we can swap.  */
        if (TREE_CODE (arg0) == NEGATE_EXPR
!         && negate_expr_p (arg1)
          && reorder_operands_p (arg0, arg1))
        return fold_build2_loc (loc, MINUS_EXPR, type,
!                           fold_convert_loc (loc, type,
!                                             negate_expr (arg1)),
!                           fold_convert_loc (loc, type,
!                                             TREE_OPERAND (arg0, 0)));
  
        /* Fold __complex__ ( x, 0 ) - __complex__ ( 0, y ) to
         __complex__ ( x, -y ).  This is not the same for SNaNs or if
--- 9681,9692 ----
      case MINUS_EXPR:
        /* (-A) - B -> (-B) - A  where B is easily negated and we can swap.  */
        if (TREE_CODE (arg0) == NEGATE_EXPR
!         && negate_expr_p (op1)
          && reorder_operands_p (arg0, arg1))
        return fold_build2_loc (loc, MINUS_EXPR, type,
!                               negate_expr (op1),
!                               fold_convert_loc (loc, type,
!                                                 TREE_OPERAND (arg0, 0)));
  
        /* Fold __complex__ ( x, 0 ) - __complex__ ( 0, y ) to
         __complex__ ( x, -y ).  This is not the same for SNaNs or if
*************** fold_binary_loc (location_t loc,
*** 9727,9743 ****
        }
  
        /* A - B -> A + (-B) if B is easily negatable.  */
!       if (negate_expr_p (arg1)
!         && !TYPE_OVERFLOW_SANITIZED (type)
          && ((FLOAT_TYPE_P (type)
                 /* Avoid this transformation if B is a positive REAL_CST.  */
!              && (TREE_CODE (arg1) != REAL_CST
!                  ||  REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg1))))
              || INTEGRAL_TYPE_P (type)))
        return fold_build2_loc (loc, PLUS_EXPR, type,
!                           fold_convert_loc (loc, type, arg0),
!                           fold_convert_loc (loc, type,
!                                             negate_expr (arg1)));
  
        /* Fold &a[i] - &a[j] to i-j.  */
        if (TREE_CODE (arg0) == ADDR_EXPR
--- 9726,9741 ----
        }
  
        /* A - B -> A + (-B) if B is easily negatable.  */
!       if (negate_expr_p (op1)
!         && ! TYPE_OVERFLOW_SANITIZED (type)
          && ((FLOAT_TYPE_P (type)
                 /* Avoid this transformation if B is a positive REAL_CST.  */
!              && (TREE_CODE (op1) != REAL_CST
!                  || REAL_VALUE_NEGATIVE (TREE_REAL_CST (op1))))
              || INTEGRAL_TYPE_P (type)))
        return fold_build2_loc (loc, PLUS_EXPR, type,
!                               fold_convert_loc (loc, type, arg0),
!                               negate_expr (op1));
  
        /* Fold &a[i] - &a[j] to i-j.  */
        if (TREE_CODE (arg0) == ADDR_EXPR
*************** fold_binary_loc (location_t loc,
*** 9781,9795 ****
        if (! FLOAT_TYPE_P (type))
        {
          /* Transform x * -C into -x * C if x is easily negatable.  */
!         if (TREE_CODE (arg1) == INTEGER_CST
!             && tree_int_cst_sgn (arg1) == -1
!             && negate_expr_p (arg0)
!             && (tem = negate_expr (arg1)) != arg1
!             && !TREE_OVERFLOW (tem))
            return fold_build2_loc (loc, MULT_EXPR, type,
!                               fold_convert_loc (loc, type,
!                                                 negate_expr (arg0)),
!                               tem);
  
          /* (A + A) * C -> A * 2 * C  */
          if (TREE_CODE (arg0) == PLUS_EXPR
--- 9779,9792 ----
        if (! FLOAT_TYPE_P (type))
        {
          /* Transform x * -C into -x * C if x is easily negatable.  */
!         if (TREE_CODE (op1) == INTEGER_CST
!             && tree_int_cst_sgn (op1) == -1
!             && negate_expr_p (op0)
!             && (tem = negate_expr (op1)) != op1
!             && ! TREE_OVERFLOW (tem))
            return fold_build2_loc (loc, MULT_EXPR, type,
!                                   fold_convert_loc (loc, type,
!                                                     negate_expr (op0)), tem);
  
          /* (A + A) * C -> A * 2 * C  */
          if (TREE_CODE (arg0) == PLUS_EXPR
*************** fold_binary_loc (location_t loc,
*** 10259,10265 ****
         undefined.  */
        if ((!INTEGRAL_TYPE_P (type) || TYPE_OVERFLOW_UNDEFINED (type))
          && TREE_CODE (arg0) == NEGATE_EXPR
!         && negate_expr_p (arg1))
        {
          if (INTEGRAL_TYPE_P (type))
            fold_overflow_warning (("assuming signed overflow does not occur "
--- 10256,10262 ----
         undefined.  */
        if ((!INTEGRAL_TYPE_P (type) || TYPE_OVERFLOW_UNDEFINED (type))
          && TREE_CODE (arg0) == NEGATE_EXPR
!         && negate_expr_p (op1))
        {
          if (INTEGRAL_TYPE_P (type))
            fold_overflow_warning (("assuming signed overflow does not occur "
*************** fold_binary_loc (location_t loc,
*** 10267,10280 ****
                                    "division"),
                                   WARN_STRICT_OVERFLOW_MISC);
          return fold_build2_loc (loc, code, type,
!                             fold_convert_loc (loc, type,
!                                               TREE_OPERAND (arg0, 0)),
!                             fold_convert_loc (loc, type,
!                                               negate_expr (arg1)));
        }
        if ((!INTEGRAL_TYPE_P (type) || TYPE_OVERFLOW_UNDEFINED (type))
          && TREE_CODE (arg1) == NEGATE_EXPR
!         && negate_expr_p (arg0))
        {
          if (INTEGRAL_TYPE_P (type))
            fold_overflow_warning (("assuming signed overflow does not occur "
--- 10264,10276 ----
                                    "division"),
                                   WARN_STRICT_OVERFLOW_MISC);
          return fold_build2_loc (loc, code, type,
!                                 fold_convert_loc (loc, type,
!                                                   TREE_OPERAND (arg0, 0)),
!                                 negate_expr (op1));
        }
        if ((!INTEGRAL_TYPE_P (type) || TYPE_OVERFLOW_UNDEFINED (type))
          && TREE_CODE (arg1) == NEGATE_EXPR
!         && negate_expr_p (op0))
        {
          if (INTEGRAL_TYPE_P (type))
            fold_overflow_warning (("assuming signed overflow does not occur "
*************** fold_binary_loc (location_t loc,
*** 10282,10291 ****
                                    "division"),
                                   WARN_STRICT_OVERFLOW_MISC);
          return fold_build2_loc (loc, code, type,
!                             fold_convert_loc (loc, type,
!                                               negate_expr (arg0)),
!                             fold_convert_loc (loc, type,
!                                               TREE_OPERAND (arg1, 0)));
        }
  
        /* If arg0 is a multiple of arg1, then rewrite to the fastest div
--- 10278,10286 ----
                                    "division"),
                                   WARN_STRICT_OVERFLOW_MISC);
          return fold_build2_loc (loc, code, type,
!                                 negate_expr (op0),
!                                 fold_convert_loc (loc, type,
!                                                   TREE_OPERAND (arg1, 0)));
        }
  
        /* If arg0 is a multiple of arg1, then rewrite to the fastest div
Index: gcc/testsuite/gcc.dg/torture/pr68528.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr68528.c      (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr68528.c      (working copy)
***************
*** 0 ****
--- 1,17 ----
+ /* { dg-do run } */
+ 
+ #define INT_MIN ( -__INT_MAX__ - 1 )
+ 
+ extern void abort (void);
+ 
+ int main (void)
+ {
+   int  x0 = INT_MIN;
+   long x1 = 0L;
+   int  x2 = 0;
+   int  t  = ( 0 || ( INT_MIN - (int) ( x0 - x1 ) ) );
+ 
+   if ( t != 0 ) { x2 = t; abort(); }
+ 
+   return 0;
+ }

Reply via email to