This splits the core loop matching lanes from plumbing around it so
that the core loop fully populates matches[] and returns false only
on fatal errors.  The plumbing then handles soft-failing and unrelated
things like vector type computations.

        * tree-vect-slp.cc (vect_build_slp_tree_3): New function,
        split out from ...
        (vect_build_slp_tree_1): ... here.
---
 gcc/tree-vect-slp.cc | 158 ++++++++++++++++++++++++-------------------
 1 file changed, 87 insertions(+), 71 deletions(-)

diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc
index d8884fbd88a..660a4dddb09 100644
--- a/gcc/tree-vect-slp.cc
+++ b/gcc/tree-vect-slp.cc
@@ -1098,11 +1098,11 @@ compatible_calls_p (gcall *call1, gcall *call2, bool 
allow_two_operators)
 }
 
 /* Verify if the scalar stmts STMTS are isomorphic, require data
-   permutation or are of unsupported types of operation.  Return
-   true if they are, otherwise return false and indicate in *MATCHES
-   which stmts are not isomorphic to the first one.  If MATCHES[0]
-   is false then this indicates the comparison could not be
-   carried out or the stmts will never be vectorized by SLP.
+   permutation or are of unsupported types of operation.
+   Return false if at least one stmt is unvectorizable or the comparison
+   could not be carried out.
+   Return true if they all are and indicate in *MATCHES which stmts are
+   not isomorphic to the first one.
 
    Note COND_EXPR is possibly isomorphic to another one after swapping its
    operands.  Set SWAP[i] to 1 if stmt I is COND_EXPR and isomorphic to
@@ -1112,11 +1112,10 @@ compatible_calls_p (gcall *call1, gcall *call2, bool 
allow_two_operators)
    to (B1 <= A1 ? X1 : Y1); or be inverted to (A1 < B1) ? Y1 : X1.  */
 
 static bool
-vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap,
+vect_build_slp_tree_3 (vec_info *vinfo, unsigned char *swap,
                       vec<stmt_vec_info> stmts, bool *matches,
-                      bool *two_operators, tree *node_vectype)
+                      bool *two_operators, tree vectype)
 {
-  unsigned int group_size = stmts.length ();
   unsigned int i;
   stmt_vec_info first_stmt_info = stmts[0];
   code_helper first_stmt_code = ERROR_MARK;
@@ -1130,54 +1129,9 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char 
*swap,
   bool first_stmt_phi_p = false;
   int first_reduc_idx = -1;
 
-  tree vectype;
-  if (!vect_get_vector_types_for_stmt (vinfo, first_stmt_info, &vectype,
-                                      group_size))
-    {
-      /* Fatal mismatch.  */
-      matches[0] = false;
-      return false;
-    }
-  if (is_a <bb_vec_info> (vinfo)
-      && known_le (TYPE_VECTOR_SUBPARTS (vectype), 1U))
-    {
-      if (dump_enabled_p ())
-       dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
-                        "Build SLP failed: not using single lane "
-                        "vector type %T\n", vectype);
-      matches[0] = false;
-      return false;
-    }
-  /* Check nunits required but continue analysis, producing matches[]
-     as if nunits was not an issue.  This allows splitting of groups
-     to happen.  */
-  bool maybe_soft_fail = false;
-  unsigned HOST_WIDE_INT const_nunits = 0;
-  if (vectype
-      && is_a <bb_vec_info> (vinfo)
-      && !multiple_p (group_size, TYPE_VECTOR_SUBPARTS (vectype)))
-    {
-      if (dump_enabled_p ())
-       dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
-                        "Build SLP failed: unrolling required "
-                        "in basic block SLP\n");
-      if (!TYPE_VECTOR_SUBPARTS (vectype).is_constant (&const_nunits)
-         || const_nunits > group_size)
-       {
-         /* Fatal mismatch.  */
-         matches[0] = false;
-         return false;
-       }
-      maybe_soft_fail = true;
-    }
-
-  gcc_assert (vectype || !gimple_get_lhs (first_stmt_info->stmt));
-  *node_vectype = vectype;
-
   basic_block common_bb = gimple_bb (first_stmt_info->stmt);
   gimple *trapping_stmt = NULL;
 
-  /* For every stmt in NODE find its def stmt/s.  */
   stmt_vec_info stmt_info;
   FOR_EACH_VEC_ELT (stmts, i, stmt_info)
     {
@@ -1214,8 +1168,6 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char 
*swap,
             work for this though but it's the easiest we can do here.  */
          if (is_a <bb_vec_info> (vinfo) && i != 0)
            continue;
-         /* Fatal mismatch.  */
-         matches[0] = false;
           return false;
         }
 
@@ -1229,8 +1181,6 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char 
*swap,
                             "GIMPLE_CALL %G", stmt);
          if (is_a <bb_vec_info> (vinfo) && i != 0)
            continue;
-         /* Fatal mismatch.  */
-         matches[0] = false;
          return false;
        }
 
@@ -1276,8 +1226,6 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char 
*swap,
                                 (gimple *) call_stmt);
              if (is_a <bb_vec_info> (vinfo) && i != 0)
                continue;
-             /* Fatal mismatch.  */
-             matches[0] = false;
              return false;
            }
        }
@@ -1341,8 +1289,6 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char 
*swap,
                    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
                                     "Build SLP failed: "
                                     "BIT_FIELD_REF not supported\n");
-                 /* Fatal mismatch.  */
-                 matches[0] = false;
                  return false;
                }
            }
@@ -1567,8 +1513,6 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char 
*swap,
 
              if (i != 0)
                continue;
-             /* Fatal mismatch.  */
-             matches[0] = false;
              return false;
            }
        }
@@ -1592,8 +1536,6 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char 
*swap,
                                 stmt);
              if (is_a <bb_vec_info> (vinfo) && i != 0)
                continue;
-             /* Fatal mismatch.  */
-             matches[0] = false;
              return false;
            }
 
@@ -1667,15 +1609,9 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char 
*swap,
        dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
                         "Build SLP failed: not all stmts in same BB but "
                         "possibly trapping operation in %G", trapping_stmt);
-      /* Fatal mismatch.  */
-      matches[0] = false;
       return false;
     }
 
-  for (i = 0; i < group_size; ++i)
-    if (!matches[i])
-      return false;
-
   /* If we allowed a two-operation SLP node verify the target can cope
      with the permute we are going to use.  */
   if (alt_stmt_code != ERROR_MARK
@@ -1686,6 +1622,86 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char 
*swap,
       *two_operators = true;
     }
 
+  return true;
+}
+
+/* Verify if the scalar stmts STMTS are isomorphic, require data
+   permutation or are of unsupported types of operation.  Return
+   true if they are, otherwise return false and indicate in *MATCHES
+   which stmts are not isomorphic to the first one.  If MATCHES[0]
+   is false then this indicates the comparison could not be
+   carried out or the stmts will never be vectorized by SLP.
+
+   Note COND_EXPR is possibly isomorphic to another one after swapping its
+   operands.  Set SWAP[i] to 1 if stmt I is COND_EXPR and isomorphic to
+   the first stmt by swapping the two operands of comparison; set SWAP[i]
+   to 2 if stmt I is isormorphic to the first stmt by inverting the code
+   of comparison.  Take A1 >= B1 ? X1 : Y1 as an example, it can be swapped
+   to (B1 <= A1 ? X1 : Y1); or be inverted to (A1 < B1) ? Y1 : X1.  */
+
+static bool
+vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap,
+                      vec<stmt_vec_info> stmts, bool *matches,
+                      bool *two_operators, tree *node_vectype)
+{
+  stmt_vec_info first_stmt_info = stmts[0];
+  unsigned int group_size = stmts.length ();
+  tree vectype;
+  if (!vect_get_vector_types_for_stmt (vinfo, first_stmt_info, &vectype,
+                                      group_size))
+    {
+      /* Fatal mismatch.  */
+      matches[0] = false;
+      return false;
+    }
+  if (is_a <bb_vec_info> (vinfo)
+      && known_le (TYPE_VECTOR_SUBPARTS (vectype), 1U))
+    {
+      if (dump_enabled_p ())
+       dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+                        "Build SLP failed: not using single lane "
+                        "vector type %T\n", vectype);
+      matches[0] = false;
+      return false;
+    }
+  /* Check nunits required but continue analysis, producing matches[]
+     as if nunits was not an issue.  This allows splitting of groups
+     to happen.  */
+  bool maybe_soft_fail = false;
+  unsigned HOST_WIDE_INT const_nunits = 0;
+  if (vectype
+      && is_a <bb_vec_info> (vinfo)
+      && !multiple_p (group_size, TYPE_VECTOR_SUBPARTS (vectype)))
+    {
+      if (dump_enabled_p ())
+       dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+                        "Build SLP failed: unrolling required "
+                        "in basic block SLP\n");
+      if (!TYPE_VECTOR_SUBPARTS (vectype).is_constant (&const_nunits)
+         || const_nunits > group_size)
+       {
+         /* Fatal mismatch.  */
+         matches[0] = false;
+         return false;
+       }
+      maybe_soft_fail = true;
+    }
+
+  gcc_assert (vectype || !gimple_get_lhs (first_stmt_info->stmt));
+  *node_vectype = vectype;
+
+  if (!vect_build_slp_tree_3 (vinfo, swap, stmts, matches, two_operators,
+                             vectype))
+    {
+      /* Fatal mismatch.  */
+      matches[0] = false;
+      return false;
+    }
+
+  for (unsigned i = 0; i < group_size; ++i)
+    if (!matches[i])
+      return false;
+
   if (maybe_soft_fail)
     {
       /* With constant vector elements simulate a mismatch at the
-- 
2.51.0

Reply via email to