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] Do better in folding of &a[i] COMPARE &a[j]


This is another pre-requesite (actually only the part that handles
arrays of empty structures explicitly) for the switch of the C
frontend to no longer emit &a for &a[0].  While I was at it I
cleaned the helper routine and made it fold things like

char *a;
int foo(char *b)
{
        return a+5+(long)b == (long)b+a;
}

to false.

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

Ok for mainline?

Thanks,
Richard.


2005-05-19  Richard Guenther  <rguenth@gcc.gnu.org>

	* fold-const.c (extract_array_ref): Handle more cases,
	do some useful canonicalization of the base.
	(fold_binary): Explicitly deal with arrays of zero-sized
	structures during folding of &a[i] == &a[j].


Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.581
diff -c -3 -p -r1.581 fold-const.c
*** fold-const.c	17 May 2005 09:55:20 -0000	1.581
--- fold-const.c	19 May 2005 13:46:04 -0000
*************** constant_boolean_node (int value, tree t
*** 5485,5510 ****

  /* Return true if expr looks like an ARRAY_REF and set base and
     offset to the appropriate trees.  If there is no offset,
!    offset is set to NULL_TREE.  */

  static bool
  extract_array_ref (tree expr, tree *base, tree *offset)
  {
-   /* We have to be careful with stripping nops as with the
-      base type the meaning of the offset can change.  */
-   tree inner_expr = expr;
-   STRIP_NOPS (inner_expr);
    /* One canonical form is a PLUS_EXPR with the first
       argument being an ADDR_EXPR with a possible NOP_EXPR
       attached.  */
    if (TREE_CODE (expr) == PLUS_EXPR)
      {
        tree op0 = TREE_OPERAND (expr, 0);
        STRIP_NOPS (op0);
!       if (TREE_CODE (op0) == ADDR_EXPR)
  	{
! 	  *base = TREE_OPERAND (expr, 0);
! 	  *offset = TREE_OPERAND (expr, 1);
  	  return true;
  	}
      }
--- 5485,5515 ----

  /* Return true if expr looks like an ARRAY_REF and set base and
     offset to the appropriate trees.  If there is no offset,
!    offset is set to NULL_TREE.  Base will be canonicalized to
!    something you can get the element type from using
!    TREE_TYPE (TREE_TYPE (base)).  */

  static bool
  extract_array_ref (tree expr, tree *base, tree *offset)
  {
    /* One canonical form is a PLUS_EXPR with the first
       argument being an ADDR_EXPR with a possible NOP_EXPR
       attached.  */
    if (TREE_CODE (expr) == PLUS_EXPR)
      {
        tree op0 = TREE_OPERAND (expr, 0);
+       tree inner_base, dummy1;
+       /* Strip NOP_EXPRs here because the C frontends and/or
+ 	 folders present us (int *)&x.a + 4B possibly.  */
        STRIP_NOPS (op0);
!       if (extract_array_ref (op0, &inner_base, &dummy1))
  	{
! 	  *base = inner_base;
! 	  if (dummy1 == NULL_TREE)
! 	    *offset = TREE_OPERAND (expr, 1);
! 	  else
! 	    *offset = fold_build2 (PLUS_EXPR, TREE_TYPE (expr),
! 				   dummy1, TREE_OPERAND (expr, 1));
  	  return true;
  	}
      }
*************** extract_array_ref (tree expr, tree *base
*** 5513,5533 ****
       offset.  For other arguments to the ADDR_EXPR we assume
       zero offset and as such do not care about the ADDR_EXPR
       type and strip possible nops from it.  */
!   else if (TREE_CODE (inner_expr) == ADDR_EXPR)
      {
!       tree op0 = TREE_OPERAND (inner_expr, 0);
        if (TREE_CODE (op0) == ARRAY_REF)
  	{
! 	  *base = build_fold_addr_expr (TREE_OPERAND (op0, 0));
  	  *offset = TREE_OPERAND (op0, 1);
  	}
        else
  	{
! 	  *base = inner_expr;
  	  *offset = NULL_TREE;
  	}
        return true;
      }

    return false;
  }
--- 5518,5550 ----
       offset.  For other arguments to the ADDR_EXPR we assume
       zero offset and as such do not care about the ADDR_EXPR
       type and strip possible nops from it.  */
!   else if (TREE_CODE (expr) == ADDR_EXPR)
      {
!       tree op0 = TREE_OPERAND (expr, 0);
        if (TREE_CODE (op0) == ARRAY_REF)
  	{
! 	  *base = TREE_OPERAND (op0, 0);
  	  *offset = TREE_OPERAND (op0, 1);
  	}
        else
  	{
! 	  /* Handle array-to-pointer decay as &a.  */
! 	  if (TREE_CODE (TREE_TYPE (op0)) == ARRAY_TYPE)
! 	    *base = TREE_OPERAND (expr, 0);
! 	  else
! 	    *base = expr;
  	  *offset = NULL_TREE;
  	}
        return true;
      }
+   /* The next canonical form is a VAR_DECL with POINTER_TYPE.  */
+   else if (SSA_VAR_P (expr)
+ 	   && TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE)
+     {
+       *base = expr;
+       *offset = NULL_TREE;
+       return true;
+     }

    return false;
  }
*************** fold_binary (enum tree_code code, tree t
*** 9014,9019 ****
--- 9031,9042 ----
  	      && extract_array_ref (arg1, &base1, &offset1)
  	      && operand_equal_p (base0, base1, 0))
  	    {
+ 	      if (TYPE_SIZE (TREE_TYPE (TREE_TYPE (base0)))
+ 		  && integer_zerop (TYPE_SIZE (TREE_TYPE (TREE_TYPE (base0)))))
+ 		offset0 = NULL_TREE;
+ 	      if (TYPE_SIZE (TREE_TYPE (TREE_TYPE (base1)))
+ 		  && integer_zerop (TYPE_SIZE (TREE_TYPE (TREE_TYPE (base1)))))
+ 		offset1 = NULL_TREE;
  	      if (offset0 == NULL_TREE
  		  && offset1 == NULL_TREE)
  		{


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