This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Negation related constant folding improvements (take 2)
- From: Roger Sayle <roger at eyesopen dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Richard Henderson <rth at redhat dot com>
- Date: Wed, 13 Aug 2003 11:37:08 -0600 (MDT)
- Subject: [PATCH] Negation related constant folding improvements (take 2)
The following revision of my "negation related constant folding
improvements" patch should address all of the issues previously
raised.
Firstly, we now check HONOR_SIGN_DEPENDENT_ROUNDING before performing
transformations that could result in multiplication or division having
a different sign. Additionally, I've still split the REAL_CST case
out from the INTEGER_CST case in negate_expr, but I've exposed the
call to GCC's floating-point emulator, and kept the original test for
TREE_OVERFLOW, adding a comment about why this should be needed for
c4x.
Hopefully, this simplification and documentation of the code should
ease the task of improving support for non sign-magnitude floating
point formats in the future.
To answer Geoff Keating's question, yes we could probably try to
canonicalize -X*Y into X*-Y. However, this wouldn't simplify the
patch below, as we need to test both symmetric cases as we already
canonicalize constants to the right with higher priority.
The following patch has been tested on i686-pc-linux-gnu with a full
"make bootstrap", all languages except treelang, and regression tested
with a top-level "make -k check" with no new failures.
Ok for mainline?
2003-08-13 Roger Sayle <roger@eyesopen.com>
* fold-const.c (negate_expr_p): MULT_EXPRs and RDIV_EXPRs are easy
to negate if either operand is easy to negate, if we don't care
about sign-dependent rounding.
(negate_expr): Make the logic to negate a REAL_CST explicit.
Attempt to negate a MULT_EXPR or RDIV_EXPR by negating an operand
that's easy to negatem if we don't honor sign-dependent rounding.
(fold <MULT_EXPR>): Optimize -A * B as A * -B if B is easy to
negate, and the symmetric A * -B as -A * B is A is easy to negate.
(fold <RDIV_EXPR>): Likewise, optimize -A/B and C/-D as A/-B and
-C/D if B and C are cheap to negate. Add an explicit rule to
optimize X/-1.0 as -X when we don't care about signaling NaNs.
Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.290
diff -c -3 -p -r1.290 fold-const.c
*** fold-const.c 12 Aug 2003 01:43:31 -0000 1.290
--- fold-const.c 13 Aug 2003 12:53:10 -0000
*************** negate_expr_p (tree t)
*** 847,852 ****
--- 847,864 ----
/* We can't turn -(A-B) into B-A when we honor signed zeros. */
return ! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations;
+ case MULT_EXPR:
+ if (TREE_UNSIGNED (TREE_TYPE (t)))
+ break;
+
+ /* Fall through. */
+
+ case RDIV_EXPR:
+ if (! HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (TREE_TYPE (t))))
+ return negate_expr_p (TREE_OPERAND (t, 1))
+ || negate_expr_p (TREE_OPERAND (t, 0));
+ break;
+
default:
break;
}
*************** negate_expr (tree t)
*** 871,883 ****
switch (TREE_CODE (t))
{
case INTEGER_CST:
- case REAL_CST:
if (! TREE_UNSIGNED (type)
&& 0 != (tem = fold (build1 (NEGATE_EXPR, type, t)))
&& ! TREE_OVERFLOW (tem))
return tem;
break;
case NEGATE_EXPR:
return convert (type, TREE_OPERAND (t, 0));
--- 883,901 ----
switch (TREE_CODE (t))
{
case INTEGER_CST:
if (! TREE_UNSIGNED (type)
&& 0 != (tem = fold (build1 (NEGATE_EXPR, type, t)))
&& ! TREE_OVERFLOW (tem))
return tem;
break;
+ case REAL_CST:
+ tem = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (t)));
+ /* Two's complement FP formats, such as c4x, may overflow. */
+ if (! TREE_OVERFLOW (tem))
+ return convert (type, tem);
+ break;
+
case NEGATE_EXPR:
return convert (type, TREE_OPERAND (t, 0));
*************** negate_expr (tree t)
*** 890,895 ****
--- 908,937 ----
TREE_OPERAND (t, 0))));
break;
+ case MULT_EXPR:
+ if (TREE_UNSIGNED (TREE_TYPE (t)))
+ break;
+
+ /* Fall through. */
+
+ case RDIV_EXPR:
+ if (! HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (TREE_TYPE (t))))
+ {
+ tem = TREE_OPERAND (t, 1);
+ if (negate_expr_p (tem))
+ return convert (type,
+ fold (build (TREE_CODE (t), TREE_TYPE (t),
+ TREE_OPERAND (t, 0),
+ negate_expr (tem))));
+ tem = TREE_OPERAND (t, 0);
+ if (negate_expr_p (tem))
+ return convert (type,
+ fold (build (TREE_CODE (t), TREE_TYPE (t),
+ negate_expr (tem),
+ TREE_OPERAND (t, 1))));
+ }
+ break;
+
default:
break;
}
*************** fold (tree expr)
*** 5965,5972 ****
case MULT_EXPR:
/* (-A) * (-B) -> A * B */
! if (TREE_CODE (arg0) == NEGATE_EXPR && TREE_CODE (arg1) == NEGATE_EXPR)
! return fold (build (MULT_EXPR, type, TREE_OPERAND (arg0, 0),
TREE_OPERAND (arg1, 0)));
if (! FLOAT_TYPE_P (type))
--- 6007,6019 ----
case MULT_EXPR:
/* (-A) * (-B) -> A * B */
! if (TREE_CODE (arg0) == NEGATE_EXPR && negate_expr_p (arg1))
! return fold (build (MULT_EXPR, type,
! TREE_OPERAND (arg0, 0),
! negate_expr (arg1)));
! if (TREE_CODE (arg1) == NEGATE_EXPR && negate_expr_p (arg0))
! return fold (build (MULT_EXPR, type,
! negate_expr (arg0),
TREE_OPERAND (arg1, 0)));
if (! FLOAT_TYPE_P (type))
*************** fold (tree expr)
*** 6315,6328 ****
return t;
/* (-A) / (-B) -> A / B */
! if (TREE_CODE (arg0) == NEGATE_EXPR && TREE_CODE (arg1) == NEGATE_EXPR)
! return fold (build (RDIV_EXPR, type, TREE_OPERAND (arg0, 0),
TREE_OPERAND (arg1, 0)));
/* In IEEE floating point, x/1 is not equivalent to x for snans. */
if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
&& real_onep (arg1))
return non_lvalue (convert (type, arg0));
/* If ARG1 is a constant, we can convert this to a multiply by the
reciprocal. This does not have the same rounding properties,
--- 6362,6385 ----
return t;
/* (-A) / (-B) -> A / B */
! if (TREE_CODE (arg0) == NEGATE_EXPR && negate_expr_p (arg1))
! return fold (build (RDIV_EXPR, type,
! TREE_OPERAND (arg0, 0),
! negate_expr (arg1)));
! if (TREE_CODE (arg1) == NEGATE_EXPR && negate_expr_p (arg0))
! return fold (build (RDIV_EXPR, type,
! negate_expr (arg0),
TREE_OPERAND (arg1, 0)));
/* In IEEE floating point, x/1 is not equivalent to x for snans. */
if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
&& real_onep (arg1))
return non_lvalue (convert (type, arg0));
+
+ /* In IEEE floating point, x/-1 is not equivalent to -x for snans. */
+ if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
+ && real_minus_onep (arg1))
+ return non_lvalue (convert (type, negate_expr (arg0)));
/* If ARG1 is a constant, we can convert this to a multiply by the
reciprocal. This does not have the same rounding properties,
Roger
--
Roger Sayle, E-mail: roger@eyesopen.com
OpenEye Scientific Software, WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road, Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507. Fax: (+1) 505-473-0833