[PATCH] Fix PR68528

Richard Biener rguenther@suse.de
Wed Nov 25 14:26:00 GMT 2015


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  <rguenther@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;
+ }



More information about the Gcc-patches mailing list