This refactors vect_get_and_check_slp_defs so that the ops and def_stmts
arrays are filled for all stmts and operands even when we signal failure.
This allows later changes for BB vectorization SLP discovery heuristics.

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

2020-10-16  Richard Biener  <rguent...@suse.de>

        * tree-vect-slp.c (vect_get_and_check_slp_defs): First analyze
        all operands and fill in the def_stmts and ops entries.
        (vect_def_types_match): New helper.
---
 gcc/tree-vect-slp.c | 141 ++++++++++++++++++++++++++------------------
 1 file changed, 82 insertions(+), 59 deletions(-)

diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index 8037b27cddd..cfb79e2651f 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -356,6 +356,16 @@ can_duplicate_and_interleave_p (vec_info *vinfo, unsigned 
int count,
     }
 }
 
+/* Return true if DTA and DTB match.  */
+
+static bool
+vect_def_types_match (enum vect_def_type dta, enum vect_def_type dtb)
+{
+  return (dta == dtb
+         || ((dta == vect_external_def || dta == vect_constant_def)
+             && (dtb == vect_external_def || dtb == vect_constant_def)));
+}
+
 /* Get the defs for the rhs of STMT (collect them in OPRNDS_INFO), check that
    they are of a valid type and that they match the defs of the first stmt of
    the SLP group (stored in OPRNDS_INFO).  This function tries to match stmts
@@ -421,9 +431,9 @@ vect_get_and_check_slp_defs (vec_info *vinfo, unsigned char 
swap,
 
   bool swapped = (swap != 0);
   gcc_assert (!swapped || first_op_cond);
+  enum vect_def_type *dts = XALLOCAVEC (enum vect_def_type, number_of_oprnds);
   for (i = 0; i < number_of_oprnds; i++)
     {
-again:
       if (first_op_cond)
        {
          /* Map indicating how operands of cond_expr should be swapped.  */
@@ -444,7 +454,7 @@ again:
       oprnd_info = (*oprnds_info)[i];
 
       stmt_vec_info def_stmt_info;
-      if (!vect_is_simple_use (oprnd, vinfo, &dt, &def_stmt_info))
+      if (!vect_is_simple_use (oprnd, vinfo, &dts[i], &def_stmt_info))
        {
          if (dump_enabled_p ())
            dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -457,9 +467,13 @@ again:
       if (def_stmt_info && is_pattern_stmt_p (def_stmt_info))
        oprnd_info->any_pattern = true;
 
-      tree type = TREE_TYPE (oprnd);
+      oprnd_info->def_stmts.quick_push (def_stmt_info);
+      oprnd_info->ops.quick_push (oprnd);
+
       if (first)
        {
+         tree type = TREE_TYPE (oprnd);
+         dt = dts[i];
          if ((dt == vect_constant_def
               || dt == vect_external_def)
              && !GET_MODE_SIZE (vinfo->vector_mode).is_constant ()
@@ -480,14 +494,48 @@ again:
              && REDUC_GROUP_FIRST_ELEMENT (stmt_info)
              && (int)i == STMT_VINFO_REDUC_IDX (stmt_info)
              && def_stmt_info)
-           dt = vect_reduction_def;
+           dts[i] = dt = vect_reduction_def;
+
+         /* Check the types of the definition.  */
+         switch (dt)
+           {
+           case vect_external_def:
+           case vect_constant_def:
+           case vect_internal_def:
+           case vect_reduction_def:
+           case vect_induction_def:
+             break;
+
+           default:
+             /* FORNOW: Not supported.  */
+             if (dump_enabled_p ())
+               dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+                                "Build SLP failed: illegal type of def %T\n",
+                                oprnd);
+             return -1;
+           }
+
          oprnd_info->first_dt = dt;
          oprnd_info->first_op_type = type;
        }
-      else
-       {
+    }
+  if (first)
+    return 0;
+
+  /* Now match the operand definition types to that of the first stmt.  */
+  for (i = 0; i < number_of_oprnds;)
+    {
+      oprnd_info = (*oprnds_info)[i];
+      dt = dts[i];
+      stmt_vec_info def_stmt_info = oprnd_info->def_stmts[stmt_num];
+      oprnd = oprnd_info->ops[stmt_num];
+      tree type = TREE_TYPE (oprnd);
+
          if (!types_compatible_p (oprnd_info->first_op_type, type))
            {
+             gcc_assert ((i != commutative_op
+                          && (commutative_op == -1U
+                              || i != commutative_op + 1)));
              if (dump_enabled_p ())
                dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
                                 "Build SLP failed: different operand types\n");
@@ -499,18 +547,14 @@ again:
             types for reduction chains: the first stmt must be a
             vect_reduction_def (a phi node), and the rest
             end in the reduction chain.  */
-         if ((oprnd_info->first_dt != dt
+         if ((!vect_def_types_match (oprnd_info->first_dt, dt)
               && !(oprnd_info->first_dt == vect_reduction_def
                    && !STMT_VINFO_DATA_REF (stmt_info)
                    && REDUC_GROUP_FIRST_ELEMENT (stmt_info)
                    && def_stmt_info
                    && !STMT_VINFO_DATA_REF (def_stmt_info)
                    && (REDUC_GROUP_FIRST_ELEMENT (def_stmt_info)
-                       == REDUC_GROUP_FIRST_ELEMENT (stmt_info)))
-              && !((oprnd_info->first_dt == vect_external_def
-                    || oprnd_info->first_dt == vect_constant_def)
-                   && (dt == vect_external_def
-                       || dt == vect_constant_def)))
+                       == REDUC_GROUP_FIRST_ELEMENT (stmt_info))))
              || (!STMT_VINFO_DATA_REF (stmt_info)
                  && REDUC_GROUP_FIRST_ELEMENT (stmt_info)
                  && ((!def_stmt_info
@@ -519,69 +563,48 @@ again:
                           != REDUC_GROUP_FIRST_ELEMENT (stmt_info)))
                      != (oprnd_info->first_dt != vect_reduction_def))))
            {
-             /* Try swapping operands if we got a mismatch.  */
+             /* Try swapping operands if we got a mismatch.  For BB
+                vectorization only in case that will improve things.  */
              if (i == commutative_op && !swapped)
                {
                  if (dump_enabled_p ())
                    dump_printf_loc (MSG_NOTE, vect_location,
                                     "trying swapped operands\n");
+                 std::swap (dts[i], dts[i+1]);
+                 std::swap ((*oprnds_info)[i]->def_stmts[stmt_num],
+                            (*oprnds_info)[i+1]->def_stmts[stmt_num]);
+                 std::swap ((*oprnds_info)[i]->ops[stmt_num],
+                            (*oprnds_info)[i+1]->ops[stmt_num]);
                  swapped = true;
-                 goto again;
+                 continue;
                }
 
              if (dump_enabled_p ())
                dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
                                 "Build SLP failed: different types\n");
-
              return 1;
            }
-       }
 
-      /* Check the types of the definitions.  */
-      switch (dt)
+      /* Make sure to demote the overall operand to external.  */
+      if (dt == vect_external_def)
+       oprnd_info->first_dt = vect_external_def;
+      /* For a SLP reduction chain we want to duplicate the reduction to
+        each of the chain members.  That gets us a sane SLP graph (still
+        the stmts are not 100% correct wrt the initial values).  */
+      else if ((dt == vect_internal_def
+               || dt == vect_reduction_def)
+              && oprnd_info->first_dt == vect_reduction_def
+              && !STMT_VINFO_DATA_REF (stmt_info)
+              && REDUC_GROUP_FIRST_ELEMENT (stmt_info)
+              && !STMT_VINFO_DATA_REF (def_stmt_info)
+              && (REDUC_GROUP_FIRST_ELEMENT (def_stmt_info)
+                  == REDUC_GROUP_FIRST_ELEMENT (stmt_info)))
        {
-       case vect_external_def:
-         /* Make sure to demote the overall operand to external.  */
-         oprnd_info->first_dt = vect_external_def;
-         /* Fallthru.  */
-       case vect_constant_def:
-         oprnd_info->def_stmts.quick_push (NULL);
-         oprnd_info->ops.quick_push (oprnd);
-         break;
-
-       case vect_internal_def:
-       case vect_reduction_def:
-         if (oprnd_info->first_dt == vect_reduction_def
-             && !STMT_VINFO_DATA_REF (stmt_info)
-             && REDUC_GROUP_FIRST_ELEMENT (stmt_info)
-             && !STMT_VINFO_DATA_REF (def_stmt_info)
-             && (REDUC_GROUP_FIRST_ELEMENT (def_stmt_info)
-                 == REDUC_GROUP_FIRST_ELEMENT (stmt_info)))
-           {
-             /* For a SLP reduction chain we want to duplicate the
-                reduction to each of the chain members.  That gets
-                us a sane SLP graph (still the stmts are not 100%
-                correct wrt the initial values).  */
-             gcc_assert (!first);
-             oprnd_info->def_stmts.quick_push (oprnd_info->def_stmts[0]);
-             oprnd_info->ops.quick_push (oprnd_info->ops[0]);
-             break;
-           }
-         /* Fallthru.  */
-       case vect_induction_def:
-         oprnd_info->def_stmts.quick_push (def_stmt_info);
-         oprnd_info->ops.quick_push (oprnd);
-         break;
-
-       default:
-         /* FORNOW: Not supported.  */
-         if (dump_enabled_p ())
-           dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
-                            "Build SLP failed: illegal type of def %T\n",
-                            oprnd);
-
-         return -1;
+         oprnd_info->def_stmts[stmt_num] = oprnd_info->def_stmts[0];
+         oprnd_info->ops[stmt_num] = oprnd_info->ops[0];
        }
+
+      ++i;
     }
 
   /* Swap operands.  */
-- 
2.26.2

Reply via email to