[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