diff options
author | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-03-17 14:34:21 +0000 |
---|---|---|
committer | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-03-17 14:34:21 +0000 |
commit | 0b4a6afcc4db5ef1f6a983363a5e72d09626a4c6 (patch) | |
tree | 953f8e21808467a87b2490c396b2f654c4d588ca /gcc | |
parent | b6d2ab40ae899bb9bda13f76c0962497aa91b42d (diff) | |
download | gcc-0b4a6afcc4db5ef1f6a983363a5e72d09626a4c6.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@133291 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/fold-const.c | 9 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/tree-ssa/pr19637.C | 33 | ||||
-rw-r--r-- | gcc/tree-ssa-ccp.c | 17 |
5 files changed, 66 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fa2ed097f62..28309279b79 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 4dc4ad72e3c..3bfe52e0081 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 10ead70ab01..9242eca671c 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 00000000000..2d1dcceba42 --- /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 f087a8d8948..7e519264f7a 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) { |