I am testing the following patch to fix PR70740. Bootstrap/regtest running on x86_64-unknown-linux-gnu.
Richard. 2016-04-21 Richard Biener <rguent...@suse.de> PR tree-optimization/70740 * tree-ssa-phiprop.c (propagate_with_phi): Handle inserted VDEF. * gcc.dg/torture/pr70740.c: New testcase. Index: gcc/tree-ssa-phiprop.c =================================================================== *** gcc/tree-ssa-phiprop.c (revision 235305) --- gcc/tree-ssa-phiprop.c (working copy) *************** propagate_with_phi (basic_block bb, gphi *** 327,339 **** continue; /* Check if we can move the loads. The def stmt of the virtual use ! needs to be in a different basic block dominating bb. */ vuse = gimple_vuse (use_stmt); def_stmt = SSA_NAME_DEF_STMT (vuse); if (!SSA_NAME_IS_DEFAULT_DEF (vuse) && (gimple_bb (def_stmt) == bb ! || !dominated_by_p (CDI_DOMINATORS, ! bb, gimple_bb (def_stmt)))) goto next; /* Found a proper dereference with an aggregate copy. Just --- 327,341 ---- continue; /* Check if we can move the loads. The def stmt of the virtual use ! needs to be in a different basic block dominating bb. When the ! def is an edge-inserted one we know it dominates us. */ vuse = gimple_vuse (use_stmt); def_stmt = SSA_NAME_DEF_STMT (vuse); if (!SSA_NAME_IS_DEFAULT_DEF (vuse) && (gimple_bb (def_stmt) == bb ! || (gimple_bb (def_stmt) ! && !dominated_by_p (CDI_DOMINATORS, ! bb, gimple_bb (def_stmt))))) goto next; /* Found a proper dereference with an aggregate copy. Just Index: gcc/testsuite/gcc.dg/torture/pr70740.c =================================================================== *** gcc/testsuite/gcc.dg/torture/pr70740.c (revision 0) --- gcc/testsuite/gcc.dg/torture/pr70740.c (working copy) *************** *** 0 **** --- 1,38 ---- + /* { dg-do compile } */ + + extern int foo (void); + extern void *memcpy (void *, const void *, __SIZE_TYPE__); + + struct + { + char a[6]; + } d; + struct + { + int a1[0]; + int a2[0]; + int a3[0]; + int a4[]; + } a, c; + int b; + + int * + bar () + { + if (b) + return a.a4; + return a.a2; + } + + void + baz () + { + int *e, *f; + if (foo ()) + e = c.a3; + else + e = c.a1; + memcpy (d.a, e, 6); + f = bar (); + memcpy (d.a, f, 1); + }