[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