When trying to discover a SLP reduction chain we eventually feed
non-binary associatable stmts to vect_slp_linearize_chain which
isn't prepared for that.  Don't.

Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.

        PR tree-optimization/125185
        * tree-vect-slp.cc (vect_analyze_slp_reduc_chain): Guard
        first vect_slp_linearize_chain call.

        * gcc.dg/torture/pr125185.c: New testcase.
---
 gcc/testsuite/gcc.dg/torture/pr125185.c | 13 ++++++
 gcc/tree-vect-slp.cc                    | 53 ++++++++++++++-----------
 2 files changed, 43 insertions(+), 23 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr125185.c

diff --git a/gcc/testsuite/gcc.dg/torture/pr125185.c 
b/gcc/testsuite/gcc.dg/torture/pr125185.c
new file mode 100644
index 00000000000..370cc0139e4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr125185.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-ftree-vectorize" } */
+/* { dg-additional-options "-mxop" { target { x86_64-*-* || i?86-*-* } } } */
+
+long sum;
+int *coef1;
+
+void ac3_sum_square_butterfly_int32_c(int i, int cap) {
+  for (; i < cap; i++) {
+    int md = i + coef1[i];
+    sum += (long)md * md;
+  }
+}
diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc
index 40ddae3526b..7be8ca03763 100644
--- a/gcc/tree-vect-slp.cc
+++ b/gcc/tree-vect-slp.cc
@@ -4356,32 +4356,39 @@ vect_analyze_slp_reduc_chain (loop_vec_info vinfo,
       auto_vec<chain_op_t> chain;
       auto_vec<std::pair<tree_code, gimple *> > worklist;
       gimple *op_stmt = NULL, *other_op_stmt = NULL;
-      vect_slp_linearize_chain (vinfo, worklist, chain, (tree_code)code,
-                               scalar_stmts[0]->stmt, op_stmt, other_op_stmt,
-                               NULL);
-
-      scalar_stmts.truncate (0);
-      stmt_vec_info tail = NULL;
-      for (auto el : chain)
+      if (is_a <gassign *> (scalar_stmts[0]->stmt)
+         /* We cannot linearize an operation that vect_slp_linearize_chain
+            would not put on its worklist.  */
+         && gimple_assign_rhs_code (scalar_stmts[0]->stmt) == (tree_code)code)
        {
-         if (el.dt == vect_external_def
-             || el.dt == vect_constant_def
-             || el.code != (tree_code) code)
-           {
-             scalar_stmts.release ();
-             return false;
-           }
-         stmt_vec_info stmt = vinfo->lookup_def (el.op);
-         if (STMT_VINFO_REDUC_IDX (stmt) != -1
-             || STMT_VINFO_REDUC_DEF (stmt))
+         vect_slp_linearize_chain (vinfo, worklist, chain, (tree_code)code,
+                                   scalar_stmts[0]->stmt, op_stmt,
+                                   other_op_stmt,
+                                   NULL);
+
+         scalar_stmts.truncate (0);
+         stmt_vec_info tail = NULL;
+         for (auto el : chain)
            {
-             gcc_assert (tail == NULL);
-             tail = stmt;
-             continue;
+             if (el.dt == vect_external_def
+                 || el.dt == vect_constant_def
+                 || el.code != (tree_code) code)
+               {
+                 scalar_stmts.release ();
+                 return false;
+               }
+             stmt_vec_info stmt = vinfo->lookup_def (el.op);
+             if (STMT_VINFO_REDUC_IDX (stmt) != -1
+                 || STMT_VINFO_REDUC_DEF (stmt))
+               {
+                 gcc_assert (tail == NULL);
+                 tail = stmt;
+                 continue;
+               }
+             scalar_stmts.safe_push (stmt);
            }
-         scalar_stmts.safe_push (stmt);
+         gcc_assert (tail);
        }
-      gcc_assert (tail);
 
       /* When this linearization didn't produce a chain see if stripping
         a wrapping sign conversion produces one.  */
@@ -4411,7 +4418,7 @@ vect_analyze_slp_reduc_chain (loop_vec_info vinfo,
                                    stmt, op_stmt, other_op_stmt, NULL);
 
          scalar_stmts.truncate (0);
-         tail = NULL;
+         stmt_vec_info tail = NULL;
          for (auto el : chain)
            {
              if (el.dt == vect_external_def
-- 
2.51.0

Reply via email to