The following makes sure to special-case VEC_PERM nodes when
comparing complex nodes.  When they still had a representative
we ended up comparing random operations (oops).

Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed.

        PR tree-optimization/126979
        * tree-vect-slp-patterns.cc (compatible_complex_nodes_p):
        Special case VEC_PERM nodes.
---
 gcc/tree-vect-slp-patterns.cc | 113 ++++++++++++++++++----------------
 1 file changed, 60 insertions(+), 53 deletions(-)

diff --git a/gcc/tree-vect-slp-patterns.cc b/gcc/tree-vect-slp-patterns.cc
index 2ff7ce2699f..bf9efacf161 100644
--- a/gcc/tree-vect-slp-patterns.cc
+++ b/gcc/tree-vect-slp-patterns.cc
@@ -763,70 +763,77 @@ compatible_complex_nodes_p (slp_compat_nodes_map_t 
*compat_cache,
       return true;
     }
 
-  auto a_stmt = STMT_VINFO_STMT (SLP_TREE_REPRESENTATIVE (a));
-  auto b_stmt = STMT_VINFO_STMT (SLP_TREE_REPRESENTATIVE (b));
-
-  if (gimple_code (a_stmt) != gimple_code (b_stmt))
-    return false;
-
-  /* code, children, type, externals, loads, constants  */
-  if (gimple_num_args (a_stmt) != gimple_num_args (b_stmt))
-    return false;
-
-  /* At this point, a and b are known to be the same gimple operations.  */
-  if (is_gimple_call (a_stmt))
-    {
-       if (!compatible_calls_p (dyn_cast <gcall *> (a_stmt),
-                                dyn_cast <gcall *> (b_stmt), false))
-         return false;
-    }
-  else if (!is_gimple_assign (a_stmt))
+  if (SLP_TREE_PERMUTE_P (a) != SLP_TREE_PERMUTE_P (b))
     return false;
+  else if (SLP_TREE_PERMUTE_P (a))
+    ;
   else
     {
-      tree_code acode = gimple_assign_rhs_code (a_stmt);
-      tree_code bcode = gimple_assign_rhs_code (b_stmt);
-      if ((acode == REALPART_EXPR || acode == IMAGPART_EXPR)
-         && (bcode == REALPART_EXPR || bcode == IMAGPART_EXPR)
-         && operand_equal_p (TREE_OPERAND (gimple_assign_rhs1 (a_stmt), 0),
-                             TREE_OPERAND (gimple_assign_rhs1 (b_stmt), 0)))
-       return true;
-
-      if (acode != bcode)
+      auto a_stmt = STMT_VINFO_STMT (SLP_TREE_REPRESENTATIVE (a));
+      auto b_stmt = STMT_VINFO_STMT (SLP_TREE_REPRESENTATIVE (b));
+
+      if (gimple_code (a_stmt) != gimple_code (b_stmt))
        return false;
-    }
 
-  if (!STMT_VINFO_DATA_REF (SLP_TREE_REPRESENTATIVE (a))
-      || !STMT_VINFO_DATA_REF (SLP_TREE_REPRESENTATIVE (b)))
-    {
-      for (unsigned i = 0; i < gimple_num_args (a_stmt); i++)
+      /* code, children, type, externals, loads, constants  */
+      if (gimple_num_args (a_stmt) != gimple_num_args (b_stmt))
+       return false;
+
+      /* At this point, a and b are known to be the same gimple operations.  */
+      if (is_gimple_call (a_stmt))
        {
-         tree t1 = gimple_arg (a_stmt, i);
-         tree t2 = gimple_arg (b_stmt, i);
-         if (TREE_CODE (t1) != TREE_CODE (t2))
+         if (!compatible_calls_p (dyn_cast <gcall *> (a_stmt),
+                                  dyn_cast <gcall *> (b_stmt), false))
            return false;
+       }
+      else if (!is_gimple_assign (a_stmt))
+       return false;
+      else
+       {
+         tree_code acode = gimple_assign_rhs_code (a_stmt);
+         tree_code bcode = gimple_assign_rhs_code (b_stmt);
+         if ((acode == REALPART_EXPR || acode == IMAGPART_EXPR)
+             && (bcode == REALPART_EXPR || bcode == IMAGPART_EXPR)
+             && operand_equal_p (TREE_OPERAND (gimple_assign_rhs1 (a_stmt), 0),
+                                 TREE_OPERAND (gimple_assign_rhs1 (b_stmt), 
0)))
+           return true;
+
+         if (acode != bcode)
+           return false;
+       }
 
-         /* If SSA name then we will need to inspect the children
-            so we can punt here.  */
-         if (TREE_CODE (t1) == SSA_NAME)
-           continue;
-
-         if (!operand_equal_p (t1, t2, 0))
+      if (!STMT_VINFO_DATA_REF (SLP_TREE_REPRESENTATIVE (a))
+         || !STMT_VINFO_DATA_REF (SLP_TREE_REPRESENTATIVE (b)))
+       {
+         for (unsigned i = 0; i < gimple_num_args (a_stmt); i++)
+           {
+             tree t1 = gimple_arg (a_stmt, i);
+             tree t2 = gimple_arg (b_stmt, i);
+             if (TREE_CODE (t1) != TREE_CODE (t2))
+               return false;
+
+             /* If SSA name then we will need to inspect the children
+                so we can punt here.  */
+             if (TREE_CODE (t1) == SSA_NAME)
+               continue;
+
+             if (!operand_equal_p (t1, t2, 0))
+               return false;
+           }
+       }
+      else
+       {
+         auto dr1 = STMT_VINFO_DATA_REF (SLP_TREE_REPRESENTATIVE (a));
+         auto dr2 = STMT_VINFO_DATA_REF (SLP_TREE_REPRESENTATIVE (b));
+         /* Don't check the last dimension as that's checked by the lineary
+            checks.  This check is also much stricter than what we need
+            because it doesn't consider loading from adjacent elements
+            in the same struct as loading from the same base object.
+            But for now, I'll play it safe.  */
+         if (!same_data_refs (dr1, dr2, 1))
            return false;
        }
     }
-  else
-    {
-      auto dr1 = STMT_VINFO_DATA_REF (SLP_TREE_REPRESENTATIVE (a));
-      auto dr2 = STMT_VINFO_DATA_REF (SLP_TREE_REPRESENTATIVE (b));
-      /* Don't check the last dimension as that's checked by the lineary
-        checks.  This check is also much stricter than what we need
-        because it doesn't consider loading from adjacent elements
-        in the same struct as loading from the same base object.
-        But for now, I'll play it safe.  */
-      if (!same_data_refs (dr1, dr2, 1))
-       return false;
-    }
 
   for (unsigned i = 0; i < SLP_TREE_CHILDREN (a).length (); i++)
     {
-- 
2.51.0

Reply via email to