The following handles the situation where we lack a loop-closed PHI for a virtual operand because a loop exit goes to a code region not having any virtual use (an endless loop). It also handles the situation of edge redirection re-allocating a PHI node in the destination block so we have to re-lookup that before populating the new PHI argument.
Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed. PR tree-optimization/113494 * tree-vect-loop-manip.cc (slpeel_tree_duplicate_loop_to_edge_cfg): Handle endless loop on exit. Handle re-allocated PHI. --- gcc/tree-vect-loop-manip.cc | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/gcc/tree-vect-loop-manip.cc b/gcc/tree-vect-loop-manip.cc index 983ed2e9b1f..1477906e96e 100644 --- a/gcc/tree-vect-loop-manip.cc +++ b/gcc/tree-vect-loop-manip.cc @@ -1629,11 +1629,17 @@ slpeel_tree_duplicate_loop_to_edge_cfg (class loop *loop, edge loop_exit, alt_loop_exit_block = split_edge (exit); if (!need_virtual_phi) continue; - if (vphi_def && !vphi) - vphi = create_phi_node (copy_ssa_name (vphi_def), - alt_loop_exit_block); if (vphi_def) - add_phi_arg (vphi, vphi_def, exit, UNKNOWN_LOCATION); + { + if (!vphi) + vphi = create_phi_node (copy_ssa_name (vphi_def), + alt_loop_exit_block); + else + /* Edge redirection might re-allocate the PHI node + so we have to rediscover it. */ + vphi = get_virtual_phi (alt_loop_exit_block); + add_phi_arg (vphi, vphi_def, exit, UNKNOWN_LOCATION); + } } set_immediate_dominator (CDI_DOMINATORS, new_preheader, @@ -1748,7 +1754,17 @@ slpeel_tree_duplicate_loop_to_edge_cfg (class loop *loop, edge loop_exit, if (virtual_operand_p (alt_arg)) { gphi *vphi = get_virtual_phi (alt_loop_exit_block); - alt_arg = gimple_phi_result (vphi); + /* ??? When the exit yields to a path without + any virtual use we can miss a LC PHI for the + live virtual operand. Simply choosing the + one live at the start of the loop header isn't + correct, but we should get here only with + early-exit vectorization which will move all + defs after the main exit, so leave a temporarily + wrong virtual operand in place. This happens + for gcc.c-torture/execute/20150611-1.c */ + if (vphi) + alt_arg = gimple_phi_result (vphi); } edge main_e = single_succ_edge (alt_loop_exit_block); SET_PHI_ARG_DEF_ON_EDGE (to_phi, main_e, alt_arg); -- 2.35.3