https://gcc.gnu.org/g:c1429e3a8da0cdfe9391e1e9b2c7228d896a3a87

commit r15-1126-gc1429e3a8da0cdfe9391e1e9b2c7228d896a3a87
Author: Richard Biener <rguent...@suse.de>
Date:   Fri Jun 7 12:15:31 2024 +0200

    tree-optimization/115383 - EXTRACT_LAST_REDUCTION with multiple stmt copies
    
    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.
    
            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.

Diff:
---
 gcc/testsuite/gcc.dg/vect/pr115383.c | 20 ++++++++++++++++++++
 gcc/tree-vect-stmts.cc               | 20 +++++++++++++++-----
 2 files changed, 35 insertions(+), 5 deletions(-)

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 5098b7fab6a..05a169ecb2d 100644
--- a/gcc/tree-vect-stmts.cc
+++ b/gcc/tree-vect-stmts.cc
@@ -12415,6 +12415,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)
     {
@@ -12557,17 +12560,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
            {

Reply via email to