The following fixes an issue with wrong loop mask registering
due to the costing code adjusting ncopies_for_cost before we
use it for mask registering.
Bootstrapped on aarch64-linux, testing in progress. Will push when
that succeeded.
Richard.
PR tree-optimization/127310
* tree-vect-loop.cc (vectorizable_lane_reducing): Apply
costing after registering loop masks.
* gcc.dg/vect/vect-pr127310.c: New testcase.
---
gcc/testsuite/gcc.dg/vect/vect-pr127310.c | 29 +++++++++++++++++
gcc/tree-vect-loop.cc | 38 +++++++++++------------
2 files changed, 48 insertions(+), 19 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/vect/vect-pr127310.c
diff --git a/gcc/testsuite/gcc.dg/vect/vect-pr127310.c
b/gcc/testsuite/gcc.dg/vect/vect-pr127310.c
new file mode 100644
index 00000000000..815b631c065
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-pr127310.c
@@ -0,0 +1,29 @@
+/* { dg-additional-options "-march=armv8-a+sve" { target aarch64_sve_hw } } */
+
+#include "tree-vect.h"
+
+__attribute__ ((noipa)) unsigned int
+mixed_dot_induction (unsigned int n)
+{
+ unsigned int sum = 0;
+ for (unsigned int i = 0; i < n; ++i)
+ sum += (signed char) i * (unsigned char) (i * 17 + 3);
+ return sum;
+}
+
+int
+main ()
+{
+ unsigned int expected = 0;
+ check_vect ();
+#pragma GCC novector
+ for (unsigned int n = 0; n <= 1025; ++n)
+ {
+ if (mixed_dot_induction (n) != expected)
+ __builtin_abort ();
+ int x = (int) (n & 127) - (int) (n & 128);
+ int y = (n * 17 + 3) & 255;
+ expected += x * y;
+ }
+ return 0;
+}
diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc
index 78c6bce0dfe..c0862577cf8 100644
--- a/gcc/tree-vect-loop.cc
+++ b/gcc/tree-vect-loop.cc
@@ -6871,25 +6871,6 @@ vectorizable_lane_reducing (loop_vec_info loop_vinfo,
stmt_vec_info stmt_info,
}
gcc_assert (ncopies_for_cost >= 1);
- if (vect_is_emulated_mixed_dot_prod (slp_node))
- {
- /* We need extra two invariants: one that contains the minimum signed
- value and one that contains half of its negative. */
- int prologue_stmts = 2;
- unsigned cost = record_stmt_cost (cost_vec, prologue_stmts,
- scalar_to_vec, slp_node, 0,
- vect_prologue);
- if (dump_enabled_p ())
- dump_printf (MSG_NOTE, "vectorizable_lane_reducing: "
- "extra prologue_cost = %d .\n", cost);
-
- /* Three dot-products and a subtraction. */
- ncopies_for_cost *= 4;
- }
-
- record_stmt_cost (cost_vec, (int) ncopies_for_cost, vector_stmt, slp_node,
- 0, vect_body);
-
if (LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo))
{
enum tree_code code = gimple_assign_rhs_code (stmt);
@@ -6910,6 +6891,25 @@ vectorizable_lane_reducing (loop_vec_info loop_vinfo,
stmt_vec_info stmt_info,
}
}
+ if (vect_is_emulated_mixed_dot_prod (slp_node))
+ {
+ /* We need extra two invariants: one that contains the minimum signed
+ value and one that contains half of its negative. */
+ int prologue_stmts = 2;
+ unsigned cost = record_stmt_cost (cost_vec, prologue_stmts,
+ scalar_to_vec, slp_node, 0,
+ vect_prologue);
+ if (dump_enabled_p ())
+ dump_printf (MSG_NOTE, "vectorizable_lane_reducing: "
+ "extra prologue_cost = %d .\n", cost);
+
+ /* Three dot-products and a subtraction. */
+ ncopies_for_cost *= 4;
+ }
+
+ record_stmt_cost (cost_vec, (int) ncopies_for_cost, vector_stmt, slp_node,
+ 0, vect_body);
+
/* Transform via vect_transform_reduction. */
SLP_TREE_TYPE (slp_node) = reduc_vec_info_type;
return true;
--
2.51.0