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] Fix PR17598


This patch fixes PR17598 by folding comparisons of addresses
of component refs to comparisons of the base addresses, if possible.

Bootstrapped and tested on x86_64-unknown-linux-gnu for all
languages but ada.

Ok for mainline?

Richard.


2004-04-25  Richard Guenther  <rguenth@gcc.gnu.org>

	PR tree-optimization/17598
	* fold-const.c (fold_binary): Fold comparisons of addresses
	of COMPONENT_REFs which reference the same field to
	comparisons of the addresses of the base objects.

	* gcc.dg/tree-ssa/pr17598.c: New testcase.


Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.570
diff -c -3 -p -r1.570 fold-const.c
*** fold-const.c	23 Apr 2005 21:34:36 -0000	1.570
--- fold-const.c	25 Apr 2005 13:01:52 -0000
*************** fold_binary (enum tree_code code, tree t
*** 9708,9713 ****
--- 9737,9775 ----
  	    return t1;
  	}

+       /* 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);
+ 	      if (TREE_CODE (op0) == INDIRECT_REF)
+ 		op0 = TREE_OPERAND (op0, 0);
+ 	      else
+ 	        {
+ 	          tree ptype = build_pointer_type (TREE_TYPE (op0));
+ 	          op0 = build1 (ADDR_EXPR, ptype, op0);
+ 		}
+ 	      if (TREE_CODE (op1) == INDIRECT_REF)
+ 		op1 = TREE_OPERAND (op1, 0);
+ 	      else
+ 	        {
+ 	          tree ptype = build_pointer_type (TREE_TYPE (op1));
+ 		  op1 = build1 (ADDR_EXPR, ptype, op1);
+ 		}
+ 	      return fold_build2 (code, type, op0, op1);
+ 	    }
+ 	}
+
        /* If this is a comparison of complex values and either or both sides
  	 are a COMPLEX_EXPR or COMPLEX_CST, it is best to split up the
  	 comparisons and join them with a TRUTH_ANDIF_EXPR or TRUTH_ORIF_EXPR.



/* { dg-do compile } */
/* { dg-options "-fdump-tree-generic" } */

struct f
{
  int i;
  int j;
};

struct g
{
  int i;
  struct f j;
  struct f *k;
};

int foo(struct f *x, struct f *y)
{
  return &x->j == &y->j; /* x == y */
}

struct f y;
int bar(struct f *x)
{
  return &x->j == &y.j; /* x == &y */
}

struct g yy;
int foobar(struct g *x)
{
  return &x->j.i == &yy.j.i; /* x == &yy */
}
int foobar2(struct g *x)
{
  return &x->k->i == &yy.k->i; /* x->k == yy.k */
}

/* { dg-final { scan-tree-dump-times "x == y" 1 "generic" } } */
/* { dg-final { scan-tree-dump-times "x == &y" 2 "generic" } } */
/* { dg-final { scan-tree-dump "x->k" "generic" } } */
/* { dg-final { scan-tree-dump "yy.k" "generic" } } */
/* { dg-final { cleanup-tree-dump "generic" } } */


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