The EXTRACT_LAST_REDUCTION code isn't ready to deal with multiple stmt
copies but SLP no longer checks for this.  The following adjusts
code generation to handle the situation.

Bootstrap and regtest running on x86_64-unknown-linux-gnu.

Testing on aarch64 appreciated, note the testcase in the testsuite
likely doesn't exercise .FOLD_EXTRACT_LAST with default opts,
the PR asks for a SVE capable CPU but fixed-length vectorization.

        PR tree-optimization/115383
        * tree-vect-stmts.cc (vectorizable_condition): Handle
        generating a chain of .FOLD_EXTRACT_LAST.

        * gcc.dg/vect/pr115383.c: New testcase.
---
 gcc/testsuite/gcc.dg/vect/pr115383.c | 20 ++++++++++++++++++++
 gcc/tree-vect-stmts.cc               | 20 +++++++++++++++-----
 2 files changed, 35 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/vect/pr115383.c

diff --git a/gcc/testsuite/gcc.dg/vect/pr115383.c 
b/gcc/testsuite/gcc.dg/vect/pr115383.c
new file mode 100644
index 00000000000..92c24699146
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr115383.c
@@ -0,0 +1,20 @@
+#include "tree-vect.h"
+
+int __attribute__((noipa))
+s331 (int i, int n)
+{
+  int j = 0;
+  for (; i < n; i++)
+    if ((float)i < 0.)
+      j = i;
+  return j;
+}
+
+int main()
+{
+  check_vect ();
+  int j = s331(-13, 17);
+  if (j != -1)
+    abort ();
+  return 0;
+}
diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc
index 69ba906a33f..0a76e81a0ea 100644
--- a/gcc/tree-vect-stmts.cc
+++ b/gcc/tree-vect-stmts.cc
@@ -12413,6 +12413,9 @@ vectorizable_condition (vec_info *vinfo,
                       reduction_type != EXTRACT_LAST_REDUCTION
                       ? else_clause : NULL, vectype, &vec_oprnds3);
 
+  if (reduction_type == EXTRACT_LAST_REDUCTION)
+    vec_else_clause = else_clause;
+
   /* Arguments are ready.  Create the new vector stmt.  */
   FOR_EACH_VEC_ELT (vec_oprnds0, i, vec_cond_lhs)
     {
@@ -12555,17 +12558,24 @@ vectorizable_condition (vec_info *vinfo,
        {
          gimple *old_stmt = vect_orig_stmt (stmt_info)->stmt;
          tree lhs = gimple_get_lhs (old_stmt);
+         if ((unsigned)i != vec_oprnds0.length () - 1)
+           lhs = copy_ssa_name (lhs);
          if (len)
            new_stmt = gimple_build_call_internal
-               (IFN_LEN_FOLD_EXTRACT_LAST, 5, else_clause, vec_compare,
-                vec_then_clause, len, bias);
+               (IFN_LEN_FOLD_EXTRACT_LAST, 5, vec_else_clause, vec_compare,
+                vec_then_clause, len, bias);
          else
            new_stmt = gimple_build_call_internal
-               (IFN_FOLD_EXTRACT_LAST, 3, else_clause, vec_compare,
-                vec_then_clause);
+               (IFN_FOLD_EXTRACT_LAST, 3, vec_else_clause, vec_compare,
+                vec_then_clause);
          gimple_call_set_lhs (new_stmt, lhs);
          SSA_NAME_DEF_STMT (lhs) = new_stmt;
-         if (old_stmt == gsi_stmt (*gsi))
+         if ((unsigned)i != vec_oprnds0.length () - 1)
+           {
+             vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
+             vec_else_clause = lhs;
+           }
+         else if (old_stmt == gsi_stmt (*gsi))
            vect_finish_replace_stmt (vinfo, stmt_info, new_stmt);
          else
            {
-- 
2.35.3

Reply via email to