The following fixes wrong excess number of lanes computation in
vect_create_constant_vectors, integrating that into
vect_get_num_copies_for_invariant because the poly computation
has to be constant.

Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed.

        PR tree-optimization/126998
        * tree-vectorizer.h (vect_get_num_copies_for_invariant):
        Adjust API.
        * tree-vect-slp.cc (vect_get_num_copies_for_invariant): Also
        compute and output the constant number of excess lanes produced.
        (vect_create_constant_vectors): Adjust.
        (vect_slp_analyze_node_operations): Likewise.
        * tree-vect-loop.cc (vectorizable_lane_reducing): Likewise.

        * gcc.dg/vect/vect-reduc-dot-pr126998-2.c: New testcase.
---
 .../gcc.dg/vect/vect-reduc-dot-pr126998-2.c   | 37 +++++++++++++++++++
 gcc/tree-vect-loop.cc                         |  5 ++-
 gcc/tree-vect-slp.cc                          | 29 +++++++++------
 gcc/tree-vectorizer.h                         |  2 +-
 4 files changed, 59 insertions(+), 14 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/vect/vect-reduc-dot-pr126998-2.c

diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-pr126998-2.c 
b/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-pr126998-2.c
new file mode 100644
index 00000000000..66f018c291d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-pr126998-2.c
@@ -0,0 +1,37 @@
+/* { dg-additional-options "-O3" } */
+/* { dg-additional-options "-msse4" { target sse4 } } */
+
+#include "tree-vect.h"
+
+unsigned a, c;
+int b, d;
+signed char e;
+  
+void __attribute__((noipa))
+f (void)
+{ 
+  for (; b; ++b)
+    {
+      c = 0;
+      for (; c < 10; c++)
+        {
+          d = 0;
+          for (; d < c; d++)
+            a += e;
+        }
+    }
+}
+
+int
+main ()
+{
+  check_vect ();
+
+  b = -3;
+  e = 2;
+  f ();
+  if (a != 3 * 45 * 2)
+    __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc
index 78f84c6269a..cb961440656 100644
--- a/gcc/tree-vect-loop.cc
+++ b/gcc/tree-vect-loop.cc
@@ -6854,9 +6854,10 @@ vectorizable_lane_reducing (loop_vec_info loop_vinfo, 
stmt_vec_info stmt_info,
 
   /* Compute number of effective vector statements for costing from the
      number of input lanes allow for excess lanes in the last input vector.  */
-  unsigned int ncopies_for_cost;
+  unsigned int ncopies_for_cost, excess_elts;
   bool res = vect_get_num_copies_for_invariant (loop_vinfo, node_in,
-                                               &ncopies_for_cost);
+                                               &ncopies_for_cost,
+                                               &excess_elts);
   gcc_assert (res && ncopies_for_cost >= 1);
 
   if (vect_is_emulated_mixed_dot_prod (slp_node))
diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc
index 35b319e95f0..52c623f75a2 100644
--- a/gcc/tree-vect-slp.cc
+++ b/gcc/tree-vect-slp.cc
@@ -8937,12 +8937,14 @@ vect_scalar_ops_slice_hash::equal (const value_type &s1,
 }
 
 /* Like vect_get_num_copies but N copies of the vector might have
-   excess elements in the last vector.  Returns false if *NVECTORS
-   cannot be computed.  */
+   excess elements in the last vector.  Stores the number of excess
+   elements in the last vector in *EXCESS_ELTS.
+   Returns false if *NVECTORS or *EXCESS_ELTS cannot be computed.  */
 
 bool
 vect_get_num_copies_for_invariant (vec_info *vinfo, slp_tree node,
-                                  unsigned *nvectors)
+                                  unsigned *nvectors,
+                                  unsigned *excess_elts)
 {
   poly_uint64 vf;
 
@@ -8953,8 +8955,12 @@ vect_get_num_copies_for_invariant (vec_info *vinfo, 
slp_tree node,
   vf *= SLP_TREE_LANES (node);
 
   tree vectype = SLP_TREE_VECTYPE (node);
-  bool res = can_div_away_from_zero_p (vf, TYPE_VECTOR_SUBPARTS (vectype),
-                                      nvectors);
+  uint64_t rem;
+  bool res = (can_div_away_from_zero_p (vf, TYPE_VECTOR_SUBPARTS (vectype),
+                                       nvectors)
+             && ((TYPE_VECTOR_SUBPARTS (vectype) * *nvectors - vf)
+                 .is_constant (&rem)));
+  *excess_elts = rem;
   return res;
 }
 
@@ -9138,8 +9144,9 @@ vect_slp_analyze_node_operations (vec_info *vinfo, 
slp_tree node,
            }
 
          /* Make sure we can generate them and then cost them.  */
-         unsigned nvectors;
-         if (!vect_get_num_copies_for_invariant (vinfo, node, &nvectors))
+         unsigned nvectors, excess_elts;
+         if (!vect_get_num_copies_for_invariant (vinfo, node, &nvectors,
+                                                 &excess_elts))
            return false;
          vect_prologue_cost_for_slp (child, nvectors, cost_vec);
        }
@@ -10908,9 +10915,10 @@ vect_create_constant_vectors (vec_info *vinfo, 
slp_tree op_node)
   /* We always want SLP_TREE_VECTYPE (op_node) here correctly set.  */
   vector_type = SLP_TREE_VECTYPE (op_node);
 
-  unsigned int number_of_vectors;
+  unsigned int number_of_vectors, excess_elts;
   bool res = vect_get_num_copies_for_invariant (vinfo, op_node,
-                                               &number_of_vectors);
+                                               &number_of_vectors,
+                                               &excess_elts);
   gcc_assert (res);
   SLP_TREE_VEC_DEFS (op_node).create (number_of_vectors);
   auto_vec<tree> voprnds (number_of_vectors);
@@ -10943,8 +10951,7 @@ vect_create_constant_vectors (vec_info *vinfo, slp_tree 
op_node)
   tree_vector_builder elts (vector_type, nunits, 1);
   elts.quick_grow (nunits);
   /* Zero-pad the last vector if necessary.  */
-  number_of_places_left_in_vector
-    = nunits - nunits * number_of_vectors % group_size;
+  number_of_places_left_in_vector = nunits - excess_elts;
   for (i = nunits; i > number_of_places_left_in_vector; --i)
     elts[i-1] = build_zero_cst (TREE_TYPE (vector_type));
   stmt_vec_info insert_after = NULL;
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index 4d542d57e6d..b3fe5acb60a 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -2790,7 +2790,7 @@ extern tree prepare_vec_mask (loop_vec_info, tree, tree, 
tree,
 extern tree vect_get_mask_load_else (int, tree);
 extern bool vect_load_perm_consecutive_p (slp_tree, unsigned = UINT_MAX);
 extern bool vect_get_num_copies_for_invariant (vec_info *, slp_tree,
-                                              unsigned *);
+                                              unsigned *, unsigned *);
 
 /* In tree-vect-patterns.cc.  */
 extern void
-- 
2.51.0

Reply via email to