gcc/ChangeLog:

        * gimple-fold.cc (gimple_build_vector): Check that the
        passed-in vector builder produces element values that
        are constant zero if they lie outside the minimum length
        of a variable-length vector type, and also a repeating tail
        of constant zeros.
        * tree-vect-slp.cc (vect_create_constant_vectors):
        Initialize the vector builder with two elements per pattern
        instead of one, if doing BB SLP vectorization and the vector
        type is variable-length or the SLP group has fewer lanes than
        needed to fill a fixed-length vector type.  Assign a zero
        constant to the second (repeating) element of each pattern.
---
 gcc/gimple-fold.cc   | 33 +++++++++++++++++++++--
 gcc/tree-vect-slp.cc | 62 +++++++++++++++++++++++++++++++++++---------
 2 files changed, 81 insertions(+), 14 deletions(-)

diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc
index fdb9b419766..132205c6ba9 100644
--- a/gcc/gimple-fold.cc
+++ b/gcc/gimple-fold.cc
@@ -11487,7 +11487,13 @@ gimple_build_vector_from_val (gimple_stmt_iterator 
*gsi,
    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.  */
+   is known to be constant should use BUILDER->build () directly.
+
+   If at least one element is non-constant and the type associated with BUILDER
+   is a variable-length vector type then the encoding used by BUILDER must have
+   two elements per pattern; the second (repeating) element of each pattern
+   must be constant zero, as must the first if it falls outside the minimum
+   vector length.  */
 
 tree
 gimple_build_vector (gimple_stmt_iterator *gsi,
@@ -11501,7 +11507,30 @@ gimple_build_vector (gimple_stmt_iterator *gsi,
       {
        gimple_seq seq = NULL;
        tree type = builder->type ();
-       unsigned int nelts = TYPE_VECTOR_SUBPARTS (type).to_constant ();
+       unsigned int min_nelts
+         = constant_lower_bound (TYPE_VECTOR_SUBPARTS (type));
+
+       /* All vector builders produce an infinitely repeating sequence; we only
+          care about truncation of that sequence if the vector type has a
+          variable length.  */
+       unsigned HOST_WIDE_INT nelts;
+       if (!TYPE_VECTOR_SUBPARTS (type).is_constant (&nelts))
+         {
+           /* Initial elements outside the minimum vector length must be
+              constant zero because that is the only implicit value that a
+              CONSTRUCTOR node can have.  */
+           for (i = min_nelts; i < builder->npatterns (); ++i)
+             gcc_assert (zerop ((*builder)[i]));
+
+           /* The builder must also produce an infinitely repeating tail of
+              constant zeros.  */
+           gcc_assert (builder->nelts_per_pattern () == 2);
+           for (i = builder->npatterns (); i < encoded_nelts; ++i)
+             gcc_assert (zerop ((*builder)[i]));
+
+           nelts = min_nelts;
+         }
+
        vec<constructor_elt, va_gc> *v;
        vec_alloc (v, nelts);
        for (i = 0; i < nelts; ++i)
diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc
index 850cb1efacc..9331f25286f 100644
--- a/gcc/tree-vect-slp.cc
+++ b/gcc/tree-vect-slp.cc
@@ -10773,7 +10773,7 @@ vect_create_constant_vectors (vec_info *vinfo, slp_tree 
op_node)
   unsigned j, number_of_places_left_in_vector;
   tree vector_type;
   tree vop;
-  int group_size = op_node->ops.length ();
+  unsigned int group_size = op_node->ops.length ();
   unsigned int vec_num, i;
   unsigned number_of_copies = 1;
   bool constant_p;
@@ -10803,18 +10803,49 @@ vect_create_constant_vectors (vec_info *vinfo, 
slp_tree op_node)
      (s1, s2, ..., s8).  We will create two vectors {s1, s2, s3, s4} and
      {s5, s6, s7, s8}.  */
 
-  /* When using duplicate_and_interleave, we just need one element for
-     each scalar statement.  */
-  if (!TYPE_VECTOR_SUBPARTS (vector_type).is_constant (&nunits))
-    nunits = group_size;
+  unsigned int npatterns, nelts_per_pattern = 1;
+  poly_uint64 type_nunits = TYPE_VECTOR_SUBPARTS (vector_type);
+  if (is_a <bb_vec_info> (vinfo))
+    {
+      /* We don't use duplicate_and_interleave for basic block vectorization.
+        We know that either the group size is exactly divisible by the vector
+        length or it fits within a single vector.  */
+      gcc_checking_assert (multiple_p (group_size, type_nunits)
+                          || known_le (group_size, type_nunits));
+
+      /* If the vector length is unknown then we need two elements per pattern
+        to encode an infinite-length tail of constant zeros.  */
+      if (!type_nunits.is_constant (&nunits))
+       {
+         nunits = constant_lower_bound (type_nunits);
+         nelts_per_pattern = 2;
+       }
+
+      npatterns = nunits;
+
+      /* If the group does not occupy a full vector then only the first
+        GROUP_SIZE elements come from scalar operands.  The remainder are
+        assigned constant zero below.  */
+      if (group_size < nunits)
+         nunits = group_size;
+    }
+  else
+    {
+      /* When using duplicate_and_interleave, we just need one element for
+        each scalar statement.  */
+      if (!type_nunits.is_constant (&nunits))
+       nunits = group_size;
+
+      npatterns = nunits;
+    }
 
   number_of_copies = nunits * number_of_vectors / group_size;
 
   number_of_places_left_in_vector = nunits;
   constant_p = true;
   tree uniform_elt = NULL_TREE;
-  tree_vector_builder elts (vector_type, nunits, 1);
-  elts.quick_grow (nunits);
+  tree_vector_builder elts (vector_type, npatterns, nelts_per_pattern);
+  elts.quick_grow (elts.encoded_nelts());
   stmt_vec_info insert_after = NULL;
   for (j = 0; j < number_of_copies; j++)
     {
@@ -10898,10 +10929,17 @@ vect_create_constant_vectors (vec_info *vinfo, 
slp_tree op_node)
 
           if (number_of_places_left_in_vector == 0)
             {
-             auto type_nunits = TYPE_VECTOR_SUBPARTS (vector_type);
              if (uniform_elt)
                vec_cst = gimple_build_vector_from_val (&ctor_seq, vector_type,
                                                        elts[0]);
+             else if (is_a <bb_vec_info> (vinfo))
+             {
+               unsigned int encoded_nelts = elts.encoded_nelts ();
+               tree zero_val = build_zero_cst (TREE_TYPE (vector_type));
+               for (unsigned int k = nunits; k < encoded_nelts; k++)
+                 elts[k] = zero_val;
+               vec_cst = gimple_build_vector (&ctor_seq, &elts);
+             }
              else if (constant_p
                       ? multiple_p (type_nunits, nunits)
                       : known_eq (type_nunits, nunits))
@@ -10951,10 +10989,10 @@ vect_create_constant_vectors (vec_info *vinfo, 
slp_tree op_node)
              insert_after = NULL;
               number_of_places_left_in_vector = nunits;
              constant_p = true;
-             elts.new_vector (vector_type, nunits, 1);
-             elts.quick_grow (nunits);
-            }
-        }
+             elts.new_vector (vector_type, npatterns, nelts_per_pattern);
+             elts.quick_grow (elts.encoded_nelts ());
+           }
+       }
     }
 
   /* Since the vectors are created in the reverse order, we should invert
-- 
2.43.0

Reply via email to