Make gimple_build_vector take a tree_vector_builder
authorRichard Sandiford <richard.sandiford@linaro.org>
Thu, 7 Dec 2017 18:41:59 +0000 (18:41 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Thu, 7 Dec 2017 18:41:59 +0000 (18:41 +0000)
This patch changes gimple_build_vector so that it takes a
tree_vector_builder instead of a size and a vector of trees.

2017-12-07  Richard Sandiford  <richard.sandiford@linaro.org>

gcc/
* vector-builder.h (vector_builder::derived): New const overload.
(vector_builder::elt): New function.
* tree-vector-builder.h (tree_vector_builder::type): New function.
(tree_vector_builder::apply_step): Declare.
* tree-vector-builder.c (tree_vector_builder::apply_step): New
function.
* gimple-fold.h (tree_vector_builder): Declare.
(gimple_build_vector): Take a tree_vector_builder instead of a
type and vector of elements.
* gimple-fold.c (gimple_build_vector): Likewise.
* tree-vect-loop.c (get_initial_def_for_reduction): Update call
accordingly.
(get_initial_defs_for_reduction): Likewise.
(vectorizable_induction): Likewise.

From-SVN: r255478

gcc/ChangeLog
gcc/gimple-fold.c
gcc/gimple-fold.h
gcc/tree-vect-loop.c
gcc/tree-vector-builder.c
gcc/tree-vector-builder.h
gcc/vector-builder.h

index 6fb516053546482cd109b7808a26d1ccecc2f4e3..d7954ff8fc63cddef33f52692e42ae4907f83568 100644 (file)
@@ -1,3 +1,20 @@
+2017-12-07  Richard Sandiford  <richard.sandiford@linaro.org>
+
+       * vector-builder.h (vector_builder::derived): New const overload.
+       (vector_builder::elt): New function.
+       * tree-vector-builder.h (tree_vector_builder::type): New function.
+       (tree_vector_builder::apply_step): Declare.
+       * tree-vector-builder.c (tree_vector_builder::apply_step): New
+       function.
+       * gimple-fold.h (tree_vector_builder): Declare.
+       (gimple_build_vector): Take a tree_vector_builder instead of a
+       type and vector of elements.
+       * gimple-fold.c (gimple_build_vector): Likewise.
+       * tree-vect-loop.c (get_initial_def_for_reduction): Update call
+       accordingly.
+       (get_initial_defs_for_reduction): Likewise.
+       (vectorizable_induction): Likewise.
+
 2017-12-07  Richard Sandiford  <richard.sandiford@linaro.org>
 
        * tree-vector-builder.h
index 6044092412cb0ccb761a39e7e733359e259d1b04..24f7e76228b9000f6250e39365843982ba15b4c8 100644 (file)
@@ -7178,23 +7178,30 @@ gimple_build_vector_from_val (gimple_seq *seq, location_t loc, tree type,
   return res;
 }
 
-/* Build a vector of type TYPE in which the elements have the values
-   given by ELTS.  Return a gimple value for the result, appending any
-   new instructions to SEQ.  */
+/* Build a vector from BUILDER, handling the case in which some elements
+   are non-constant.  Return a gimple value for the result, appending any
+   new instructions to SEQ.
+
+   BUILDER must not have a stepped encoding on entry.  This is because
+   the function is not geared up to handle the arithmetic that would
+   be needed in the variable case, and any code building a vector that
+   is known to be constant should use BUILDER->build () directly.  */
 
 tree
-gimple_build_vector (gimple_seq *seq, location_t loc, tree type,
-                    vec<tree> elts)
+gimple_build_vector (gimple_seq *seq, location_t loc,
+                    tree_vector_builder *builder)
 {
-  unsigned int nelts = elts.length ();
-  gcc_assert (nelts == TYPE_VECTOR_SUBPARTS (type));
-  for (unsigned int i = 0; i < nelts; ++i)
-    if (!TREE_CONSTANT (elts[i]))
+  gcc_assert (builder->nelts_per_pattern () <= 2);
+  unsigned int encoded_nelts = builder->encoded_nelts ();
+  for (unsigned int i = 0; i < encoded_nelts; ++i)
+    if (!TREE_CONSTANT ((*builder)[i]))
       {
+       tree type = builder->type ();
+       unsigned int nelts = TYPE_VECTOR_SUBPARTS (type);
        vec<constructor_elt, va_gc> *v;
        vec_alloc (v, nelts);
        for (i = 0; i < nelts; ++i)
-         CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, elts[i]);
+         CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, builder->elt (i));
 
        tree res;
        if (gimple_in_ssa_p (cfun))
@@ -7206,7 +7213,7 @@ gimple_build_vector (gimple_seq *seq, location_t loc, tree type,
        gimple_seq_add_stmt_without_update (seq, stmt);
        return res;
       }
-  return build_vector (type, elts);
+  return builder->build ();
 }
 
 /* Return true if the result of assignment STMT is known to be non-negative.
index ddbc4f0a7c54a909ce29c4c962601a9c076edbaf..83babfa4fd531f7401511fd7a017d86366821109 100644 (file)
@@ -135,11 +135,13 @@ gimple_build_vector_from_val (gimple_seq *seq, tree type, tree op)
   return gimple_build_vector_from_val (seq, UNKNOWN_LOCATION, type, op);
 }
 
-extern tree gimple_build_vector (gimple_seq *, location_t, tree, vec<tree>);
+class tree_vector_builder;
+extern tree gimple_build_vector (gimple_seq *, location_t,
+                                tree_vector_builder *);
 inline tree
-gimple_build_vector (gimple_seq *seq, tree type, vec<tree> elts)
+gimple_build_vector (gimple_seq *seq, tree_vector_builder *builder)
 {
-  return gimple_build_vector (seq, UNKNOWN_LOCATION, type, elts);
+  return gimple_build_vector (seq, UNKNOWN_LOCATION, builder);
 }
 
 extern bool gimple_stmt_nonnegative_warnv_p (gimple *, bool *, int = 0);
index 566e2a6c3e72f7e0b54b2e31c798eaddd1edc2ed..1759655fd0728bdb6faf99b9be3a362df260da32 100644 (file)
@@ -3978,11 +3978,9 @@ get_initial_def_for_reduction (gimple *stmt, tree init_val,
   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
   tree scalar_type = TREE_TYPE (init_val);
   tree vectype = get_vectype_for_scalar_type (scalar_type);
-  int nunits;
   enum tree_code code = gimple_assign_rhs_code (stmt);
   tree def_for_init;
   tree init_def;
-  int i;
   bool nested_in_vect_loop = false;
   REAL_VALUE_TYPE real_init_val = dconst0;
   int int_init_val = 0;
@@ -3990,7 +3988,6 @@ get_initial_def_for_reduction (gimple *stmt, tree init_val,
   gimple_seq stmts = NULL;
 
   gcc_assert (vectype);
-  nunits = TYPE_VECTOR_SUBPARTS (vectype);
 
   gcc_assert (POINTER_TYPE_P (scalar_type) || INTEGRAL_TYPE_P (scalar_type)
              || SCALAR_FLOAT_TYPE_P (scalar_type));
@@ -4063,11 +4060,10 @@ get_initial_def_for_reduction (gimple *stmt, tree init_val,
        else
          {
            /* Option2: the first element is INIT_VAL.  */
-           auto_vec<tree, 32> elts (nunits);
+           tree_vector_builder elts (vectype, 1, 2);
            elts.quick_push (init_val);
-           for (i = 1; i < nunits; ++i)
-             elts.quick_push (def_for_init);
-           init_def = gimple_build_vector (&stmts, vectype, elts);
+           elts.quick_push (def_for_init);
+           init_def = gimple_build_vector (&stmts, &elts);
          }
       }
       break;
@@ -4192,7 +4188,7 @@ get_initial_defs_for_reduction (slp_tree slp_node,
   number_of_copies = nunits * number_of_vectors / group_size;
 
   number_of_places_left_in_vector = nunits;
-  auto_vec<tree, 32> elts (nunits);
+  tree_vector_builder elts (vector_type, nunits, 1);
   elts.quick_grow (nunits);
   for (j = 0; j < number_of_copies; j++)
     {
@@ -4215,12 +4211,14 @@ get_initial_defs_for_reduction (slp_tree slp_node,
           if (number_of_places_left_in_vector == 0)
             {
              gimple_seq ctor_seq = NULL;
-             tree init = gimple_build_vector (&ctor_seq, vector_type, elts);
+             tree init = gimple_build_vector (&ctor_seq, &elts);
              if (ctor_seq != NULL)
                gsi_insert_seq_on_edge_immediate (pe, ctor_seq);
              voprnds.quick_push (init);
 
               number_of_places_left_in_vector = nunits;
+             elts.new_vector (vector_type, nunits, 1);
+             elts.quick_grow (nunits);
             }
         }
     }
@@ -6708,7 +6706,7 @@ vectorizable_induction (gimple *phi,
       unsigned ivn;
       for (ivn = 0; ivn < nivs; ++ivn)
        {
-         auto_vec<tree, 32> elts (nunits);
+         tree_vector_builder elts (vectype, nunits, 1);
          stmts = NULL;
          for (unsigned eltn = 0; eltn < nunits; ++eltn)
            {
@@ -6718,7 +6716,7 @@ vectorizable_induction (gimple *phi,
                                    elt, step_expr);
              elts.quick_push (elt);
            }
-         vec_init = gimple_build_vector (&stmts, vectype, elts);
+         vec_init = gimple_build_vector (&stmts, &elts);
          if (stmts)
            {
              new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts);
@@ -6825,7 +6823,7 @@ vectorizable_induction (gimple *phi,
       stmts = NULL;
       new_name = gimple_convert (&stmts, TREE_TYPE (vectype), init_expr);
 
-      auto_vec<tree, 32> elts (nunits);
+      tree_vector_builder elts (vectype, nunits, 1);
       elts.quick_push (new_name);
       for (i = 1; i < nunits; i++)
        {
@@ -6836,7 +6834,7 @@ vectorizable_induction (gimple *phi,
        }
       /* Create a vector from [new_name_0, new_name_1, ...,
         new_name_nunits-1]  */
-      vec_init = gimple_build_vector (&stmts, vectype, elts);
+      vec_init = gimple_build_vector (&stmts, &elts);
       if (stmts)
        {
          new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts);
index a8a98970f37eee236419323307ac7b89bc98e409..954dbcd721515ddc459ed931f59db95df1076e9d 100644 (file)
@@ -96,6 +96,16 @@ tree_vector_builder::new_binary_operation (tree type, tree t1, tree t2,
   return true;
 }
 
+/* Return a vector element with the value BASE + FACTOR * STEP.  */
+
+tree
+tree_vector_builder::apply_step (tree base, unsigned int factor,
+                                const wide_int &step) const
+{
+  return wide_int_to_tree (TREE_TYPE (base),
+                          wi::to_wide (base) + factor * step);
+}
+
 /* Return a VECTOR_CST for the current constant.  */
 
 tree
index b89d3ab3af629fca2bf0173341650f40621c90eb..1038be77c151392a9d3dd6292502ed2d680976e4 100644 (file)
@@ -45,6 +45,7 @@ private:
   bool allow_steps_p () const;
   bool integral_p (const_tree) const;
   wide_int step (const_tree, const_tree) const;
+  tree apply_step (tree, unsigned int, const wide_int &) const;
   bool can_elide_p (const_tree) const;
   void note_representative (tree *, tree);
 
index ae30b3bba2f9cbe807e648809e3339302bf5e90c..0edd6f5c0927ba091c240ffb631ffc112c54974c 100644 (file)
@@ -68,6 +68,10 @@ along with GCC; see the file COPYING3.  If not see
          given integral_p (ELT1) && integral_p (ELT2).  There is no fixed
          choice of StepType.
 
+      T apply_step (T base, unsigned int factor, StepType step) const;
+
+         Return a vector element with the value BASE + FACTOR * STEP.
+
       bool can_elide_p (T elt) const;
 
          Return true if we can drop element ELT, even if the retained
@@ -91,6 +95,7 @@ public:
   unsigned int nelts_per_pattern () const { return m_nelts_per_pattern; }
   unsigned int encoded_nelts () const;
   bool encoded_full_vector_p () const;
+  T elt (unsigned int) const;
 
   void finalize ();
 
@@ -163,6 +168,38 @@ vector_builder<T, Derived>::new_vector (unsigned int full_nelts,
   this->truncate (0);
 }
 
+/* Return the value of vector element I, which might or might not be
+   encoded explicitly.  */
+
+template<typename T, typename Derived>
+T
+vector_builder<T, Derived>::elt (unsigned int i) const
+{
+  /* This only makes sense if the encoding has been fully populated.  */
+  gcc_checking_assert (encoded_nelts () <= this->length ());
+
+  /* First handle elements that are already present in the underlying
+     vector, regardless of whether they're part of the encoding or not.  */
+  if (i < this->length ())
+    return (*this)[i];
+
+  /* Identify the pattern that contains element I and work out the index of
+     the last encoded element for that pattern.  */
+  unsigned int pattern = i % m_npatterns;
+  unsigned int count = i / m_npatterns;
+  unsigned int final_i = encoded_nelts () - m_npatterns + pattern;
+  T final = (*this)[final_i];
+
+  /* If there are no steps, the final encoded value is the right one.  */
+  if (m_nelts_per_pattern <= 2)
+    return final;
+
+  /* Otherwise work out the value from the last two encoded elements.  */
+  T prev = (*this)[final_i - m_npatterns];
+  return derived ()->apply_step (final, count - 2,
+                                derived ()->step (prev, final));
+}
+
 /* Change the encoding to NPATTERNS patterns of NELTS_PER_PATTERN each,
    but without changing the underlying vector.  */