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]

Re: [PATCH] Fold comparison of local addresses


On Tue, 25 Mar 2008, Richard Guenther wrote:

> 
> I was surprised we don't handle this yet.
> 
> Bootstrap & regtest in progress, I'll apply it after that succeeded.

I ended up with a different patch, which is as below.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to
mainline.

Richard.

2008-03-26  Richard Guenther  <rguenther@suse.de>

	* fold-const.c (target.h): Include.
	(fold_comparison): Fold comparison of addresses of two decls
	that bind locally.  Consolidate address folding code.

	* gcc.dg/fold-addr-1.c: New testcase.

Index: testsuite/gcc.dg/fold-addr-1.c
===================================================================
*** testsuite/gcc.dg/fold-addr-1.c	(revision 0)
--- testsuite/gcc.dg/fold-addr-1.c	(revision 0)
***************
*** 0 ****
--- 1,10 ----
+ /* { dg-do compile } */
+ /* { dg-options "-fdump-tree-original" } */
+ 
+ int bar(char p1, char p2)
+ {
+   return &p1 == &p2;
+ }
+ 
+ /* { dg-final { scan-tree-dump "return 0;" "original" } } */
+ /* { dg-final { cleanup-tree-dump "original" } } */
Index: fold-const.c
===================================================================
*** fold-const.c	(revision 133506)
--- fold-const.c	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 58,63 ****
--- 58,64 ----
  #include "rtl.h"
  #include "expr.h"
  #include "tm_p.h"
+ #include "target.h"
  #include "toplev.h"
  #include "intl.h"
  #include "ggc.h"
*************** fold_comparison (enum tree_code code, tr
*** 8481,8491 ****
        HOST_WIDE_INT bitsize, bitpos0 = 0, bitpos1 = 0;
        enum machine_mode mode;
        int volatilep, unsignedp;
!       bool indirect_base0 = false;
  
        /* Get base and offset for the access.  Strip ADDR_EXPR for
  	 get_inner_reference, but put it back by stripping INDIRECT_REF
! 	 off the base object if possible.  */
        base0 = arg0;
        if (TREE_CODE (arg0) == ADDR_EXPR)
  	{
--- 8482,8493 ----
        HOST_WIDE_INT bitsize, bitpos0 = 0, bitpos1 = 0;
        enum machine_mode mode;
        int volatilep, unsignedp;
!       bool indirect_base0 = false, indirect_base1 = false;
  
        /* Get base and offset for the access.  Strip ADDR_EXPR for
  	 get_inner_reference, but put it back by stripping INDIRECT_REF
! 	 off the base object if possible.  indirect_baseN will be true
! 	 if baseN is not an address but refers to the object itself.  */
        base0 = arg0;
        if (TREE_CODE (arg0) == ADDR_EXPR)
  	{
*************** fold_comparison (enum tree_code code, tr
*** 8509,8532 ****
  	  base1 = get_inner_reference (TREE_OPERAND (arg1, 0),
  				       &bitsize, &bitpos1, &offset1, &mode,
  				       &unsignedp, &volatilep, false);
! 	  /* We have to make sure to have an indirect/non-indirect base1
! 	     just the same as we did for base0.  */
! 	  if (TREE_CODE (base1) == INDIRECT_REF
! 	      && !indirect_base0)
  	    base1 = TREE_OPERAND (base1, 0);
! 	  else if (!indirect_base0)
! 	    base1 = NULL_TREE;
  	}
        else if (TREE_CODE (arg1) == POINTER_PLUS_EXPR)
  	{
  	  base1 = TREE_OPERAND (arg1, 0);
  	  offset1 = TREE_OPERAND (arg1, 1);
  	}
-       else if (indirect_base0)
- 	base1 = NULL_TREE;
  
        /* If we have equivalent bases we might be able to simplify.  */
!       if (base0 && base1
  	  && operand_equal_p (base0, base1, 0))
  	{
  	  /* We can fold this expression to a constant if the non-constant
--- 8511,8529 ----
  	  base1 = get_inner_reference (TREE_OPERAND (arg1, 0),
  				       &bitsize, &bitpos1, &offset1, &mode,
  				       &unsignedp, &volatilep, false);
! 	  if (TREE_CODE (base1) == INDIRECT_REF)
  	    base1 = TREE_OPERAND (base1, 0);
! 	  else
! 	    indirect_base1 = true;
  	}
        else if (TREE_CODE (arg1) == POINTER_PLUS_EXPR)
  	{
  	  base1 = TREE_OPERAND (arg1, 0);
  	  offset1 = TREE_OPERAND (arg1, 1);
  	}
  
        /* If we have equivalent bases we might be able to simplify.  */
!       if (indirect_base0 == indirect_base1
  	  && operand_equal_p (base0, base1, 0))
  	{
  	  /* We can fold this expression to a constant if the non-constant
*************** fold_comparison (enum tree_code code, tr
*** 8581,8586 ****
--- 8578,8614 ----
  	      return fold_build2 (code, type, offset0, offset1);
  	    }
  	}
+       /* For non-equal bases we can simplify if they are plain decls.  */
+       else if (!indirect_base0 && !indirect_base1
+ 	       && TREE_CODE (arg0) == ADDR_EXPR
+ 	       && TREE_CODE (arg1) == ADDR_EXPR
+ 	       && DECL_P (base0) && DECL_P (base1)
+ 	       && !operand_equal_p (base0, base1, 0)
+ 	       && targetm.binds_local_p (base0)
+ 	       && targetm.binds_local_p (base1))
+ 	{
+ 	  if (code == EQ_EXPR)
+ 	    return omit_two_operands (type, boolean_false_node, arg0, arg1);
+ 	  else if (code == NE_EXPR)
+ 	    return omit_two_operands (type, boolean_true_node, arg0, arg1);
+ 	}
+       /* For equal offsets we can simplify to a comparison of the
+ 	 base addresses.  */
+       else if (bitpos0 == bitpos1
+ 	       && (indirect_base0
+ 		   ? base0 != TREE_OPERAND (arg0, 0) : base0 != arg0)
+ 	       && (indirect_base1
+ 		   ? base1 != TREE_OPERAND (arg1, 0) : base1 != arg1)
+ 	       && ((offset0 == offset1)
+ 		   || (offset0 && offset1
+ 		       && operand_equal_p (offset0, offset1, 0))))
+ 	{
+ 	  if (indirect_base0)
+ 	    base0 = fold_addr_expr (base0);
+ 	  if (indirect_base1)
+ 	    base1 = fold_addr_expr (base1);
+ 	  return fold_build2 (code, type, base0, base1);
+ 	}
      }
  
    /* Transform comparisons of the form X +- C1 CMP Y +- C2 to
*************** fold_comparison (enum tree_code code, tr
*** 8927,8953 ****
  	}
      }
  
-   /* Fold a comparison of the address of COMPONENT_REFs with the same
-      type and component to a comparison of the address of the base
-      object.  In short, &x->a OP &y->a to x OP y and
-      &x->a OP &y.a to x OP &y  */
-   if (TREE_CODE (arg0) == ADDR_EXPR
-       && TREE_CODE (TREE_OPERAND (arg0, 0)) == COMPONENT_REF
-       && TREE_CODE (arg1) == ADDR_EXPR
-       && TREE_CODE (TREE_OPERAND (arg1, 0)) == COMPONENT_REF)
-     {
-       tree cref0 = TREE_OPERAND (arg0, 0);
-       tree cref1 = TREE_OPERAND (arg1, 0);
-       if (TREE_OPERAND (cref0, 1) == TREE_OPERAND (cref1, 1))
- 	{
- 	  tree op0 = TREE_OPERAND (cref0, 0);
- 	  tree op1 = TREE_OPERAND (cref1, 0);
- 	  return fold_build2 (code, type,
- 			      fold_addr_expr (op0),
- 			      fold_addr_expr (op1));
- 	}
-     }
- 
    /* We can fold X/C1 op C2 where C1 and C2 are integer constants
       into a single range test.  */
    if ((TREE_CODE (arg0) == TRUNC_DIV_EXPR
--- 8955,8960 ----


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