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

Reply via email to