This fixes PR58956 where we TER a load into a call statement lhs that is modified by the call. TER already has measures to avoid doing this for regular assignments so the following simply extends it to arbitrary stmts (including ASMs).
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2013-11-19 Richard Biener <rguent...@suse.de> PR middle-end/58956 * tree-ssa-ter.c (find_replaceable_in_bb): Avoid forwarding loads into stmts that may clobber it. * gcc.dg/torture/pr58956.c: New testcase. Index: gcc/tree-ssa-ter.c =================================================================== *** gcc/tree-ssa-ter.c (revision 205009) --- gcc/tree-ssa-ter.c (working copy) *************** find_replaceable_in_bb (temp_expr_table_ *** 601,608 **** /* If the stmt does a memory store and the replacement is a load aliasing it avoid creating overlapping assignments which we cannot expand correctly. */ ! if (gimple_vdef (stmt) ! && gimple_assign_single_p (stmt)) { gimple def_stmt = SSA_NAME_DEF_STMT (use); while (is_gimple_assign (def_stmt) --- 607,613 ---- /* If the stmt does a memory store and the replacement is a load aliasing it avoid creating overlapping assignments which we cannot expand correctly. */ ! if (gimple_vdef (stmt)) { gimple def_stmt = SSA_NAME_DEF_STMT (use); while (is_gimple_assign (def_stmt) *************** find_replaceable_in_bb (temp_expr_table_ *** 611,618 **** = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (def_stmt)); if (gimple_vuse (def_stmt) && gimple_assign_single_p (def_stmt) ! && refs_may_alias_p (gimple_assign_lhs (stmt), ! gimple_assign_rhs1 (def_stmt))) same_root_var = true; } --- 616,623 ---- = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (def_stmt)); if (gimple_vuse (def_stmt) && gimple_assign_single_p (def_stmt) ! && stmt_may_clobber_ref_p (stmt, ! gimple_assign_rhs1 (def_stmt))) same_root_var = true; } Index: gcc/testsuite/gcc.dg/torture/pr58956.c =================================================================== *** gcc/testsuite/gcc.dg/torture/pr58956.c (revision 0) --- gcc/testsuite/gcc.dg/torture/pr58956.c (working copy) *************** *** 0 **** --- 1,30 ---- + /* { dg-do run } */ + + extern void abort (void); + + struct S + { + int f0; + } a = {1}, b, g, *c = &b, **f = &c; + + int *d, **e = &d, h; + + struct S + foo () + { + *e = &h; + if (!d) + __builtin_unreachable (); + *f = &g; + return a; + } + + int + main () + { + struct S *i = c; + *i = foo (); + if (b.f0 != 1) + abort (); + return 0; + }