This makes hybrid SLP discovery deal with stmts indirectly consumed
by SLP, for example via patterns.  This means that all uses of a
stmt end up in SLP vectorized stmts.

This helps my prototype patches for PR97832 where I make SLP discovery
re-associate chains to make operands match.  This ends up building
SLP computation nodes without 1:1 representatives in the scalar IL
and thus no scalar lane defs in SLP_TREE_SCALAR_STMTS.  Nevertheless
all of the original scalar stmts are consumed so this represents
another kind of SLP pattern for the computation chain result.

Bootstrapped and tested on x86_64-unknown-linux-gnu.

Tamar - can you check if this helps you avoiding all the
relevancy push/pop stuff as well as avoiding any pattern
marking for SLP patterns at all?

2020-11-20  Richard Biener  <rguent...@suse.de>

        * tree-vect-slp.c (maybe_push_to_hybrid_worklist): New function.
        (vect_detect_hybrid_slp): Use it.  Perform a backward walk
        over the IL.
---
 gcc/tree-vect-slp.c | 79 +++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 72 insertions(+), 7 deletions(-)

diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index 486ee95d5d2..f87ac3c049f 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -3439,6 +3439,63 @@ vect_detect_hybrid_slp (tree *tp, int *, void *data)
   return NULL_TREE;
 }
 
+/* Look if STMT_INFO is consumed by SLP indirectly and mark it pure_slp
+   if so, otherwise pushing it to WORKLIST.  */
+
+static void
+maybe_push_to_hybrid_worklist (vec_info *vinfo,
+                              vec<stmt_vec_info> &worklist,
+                              stmt_vec_info stmt_info)
+{
+  if (dump_enabled_p ())
+    dump_printf_loc (MSG_NOTE, vect_location,
+                    "Processing hybrid candidate : %G", stmt_info->stmt);
+  stmt_vec_info orig_info = vect_orig_stmt (stmt_info);
+  imm_use_iterator iter2;
+  ssa_op_iter iter1;
+  use_operand_p use_p;
+  def_operand_p def_p;
+  bool any_def = false;
+  FOR_EACH_PHI_OR_STMT_DEF (def_p, orig_info->stmt, iter1, SSA_OP_DEF)
+    {
+      any_def = true;
+      FOR_EACH_IMM_USE_FAST (use_p, iter2, DEF_FROM_PTR (def_p))
+       {
+         stmt_vec_info use_info = vinfo->lookup_stmt (USE_STMT (use_p));
+         /* An out-of loop use means this is a loop_vect sink.  */
+         if (!use_info)
+           {
+             if (dump_enabled_p ())
+               dump_printf_loc (MSG_NOTE, vect_location,
+                                "Found loop_vect sink: %G", stmt_info->stmt);
+             worklist.safe_push (stmt_info);
+             return;
+           }
+         else if (!STMT_SLP_TYPE (vect_stmt_to_vectorize (use_info)))
+           {
+             if (dump_enabled_p ())
+               dump_printf_loc (MSG_NOTE, vect_location,
+                                "Found loop_vect use: %G", use_info->stmt);
+             worklist.safe_push (stmt_info);
+             return;
+           }
+       }
+    }
+  /* No def means this is a loo_vect sink.  */
+  if (!any_def)
+    {
+      if (dump_enabled_p ())
+       dump_printf_loc (MSG_NOTE, vect_location,
+                        "Found loop_vect sink: %G", stmt_info->stmt);
+      worklist.safe_push (stmt_info);
+      return;
+    }
+  if (dump_enabled_p ())
+    dump_printf_loc (MSG_NOTE, vect_location,
+                    "Marked SLP consumed stmt pure: %G", stmt_info->stmt);
+  STMT_SLP_TYPE (stmt_info) = pure_slp;
+}
+
 /* Find stmts that must be both vectorized and SLPed.  */
 
 void
@@ -3448,9 +3505,14 @@ vect_detect_hybrid_slp (loop_vec_info loop_vinfo)
 
   /* All stmts participating in SLP are marked pure_slp, all other
      stmts are loop_vect.
-     First collect all loop_vect stmts into a worklist.  */
+     First collect all loop_vect stmts into a worklist.
+     SLP patterns cause not all original scalar stmts to appear in
+     SLP_TREE_SCALAR_STMTS and thus not all of them are marked pure_slp.
+     Rectify this here and do a backward walk over the IL only considering
+     stmts as loop_vect when they are used by a loop_vect stmt and otherwise
+     mark them as pure_slp.  */
   auto_vec<stmt_vec_info> worklist;
-  for (unsigned i = 0; i < LOOP_VINFO_LOOP (loop_vinfo)->num_nodes; ++i)
+  for (int i = LOOP_VINFO_LOOP (loop_vinfo)->num_nodes - 1; i >= 0; --i)
     {
       basic_block bb = LOOP_VINFO_BBS (loop_vinfo)[i];
       for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
@@ -3459,10 +3521,11 @@ vect_detect_hybrid_slp (loop_vec_info loop_vinfo)
          gphi *phi = gsi.phi ();
          stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (phi);
          if (!STMT_SLP_TYPE (stmt_info) && STMT_VINFO_RELEVANT (stmt_info))
-           worklist.safe_push (stmt_info);
+           maybe_push_to_hybrid_worklist (loop_vinfo,
+                                          worklist, stmt_info);
        }
-      for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
-          gsi_next (&gsi))
+      for (gimple_stmt_iterator gsi = gsi_last_bb (bb); !gsi_end_p (gsi);
+          gsi_prev (&gsi))
        {
          gimple *stmt = gsi_stmt (gsi);
          if (is_gimple_debug (stmt))
@@ -3478,12 +3541,14 @@ vect_detect_hybrid_slp (loop_vec_info loop_vinfo)
                    = loop_vinfo->lookup_stmt (gsi_stmt (gsi2));
                  if (!STMT_SLP_TYPE (patt_info)
                      && STMT_VINFO_RELEVANT (patt_info))
-                   worklist.safe_push (patt_info);
+                   maybe_push_to_hybrid_worklist (loop_vinfo,
+                                                  worklist, patt_info);
                }
              stmt_info = STMT_VINFO_RELATED_STMT (stmt_info);
            }
          if (!STMT_SLP_TYPE (stmt_info) && STMT_VINFO_RELEVANT (stmt_info))
-           worklist.safe_push (stmt_info);
+           maybe_push_to_hybrid_worklist (loop_vinfo,
+                                          worklist, stmt_info);
        }
     }
 
-- 
2.26.2

Reply via email to