The following avoids using vect_get_num_copies on the SLP input
from vectorizable_lane_reducing which is in this case used
for costing. The transform phase will simply look at the actual
number of vector inputs code generated, but for costing we
can use vect_get_num_copies_for_invariant which is exported with
the patch. It must be possible to compute the number from
the number of vector outputs, the number of SLP lanes and the
width of the elements involved, but given what the transform
phase does this matches it exactly.
PR tree-optimization/126998
* tree-vectorizer.h (vect_get_num_copies_for_invariant):
Declare.
* tree-vect-slp.cc (vect_get_num_copies_for_invariant): Export.
* tree-vect-loop.cc (vectorizable_lane_reducing): Use
vect_get_num_copies_for_invariant on the SLP input.
* gcc.dg/vect/vect-reduc-dot-pr126998.c: New testcase.
---
.../gcc.dg/vect/vect-reduc-dot-pr126998.c | 36 +++++++++++++++++++
gcc/tree-vect-loop.cc | 9 +++--
gcc/tree-vect-slp.cc | 2 +-
gcc/tree-vectorizer.h | 2 ++
4 files changed, 45 insertions(+), 4 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/vect/vect-reduc-dot-pr126998.c
diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-pr126998.c
b/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-pr126998.c
new file mode 100644
index 00000000000..958ac5dbcc6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-pr126998.c
@@ -0,0 +1,36 @@
+/* { dg-additional-options "-O3" } */
+
+#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 590d8477c96..20397e6f783 100644
--- a/gcc/tree-vect-loop.cc
+++ b/gcc/tree-vect-loop.cc
@@ -6852,9 +6852,12 @@ vectorizable_lane_reducing (loop_vec_info loop_vinfo,
stmt_vec_info stmt_info,
tree vectype_in = SLP_TREE_VECTYPE (node_in);
gcc_assert (vectype_in);
- /* Compute number of effective vector statements for costing. */
- unsigned int ncopies_for_cost = vect_get_num_copies (loop_vinfo, node_in);
- gcc_assert (ncopies_for_cost >= 1);
+ /* 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;
+ bool res = vect_get_num_copies_for_invariant (loop_vinfo, slp_node,
+ &ncopies_for_cost);
+ 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 492562bd631..97a6c8e1e0a 100644
--- a/gcc/tree-vect-slp.cc
+++ b/gcc/tree-vect-slp.cc
@@ -8992,7 +8992,7 @@ vect_scalar_ops_slice_hash::equal (const value_type &s1,
excess elements in the last vector. Returns false if *NVECTORS
cannot be computed. */
-static bool
+bool
vect_get_num_copies_for_invariant (vec_info *vinfo, slp_tree node,
unsigned *nvectors)
{
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index d21f132a9e5..4d542d57e6d 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -2789,6 +2789,8 @@ extern tree prepare_vec_mask (loop_vec_info, tree, tree,
tree,
gimple_stmt_iterator *);
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 *);
/* In tree-vect-patterns.cc. */
extern void
--
2.51.0