The following re-purposes STMT_SLP_TYPE for BB vectorization to indicate
the scalar (non-pattern) stmt coverage of the vectorized SLP graph.
This will allow for simpler and more precise determining of live lanes
and scalar costing.

        * tree-vect-slp.cc (vect_slp_analyze_bb_1): Split out pure_slp
        marking into ...
        (vect_bb_slp_mark_stmts_vectorized): ... new function.  Compute
        full scalar stmt coverage of the SLP graph.
        (vect_slp_gather_extern_scalar_stmts): New helper.
        (vect_bb_slp_mark_live_stmts): Adjust.
        * tree-vect-loop.cc (vectorizable_live_operation): Likewise.
---
 gcc/tree-vect-loop.cc |   2 +-
 gcc/tree-vect-slp.cc  | 122 +++++++++++++++++++++++++-----------------
 2 files changed, 75 insertions(+), 49 deletions(-)

diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc
index 670a03ea06b..5518be4d392 100644
--- a/gcc/tree-vect-loop.cc
+++ b/gcc/tree-vect-loop.cc
@@ -10418,7 +10418,7 @@ vectorizable_live_operation (vec_info *vinfo, 
stmt_vec_info stmt_info,
       FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, lhs)
        if (!is_gimple_debug (use_stmt)
            && (!(use_stmt_info = vinfo->lookup_stmt (use_stmt))
-               || !PURE_SLP_STMT (vect_stmt_to_vectorize (use_stmt_info))))
+               || !PURE_SLP_STMT (use_stmt_info)))
          {
            /* ???  This can happen when the live lane ends up being
               rooted in a vector construction code-generated by an
diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc
index 97d981d49b8..15086394d92 100644
--- a/gcc/tree-vect-slp.cc
+++ b/gcc/tree-vect-slp.cc
@@ -3480,51 +3480,86 @@ debug (slp_instance instance)
                        SLP_INSTANCE_TREE (instance));
 }
 
-/* Mark the tree rooted at NODE with PURE_SLP.  */
+
+/* Compute the set of scalar stmts participating in external nodes.  */
 
 static void
-vect_mark_slp_stmts (vec_info *vinfo, slp_tree node,
-                    hash_set<slp_tree> &visited)
+vect_slp_gather_extern_scalar_stmts (vec_info *vinfo, slp_tree node,
+                                    hash_set<slp_tree> &visited,
+                                    hash_set<stmt_vec_info> &estmts)
 {
-  int i;
-  stmt_vec_info stmt_info;
-  slp_tree child;
-
-  if (SLP_TREE_DEF_TYPE (node) != vect_internal_def)
-    return;
-
   if (visited.add (node))
     return;
 
-  FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt_info)
-    if (stmt_info)
+  if (SLP_TREE_DEF_TYPE (node) == vect_internal_def)
+    {
+      slp_tree child;
+      int i;
+      FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
+       if (child)
+         vect_slp_gather_extern_scalar_stmts (vinfo, child, visited, estmts);
+    }
+  else
+    for (tree def : SLP_TREE_SCALAR_OPS (node))
       {
-       STMT_SLP_TYPE (stmt_info) = pure_slp;
-       /* ???  For .MASK_LOAD and .MASK_STORE detected as load/store-lanes
-          when there is the mask_conversion pattern applied we have lost the
-          alternate lanes of the uniform mask which nevertheless
-          have separate pattern defs.  To not confuse hybrid
-          analysis we mark those as covered as well here.  */
-       if (node->ldst_lanes)
-         if (gcall *call = dyn_cast <gcall *> (stmt_info->stmt))
-           if (gimple_call_internal_p (call, IFN_MASK_LOAD)
-               || gimple_call_internal_p (call, IFN_MASK_STORE))
-             {
-               tree mask = gimple_call_arg (call,
-                                            internal_fn_mask_index
-                                            (gimple_call_internal_fn (call)));
-               if (TREE_CODE (mask) == SSA_NAME)
-                 if (stmt_vec_info mask_info = vinfo->lookup_def (mask))
-                   {
-                     mask_info = vect_stmt_to_vectorize (mask_info);
-                     STMT_SLP_TYPE (mask_info) = pure_slp;
-                   }
-             }
+       stmt_vec_info def_stmt = vinfo->lookup_def (def);
+       if (def_stmt)
+         estmts.add (def_stmt);
       }
+}
 
-  FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
-    if (child)
-      vect_mark_slp_stmts (vinfo, child, visited);
+/* Mark the original scalar stmt coverage of the vector SLP graph of VINFO
+   with STMT_SLP_TYPE == pure_slp.  */
+
+static void
+vect_bb_slp_mark_stmts_vectorized (bb_vec_info vinfo)
+{
+  /* Gather the scalar stmt leafs of the SLP graph to stop the below DFS
+     walk on.  */
+  hash_set<stmt_vec_info> scalar_stmts_in_externs;
+  hash_set<slp_tree> visited;
+  for (auto instance : BB_VINFO_SLP_INSTANCES (vinfo))
+    vect_slp_gather_extern_scalar_stmts (vinfo, SLP_INSTANCE_TREE (instance),
+                                        visited, scalar_stmts_in_externs);
+
+  /* DFS walk scalar stmts to compute the vectorized coverage indicated
+     by STMT_SLP_TYPE (stmt) == pure_slp on the original scalar (non-pattern)
+     stmts.  */
+  for (auto instance : BB_VINFO_SLP_INSTANCES (vinfo))
+    {
+      for (auto stmt : SLP_INSTANCE_ROOT_STMTS (instance))
+       STMT_SLP_TYPE (stmt) = pure_slp;
+      auto_vec<stmt_vec_info> worklist;
+      for (auto stmt : SLP_TREE_SCALAR_STMTS (SLP_INSTANCE_TREE (instance)))
+       {
+         stmt = vect_orig_stmt (stmt);
+         if (!scalar_stmts_in_externs.contains (stmt)
+             && STMT_SLP_TYPE (stmt) != pure_slp)
+           {
+             STMT_SLP_TYPE (stmt) = pure_slp;
+             worklist.safe_push (stmt);
+           }
+       }
+      while (!worklist.is_empty ())
+       {
+         stmt_vec_info stmt = worklist.pop ();
+
+         /* Now walk relevant parts of the SSA use-def graph.  */
+         slp_oprnds child_ops (stmt);
+         for (unsigned i = 0; i < child_ops.num_slp_children; ++i)
+           {
+             tree op = child_ops.get_op_for_slp_child (stmt, i);
+             stmt_vec_info def = vinfo->lookup_def (op);
+             if (def
+                 && !scalar_stmts_in_externs.contains (def)
+                 && STMT_SLP_TYPE (def) != pure_slp)
+               {
+                 STMT_SLP_TYPE (def) = pure_slp;
+                 worklist.safe_push (def);
+               }
+           }
+       }
+    }
 }
 
 /* Mark the statements of the tree rooted at NODE as relevant (vect_used).  */
@@ -9085,7 +9120,7 @@ vect_bb_slp_mark_live_stmts (bb_vec_info bb_vinfo, 
slp_tree node,
            FOR_EACH_IMM_USE_STMT (use_stmt, use_iter, DEF_FROM_PTR (def_p))
              if (!is_gimple_debug (use_stmt)
                  && (!(use_stmt_info = bb_vinfo->lookup_stmt (use_stmt))
-                     || !PURE_SLP_STMT (vect_stmt_to_vectorize 
(use_stmt_info)))
+                     || !PURE_SLP_STMT (use_stmt_info))
                  && !vect_stmt_dominates_stmt_p (last_stmt->stmt, use_stmt))
                {
                  if (dump_enabled_p ())
@@ -10305,17 +10340,8 @@ vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int 
n_stmts, bool &fatal,
       return false;
     }
 
-  /* Mark all the statements that we want to vectorize as pure SLP.  */
-  hash_set<slp_tree> visited;
-  for (auto instance : BB_VINFO_SLP_INSTANCES (bb_vinfo))
-    {
-      vect_mark_slp_stmts (bb_vinfo, SLP_INSTANCE_TREE (instance), visited);
-      unsigned j;
-      stmt_vec_info root;
-      /* Likewise consider instance root stmts as vectorized.  */
-      FOR_EACH_VEC_ELT (SLP_INSTANCE_ROOT_STMTS (instance), j, root)
-       STMT_SLP_TYPE (root) = pure_slp;
-    }
+  /* Mark all the statements that we vectorize.  */
+  vect_bb_slp_mark_stmts_vectorized (bb_vinfo);
 
   /* Compute vectorizable live stmts.  */
   vect_bb_slp_mark_live_stmts (bb_vinfo);
-- 
2.51.0

Reply via email to