I was incorrect previously thinking PR 126301 only affected partial
vectors.

This duplicates Tamars fix for the other two control flow branches.

        PR tree-optimization/126301

gcc/ChangeLog:

        * tree-vect-loop-manip.cc (vect_use_loop_latch_condition_p):
        Remove restriction for avx512 and non-partial vectors.
        (vect_set_loop_condition_partial_vectors_avx512):
        Add logic for do loop transformation.
        (vect_set_loop_condition_normal): Likewise.

Co-Authored-By: Tamar Christina <[email protected]>
---
 gcc/tree-vect-loop-manip.cc | 92 +++++++++++++++++++++++++++++++------
 1 file changed, 77 insertions(+), 15 deletions(-)

diff --git a/gcc/tree-vect-loop-manip.cc b/gcc/tree-vect-loop-manip.cc
index 385353bda2b..f8e259c19bd 100644
--- a/gcc/tree-vect-loop-manip.cc
+++ b/gcc/tree-vect-loop-manip.cc
@@ -520,10 +520,7 @@ static bool
 vect_use_loop_latch_condition_p (loop_vec_info loop_vinfo)
 {
   return (loop_vinfo
-         && LOOP_VINFO_EARLY_BREAKS_VECT_PEELED (loop_vinfo)
-         && LOOP_VINFO_USING_PARTIAL_VECTORS_P (loop_vinfo)
-         && (LOOP_VINFO_PARTIAL_VECTORS_STYLE (loop_vinfo)
-             != vect_partial_vectors_avx512));
+         && LOOP_VINFO_EARLY_BREAKS_VECT_PEELED (loop_vinfo));
 }
 
 /* Helper for vect_set_loop_condition_partial_vectors.  Generate definitions
@@ -1347,7 +1344,36 @@ vect_set_loop_condition_partial_vectors_avx512 (class 
loop *loop,
      iv_type.  */
   gcond *cond_stmt = gimple_build_cond (code, index_before_incr, iv_step,
                                        NULL_TREE, NULL_TREE);
-  gsi_insert_before (&loop_cond_gsi, cond_stmt, GSI_SAME_STMT);
+  edge latch_exit_edge = NULL;
+  if (vect_use_loop_latch_condition_p (loop_vinfo))
+    {
+      basic_block latch = loop->latch;
+      edge latch_e = single_succ_edge (latch);
+      int exit_flags = exit_edge->flags & (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
+
+      latch_e->flags &= ~(EDGE_FALLTHRU | EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
+      latch_e->flags |= (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE) ^ exit_flags;
+      latch_exit_edge = make_edge (latch, exit_edge->dest, exit_flags);
+      latch_exit_edge->probability = exit_edge->probability;
+      latch_exit_edge->count () = exit_edge->count ();
+      copy_phi_arg_into_existing_phi (exit_edge, latch_exit_edge);
+      if (gphi *vphi = get_virtual_phi (latch_exit_edge->dest))
+       SET_PHI_ARG_DEF_ON_EDGE (vphi, latch_exit_edge,
+                                get_live_virtual_operand_on_edge
+                                  (latch_exit_edge));
+      gimple_stmt_iterator latch_gsi = gsi_last_bb (latch);
+      gsi_insert_after (&latch_gsi, cond_stmt, GSI_NEW_STMT);
+      LOOP_VINFO_MAIN_EXIT (loop_vinfo) = latch_exit_edge;
+
+      gcond *old_cond = as_a <gcond *> (gsi_stmt (loop_cond_gsi));
+      if (exit_edge->flags & EDGE_TRUE_VALUE)
+       gimple_cond_make_false (old_cond);
+      else
+       gimple_cond_make_true (old_cond);
+      update_stmt (old_cond);
+    }
+  else
+    gsi_insert_before (&loop_cond_gsi, cond_stmt, GSI_SAME_STMT);
 
   /* The loop iterates (NITERS - 1 + NITERS_SKIP) / VF + 1 times.
      Subtract one from this to get the latch count.  */
@@ -1485,16 +1511,43 @@ vect_set_loop_condition_normal (loop_vec_info 
loop_vinfo, edge exit_edge,
             &indx_before_incr, &indx_after_incr,
             !loop_vinfo || LOOP_VINFO_IV_INCREMENT_INVARIANT_P (loop_vinfo));
 
-  indx_after_incr = force_gimple_operand_gsi (&loop_cond_gsi, indx_after_incr,
-                                             true, NULL_TREE, true,
-                                             GSI_SAME_STMT);
-  limit = force_gimple_operand_gsi (&loop_cond_gsi, limit, true, NULL_TREE,
-                                    true, GSI_SAME_STMT);
-
   cond_stmt = gimple_build_cond (code, indx_after_incr, limit, NULL_TREE,
                                 NULL_TREE);
 
-  gsi_insert_before (&loop_cond_gsi, cond_stmt, GSI_SAME_STMT);
+  edge latch_exit_edge = NULL;
+  if (vect_use_loop_latch_condition_p (loop_vinfo))
+    {
+      basic_block latch = loop->latch;
+      edge latch_e = single_succ_edge (latch);
+      int exit_flags = exit_edge->flags & (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
+
+      latch_e->flags &= ~(EDGE_FALLTHRU | EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
+      latch_e->flags |= (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE) ^ exit_flags;
+      latch_exit_edge = make_edge (latch, exit_edge->dest, exit_flags);
+      latch_exit_edge->probability = exit_edge->probability;
+      latch_exit_edge->count () = exit_edge->count ();
+      copy_phi_arg_into_existing_phi (exit_edge, latch_exit_edge);
+      if (gphi *vphi = get_virtual_phi (latch_exit_edge->dest))
+       SET_PHI_ARG_DEF_ON_EDGE (vphi, latch_exit_edge,
+                                get_live_virtual_operand_on_edge
+                                  (latch_exit_edge));
+      gimple_stmt_iterator latch_gsi = gsi_last_bb (latch);
+      gsi_insert_after (&latch_gsi, cond_stmt, GSI_NEW_STMT);
+      LOOP_VINFO_MAIN_EXIT (loop_vinfo) = latch_exit_edge;
+
+      gcond *old_cond = as_a <gcond *> (gsi_stmt (loop_cond_gsi));
+      if (exit_edge->flags & EDGE_TRUE_VALUE)
+       gimple_cond_make_false (old_cond);
+      else
+       gimple_cond_make_true (old_cond);
+      update_stmt (old_cond);
+    }
+  else
+    {
+      limit = force_gimple_operand_gsi (&loop_cond_gsi, limit, true, NULL_TREE,
+                                       true, GSI_SAME_STMT);
+      gsi_insert_before (&loop_cond_gsi, cond_stmt, GSI_SAME_STMT);
+    }
 
   /* Record the number of latch iterations.  */
   if (limit == niters)
@@ -1511,7 +1564,6 @@ vect_set_loop_condition_normal (loop_vec_info loop_vinfo, 
edge exit_edge,
   if (final_iv)
     {
       gassign *assign;
-      gcc_assert (single_pred_p (exit_edge->dest));
       tree phi_dest
        = integer_zerop (init) ? final_iv : copy_ssa_name (indx_after_incr);
       /* Make sure to maintain LC SSA form here and elide the subtraction
@@ -1520,8 +1572,18 @@ vect_set_loop_condition_normal (loop_vec_info 
loop_vinfo, edge exit_edge,
       add_phi_arg (phi, indx_after_incr, exit_edge, UNKNOWN_LOCATION);
       if (!integer_zerop (init))
        {
-         assign = gimple_build_assign (final_iv, MINUS_EXPR,
-                                       phi_dest, init);
+         /* If vectorizing an inverted early break loop we have to restart the
+            scalar loop at niters - vf.  This matches what we do in
+            vect_gen_vector_loop_niters_mult_vf for non-masked loops.  */
+         if (LOOP_VINFO_EARLY_BREAKS_VECT_PEELED (loop_vinfo))
+           {
+             tree ftype = TREE_TYPE (final_iv);
+             tree vf
+               = build_int_cst (ftype, LOOP_VINFO_VECT_FACTOR (loop_vinfo));
+             assign = gimple_build_assign (final_iv, MINUS_EXPR, init, vf);
+           }
+         else
+           assign = gimple_build_assign (final_iv, MINUS_EXPR, phi_dest, init);
          gimple_stmt_iterator gsi = gsi_after_labels (exit_edge->dest);
          gsi_insert_before (&gsi, assign, GSI_SAME_STMT);
        }
-- 
2.55.0

Reply via email to