This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Fold comparison of local addresses
Hi,
This patch may be the cause for
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35706
I will know for sure within an hour.
H.J.
On Wed, Mar 26, 2008 at 5:35 AM, Richard Guenther <rguenther@suse.de> wrote:
> 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 ----
>