This fixes PR49115 - we cannot assume that a stmt that can throw internally is a kill.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk, queued for backporting. Richard. 2011-05-23 Richard Guenther <rguent...@suse.de> PR tree-optimization/49115 * tree-ssa-alias.c (stmt_kills_ref_p_1): If the assignment is not necessarily carried out, do not claim it kills the ref. * tree-ssa-dce.c (mark_aliased_reaching_defs_necessary_1): Likewise. * g++.dg/torture/pr49115.C: New testcase. Index: gcc/tree-ssa-alias.c =================================================================== *** gcc/tree-ssa-alias.c (revision 174059) --- gcc/tree-ssa-alias.c (working copy) *************** stmt_kills_ref_p_1 (gimple stmt, ao_ref *** 1633,1639 **** return false; if (gimple_has_lhs (stmt) ! && TREE_CODE (gimple_get_lhs (stmt)) != SSA_NAME) { tree base, lhs = gimple_get_lhs (stmt); HOST_WIDE_INT size, offset, max_size; --- 1643,1656 ---- return false; if (gimple_has_lhs (stmt) ! && TREE_CODE (gimple_get_lhs (stmt)) != SSA_NAME ! /* The assignment is not necessarily carried out if it can throw ! and we can catch it in the current function where we could inspect ! the previous value. ! ??? We only need to care about the RHS throwing. For aggregate ! assignments or similar calls and non-call exceptions the LHS ! might throw as well. */ ! && !stmt_can_throw_internal (stmt)) { tree base, lhs = gimple_get_lhs (stmt); HOST_WIDE_INT size, offset, max_size; Index: gcc/tree-ssa-dce.c =================================================================== *** gcc/tree-ssa-dce.c (revision 174059) --- gcc/tree-ssa-dce.c (working copy) *************** mark_aliased_reaching_defs_necessary_1 ( *** 521,527 **** /* If the stmt lhs kills ref, then we can stop walking. */ if (gimple_has_lhs (def_stmt) ! && TREE_CODE (gimple_get_lhs (def_stmt)) != SSA_NAME) { tree base, lhs = gimple_get_lhs (def_stmt); HOST_WIDE_INT size, offset, max_size; --- 521,534 ---- /* If the stmt lhs kills ref, then we can stop walking. */ if (gimple_has_lhs (def_stmt) ! && TREE_CODE (gimple_get_lhs (def_stmt)) != SSA_NAME ! /* The assignment is not necessarily carried out if it can throw ! and we can catch it in the current function where we could inspect ! the previous value. ! ??? We only need to care about the RHS throwing. For aggregate ! assignments or similar calls and non-call exceptions the LHS ! might throw as well. */ ! && !stmt_can_throw_internal (def_stmt)) { tree base, lhs = gimple_get_lhs (def_stmt); HOST_WIDE_INT size, offset, max_size; Index: gcc/testsuite/g++.dg/torture/pr49115.C =================================================================== *** gcc/testsuite/g++.dg/torture/pr49115.C (revision 0) --- gcc/testsuite/g++.dg/torture/pr49115.C (revision 0) *************** *** 0 **** --- 1,25 ---- + // { dg-do run } + + extern "C" void abort (void); + struct MyException {}; + struct Data { + int nr; + Data() : nr(66) {} + }; + Data __attribute__((noinline,noclone)) getData(int i) + { + if (i) throw MyException(); + Data data; + data.nr = i; + return data; + } + int main(int, char **) + { + Data data; + try { + data = getData(1); + } catch (MyException& e) { + if (data.nr != 66) + abort (); + } + }