fold-const.c (extract_array_ref): Remove.

2007-10-15  Richard Guenther  <rguenther@suse.de>

	* fold-const.c (extract_array_ref): Remove.
	(fold_comparison): Handle POINTER_PLUS_EXPR with the
	generic address expression comparison folding.  Remove
	the folding that used extract_array_ref.

From-SVN: r129347
This commit is contained in:
Richard Guenther 2007-10-15 14:49:55 +00:00 committed by Richard Biener
parent eb64c8e52f
commit 3e0de2559e
2 changed files with 22 additions and 114 deletions

View File

@ -1,3 +1,10 @@
2007-10-15 Richard Guenther <rguenther@suse.de>
* fold-const.c (extract_array_ref): Remove.
(fold_comparison): Handle POINTER_PLUS_EXPR with the
generic address expression comparison folding. Remove
the folding that used extract_array_ref.
2007-10-15 Maxim Kuvyrkov <maxim@codesourcery.com>
PR target/33133

View File

@ -6322,76 +6322,6 @@ constant_boolean_node (int value, tree type)
}
/* 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)). Offset will be the offset
in bytes to the base in sizetype. */
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) == POINTER_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 p+ 4 possibly. */
STRIP_NOPS (op0);
if (extract_array_ref (op0, &inner_base, &dummy1))
{
*base = inner_base;
*offset = fold_convert (sizetype, TREE_OPERAND (expr, 1));
if (dummy1 != NULL_TREE)
*offset = fold_build2 (PLUS_EXPR, sizetype,
dummy1, *offset);
return true;
}
}
/* Other canonical form is an ADDR_EXPR of an ARRAY_REF,
which we transform into an ADDR_EXPR with appropriate
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)
{
tree idx = TREE_OPERAND (op0, 1);
*base = TREE_OPERAND (op0, 0);
*offset = fold_build2 (MULT_EXPR, TREE_TYPE (idx), idx,
array_ref_element_size (op0));
*offset = fold_convert (sizetype, *offset);
}
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;
}
/* Transform `a + (b ? x : y)' into `b ? (a + x) : (a + y)'.
Transform, `a + (x < y)' into `(x < y) ? (a + 1) : (a + 0)'. Here
CODE corresponds to the `+', COND to the `(b ? x : y)' or `(x < y)'
@ -8802,11 +8732,13 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
/* For comparisons of pointers we can decompose it to a compile time
comparison of the base objects and the offsets into the object.
This requires at least one operand being an ADDR_EXPR to do more
than the operand_equal_p test below. */
This requires at least one operand being an ADDR_EXPR or a
POINTER_PLUS_EXPR to do more than the operand_equal_p test below. */
if (POINTER_TYPE_P (TREE_TYPE (arg0))
&& (TREE_CODE (arg0) == ADDR_EXPR
|| TREE_CODE (arg1) == ADDR_EXPR))
|| TREE_CODE (arg1) == ADDR_EXPR
|| TREE_CODE (arg0) == POINTER_PLUS_EXPR
|| TREE_CODE (arg1) == POINTER_PLUS_EXPR))
{
tree base0, base1, offset0 = NULL_TREE, offset1 = NULL_TREE;
HOST_WIDE_INT bitsize, bitpos0 = 0, bitpos1 = 0;
@ -8828,6 +8760,11 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
else
indirect_base0 = true;
}
else if (TREE_CODE (arg0) == POINTER_PLUS_EXPR)
{
base0 = TREE_OPERAND (arg0, 0);
offset0 = TREE_OPERAND (arg0, 1);
}
base1 = arg1;
if (TREE_CODE (arg1) == ADDR_EXPR)
@ -8843,6 +8780,11 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
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;
@ -8904,47 +8846,6 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
}
}
/* 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 in
signed size type. This is possible because pointer arithmetic is
restricted to retain within an object and overflow on pointer differences
is undefined as of 6.5.6/8 and /9 with respect to the signed ptrdiff_t.
We check flag_wrapv directly because pointers types are unsigned,
and therefore TYPE_OVERFLOW_WRAPS returns true for them. That is
normally what we want to avoid certain odd overflow cases, but
not here. */
if (POINTER_TYPE_P (TREE_TYPE (arg0))
&& !flag_wrapv
&& !TYPE_OVERFLOW_TRAPS (TREE_TYPE (arg0)))
{
tree base0, offset0, base1, offset1;
if (extract_array_ref (arg0, &base0, &offset0)
&& extract_array_ref (arg1, &base1, &offset1)
&& operand_equal_p (base0, base1, 0))
{
tree signed_size_type_node;
signed_size_type_node = signed_type_for (size_type_node);
/* By converting to signed size type we cover middle-end pointer
arithmetic which operates on unsigned pointer types of size
type size and ARRAY_REF offsets which are properly sign or
zero extended from their type in case it is narrower than
size type. */
if (offset0 == NULL_TREE)
offset0 = build_int_cst (signed_size_type_node, 0);
else
offset0 = fold_convert (signed_size_type_node, offset0);
if (offset1 == NULL_TREE)
offset1 = build_int_cst (signed_size_type_node, 0);
else
offset1 = fold_convert (signed_size_type_node, offset1);
return fold_build2 (code, type, offset0, offset1);
}
}
/* Transform comparisons of the form X +- C1 CMP Y +- C2 to
X CMP Y +- C2 +- C1 for signed X, Y. This is valid if
the resulting offset is smaller in absolute value than the