This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Handle const functions in operand_equal_p


This patch is a variant of Jeff Law's "CALL_EXPR support for
operand_equal_p" patch for mainline, with a few minor tweaks.

The first is that instead of testing TREE_SIDE_EFFECTS to
determine whether the function is pure or const, we explicitly
call flags_from_decl_or_type and check for ECF_CONST explicitly.
Firstly, it isn't immediately obvious that all uses of
operand_equal_p guarantee no memory writes can occur between
the operands being evaluated.  Hence this patch restricts this
optimization to only "const" function calls.  Secondly, mainline
currently always sets TREE_SIDE_EFFECTS unconditionally on a
CALL_EXPR [this is even documented above TREE_SIDE_EFFECTS in
tree.h].  I know that Jeff was hoping the gimple simplifiers
would update these fields, but for mainline its better to check
the perceived attributes of the function decl ourselves.  This
then works with function calls created by the Java and FORTRAN
front-ends for example.

My apologies in advance to Diego, as this patch will conflict
with Jeff's version on the tree-ssa branch come the next merge.


Finally, I also add an additional case to operand_equal_p to
notice that different names of the same built-in function are
equivalent, i.e. __builtin_foo is identical to foo (and also
std::foo in the C++ front-end).  This is required to fix a
failure in builtins-20.c on sh-elf.  In this particular case,
"sin(x)/cos(x) != tan(x)" is transformed into "__builtin_tan(x)
!= tan(x)", where the equivalence isn't recognized at the RTL
level.  I'm investigating further.  However, constant folding
this inequality at the tree-level with -ffast-math fixes the
failure.

Ok for mainline?  Jeff would you prefer this version on tree-ssa
for the time being?

Many thanks in advance,


2003-06-13  Roger Sayle  <roger@eyesopen.com>
	    Jeff Law  <law@redhat.com>

	* fold-const.c (operand_equal_p): Consider two calls to "const"
	functions with identical non-volatile arguments to be equal.
	Consider the FUNCTION_DECL for the "__builtin_foo" form of a
	built-in function to be equal to the "foo" form.


Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.261
diff -c -3 -p -r1.261 fold-const.c
*** fold-const.c	12 Jun 2003 20:33:00 -0000	1.261
--- fold-const.c	13 Jun 2003 23:25:56 -0000
*************** operand_equal_p (arg0, arg1, only_const)
*** 1968,1975 ****
  				  TREE_OPERAND (arg1, 0), 0));

      case 'r':
!       /* If either of the pointer (or reference) expressions we are dereferencing
! 	 contain a side effect, these cannot be equal.  */
        if (TREE_SIDE_EFFECTS (arg0)
  	  || TREE_SIDE_EFFECTS (arg1))
  	return 0;
--- 1968,1975 ----
  				  TREE_OPERAND (arg1, 0), 0));

      case 'r':
!       /* If either of the pointer (or reference) expressions we are
! 	 dereferencing contain a side effect, these cannot be equal.  */
        if (TREE_SIDE_EFFECTS (arg0)
  	  || TREE_SIDE_EFFECTS (arg1))
  	return 0;
*************** operand_equal_p (arg0, arg1, only_const)
*** 2010,2018 ****
--- 2010,2060 ----
  	case RTL_EXPR:
  	  return rtx_equal_p (RTL_EXPR_RTL (arg0), RTL_EXPR_RTL (arg1));

+ 	case CALL_EXPR:
+ 	  /* If the CALL_EXPRs call different functions, then they
+ 	     clearly can not be equal.  */
+ 	  if (! operand_equal_p (TREE_OPERAND (arg0, 0),
+ 				 TREE_OPERAND (arg1, 0), 0))
+ 	    return 0;
+
+ 	  /* Only consider const functions equivalent.  */
+ 	  if (TREE_CODE (TREE_OPERAND (arg0, 0)) == ADDR_EXPR)
+ 	    {
+ 	      tree fndecl = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
+ 	      if (! (flags_from_decl_or_type (fndecl) & ECF_CONST))
+ 		return 0;
+ 	    }
+ 	  else
+ 	    return 0;
+
+ 	  /* Now see if all the arguments are the same.  operand_equal_p
+ 	     does not handle TREE_LIST, so we walk the operands here
+ 	     feeding them to operand_equal_p.  */
+ 	  arg0 = TREE_OPERAND (arg0, 1);
+ 	  arg1 = TREE_OPERAND (arg1, 1);
+ 	  while (arg0 && arg1)
+ 	    {
+ 	      if (! operand_equal_p (TREE_VALUE (arg0), TREE_VALUE (arg1), 0))
+ 		return 0;
+
+ 	      arg0 = TREE_CHAIN (arg0);
+ 	      arg1 = TREE_CHAIN (arg1);
+ 	    }
+
+ 	  /* If we get here and both argument lists are exhausted
+ 	     then the CALL_EXPRs are equal.  */
+ 	  return ! (arg0 || arg1);
+
  	default:
  	  return 0;
  	}
+
+     case 'd':
+ 	/* Consider __builtin_sqrt equal to sqrt.  */
+ 	return TREE_CODE (arg0) == FUNCTION_DECL
+ 	       && DECL_BUILT_IN (arg0) && DECL_BUILT_IN (arg1)
+ 	       && DECL_BUILT_IN_CLASS (arg0) == DECL_BUILT_IN_CLASS (arg1)
+ 	       && DECL_FUNCTION_CODE (arg0) == DECL_FUNCTION_CODE (arg1);

      default:
        return 0;

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]