[PATCH] Improved SAVE_EXPR handling in operand_equal_p.
Roger Sayle
roger@eyesopen.com
Tue Sep 2 13:25:00 GMT 2003
This patch fixes a defficiency in fold-const.c's operand_equal_p
routine recently found by Kaveh when writing new test cases for the
testsuite. We'd fail the following test with -O0 -ffast-math:
extern void link_failure(void);
void test_cabs(_Complex double d)
{ if (cabs(d) != cabs(d)) link_failure(); }
The problem stems from GCC's -ffast-math optimization to convert
cabs(d) into sqrt(__real__ d * __real__ d + __imag__ d * __imag__ d).
To avoid re-evaluation of the "d", this transformation wraps it in
a SAVE_EXPR. This then confuses "fold" as we only consider two
SAVE_EXPRs equivalent if they are the "same" expression by pointer
equality.
The patch below fixes this by considering two SAVE_EXPRs that wrap
operand_equal_p subexpressions (which ensures they have no side-effects)
as equal. This is also extended slightly by treating SAVE_EXPR much
like a NOP, so that a SAVE_EXPR(x) is also considered equal to x.
A SAVE_EXPR around an expression without side-effects is just an
efficiency "tool" for the middle-end, and skipping an evaluation of
it does not affect the program's behaviour.
Then finally, I noticed that although we already call "save_expr" in
this fold_builtin_cabs optimization, I'd missed another place it is
needed.
The following patch has been tested on i686-pc-linux-gnu with a complete
"make bootstrap", all languages except treelang, and regression tested
with a top-level "make -k check" with no new failures. As mentioned
above Kaveh has some new tests that will confirm/ensure this stuff is
working.
Ok for mainline?
2003-09-02 Roger Sayle <roger@eyesopen.com>
* fold-const.c (operand_equal_p): Strip SAVE_EXPR nodes when
checking for operand equality.
* builtins.c (fold_builtin_cabs): Protect the complex argument
against multiple evaluation when optimizing cabs* into sqrt*.
Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.300
diff -c -3 -p -r1.300 fold-const.c
*** fold-const.c 1 Sep 2003 05:02:08 -0000 1.300
--- fold-const.c 2 Sep 2003 01:16:02 -0000
*************** operand_equal_p (tree arg0, tree arg1, i
*** 1844,1853 ****
STRIP_NOPS (arg0);
STRIP_NOPS (arg1);
! if (TREE_CODE (arg0) != TREE_CODE (arg1)
! /* This is needed for conversions and for COMPONENT_REF.
! Might as well play it safe and always test this. */
! || TREE_CODE (TREE_TYPE (arg0)) == ERROR_MARK
|| TREE_CODE (TREE_TYPE (arg1)) == ERROR_MARK
|| TYPE_MODE (TREE_TYPE (arg0)) != TYPE_MODE (TREE_TYPE (arg1)))
return 0;
--- 1844,1866 ----
STRIP_NOPS (arg0);
STRIP_NOPS (arg1);
! if (TREE_CODE (arg0) != TREE_CODE (arg1))
! {
! if (! only_const)
! {
! /* A SAVE_EXPR around an expression without side-effects is
! transparent as far as operand equality is concerned. */
! if (TREE_CODE (arg0) == SAVE_EXPR)
! return operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0);
! if (TREE_CODE (arg1) == SAVE_EXPR)
! return operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0);
! }
! return 0;
! }
!
! /* This is needed for conversions and for COMPONENT_REF.
! Might as well play it safe and always test this. */
! if (TREE_CODE (TREE_TYPE (arg0)) == ERROR_MARK
|| TREE_CODE (TREE_TYPE (arg1)) == ERROR_MARK
|| TYPE_MODE (TREE_TYPE (arg0)) != TYPE_MODE (TREE_TYPE (arg1)))
return 0;
*************** operand_equal_p (tree arg0, tree arg1, i
*** 1990,1995 ****
--- 2003,2009 ----
switch (TREE_CODE (arg0))
{
case ADDR_EXPR:
+ case SAVE_EXPR:
case TRUTH_NOT_EXPR:
return operand_equal_p (TREE_OPERAND (arg0, 0),
TREE_OPERAND (arg1, 0), 0);
Index: builtins.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.c,v
retrieving revision 1.247
diff -c -3 -p -r1.247 builtins.c
*** builtins.c 31 Aug 2003 11:18:59 -0000 1.247
--- builtins.c 2 Sep 2003 01:16:05 -0000
*************** fold_builtin_cabs (tree fndecl, tree arg
*** 5729,5734 ****
--- 5729,5736 ----
{
tree rpart, ipart, result, arglist;
+ arg = save_expr (arg);
+
rpart = fold (build1 (REALPART_EXPR, type, arg));
ipart = fold (build1 (IMAGPART_EXPR, type, arg));
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
More information about the Gcc-patches
mailing list