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

Reply via email to