[PATCH][RFC] Optimize more with PAREN_EXPR

Richard Guenther rguenther@suse.de
Thu Feb 21 10:16:00 GMT 2008


As currently in mainline only the very obviously correct optimizations
are permitted with PAREN_EXPR (removing it around other PAREN_EXPR and
around constants).  There are two more important cases and one that
may matter.

One is that we want to be able to still fold the difference of
x - ((x)) to zero.  Basically whenever we ask for the value of
x or ((x)) it should be the same, while still not substituting
one for the other.

To allow this this patch makes SCCVN expose a PAREN_EXPR to the
folder, thus fold x_1 - ((x_1)) instead of x_1 - x_2 (where x_2
is the value number for ((x_1))).  This is pretty straight-forward.

To not need to adjust individual transformations I chose to extend
operand_equal_p to simply look through PAREN_EXPR, making it
treating x and ((x)) the same.  I think this is wrong, but this
was the easiest thing to do for experimenting.  Any different
opinion on that?  I don't think an existing transformation will
break because of this, though.

The third thing is simply transforming ((U x)) to U ((x)) where
U is any unary operator with the simple reasoning that you cannot
associate unary expressions.  This allows x + ((-x)) or similar
constructs to simplify.

I have bootstrapped and tested this change on x86_64-unknown-linux-gnu,
but will wait for comments on the second issue before committing.

Thanks,
Richard.

2008-02-19  Richard Guenther  <rguenther@suse.de>

	* fold-const.c (operand_equal_p): See through PAREN_EXPR.
	(fold_unary): Move PAREN_EXPR around unary operations inside
	around its operand.
	* tree-ssa-sccvn.c (simplify_binary_expression): Make
	PAREN_EXPR visible to fold.
	(simplify_unary_expression): Likewise.

	* gfortran.dg/reassoc_4.f90: New testcase.
	* gfortran.dg/reassoc_5.f90: Likewise.

Index: trunk/gcc/fold-const.c
===================================================================
*** trunk.orig/gcc/fold-const.c	2008-02-19 16:36:49.000000000 +0100
--- trunk/gcc/fold-const.c	2008-02-19 16:52:26.000000000 +0100
*************** operand_equal_p (const_tree arg0, const_
*** 3037,3042 ****
--- 3037,3051 ----
    STRIP_NOPS (arg0);
    STRIP_NOPS (arg1);
  
+   /* ???  The following is valid only if we compare values.  */
+   if (!(flags & OEP_ONLY_CONST))
+     {
+       if (TREE_CODE (arg0) == PAREN_EXPR)
+ 	arg0 = TREE_OPERAND (arg0, 0);
+       if (TREE_CODE (arg1) == PAREN_EXPR)
+ 	arg1 = TREE_OPERAND (arg1, 0);
+     }
+ 
    /* In case both args are comparisons but with different comparison
       code, try to swap the comparison operands of one arg to produce
       a match and compare that variant.  */
*************** fold_unary (enum tree_code code, tree ty
*** 8034,8039 ****
--- 8043,8057 ----
        if (CONSTANT_CLASS_P (op0)
  	  || TREE_CODE (op0) == PAREN_EXPR)
  	return fold_convert (type, op0);
+       /* There is nothing to re-associate for an unary operation, so move
+ 	 the re-association barrier inside.  */
+       if (UNARY_CLASS_P (op0))
+ 	{
+ 	  tree tem = fold_build1 (PAREN_EXPR, TREE_TYPE (TREE_OPERAND (op0, 0)),
+ 				  TREE_OPERAND (op0, 0));
+ 	  return fold_convert (type, fold_build1 (TREE_CODE (op0),
+ 						  TREE_TYPE (op0), tem));
+ 	}
        return NULL_TREE;
  
      case NOP_EXPR:
Index: trunk/gcc/tree-ssa-sccvn.c
===================================================================
*** trunk.orig/gcc/tree-ssa-sccvn.c	2008-02-15 14:46:44.000000000 +0100
--- trunk/gcc/tree-ssa-sccvn.c	2008-02-19 17:35:46.000000000 +0100
*************** simplify_binary_expression (tree stmt, t
*** 1433,1442 ****
    /* This will not catch every single case we could combine, but will
       catch those with constants.  The goal here is to simultaneously
       combine constants between expressions, but avoid infinite
!      expansion of expressions during simplification.  */
    if (TREE_CODE (op0) == SSA_NAME)
      {
!       if (VN_INFO (op0)->has_constants)
  	op0 = valueize_expr (VN_INFO (op0)->expr);
        else if (SSA_VAL (op0) != VN_TOP && SSA_VAL (op0) != op0)
  	op0 = SSA_VAL (op0);
--- 1433,1446 ----
    /* This will not catch every single case we could combine, but will
       catch those with constants.  The goal here is to simultaneously
       combine constants between expressions, but avoid infinite
!      expansion of expressions during simplification.
!      Make sure to expand PAREN_EXPR here as that doesn't change
!      its argument value and fold can do for example simplification
!      of x - (x).  */
    if (TREE_CODE (op0) == SSA_NAME)
      {
!       if (VN_INFO (op0)->has_constants
! 	  || TREE_CODE (VN_INFO (op0)->expr) == PAREN_EXPR)
  	op0 = valueize_expr (VN_INFO (op0)->expr);
        else if (SSA_VAL (op0) != VN_TOP && SSA_VAL (op0) != op0)
  	op0 = SSA_VAL (op0);
*************** simplify_binary_expression (tree stmt, t
*** 1444,1450 ****
  
    if (TREE_CODE (op1) == SSA_NAME)
      {
!       if (VN_INFO (op1)->has_constants)
  	op1 = valueize_expr (VN_INFO (op1)->expr);
        else if (SSA_VAL (op1) != VN_TOP && SSA_VAL (op1) != op1)
  	op1 = SSA_VAL (op1);
--- 1448,1455 ----
  
    if (TREE_CODE (op1) == SSA_NAME)
      {
!       if (VN_INFO (op1)->has_constants
! 	  || TREE_CODE (VN_INFO (op1)->expr) == PAREN_EXPR)
  	op1 = valueize_expr (VN_INFO (op1)->expr);
        else if (SSA_VAL (op1) != VN_TOP && SSA_VAL (op1) != op1)
  	op1 = SSA_VAL (op1);
*************** simplify_unary_expression (tree rhs)
*** 1488,1493 ****
--- 1493,1499 ----
      op0 = valueize_expr (VN_INFO (op0)->expr);
    else if (TREE_CODE (rhs) == NOP_EXPR
  	   || TREE_CODE (rhs) == CONVERT_EXPR
+ 	   || TREE_CODE (rhs) == PAREN_EXPR
  	   || TREE_CODE (rhs) == REALPART_EXPR
  	   || TREE_CODE (rhs) == IMAGPART_EXPR)
      {
Index: trunk/gcc/testsuite/gfortran.dg/reassoc_4.f90
===================================================================
*** trunk.orig/gcc/testsuite/gfortran.dg/reassoc_4.f90	(revision 0)
--- trunk/gcc/testsuite/gfortran.dg/reassoc_4.f90	(revision 0)
***************
*** 0 ****
--- 1,11 ----
+ ! { dg-do compile }
+ ! { dg-options "-O -ffinite-math-only -fdump-tree-optimized" }
+ 
+ function test(b, c)
+   real a, b, c
+   a = (b + c)
+   a = b + c - a
+   test = a
+ end
+ 
+ ! { dg-final { scan-tree-dump "return 0" "optimized" } }
Index: trunk/gcc/testsuite/gfortran.dg/reassoc_5.f90
===================================================================
*** trunk.orig/gcc/testsuite/gfortran.dg/reassoc_5.f90	(revision 0)
--- trunk/gcc/testsuite/gfortran.dg/reassoc_5.f90	(revision 0)
***************
*** 0 ****
--- 1,10 ----
+ ! { dg-do compile }
+ ! { dg-options "-O0 -ffinite-math-only -fdump-tree-original" }
+ 
+ function test(b, c)
+   real a, b, c
+   a = b + c - (b + c)
+   test = a
+ end
+ 
+ ! { dg-final { scan-tree-dump "a = 0.0" "original" } }



More information about the Fortran mailing list