This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH][no-undefined-overflow] Adjust negate_expr_p and friends
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 12 Mar 2009 11:02:42 +0100 (CET)
- Subject: [PATCH][no-undefined-overflow] Adjust negate_expr_p and friends
This tries to deal with *NV_EXPRs in negate_expr_p and friends. I noticed
/* Determine whether an expression T can be cheaply negated using
the function negate_expr without introducing undefined overflow. */
and it indeed would be nice to have negate_expr_p return a consistent
tri-state - whether the negation does not overflow, whether the negation
is cheap or if non of this is true. That would help to make foldings
involving negation preserve non-overflowness if possible.
-> That's now an entry on the TODO list in the wiki.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to the
branch.
Richard.
2009-03-12 Richard Guenther <rguenther@suse.de>
* fold-const.c (may_negate_without_overflow_p): Unsigned zero
can be negated without overflow.
(negate_expr_p): Handle *NV_EXPR.
(fold_negate_expr): Likewise.
(fold_binary): Avoid loosing non-overflow flag during
A - B -> A + (-B) folding with constant B.
Index: no-undefined-overflow/gcc/fold-const.c
===================================================================
*** no-undefined-overflow.orig/gcc/fold-const.c 2009-03-10 17:59:58.000000000 +0100
--- no-undefined-overflow/gcc/fold-const.c 2009-03-12 10:48:54.000000000 +0100
*************** may_negate_without_overflow_p (const_tre
*** 1091,1097 ****
type = TREE_TYPE (t);
if (TYPE_UNSIGNED (type))
! return false;
prec = TYPE_PRECISION (type);
if (prec > HOST_BITS_PER_WIDE_INT)
--- 1091,1097 ----
type = TREE_TYPE (t);
if (TYPE_UNSIGNED (type))
! return integer_zerop (t);
prec = TYPE_PRECISION (type);
if (prec > HOST_BITS_PER_WIDE_INT)
*************** negate_expr_p (tree t)
*** 1135,1140 ****
--- 1135,1141 ----
case FIXED_CST:
case REAL_CST:
case NEGATE_EXPR:
+ case NEGATENV_EXPR:
return true;
case COMPLEX_CST:
*************** negate_expr_p (tree t)
*** 1149,1154 ****
--- 1150,1156 ----
return negate_expr_p (TREE_OPERAND (t, 0));
case PLUS_EXPR:
+ case PLUSNV_EXPR:
if (HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (type))
|| HONOR_SIGNED_ZEROS (TYPE_MODE (type)))
return false;
*************** negate_expr_p (tree t)
*** 1161,1166 ****
--- 1163,1169 ----
return negate_expr_p (TREE_OPERAND (t, 0));
case MINUS_EXPR:
+ case MINUSNV_EXPR:
/* We can't turn -(A-B) into B-A when we honor signed zeros. */
return !HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (type))
&& !HONOR_SIGNED_ZEROS (TYPE_MODE (type))
*************** negate_expr_p (tree t)
*** 1168,1173 ****
--- 1171,1177 ----
TREE_OPERAND (t, 1));
case MULT_EXPR:
+ case MULTNV_EXPR:
if (TYPE_UNSIGNED (TREE_TYPE (t)))
break;
*************** negate_expr_p (tree t)
*** 1192,1198 ****
return negate_expr_p (TREE_OPERAND (t, 1))
|| negate_expr_p (TREE_OPERAND (t, 0));
! case NOP_EXPR:
/* Negate -((double)float) as (double)(-float). */
if (TREE_CODE (type) == REAL_TYPE)
{
--- 1196,1202 ----
return negate_expr_p (TREE_OPERAND (t, 1))
|| negate_expr_p (TREE_OPERAND (t, 0));
! CASE_CONVERT:
/* Negate -((double)float) as (double)(-float). */
if (TREE_CODE (type) == REAL_TYPE)
{
*************** fold_negate_expr (tree t)
*** 1295,1300 ****
--- 1299,1305 ----
return TREE_OPERAND (t, 0);
case PLUS_EXPR:
+ case PLUSNV_EXPR:
if (!HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (type))
&& !HONOR_SIGNED_ZEROS (TYPE_MODE (type)))
{
*************** fold_negate_expr (tree t)
*** 1319,1324 ****
--- 1324,1330 ----
break;
case MINUS_EXPR:
+ case MINUSNV_EXPR:
/* - (A - B) -> B - A */
if (!HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (type))
&& !HONOR_SIGNED_ZEROS (TYPE_MODE (type))
*************** fold_negate_expr (tree t)
*** 1328,1333 ****
--- 1334,1340 ----
break;
case MULT_EXPR:
+ case MULTNV_EXPR:
if (TYPE_UNSIGNED (type))
break;
*************** fold_negate_expr (tree t)
*** 1368,1374 ****
}
break;
! case NOP_EXPR:
/* Convert -((double)float) into (double)(-float). */
if (TREE_CODE (type) == REAL_TYPE)
{
--- 1375,1381 ----
}
break;
! CASE_CONVERT:
/* Convert -((double)float) into (double)(-float). */
if (TREE_CODE (type) == REAL_TYPE)
{
*************** fold_binary (enum tree_code code, tree t
*** 10478,10492 ****
return fold_convert (type, integer_zero_node);
/* A - B -> A + (-B) if B is easily negatable. */
! if (negate_expr_p (arg1)
&& ((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 (PLUS_EXPR, type,
! fold_convert (type, arg0),
! fold_convert (type, negate_expr (arg1)));
/* Try folding difference of addresses. */
{
--- 10485,10514 ----
return fold_convert (type, integer_zero_node);
/* A - B -> A + (-B) if B is easily negatable. */
! if ((negate_expr_p (arg1)
! /* Avoid negating constants if that would change overflow
! behavior. */
! && (code == MINUS_EXPR
! || TREE_CODE (arg1) != INTEGER_CST
! || may_negate_without_overflow_p (arg1)))
&& ((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)))
! {
! enum tree_code ncode = PLUS_EXPR;
! /* If the original subtraction is signed and did not overflow
! so does the new addition if the negation of arg1 does not
! overflow (which we know for constants only). */
! if (code == MINUSNV_EXPR
! && TREE_CODE (arg1) == INTEGER_CST
! && !TYPE_UNSIGNED (type))
! ncode = PLUSNV_EXPR;
! return fold_build2 (ncode, type,
! fold_convert (type, arg0),
! fold_convert (type, negate_expr (arg1)));
! }
/* Try folding difference of addresses. */
{