Hi All,

The complex FMS detection is missing a check on if the nodes of the VEC_PERM
has the amount of children we expect before it recurses.

This check is there on MUL and FMA but was missing for FMS, due to this the
compiler goes on further than it should and hits an assert.

Bootstrapped Regtested on aarch64-none-linux-gnu, x86_64-pc-linux-gnu
and no issues.

Ok for master?

Thanks,
Tamar

gcc/ChangeLog:

        PR tree-optimizations/103007
        * tree-vect-slp-patterns.c (complex_fms_pattern::matches): Add elem
        check.

gcc/testsuite/ChangeLog:

        PR tree-optimizations/103007
        * g++.dg/pr103007.C: New test.

--- inline copy of patch -- 
diff --git a/gcc/testsuite/g++.dg/pr103007.C b/gcc/testsuite/g++.dg/pr103007.C
new file mode 100644
index 
0000000000000000000000000000000000000000..1631a85080039f29b83c97d2f62c66be9eac109f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr103007.C
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O3" } */
+
+typedef float MushMeshVector[4];
+struct MushMeshQuaternionPair {
+  void VectorRotate(MushMeshVector &);
+  MushMeshVector m_first;
+  MushMeshVector m_second;
+};
+void 
+MushMeshQuaternionPair::
+VectorRotate(MushMeshVector &ioVec)  {
+  ioVec[2] = (2 - m_first[1] + m_first[3] * 0);
+  ioVec[3] = (m_first[3] + m_first[1] - m_first[2] * 0);
+  float c = ioVec[2], d = ioVec[3];
+  ioVec[2] = (0 - d * m_second[1]);
+  ioVec[3] = (2 - c * m_second[1]);
+}
+
diff --git a/gcc/tree-vect-slp-patterns.c b/gcc/tree-vect-slp-patterns.c
index 
6b37e9bac6f3f86a51d1a532a4c570a37af76eac..5e64a9bc417ab6b855e8791fd482dba23287f467
 100644
--- a/gcc/tree-vect-slp-patterns.c
+++ b/gcc/tree-vect-slp-patterns.c
@@ -1250,13 +1250,17 @@ complex_fms_pattern::matches (complex_operation_t op,
 
   auto childs = SLP_TREE_CHILDREN (nodes[0]);
   auto l0node = SLP_TREE_CHILDREN (childs[0]);
-  auto l1node = SLP_TREE_CHILDREN (childs[1]);
 
   /* Now operand2+4 may lead to another expression.  */
   auto_vec<slp_tree> left_op, right_op;
   left_op.safe_splice (SLP_TREE_CHILDREN (l0node[1]));
   right_op.safe_splice (SLP_TREE_CHILDREN (nodes[1]));
 
+  /* If these nodes don't have any children then they're
+     not ones we're interested in.  */
+  if (left_op.length () != 2 || right_op.length () != 2)
+    return IFN_LAST;
+
   bool is_neg = vect_normalize_conj_loc (left_op);
 
   bool conj_first_operand = false;


-- 
diff --git a/gcc/testsuite/g++.dg/pr103007.C b/gcc/testsuite/g++.dg/pr103007.C
new file mode 100644
index 0000000000000000000000000000000000000000..1631a85080039f29b83c97d2f62c66be9eac109f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr103007.C
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O3" } */
+
+typedef float MushMeshVector[4];
+struct MushMeshQuaternionPair {
+  void VectorRotate(MushMeshVector &);
+  MushMeshVector m_first;
+  MushMeshVector m_second;
+};
+void 
+MushMeshQuaternionPair::
+VectorRotate(MushMeshVector &ioVec)  {
+  ioVec[2] = (2 - m_first[1] + m_first[3] * 0);
+  ioVec[3] = (m_first[3] + m_first[1] - m_first[2] * 0);
+  float c = ioVec[2], d = ioVec[3];
+  ioVec[2] = (0 - d * m_second[1]);
+  ioVec[3] = (2 - c * m_second[1]);
+}
+
diff --git a/gcc/tree-vect-slp-patterns.c b/gcc/tree-vect-slp-patterns.c
index 6b37e9bac6f3f86a51d1a532a4c570a37af76eac..5e64a9bc417ab6b855e8791fd482dba23287f467 100644
--- a/gcc/tree-vect-slp-patterns.c
+++ b/gcc/tree-vect-slp-patterns.c
@@ -1250,13 +1250,17 @@ complex_fms_pattern::matches (complex_operation_t op,
 
   auto childs = SLP_TREE_CHILDREN (nodes[0]);
   auto l0node = SLP_TREE_CHILDREN (childs[0]);
-  auto l1node = SLP_TREE_CHILDREN (childs[1]);
 
   /* Now operand2+4 may lead to another expression.  */
   auto_vec<slp_tree> left_op, right_op;
   left_op.safe_splice (SLP_TREE_CHILDREN (l0node[1]));
   right_op.safe_splice (SLP_TREE_CHILDREN (nodes[1]));
 
+  /* If these nodes don't have any children then they're
+     not ones we're interested in.  */
+  if (left_op.length () != 2 || right_op.length () != 2)
+    return IFN_LAST;
+
   bool is_neg = vect_normalize_conj_loc (left_op);
 
   bool conj_first_operand = false;

Reply via email to