aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2008-03-17 14:34:21 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2008-03-17 14:34:21 +0000
commitc4e5b5a8bf81daa9e21c17149a4943b96c8099b3 (patch)
tree953f8e21808467a87b2490c396b2f654c4d588ca
parentec286fe7ab26dbfeeb7e7d05d9d747745c108393 (diff)
downloadgcc-c4e5b5a8bf81daa9e21c17149a4943b96c8099b3.zip
gcc-c4e5b5a8bf81daa9e21c17149a4943b96c8099b3.tar.gz
gcc-c4e5b5a8bf81daa9e21c17149a4943b96c8099b3.tar.bz2
re PR tree-optimization/19637 (Missed VRP and FRE opportunities in the presence of casts)
2008-03-17 Richard Guenther <rguenther@suse.de> PR tree-optimization/19637 * fold-const.c (fold_unary): Remove restrictions of removing intermediate pointer-conversions (P2)(P1)P0. * tree-ssa-ccp.c (maybe_fold_stmt_addition): Recover from conversion to void pointer. (get_maxval_strlen): Handle addresses of the form &(*p)[0]. * g++.dg/tree-ssa/pr19637.C: New testcase. From-SVN: r133291
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/fold-const.c9
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr19637.C33
-rw-r--r--gcc/tree-ssa-ccp.c17
5 files changed, 66 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index fa2ed09..2830927 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2008-03-17 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/19637
+ * fold-const.c (fold_unary): Remove restrictions of removing
+ intermediate pointer-conversions (P2)(P1)P0.
+ * tree-ssa-ccp.c (maybe_fold_stmt_addition): Recover from
+ conversion to void pointer.
+ (get_maxval_strlen): Handle addresses of the form &(*p)[0].
+
2008-03-16 James E. Wilson <wilson@tuliptree.org>
PR debug/31510
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 4dc4ad7..3bfe52e 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -7784,9 +7784,7 @@ fold_unary (enum tree_code code, tree type, tree op0)
- the initial type is a pointer type and the precisions of the
intermediate and final types differ, or
- the final type is a pointer type and the precisions of the
- initial and intermediate types differ.
- - the initial type is a pointer to an array and the final type
- not. */
+ initial and intermediate types differ. */
if (! inside_float && ! inter_float && ! final_float
&& ! inside_vec && ! inter_vec && ! final_vec
&& (inter_prec >= inside_prec || inter_prec >= final_prec)
@@ -7798,10 +7796,7 @@ fold_unary (enum tree_code code, tree type, tree op0)
&& ! (inside_ptr && inter_prec != final_prec)
&& ! (final_ptr && inside_prec != inter_prec)
&& ! (final_prec != GET_MODE_BITSIZE (TYPE_MODE (type))
- && TYPE_MODE (type) == TYPE_MODE (inter_type))
- && ! (inside_ptr && final_ptr
- && TREE_CODE (TREE_TYPE (inside_type)) == ARRAY_TYPE
- && TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE))
+ && TYPE_MODE (type) == TYPE_MODE (inter_type)))
return fold_build1 (code, type, TREE_OPERAND (op0, 0));
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 10ead70..9242eca 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2008-03-17 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/19637
+ * g++.dg/tree-ssa/pr19637.C: New testcase.
+
2008-03-16 Paul Thomas <pault@gcc.gnu.org>
PR fortran/35470
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr19637.C b/gcc/testsuite/g++.dg/tree-ssa/pr19637.C
new file mode 100644
index 0000000..2d1dcceb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr19637.C
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-dom1" } */
+
+#include <new>
+
+struct Foo {
+ Foo() { i[0] = 1; }
+ int i[2];
+};
+
+int foo_char(void)
+{
+ int i[2];
+ new (reinterpret_cast<char *>(i)) Foo();
+ return reinterpret_cast<Foo *>(i)->i[0];
+}
+
+int foo_void(void)
+{
+ int i[2];
+ new (reinterpret_cast<void *>(i)) Foo();
+ return reinterpret_cast<Foo *>(i)->i[0];
+}
+
+int foo_void_offset(void)
+{
+ int i[2];
+ new (reinterpret_cast<void *>(&i[0])) Foo();
+ return reinterpret_cast<Foo *>(&i[0])->i[0];
+}
+
+/* { dg-final { scan-tree-dump-times "return 1;" 3 "dom1" } } */
+/* { dg-final { cleanup-tree-dump "dom1" } } */
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index f087a8d..7e51926 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -2105,6 +2105,12 @@ maybe_fold_stmt_addition (tree expr)
}
ptd_type = TREE_TYPE (ptr_type);
+ /* If we want a pointer to void, reconstruct the reference from the
+ array element type. A pointer to that can be trivially converted
+ to void *. This happens as we fold (void *)(ptr p+ off). */
+ if (VOID_TYPE_P (ptd_type)
+ && TREE_CODE (TREE_TYPE (op0)) == ARRAY_TYPE)
+ ptd_type = TREE_TYPE (TREE_TYPE (op0));
/* At which point we can try some of the same things as for indirects. */
t = maybe_fold_offset_to_array_ref (op0, op1, ptd_type, true);
@@ -2292,6 +2298,17 @@ get_maxval_strlen (tree arg, tree *length, bitmap visited, int type)
if (TREE_CODE (arg) == COND_EXPR)
return get_maxval_strlen (COND_EXPR_THEN (arg), length, visited, type)
&& get_maxval_strlen (COND_EXPR_ELSE (arg), length, visited, type);
+ /* We can end up with &(*iftmp_1)[0] here as well, so handle it. */
+ else if (TREE_CODE (arg) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (arg, 0)) == ARRAY_REF
+ && integer_zerop (TREE_OPERAND (TREE_OPERAND (arg, 0), 1)))
+ {
+ tree aop0 = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
+ if (TREE_CODE (aop0) == INDIRECT_REF
+ && TREE_CODE (TREE_OPERAND (aop0, 0)) == SSA_NAME)
+ return get_maxval_strlen (TREE_OPERAND (aop0, 0),
+ length, visited, type);
+ }
if (type == 2)
{