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:
parent
eb64c8e52f
commit
3e0de2559e
@ -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
|
||||
|
129
gcc/fold-const.c
129
gcc/fold-const.c
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user