The following patch fixes store sinking to properly account for self-assignments in the same way DSE does (which means this patch also enhances store-sinking).
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2013-05-21 Richard Biener <rguent...@suse.de> PR tree-optimization/57303 * tree-ssa-sink.c (statement_sink_location): Improve killing stmt detection and properly handle self-assignments. * gcc.dg/torture/pr57303.c: New testcase. Index: gcc/tree-ssa-sink.c =================================================================== *** gcc/tree-ssa-sink.c (revision 199004) --- gcc/tree-ssa-sink.c (working copy) *************** statement_sink_location (gimple stmt, ba *** 331,341 **** gimple use_stmt = USE_STMT (use_p); /* A killing definition is not a use. */ ! if (gimple_assign_single_p (use_stmt) ! && gimple_vdef (use_stmt) ! && operand_equal_p (gimple_assign_lhs (stmt), ! gimple_assign_lhs (use_stmt), 0)) ! continue; if (gimple_code (use_stmt) != GIMPLE_PHI) return false; --- 331,349 ---- gimple use_stmt = USE_STMT (use_p); /* A killing definition is not a use. */ ! if ((gimple_has_lhs (use_stmt) ! && operand_equal_p (gimple_assign_lhs (stmt), ! gimple_get_lhs (use_stmt), 0)) ! || stmt_kills_ref_p (use_stmt, gimple_assign_lhs (stmt))) ! { ! /* If use_stmt is or might be a nop assignment then USE_STMT ! acts as a use as well as definition. */ ! if (stmt != use_stmt ! && ref_maybe_used_by_stmt_p (use_stmt, ! gimple_assign_lhs (stmt))) ! return false; ! continue; ! } if (gimple_code (use_stmt) != GIMPLE_PHI) return false; Index: gcc/testsuite/gcc.dg/torture/pr57303.c =================================================================== *** gcc/testsuite/gcc.dg/torture/pr57303.c (revision 0) --- gcc/testsuite/gcc.dg/torture/pr57303.c (working copy) *************** *** 0 **** --- 1,33 ---- + /* { dg-do run } */ + + void abort (void); + + struct S0 + { + int f0; + }; + struct S1 + { + struct S0 f0; + }; + + struct S1 x = { {0} }; + struct S1 y = { {1} }; + + static void + foo (struct S0 p) + { + struct S0 *l = &y.f0; + *l = x.f0; + if (p.f0) + *l = *l; + } + + int + main () + { + foo(y.f0); + if (y.f0.f0 != 0) + abort (); + return 0; + }