tree-optimization/125185 - fix ICE with associating DOT_PROD_EXPR

Message ID 20260505084855.728174B9DB4A@sourceware.org
State New
Headers
Series tree-optimization/125185 - fix ICE with associating DOT_PROD_EXPR |

Commit Message

Richard Biener May 5, 2026, 8:47 a.m. UTC
  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
  

Patch

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