The following is a prototype-quality patch to make us record the
get_load_store_info results from load/store analysis and re-use
them during transform.  Rather than mass-replacing references to
variables I've kept the locals but made them read-only, only
adjusting a few elsval setters and adding a FIXME to strided SLP
handling of alignment (allowing local override there).

In particular for gs_info the recorded data is likely excessive,
most data isn't actually necessary later.  I'll fix this up
for the final patch.  Also in particular for gs_info this should
allow us to scrap the DR updating from update_epilogue_loop_vinfo
(to some extent).

The FIXME shows that while a lot of analysis is done in
get_load_store_type that's far from all of it.

The patch does provide a recipie how to handle storing of local
analysis results, it adds a vect_load_store_data type, local
data in vectorizable_load/store and an alias that either refers
to previous analysis results or the local data:

+  vect_load_store_data _ls_data;
+  vect_load_store_data &ls = cost_vec ? _ls_data : *slp_node->u.ls;

and it shows how to then record it with the current union abstraction:

       SLP_TREE_TYPE (slp_node) = store_vec_info_type;
+      slp_node->u.ls = new vect_load_store_data (ls);


2nd attempt to trigger the CI

        * tree-vectorizer.h (gather_scatter_info): Move.
        (vect_load_store_data): New.
        (_slp_tree::u::ls): New.
        * tree-vect-stmts.cc (get_load_store_type): Take pointer
        to vect_load_store_data instead of individual pointers.
        (vectorizable_store): Adjust.  Re-use get_load_store_type
        result from analysis time.
        (vectorizable_load): Likewise.
        * tree-vect-slp.cc (_slp_tree::~_slp_tree): Delete load-store
        data.
---
 gcc/tree-vect-slp.cc   |   8 ++++
 gcc/tree-vect-stmts.cc | 101 ++++++++++++++++++++++++-----------------
 gcc/tree-vectorizer.h  |  92 +++++++++++++++++++++++--------------
 3 files changed, 125 insertions(+), 76 deletions(-)

diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc
index a9c7105f47e..55d02fcea39 100644
--- a/gcc/tree-vect-slp.cc
+++ b/gcc/tree-vect-slp.cc
@@ -153,6 +153,14 @@ _slp_tree::~_slp_tree ()
   SLP_TREE_SIMD_CLONE_INFO (this).release ();
   if (this->failed)
     free (failed);
+  switch (SLP_TREE_TYPE (this))
+    {
+    case load_vec_info_type:
+    case store_vec_info_type:
+      delete this->u.ls;
+      break;
+    default:;
+    }
 }
 
 /* Push the single SSA definition in DEF to the vector of vector defs.  */
diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc
index 1dfb148e803..c617d80e4e7 100644
--- a/gcc/tree-vect-stmts.cc
+++ b/gcc/tree-vect-stmts.cc
@@ -2350,14 +2350,17 @@ get_load_store_type (vec_info  *vinfo, stmt_vec_info 
stmt_info,
                     tree vectype, slp_tree slp_node,
                     bool masked_p, vec_load_store_type vls_type,
                     unsigned int,
-                    vect_memory_access_type *memory_access_type,
-                    poly_int64 *poffset,
-                    dr_alignment_support *alignment_support_scheme,
-                    int *misalignment,
-                    gather_scatter_info *gs_info,
-                    internal_fn *lanes_ifn,
-                    vec<int> *elsvals = nullptr)
+                    vect_load_store_data *ls)
 {
+  vect_memory_access_type *memory_access_type = &ls->memory_access_type;
+  poly_int64 *poffset = &ls->poffset;
+  dr_alignment_support *alignment_support_scheme
+    = &ls->alignment_support_scheme;
+  int *misalignment = &ls->misalignment;
+  gather_scatter_info *gs_info = &ls->gs_info;
+  internal_fn *lanes_ifn = &ls->lanes_ifn;
+  vec<int> *elsvals = &ls->elsvals;
+
   loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
   poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
   *misalignment = DR_MISALIGNMENT_UNKNOWN;
@@ -7762,7 +7765,6 @@ vectorizable_store (vec_info *vinfo,
   unsigned int vec_num;
   bb_vec_info bb_vinfo = dyn_cast <bb_vec_info> (vinfo);
   tree aggr_type;
-  gather_scatter_info gs_info;
   poly_uint64 vf;
   vec_load_store_type vls_type;
   tree ref_type;
@@ -7852,16 +7854,20 @@ vectorizable_store (vec_info *vinfo,
   if (!STMT_VINFO_DATA_REF (stmt_info))
     return false;
 
-  vect_memory_access_type memory_access_type;
-  enum dr_alignment_support alignment_support_scheme;
-  int misalignment;
-  poly_int64 poffset;
-  internal_fn lanes_ifn;
-  if (!get_load_store_type (vinfo, stmt_info, vectype, slp_node, mask, 
vls_type,
-                           1, &memory_access_type, &poffset,
-                           &alignment_support_scheme, &misalignment, &gs_info,
-                           &lanes_ifn))
+  vect_load_store_data _ls_data;
+  vect_load_store_data &ls = cost_vec ? _ls_data : *slp_node->u.ls;
+  if (cost_vec
+      && !get_load_store_type (vinfo, stmt_info, vectype, slp_node, mask,
+                              vls_type, 1, &_ls_data))
     return false;
+  /* Temporary aliases to analysis data, should not be modified through
+     these.  */
+  const vect_memory_access_type memory_access_type = ls.memory_access_type;
+  const dr_alignment_support alignment_support_scheme = 
ls.alignment_support_scheme;
+  const int misalignment = ls.misalignment;
+  const poly_int64 poffset = ls.poffset;
+  const internal_fn lanes_ifn = ls.lanes_ifn;
+  const gather_scatter_info &gs_info = ls.gs_info;
 
   if (slp_node->ldst_lanes
       && memory_access_type != VMAT_LOAD_STORE_LANES)
@@ -7963,6 +7969,7 @@ vectorizable_store (vec_info *vinfo,
                         "Vectorizing an unaligned access.\n");
 
       SLP_TREE_TYPE (slp_node) = store_vec_info_type;
+      slp_node->u.ls = new vect_load_store_data (ls);
     }
   gcc_assert (memory_access_type == SLP_TREE_MEMORY_ACCESS_TYPE (slp_node));
 
@@ -8060,6 +8067,14 @@ vectorizable_store (vec_info *vinfo,
             ...
          */
 
+      /* ???  Modify local copies of alignment_support_scheme and
+        misalignment, but this part of analysis should be done
+        earlier and remembered, likewise the chosen load mode.  */
+      const dr_alignment_support tem = alignment_support_scheme;
+      dr_alignment_support alignment_support_scheme = tem;
+      const int tem2 = misalignment;
+      int misalignment = tem2;
+
       unsigned nstores = const_nunits;
       unsigned lnel = 1;
       tree ltype = elem_type;
@@ -9278,7 +9293,6 @@ vectorizable_load (vec_info *vinfo,
   bb_vec_info bb_vinfo = dyn_cast <bb_vec_info> (vinfo);
   poly_uint64 vf;
   tree aggr_type;
-  gather_scatter_info gs_info;
   tree ref_type;
   enum vect_def_type mask_dt = vect_unknown_def_type;
   enum vect_def_type els_dt = vect_unknown_def_type;
@@ -9412,20 +9426,25 @@ vectorizable_load (vec_info *vinfo,
   else
     group_size = 1;
 
-  vect_memory_access_type memory_access_type;
-  enum dr_alignment_support alignment_support_scheme;
-  int misalignment;
-  poly_int64 poffset;
-  internal_fn lanes_ifn;
-  auto_vec<int> elsvals;
-  int maskload_elsval = 0;
-  bool need_zeroing = false;
-  if (!get_load_store_type (vinfo, stmt_info, vectype, slp_node, mask, 
VLS_LOAD,
-                           1, &memory_access_type, &poffset,
-                           &alignment_support_scheme, &misalignment, &gs_info,
-                           &lanes_ifn, &elsvals))
+  vect_load_store_data _ls_data;
+  vect_load_store_data &ls = cost_vec ? _ls_data : *slp_node->u.ls;
+  if (cost_vec
+      && !get_load_store_type (vinfo, stmt_info, vectype, slp_node, mask,
+                              VLS_LOAD, 1, &ls))
     return false;
+  /* Temporary aliases to analysis data, should not be modified through
+     these.  */
+  const vect_memory_access_type memory_access_type = ls.memory_access_type;
+  const dr_alignment_support alignment_support_scheme
+    = ls.alignment_support_scheme;
+  const int misalignment = ls.misalignment;
+  const poly_int64 poffset = ls.poffset;
+  const internal_fn lanes_ifn = ls.lanes_ifn;
+  const vec<int> &elsvals = ls.elsvals;
+  const gather_scatter_info &gs_info = ls.gs_info;
 
+  int maskload_elsval = 0;
+  bool need_zeroing = false;
 
   /* We might need to explicitly zero inactive elements if there are
      padding bits in the type that might leak otherwise.
@@ -9496,7 +9515,7 @@ vectorizable_load (vec_info *vinfo,
          if (!VECTOR_MODE_P (vec_mode)
              || !can_vec_mask_load_store_p (vec_mode,
                                             TYPE_MODE (mask_vectype),
-                                            true, NULL, &elsvals))
+                                            true, NULL, &ls.elsvals))
            return false;
        }
       else if (memory_access_type != VMAT_LOAD_STORE_LANES
@@ -9546,7 +9565,7 @@ vectorizable_load (vec_info *vinfo,
        check_load_store_for_partial_vectors (loop_vinfo, vectype, slp_node,
                                              VLS_LOAD, group_size,
                                              memory_access_type, &gs_info,
-                                             mask, &elsvals);
+                                             mask, &ls.elsvals);
 
       if (dump_enabled_p ()
          && memory_access_type != VMAT_ELEMENTWISE
@@ -9561,16 +9580,7 @@ vectorizable_load (vec_info *vinfo,
        vinfo->any_known_not_updated_vssa = true;
 
       SLP_TREE_TYPE (slp_node) = load_vec_info_type;
-    }
-  else
-    {
-      /* Here just get the else values.  */
-      if (loop_vinfo
-         && LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo))
-       check_load_store_for_partial_vectors (loop_vinfo, vectype, slp_node,
-                                             VLS_LOAD, group_size,
-                                             memory_access_type, &gs_info,
-                                             mask, &elsvals);
+      slp_node->u.ls = new vect_load_store_data (ls);
     }
 
   /* If the type needs padding we must zero inactive elements.
@@ -9763,6 +9773,13 @@ vectorizable_load (vec_info *vinfo,
       tree ltype = TREE_TYPE (vectype);
       tree lvectype = vectype;
       auto_vec<tree> dr_chain;
+      /* ???  Modify local copies of alignment_support_scheme and
+        misalignment, but this part of analysis should be done
+        earlier and remembered, likewise the chosen load mode.  */
+      const dr_alignment_support tem = alignment_support_scheme;
+      dr_alignment_support alignment_support_scheme = tem;
+      const int tem2 = misalignment;
+      int misalignment = tem2;
       if (memory_access_type == VMAT_STRIDED_SLP)
        {
          HOST_WIDE_INT n = gcd (group_size, const_nunits);
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index 7e7b2b4b836..83aadf051d3 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -231,6 +231,40 @@ enum stmt_vec_info_type {
   loop_exit_ctrl_vec_info_type
 };
 
+/* Information about a gather/scatter call.  */
+struct gather_scatter_info {
+  /* The internal function to use for the gather/scatter operation,
+     or IFN_LAST if a built-in function should be used instead.  */
+  internal_fn ifn;
+
+  /* The FUNCTION_DECL for the built-in gather/scatter function,
+     or null if an internal function should be used instead.  */
+  tree decl;
+
+  /* The loop-invariant base value.  */
+  tree base;
+
+  /* The TBBA alias pointer the value of which determines the alignment
+     of the scalar accesses.  */
+  tree alias_ptr;
+
+  /* The original scalar offset, which is a non-loop-invariant SSA_NAME.  */
+  tree offset;
+
+  /* Each offset element should be multiplied by this amount before
+     being added to the base.  */
+  int scale;
+
+  /* The type of the vectorized offset.  */
+  tree offset_vectype;
+
+  /* The type of the scalar elements after loading or before storing.  */
+  tree element_type;
+
+  /* The type of the scalar elements being loaded or stored.  */
+  tree memory_type;
+};
+
 /************************************************************************
   SLP
  ************************************************************************/
@@ -239,6 +273,28 @@ typedef auto_vec<std::pair<unsigned, unsigned>, 16> 
auto_lane_permutation_t;
 typedef vec<unsigned> load_permutation_t;
 typedef auto_vec<unsigned, 16> auto_load_permutation_t;
 
+/* Analysis data from vectorizable_load and vectorizable_store.  */
+struct vect_load_store_data {
+  vect_load_store_data (vect_load_store_data &other)
+    : alignment_support_scheme (other.alignment_support_scheme),
+    memory_access_type (other.memory_access_type),
+    misalignment (other.misalignment),
+    poffset (other.poffset),
+    lanes_ifn (other.lanes_ifn),
+    gs_info (other.gs_info)
+  {
+    elsvals = std::move (other.elsvals);
+  }
+  vect_load_store_data () = default;
+  dr_alignment_support alignment_support_scheme;
+  vect_memory_access_type memory_access_type;
+  int misalignment;
+  poly_int64 poffset;
+  internal_fn lanes_ifn;
+  auto_vec<int> elsvals;
+  gather_scatter_info gs_info;
+};
+
 /* A computation tree of an SLP instance.  Each node corresponds to a group of
    stmts to be packed in a SIMD stmt.  */
 struct _slp_tree {
@@ -310,6 +366,8 @@ struct _slp_tree {
   enum stmt_vec_info_type type;
   union {
       void *undef;
+      /* load_vec_info_type, store_vec_info_type */
+      vect_load_store_data *ls;
   } u;
 
   /* If not NULL this is a cached failed SLP discovery attempt with
@@ -1536,40 +1594,6 @@ public:
   bool slp_vect_pattern_only_p;
 };
 
-/* Information about a gather/scatter call.  */
-struct gather_scatter_info {
-  /* The internal function to use for the gather/scatter operation,
-     or IFN_LAST if a built-in function should be used instead.  */
-  internal_fn ifn;
-
-  /* The FUNCTION_DECL for the built-in gather/scatter function,
-     or null if an internal function should be used instead.  */
-  tree decl;
-
-  /* The loop-invariant base value.  */
-  tree base;
-
-  /* The TBBA alias pointer the value of which determines the alignment
-     of the scalar accesses.  */
-  tree alias_ptr;
-
-  /* The original scalar offset, which is a non-loop-invariant SSA_NAME.  */
-  tree offset;
-
-  /* Each offset element should be multiplied by this amount before
-     being added to the base.  */
-  int scale;
-
-  /* The type of the vectorized offset.  */
-  tree offset_vectype;
-
-  /* The type of the scalar elements after loading or before storing.  */
-  tree element_type;
-
-  /* The type of the scalar elements being loaded or stored.  */
-  tree memory_type;
-};
-
 /* Access Functions.  */
 #define STMT_VINFO_STMT(S)                 (S)->stmt
 #define STMT_VINFO_RELEVANT(S)             (S)->relevant
-- 
2.43.0

Reply via email to