aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/fold-const.c129
2 files changed, 22 insertions, 114 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 536ef54..12452b5 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 4a8153c..fd5a708 100644
--- a/gcc/fold-const.c
+++ b/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