diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a916993a799..ff382751044 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2008-11-17 Jakub Jelinek + + PR middle-end/38140 + * tree-ssa-forwprop.c (forward_propagate_addr_expr_1): If + propagating x = &a into *x = b, add a cast if not useless + type conversion or don't optimize if another stmt would be + needed. + 2008-11-17 Uros Bizjak PR middle-end/37908 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0c0dc1d0a5c..00b7cef1442 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2008-11-17 Jakub Jelinek + + PR middle-end/38140 + * gcc.dg/pr38140.c: New test. + 2008-11-17 Jack Howarth PR testsuite/38099 diff --git a/gcc/testsuite/gcc.dg/pr38140.c b/gcc/testsuite/gcc.dg/pr38140.c new file mode 100644 index 00000000000..35f6010089e --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr38140.c @@ -0,0 +1,10 @@ +/* PR middle-end/38140 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-strict-aliasing" } */ + +int foo (void *x) +{ + int (*fn) (int); + *(void **)&fn = x; + return fn (6); +} diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c index 5626b103429..333ef828473 100644 --- a/gcc/tree-ssa-forwprop.c +++ b/gcc/tree-ssa-forwprop.c @@ -721,13 +721,28 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs, && TREE_OPERAND (lhs, 0) == name && may_propagate_address_into_dereference (def_rhs, lhs)) { - *lhsp = unshare_expr (TREE_OPERAND (def_rhs, 0)); - fold_stmt_inplace (use_stmt); - tidy_after_forward_propagate_addr (use_stmt); + bool valid = true; + if (lhsp == gimple_assign_lhs_ptr (use_stmt) + && !useless_type_conversion_p (TREE_TYPE (TREE_OPERAND (def_rhs, 0)), + TREE_TYPE (rhs)) + && !CONVERT_EXPR_CODE_P (rhs_code)) + { + if (rhs_code == SSA_NAME) + gimple_assign_set_rhs_code (use_stmt, NOP_EXPR); + else + valid = false; + } + if (valid) + { + *lhsp = unshare_expr (TREE_OPERAND (def_rhs, 0)); + fold_stmt_inplace (use_stmt); + tidy_after_forward_propagate_addr (use_stmt); - /* Continue propagating into the RHS if this was not the only use. */ - if (single_use_p) - return true; + /* Continue propagating into the RHS if this was not the only + use. */ + if (single_use_p) + return true; + } } /* Strip away any outer COMPONENT_REF, ARRAY_REF or ADDR_EXPR