When LIM ends up using predicated store motion it can wreck the IL too much for PHI hoisting to still apply when it should. The following avoids messing with existing PHIs (apart from virtuals) by splitting the edge in the problematical case to have a joiner before the existing PHI.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied. Richard. 2015-09-15 Richard Biener <rguent...@suse.de> PR tree-optimization/67470 * tree-ssa-loop-im.c (execute_sm_if_changed): Preserve PHI structure for PHI hoisting by inserting a forwarder block if appropriate. * gcc.dg/torture/pr67470.c: New testcase. Index: gcc/tree-ssa-loop-im.c =================================================================== *** gcc/tree-ssa-loop-im.c (revision 227779) --- gcc/tree-ssa-loop-im.c (working copy) *************** execute_sm_if_changed (edge ex, tree mem *** 1839,1844 **** --- 1900,1922 ---- if (loop_has_only_one_exit) ex = split_block_after_labels (ex->dest); + else + { + for (gphi_iterator gpi = gsi_start_phis (ex->dest); + !gsi_end_p (gpi); gsi_next (&gpi)) + { + gphi *phi = gpi.phi (); + if (virtual_operand_p (gimple_phi_result (phi))) + continue; + + /* When the destination has a non-virtual PHI node with multiple + predecessors make sure we preserve the PHI structure by + forcing a forwarder block so that hoisting of that PHI will + still work. */ + split_edge (ex); + break; + } + } old_dest = ex->dest; new_bb = split_edge (ex); Index: gcc/testsuite/gcc.dg/torture/pr67470.c =================================================================== *** gcc/testsuite/gcc.dg/torture/pr67470.c (revision 0) --- gcc/testsuite/gcc.dg/torture/pr67470.c (working copy) *************** *** 0 **** --- 1,30 ---- + /* { dg-do run } */ + + int a, b, *c, d, e; + + void abort (void); + + int + main () + { + int f, *g, **h = &g; + for (; b;) + { + c = &a; + for (e = 0; e < 1; e++) + *h = 0; + for (; d; d++) + if (f) + *c = 0; + else + { + *c = e = 0; + *h = &a; + } + + if (a && !g) + abort (); + + } + return 0; + }