Hi,

Similar to the existing function vect_build_gather_load_calls,
this patch is to factor out the handling on scatter store
having gs_info.decl to vect_build_scatter_store_calls which
is a new function.  It also does some minor refactoring like
moving some variables' declarations close to their uses and
restrict the scope for some of them etc.

It's a pre-patch for upcoming vectorizable_store re-structuring
for costing.

Bootstrapped and regtested on x86_64-redhat-linux,
aarch64-linux-gnu and powerpc64{,le}-linux-gnu.

Is it ok for trunk?

BR,
Kewen
-----

gcc/ChangeLog:

        * tree-vect-stmts.cc (vect_build_scatter_store_calls): New, factor
        out from ...
        (vectorizable_store): ... here.
---
 gcc/tree-vect-stmts.cc | 411 +++++++++++++++++++++--------------------
 1 file changed, 212 insertions(+), 199 deletions(-)

diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc
index cd8e0a76374..f8a904de503 100644
--- a/gcc/tree-vect-stmts.cc
+++ b/gcc/tree-vect-stmts.cc
@@ -2989,6 +2989,216 @@ vect_build_gather_load_calls (vec_info *vinfo, 
stmt_vec_info stmt_info,
   *vec_stmt = STMT_VINFO_VEC_STMTS (stmt_info)[0];
 }

+/* Build a scatter store call while vectorizing STMT_INFO.  Insert new
+   instructions before GSI and add them to VEC_STMT.  GS_INFO describes
+   the scatter store operation.  If the store is conditional, MASK is the
+   unvectorized condition, otherwise MASK is null.  */
+
+static void
+vect_build_scatter_store_calls (vec_info *vinfo, stmt_vec_info stmt_info,
+                               gimple_stmt_iterator *gsi, gimple **vec_stmt,
+                               gather_scatter_info *gs_info, tree mask)
+{
+  loop_vec_info loop_vinfo = dyn_cast<loop_vec_info> (vinfo);
+  tree vectype = STMT_VINFO_VECTYPE (stmt_info);
+  poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
+  int ncopies = vect_get_num_copies (loop_vinfo, vectype);
+  enum { NARROW, NONE, WIDEN } modifier;
+  poly_uint64 scatter_off_nunits
+    = TYPE_VECTOR_SUBPARTS (gs_info->offset_vectype);
+
+  tree perm_mask = NULL_TREE, mask_halfvectype = NULL_TREE;
+  if (known_eq (nunits, scatter_off_nunits))
+    modifier = NONE;
+  else if (known_eq (nunits * 2, scatter_off_nunits))
+    {
+      modifier = WIDEN;
+
+      /* Currently gathers and scatters are only supported for
+        fixed-length vectors.  */
+      unsigned int count = scatter_off_nunits.to_constant ();
+      vec_perm_builder sel (count, count, 1);
+      for (unsigned i = 0; i < (unsigned int) count; ++i)
+       sel.quick_push (i | (count / 2));
+
+      vec_perm_indices indices (sel, 1, count);
+      perm_mask = vect_gen_perm_mask_checked (gs_info->offset_vectype, 
indices);
+      gcc_assert (perm_mask != NULL_TREE);
+    }
+  else if (known_eq (nunits, scatter_off_nunits * 2))
+    {
+      modifier = NARROW;
+
+      /* Currently gathers and scatters are only supported for
+        fixed-length vectors.  */
+      unsigned int count = nunits.to_constant ();
+      vec_perm_builder sel (count, count, 1);
+      for (unsigned i = 0; i < (unsigned int) count; ++i)
+       sel.quick_push (i | (count / 2));
+
+      vec_perm_indices indices (sel, 2, count);
+      perm_mask = vect_gen_perm_mask_checked (vectype, indices);
+      gcc_assert (perm_mask != NULL_TREE);
+      ncopies *= 2;
+
+      if (mask)
+       mask_halfvectype = truth_type_for (gs_info->offset_vectype);
+    }
+  else
+    gcc_unreachable ();
+
+  tree rettype = TREE_TYPE (TREE_TYPE (gs_info->decl));
+  tree arglist = TYPE_ARG_TYPES (TREE_TYPE (gs_info->decl));
+  tree ptrtype = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist);
+  tree masktype = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist);
+  tree idxtype = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist);
+  tree srctype = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist);
+  tree scaletype = TREE_VALUE (arglist);
+
+  gcc_checking_assert (TREE_CODE (masktype) == INTEGER_TYPE
+                      && TREE_CODE (rettype) == VOID_TYPE);
+
+  tree ptr = fold_convert (ptrtype, gs_info->base);
+  if (!is_gimple_min_invariant (ptr))
+    {
+      gimple_seq seq;
+      ptr = force_gimple_operand (ptr, &seq, true, NULL_TREE);
+      class loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
+      edge pe = loop_preheader_edge (loop);
+      basic_block new_bb = gsi_insert_seq_on_edge_immediate (pe, seq);
+      gcc_assert (!new_bb);
+    }
+
+  tree mask_arg = NULL_TREE;
+  if (mask == NULL_TREE)
+    {
+      mask_arg = build_int_cst (masktype, -1);
+      mask_arg = vect_init_vector (vinfo, stmt_info, mask_arg, masktype, NULL);
+    }
+
+  tree scale = build_int_cst (scaletype, gs_info->scale);
+
+  auto_vec<tree> vec_oprnds0;
+  auto_vec<tree> vec_oprnds1;
+  auto_vec<tree> vec_masks;
+  if (mask)
+    {
+      tree mask_vectype = truth_type_for (vectype);
+      vect_get_vec_defs_for_operand (vinfo, stmt_info,
+                                    modifier == NARROW ? ncopies / 2 : ncopies,
+                                    mask, &vec_masks, mask_vectype);
+    }
+  vect_get_vec_defs_for_operand (vinfo, stmt_info,
+                                modifier == WIDEN ? ncopies / 2 : ncopies,
+                                gs_info->offset, &vec_oprnds0);
+  tree op = vect_get_store_rhs (stmt_info);
+  vect_get_vec_defs_for_operand (vinfo, stmt_info,
+                                modifier == NARROW ? ncopies / 2 : ncopies, op,
+                                &vec_oprnds1);
+
+  tree vec_oprnd0 = NULL_TREE, vec_oprnd1 = NULL_TREE;
+  tree mask_op = NULL_TREE;
+  tree src, vec_mask;
+  for (int j = 0; j < ncopies; ++j)
+    {
+      if (modifier == WIDEN)
+       {
+         if (j & 1)
+           op = permute_vec_elements (vinfo, vec_oprnd0, vec_oprnd0, perm_mask,
+                                      stmt_info, gsi);
+         else
+           op = vec_oprnd0 = vec_oprnds0[j / 2];
+         src = vec_oprnd1 = vec_oprnds1[j];
+         if (mask)
+           mask_op = vec_mask = vec_masks[j];
+       }
+      else if (modifier == NARROW)
+       {
+         if (j & 1)
+           src = permute_vec_elements (vinfo, vec_oprnd1, vec_oprnd1,
+                                       perm_mask, stmt_info, gsi);
+         else
+           src = vec_oprnd1 = vec_oprnds1[j / 2];
+         op = vec_oprnd0 = vec_oprnds0[j];
+         if (mask)
+           mask_op = vec_mask = vec_masks[j / 2];
+       }
+      else
+       {
+         op = vec_oprnd0 = vec_oprnds0[j];
+         src = vec_oprnd1 = vec_oprnds1[j];
+         if (mask)
+           mask_op = vec_mask = vec_masks[j];
+       }
+
+      if (!useless_type_conversion_p (srctype, TREE_TYPE (src)))
+       {
+         gcc_assert (known_eq (TYPE_VECTOR_SUBPARTS (TREE_TYPE (src)),
+                               TYPE_VECTOR_SUBPARTS (srctype)));
+         tree var = vect_get_new_ssa_name (srctype, vect_simple_var);
+         src = build1 (VIEW_CONVERT_EXPR, srctype, src);
+         gassign *new_stmt = gimple_build_assign (var, VIEW_CONVERT_EXPR, src);
+         vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
+         src = var;
+       }
+
+      if (!useless_type_conversion_p (idxtype, TREE_TYPE (op)))
+       {
+         gcc_assert (known_eq (TYPE_VECTOR_SUBPARTS (TREE_TYPE (op)),
+                               TYPE_VECTOR_SUBPARTS (idxtype)));
+         tree var = vect_get_new_ssa_name (idxtype, vect_simple_var);
+         op = build1 (VIEW_CONVERT_EXPR, idxtype, op);
+         gassign *new_stmt = gimple_build_assign (var, VIEW_CONVERT_EXPR, op);
+         vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
+         op = var;
+       }
+
+      if (mask)
+       {
+         tree utype;
+         mask_arg = mask_op;
+         if (modifier == NARROW)
+           {
+             tree var
+               = vect_get_new_ssa_name (mask_halfvectype, vect_simple_var);
+             gassign *new_stmt
+               = gimple_build_assign (var,
+                                      (j & 1) ? VEC_UNPACK_HI_EXPR
+                                              : VEC_UNPACK_LO_EXPR,
+                                      mask_op);
+             vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
+             mask_arg = var;
+           }
+         tree optype = TREE_TYPE (mask_arg);
+         if (TYPE_MODE (masktype) == TYPE_MODE (optype))
+           utype = masktype;
+         else
+           utype = lang_hooks.types.type_for_mode (TYPE_MODE (optype), 1);
+         tree var = vect_get_new_ssa_name (utype, vect_scalar_var);
+         mask_arg = build1 (VIEW_CONVERT_EXPR, utype, mask_arg);
+         gassign *new_stmt
+           = gimple_build_assign (var, VIEW_CONVERT_EXPR, mask_arg);
+         vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
+         mask_arg = var;
+         if (!useless_type_conversion_p (masktype, utype))
+           {
+             gcc_assert (TYPE_PRECISION (utype) <= TYPE_PRECISION (masktype));
+             tree var = vect_get_new_ssa_name (masktype, vect_scalar_var);
+             new_stmt = gimple_build_assign (var, NOP_EXPR, mask_arg);
+             vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
+             mask_arg = var;
+           }
+       }
+
+      gcall *new_stmt
+       = gimple_build_call (gs_info->decl, 5, ptr, mask_arg, op, src, scale);
+      vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
+
+      STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt);
+    }
+  *vec_stmt = STMT_VINFO_VEC_STMTS (stmt_info)[0];
+}
+
 /* Prepare the base and offset in GS_INFO for vectorization.
    Set *DATAREF_PTR to the loop-invariant base address and *VEC_OFFSET
    to the vectorized offset argument for the first copy of STMT_INFO.
@@ -8212,205 +8422,8 @@ vectorizable_store (vec_info *vinfo,

   if (memory_access_type == VMAT_GATHER_SCATTER && gs_info.decl)
     {
-      tree vec_oprnd0 = NULL_TREE, vec_oprnd1 = NULL_TREE, src;
-      tree arglist = TYPE_ARG_TYPES (TREE_TYPE (gs_info.decl));
-      tree rettype, srctype, ptrtype, idxtype, masktype, scaletype;
-      tree ptr, var, scale, vec_mask;
-      tree mask_arg = NULL_TREE, mask_op = NULL_TREE, perm_mask = NULL_TREE;
-      tree mask_halfvectype = mask_vectype;
-      edge pe = loop_preheader_edge (loop);
-      gimple_seq seq;
-      basic_block new_bb;
-      enum { NARROW, NONE, WIDEN } modifier;
-      poly_uint64 scatter_off_nunits
-       = TYPE_VECTOR_SUBPARTS (gs_info.offset_vectype);
-
-      if (known_eq (nunits, scatter_off_nunits))
-       modifier = NONE;
-      else if (known_eq (nunits * 2, scatter_off_nunits))
-       {
-         modifier = WIDEN;
-
-         /* Currently gathers and scatters are only supported for
-            fixed-length vectors.  */
-         unsigned int count = scatter_off_nunits.to_constant ();
-         vec_perm_builder sel (count, count, 1);
-         for (i = 0; i < (unsigned int) count; ++i)
-           sel.quick_push (i | (count / 2));
-
-         vec_perm_indices indices (sel, 1, count);
-         perm_mask = vect_gen_perm_mask_checked (gs_info.offset_vectype,
-                                                 indices);
-         gcc_assert (perm_mask != NULL_TREE);
-       }
-      else if (known_eq (nunits, scatter_off_nunits * 2))
-       {
-         modifier = NARROW;
-
-         /* Currently gathers and scatters are only supported for
-            fixed-length vectors.  */
-         unsigned int count = nunits.to_constant ();
-         vec_perm_builder sel (count, count, 1);
-         for (i = 0; i < (unsigned int) count; ++i)
-           sel.quick_push (i | (count / 2));
-
-         vec_perm_indices indices (sel, 2, count);
-         perm_mask = vect_gen_perm_mask_checked (vectype, indices);
-         gcc_assert (perm_mask != NULL_TREE);
-         ncopies *= 2;
-
-         if (mask)
-           mask_halfvectype = truth_type_for (gs_info.offset_vectype);
-       }
-      else
-       gcc_unreachable ();
-
-      rettype = TREE_TYPE (TREE_TYPE (gs_info.decl));
-      ptrtype = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist);
-      masktype = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist);
-      idxtype = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist);
-      srctype = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist);
-      scaletype = TREE_VALUE (arglist);
-
-      gcc_checking_assert (TREE_CODE (masktype) == INTEGER_TYPE
-                          && TREE_CODE (rettype) == VOID_TYPE);
-
-      ptr = fold_convert (ptrtype, gs_info.base);
-      if (!is_gimple_min_invariant (ptr))
-       {
-         ptr = force_gimple_operand (ptr, &seq, true, NULL_TREE);
-         new_bb = gsi_insert_seq_on_edge_immediate (pe, seq);
-         gcc_assert (!new_bb);
-       }
-
-      if (mask == NULL_TREE)
-       {
-         mask_arg = build_int_cst (masktype, -1);
-         mask_arg = vect_init_vector (vinfo, stmt_info,
-                                      mask_arg, masktype, NULL);
-       }
-
-      scale = build_int_cst (scaletype, gs_info.scale);
-
-      auto_vec<tree> vec_oprnds0;
-      auto_vec<tree> vec_oprnds1;
-      auto_vec<tree> vec_masks;
-      if (mask)
-       {
-         tree mask_vectype = truth_type_for (vectype);
-         vect_get_vec_defs_for_operand (vinfo, stmt_info,
-                                        modifier == NARROW
-                                        ? ncopies / 2 : ncopies,
-                                        mask, &vec_masks, mask_vectype);
-       }
-      vect_get_vec_defs_for_operand (vinfo, stmt_info,
-                                    modifier == WIDEN
-                                    ? ncopies / 2 : ncopies,
-                                    gs_info.offset, &vec_oprnds0);
-      vect_get_vec_defs_for_operand (vinfo, stmt_info,
-                                    modifier == NARROW
-                                    ? ncopies / 2 : ncopies,
-                                    op, &vec_oprnds1);
-      for (j = 0; j < ncopies; ++j)
-       {
-         if (modifier == WIDEN)
-           {
-             if (j & 1)
-               op = permute_vec_elements (vinfo, vec_oprnd0, vec_oprnd0,
-                                          perm_mask, stmt_info, gsi);
-             else
-               op = vec_oprnd0 = vec_oprnds0[j / 2];
-             src = vec_oprnd1 = vec_oprnds1[j];
-             if (mask)
-               mask_op = vec_mask = vec_masks[j];
-           }
-         else if (modifier == NARROW)
-           {
-             if (j & 1)
-               src = permute_vec_elements (vinfo, vec_oprnd1, vec_oprnd1,
-                                           perm_mask, stmt_info, gsi);
-             else
-               src = vec_oprnd1 = vec_oprnds1[j / 2];
-             op = vec_oprnd0 = vec_oprnds0[j];
-             if (mask)
-               mask_op = vec_mask = vec_masks[j / 2];
-           }
-         else
-           {
-             op = vec_oprnd0 = vec_oprnds0[j];
-             src = vec_oprnd1 = vec_oprnds1[j];
-             if (mask)
-               mask_op = vec_mask = vec_masks[j];
-           }
-
-         if (!useless_type_conversion_p (srctype, TREE_TYPE (src)))
-           {
-             gcc_assert (known_eq (TYPE_VECTOR_SUBPARTS (TREE_TYPE (src)),
-                                   TYPE_VECTOR_SUBPARTS (srctype)));
-             var = vect_get_new_ssa_name (srctype, vect_simple_var);
-             src = build1 (VIEW_CONVERT_EXPR, srctype, src);
-             gassign *new_stmt
-               = gimple_build_assign (var, VIEW_CONVERT_EXPR, src);
-             vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
-             src = var;
-           }
-
-         if (!useless_type_conversion_p (idxtype, TREE_TYPE (op)))
-           {
-             gcc_assert (known_eq (TYPE_VECTOR_SUBPARTS (TREE_TYPE (op)),
-                                   TYPE_VECTOR_SUBPARTS (idxtype)));
-             var = vect_get_new_ssa_name (idxtype, vect_simple_var);
-             op = build1 (VIEW_CONVERT_EXPR, idxtype, op);
-             gassign *new_stmt
-               = gimple_build_assign (var, VIEW_CONVERT_EXPR, op);
-             vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
-             op = var;
-           }
-
-         if (mask)
-           {
-             tree utype;
-             mask_arg = mask_op;
-             if (modifier == NARROW)
-               {
-                 var = vect_get_new_ssa_name (mask_halfvectype,
-                                              vect_simple_var);
-                 gassign *new_stmt
-                   = gimple_build_assign (var, (j & 1) ? VEC_UNPACK_HI_EXPR
-                                                       : VEC_UNPACK_LO_EXPR,
-                                          mask_op);
-                 vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
-                 mask_arg = var;
-               }
-             tree optype = TREE_TYPE (mask_arg);
-             if (TYPE_MODE (masktype) == TYPE_MODE (optype))
-               utype = masktype;
-             else
-               utype = lang_hooks.types.type_for_mode (TYPE_MODE (optype), 1);
-             var = vect_get_new_ssa_name (utype, vect_scalar_var);
-             mask_arg = build1 (VIEW_CONVERT_EXPR, utype, mask_arg);
-             gassign *new_stmt
-               = gimple_build_assign (var, VIEW_CONVERT_EXPR, mask_arg);
-             vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
-             mask_arg = var;
-             if (!useless_type_conversion_p (masktype, utype))
-               {
-                 gcc_assert (TYPE_PRECISION (utype)
-                             <= TYPE_PRECISION (masktype));
-                 var = vect_get_new_ssa_name (masktype, vect_scalar_var);
-                 new_stmt = gimple_build_assign (var, NOP_EXPR, mask_arg);
-                 vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
-                 mask_arg = var;
-               }
-           }
-
-         gcall *new_stmt
-           = gimple_build_call (gs_info.decl, 5, ptr, mask_arg, op, src, 
scale);
-          vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
-
-         STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt);
-       }
-      *vec_stmt = STMT_VINFO_VEC_STMTS (stmt_info)[0];
+      vect_build_scatter_store_calls (vinfo, stmt_info, gsi, vec_stmt,
+                                     &gs_info, mask);
       return true;
     }
   else if (STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) >= 3)
--
2.31.1

Reply via email to