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 ();
+   }
+ }

Reply via email to