aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/fold-const.c63
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/loop-17.c19
4 files changed, 67 insertions, 28 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 977f32a..fd3d122 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2006-06-04 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/27039
+ * fold-const.c (fold_comparison): Handle pointer comparison
+ again for all comparison codes. Compare offsets in signed
+ size type.
+ (fold_binary): Move code from here.
+
2006-06-03 Roger Sayle <roger@eyesopen.com>
PR target/26223
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 7930bb4..3c8575e 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -7764,6 +7764,41 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
return fold_build2 (code, type, variable, lhs);
}
+ /* 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. */
+ if (POINTER_TYPE_P (TREE_TYPE (arg0))
+ && !flag_wrapv && !flag_trapv)
+ {
+ 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);
+ }
+ }
+
if (FLOAT_TYPE_P (TREE_TYPE (arg0)))
{
tree targ0 = strip_float_extensions (arg0);
@@ -10539,34 +10574,6 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
tem, build_int_cst (TREE_TYPE (tem), 0));
}
- /* 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. This is only safe for
- EQ_EXPR and NE_EXPR because of overflow issues. */
- {
- tree base0, offset0, base1, offset1;
-
- if (extract_array_ref (arg0, &base0, &offset0)
- && extract_array_ref (arg1, &base1, &offset1)
- && operand_equal_p (base0, base1, 0))
- {
- /* Handle no offsets on both sides specially. */
- if (offset0 == NULL_TREE && offset1 == NULL_TREE)
- return fold_build2 (code, type, integer_zero_node,
- integer_zero_node);
-
- if (!offset0 || !offset1
- || TREE_TYPE (offset0) == TREE_TYPE (offset1))
- {
- if (offset0 == NULL_TREE)
- offset0 = build_int_cst (TREE_TYPE (offset1), 0);
- if (offset1 == NULL_TREE)
- offset1 = build_int_cst (TREE_TYPE (offset0), 0);
- return fold_build2 (code, type, offset0, offset1);
- }
- }
- }
-
if (integer_zerop (arg1)
&& tree_expr_nonzero_p (arg0))
{
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 1553c98..21fa273 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2006-06-04 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/27039
+ * gcc.dg/tree-ssa/loop-17.c: New testcase.
+
2006-06-03 Roger Sayle <roger@eyesopen.com>
PR target/26223
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-17.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-17.c
new file mode 100644
index 0000000..26e4986
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-17.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-sccp-details" } */
+
+/* To determine the number of iterations in this loop we need to fold
+ p_4 + 4B > p_4 + 8B to false. This transformation has caused
+ troubles in the past due to overflow issues. */
+
+int foo (int *p)
+{
+ int i = 0, *x;
+
+ for (x = p; x < p + 2; x++)
+ i++;
+
+ return i;
+}
+
+/* { dg-final { scan-tree-dump "set_nb_iterations_in_loop = 2" "sccp" } } */
+/* { dg-final { cleanup-tree-dump "sccp" } } */