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 PR15791, 2nd try


Second try - this time it works for even more weird cases.
Also maybe all comments have been addressed.

Another round of testing is in work.

Richard.


2005-Jan-27  Richard Guenther <richard.guenther@uni-tuebingen.de>

	* fold-const.c (extract_array_ref): new function.
	(fold): fold comparisons between &a[i] and &a[j]
	and semantically equivalent variants.


Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.497
diff -u -c -3 -p -r1.497 fold-const.c
*** fold-const.c	23 Jan 2005 15:05:29 -0000	1.497
--- fold-const.c	27 Jan 2005 17:05:24 -0000
*************** extract_muldiv_1 (tree t, tree c, enum t
*** 5356,5361 ****
--- 5356,5407 ----

    return 0;
  }
+
+
+ /* 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)
+ {
+   tree inner_expr = expr;
+   STRIP_NOPS (inner_expr);
+   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;
+ 	}
+     }
+   else if (TREE_CODE (inner_expr) == ADDR_EXPR)
+     {
+       tree op0 = TREE_OPERAND (inner_expr, 0);
+       if (TREE_CODE (op0) == ARRAY_REF)
+ 	{
+ 	  *base = TREE_OPERAND (op0, 0);
+ 	  *offset = TREE_OPERAND (op0, 1);
+ 	}
+       else if (TREE_CODE (op0) == COMPONENT_REF)
+ 	{
+ 	  *base = op0;
+ 	  *offset = NULL_TREE;
+ 	}
+       else
+ 	{
+ 	  *base = expr;
+ 	  *offset = NULL_TREE;
+ 	}
+       return true;
+     }
+
+   return false;
+ }
+

  /* Return a node which has the indicated constant VALUE (either 0 or
     1), and is of the indicated TYPE.  */
*************** fold (tree expr)
*** 8245,8250 ****
--- 8291,8324 ----
  				      ? code == EQ_EXPR : code != EQ_EXPR,
  				      type);

+       /* If this is a comparison of two exprs that look like an
+ 	 ARRAY_REF of the same object, then we can fold this to a
+ 	 comparison of the two offsets.  */
+       if (COMPARISON_CLASS_P (t))
+ 	{
+ 	  tree base0, offset0, base1, offset1;
+
+ 	  if (extract_array_ref (arg0, &base0, &offset0)
+ 	      && extract_array_ref (arg1, &base1, &offset1)
+ 	      && operand_equal_p (base0, base1, 0))
+ 	    {
+ 	      if (offset0 == NULL_TREE
+ 		  && offset1 == NULL_TREE)
+ 		{
+ 		  offset0 = integer_zero_node;
+ 		  offset1 = integer_zero_node;
+ 		}
+ 	      else if (offset0 == NULL_TREE)
+ 		offset0 = build_int_cst (TREE_TYPE (offset1), 0);
+ 	      else if (offset1 == NULL_TREE)
+ 		offset1 = build_int_cst (TREE_TYPE (offset0), 0);
+
+ 	      if (TYPE_MAIN_VARIANT (TREE_TYPE (offset0))
+ 		  == TYPE_MAIN_VARIANT (TREE_TYPE (offset1)))
+ 		return fold (build2 (code, type, offset0, offset1));
+ 	    }
+ 	}
+
        if (FLOAT_TYPE_P (TREE_TYPE (arg0)))
  	{
  	  tree targ0 = strip_float_extensions (arg0);


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