Don't defer choice of vector type for bools (PR 92596)
authorRichard Sandiford <richard.sandiford@arm.com>
Fri, 29 Nov 2019 14:47:44 +0000 (14:47 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Fri, 29 Nov 2019 14:47:44 +0000 (14:47 +0000)
Now that stmt_vec_info records the choice between vector mask
types and normal nonmask types, we can use that information in
vect_get_vector_types_for_stmt instead of deferring the choice
of vector type till later.

vect_get_mask_type_for_stmt used to check whether the boolean inputs
to an operation:
(a) consistently used mask types or consistently used nonmask types; and
(b) agreed on the number of elements.

(b) shouldn't be a problem when (a) is met.  If the operation
consistently uses mask types, tree-vect-patterns.c will have corrected
any mismatches in mask precision.  (This is because we only use mask
types for a small well-known set of operations and tree-vect-patterns.c
knows how to handle any that could have different mask precisions.)
And if the operation consistently uses normal nonmask types, there's
no reason why booleans should need extra vector compatibility checks
compared to ordinary integers.

So the potential difficulties all seem to come from (a).  Now that
we've chosen the result type ahead of time, we also have to consider
whether the outputs and inputs consistently use mask types.

Taking each vectorizable_* routine in turn:

- vectorizable_call

    vect_get_vector_types_for_stmt only handled booleans specially
    for gassigns, so vect_get_mask_type_for_stmt never had chance to
    handle calls.  I'm not sure we support any calls that operate on
    booleans, but as things stand, a boolean result would always have
    a nonmask type.  Presumably any vector argument would also need to
    use nonmask types, unless it corresponds to internal_fn_mask_index
    (which is already a special case).

    For safety, I've added a check for mask/nonmask combinations here
    even though we didn't check this previously.

- vectorizable_simd_clone_call

    Again, vect_get_mask_type_for_stmt never had chance to handle calls.
    The result of the call will always be a nonmask type and the patch
    for PR 92710 rejects mask arguments.  So all booleans should
    consistently use nonmask types here.

- vectorizable_conversion

    The function already rejects any conversion between booleans in which
    one type isn't a mask type.

- vectorizable_operation

    This function definitely needs a consistency check, e.g. to handle
    & and | in which one operand is loaded from memory and the other is
    a comparison result.  Ideally we'd handle this via pattern stmts
    instead (like we do for the all-mask case), but that's future work.

- vectorizable_assignment

    VECT_SCALAR_BOOLEAN_TYPE_P requires single-bit precision, so the
    current code already rejects problematic cases.

- vectorizable_load

    Loads always produce nonmask types and there are no relevant inputs
    to check against.

- vectorizable_store

    vect_check_store_rhs already rejects mask/nonmask combinations
    via useless_type_conversion_p.

- vectorizable_reduction
- vectorizable_lc_phi

    PHIs always have nonmask types.  After the change above, attempts
    to combine the PHI result with a mask type would be rejected by
    vectorizable_operation.  (Again, it would be better to handle
    this using pattern stmts.)

- vectorizable_induction

    We don't generate inductions for booleans.

- vectorizable_shift

    The function already rejects boolean shifts via type_has_mode_precision_p.

- vectorizable_condition

    The function already rejects mismatches via useless_type_conversion_p.

- vectorizable_comparison

    The function already rejects comparisons between mask and nonmask types.
    The result is always a mask type.

2019-11-29  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
PR tree-optimization/92596
* tree-vect-stmts.c (vectorizable_call): Punt on hybrid mask/nonmask
operations.
(vectorizable_operation): Likewise, instead of relying on
vect_get_mask_type_for_stmt to do this.
(vect_get_vector_types_for_stmt): Always return a vector type
immediately, rather than deferring the choice for boolean results.
Use a vector mask type instead of a normal vector if
vect_use_mask_type_p.
(vect_get_mask_type_for_stmt): Delete.
* tree-vect-loop.c (vect_determine_vf_for_stmt_1): Remove
mask_producers argument and special boolean_type_node handling.
(vect_determine_vf_for_stmt): Remove mask_producers argument and
update calls to vect_determine_vf_for_stmt_1.  Remove doubled call.
(vect_determine_vectorization_factor): Update call accordingly.
* tree-vect-slp.c (vect_build_slp_tree_1): Remove special
boolean_type_node handling.
(vect_slp_analyze_node_operations_1): Likewise.

gcc/testsuite/
PR tree-optimization/92596
* gcc.dg/vect/bb-slp-pr92596.c: New test.
* gcc.dg/vect/bb-slp-43.c: Likewise.

From-SVN: r278851

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/vect/bb-slp-43.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/bb-slp-pr92596.c [new file with mode: 0644]
gcc/tree-vect-loop.c
gcc/tree-vect-slp.c
gcc/tree-vect-stmts.c

index e1bd340e4bc9698899318f91d138bac93e38f5f8..002d9aa1217c1d67fc366ed29e7f17b2eaf95485 100644 (file)
@@ -1,3 +1,24 @@
+2019-11-29  Richard Sandiford  <richard.sandiford@arm.com>
+
+       PR tree-optimization/92596
+       * tree-vect-stmts.c (vectorizable_call): Punt on hybrid mask/nonmask
+       operations.
+       (vectorizable_operation): Likewise, instead of relying on
+       vect_get_mask_type_for_stmt to do this.
+       (vect_get_vector_types_for_stmt): Always return a vector type
+       immediately, rather than deferring the choice for boolean results.
+       Use a vector mask type instead of a normal vector if
+       vect_use_mask_type_p.
+       (vect_get_mask_type_for_stmt): Delete.
+       * tree-vect-loop.c (vect_determine_vf_for_stmt_1): Remove
+       mask_producers argument and special boolean_type_node handling.
+       (vect_determine_vf_for_stmt): Remove mask_producers argument and
+       update calls to vect_determine_vf_for_stmt_1.  Remove doubled call.
+       (vect_determine_vectorization_factor): Update call accordingly.
+       * tree-vect-slp.c (vect_build_slp_tree_1): Remove special
+       boolean_type_node handling.
+       (vect_slp_analyze_node_operations_1): Likewise.
+
 2019-11-29  Richard Sandiford  <richard.sandiford@arm.com>
 
        * tree-vectorizer.h (stmt_vec_info::mask_precision): New field.
index 8c06ec3318dafe239343bc09474bc09cc9874b82..57544a5c17a3c4265b59ac263c5be977748452f9 100644 (file)
@@ -1,3 +1,9 @@
+2019-11-29  Richard Sandiford  <richard.sandiford@arm.com>
+
+       PR tree-optimization/92596
+       * gcc.dg/vect/bb-slp-pr92596.c: New test.
+       * gcc.dg/vect/bb-slp-43.c: Likewise.
+
 2019-11-29  Richard Sandiford  <richard.sandiford@arm.com>
 
        * gcc.dg/vect/vect-bool-cmp-2.c: New test.
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-43.c b/gcc/testsuite/gcc.dg/vect/bb-slp-43.c
new file mode 100644 (file)
index 0000000..a65d951
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+
+void
+f (int *restrict x, short *restrict y)
+{
+  x[0] = x[0] == 1 & y[0] == 2;
+  x[1] = x[1] == 1 & y[1] == 2;
+  x[2] = x[2] == 1 & y[2] == 2;
+  x[3] = x[3] == 1 & y[3] == 2;
+  x[4] = x[4] == 1 & y[4] == 2;
+  x[5] = x[5] == 1 & y[5] == 2;
+  x[6] = x[6] == 1 & y[6] == 2;
+  x[7] = x[7] == 1 & y[7] == 2;
+}
+
+/* { dg-final { scan-tree-dump-not "mixed mask and nonmask" "slp2" } } */
+/* { dg-final { scan-tree-dump-not "vector operands from scalars" "slp2" { target { { vect_int && vect_bool_cmp } && { vect_unpack && vect_hw_misalign } } xfail vect_variable_length } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr92596.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr92596.c
new file mode 100644 (file)
index 0000000..f3dd08d
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O3" } */
+
+typedef struct {
+  long n[5];
+} secp256k1_fe;
+
+secp256k1_fe a;
+
+void fn1(int p1) { a.n[0] = a.n[1] = a.n[2] = p1; }
+void fn2() {
+  int b;
+  fn1(!b);
+}
index ca8c8187f6008af7ba1987698a0a5251dca6eca8..ab48a05dbed35ec59904cd409d9a84b87f1b62fc 100644 (file)
@@ -163,8 +163,7 @@ static stmt_vec_info vect_is_simple_reduction (loop_vec_info, stmt_vec_info,
 static opt_result
 vect_determine_vf_for_stmt_1 (stmt_vec_info stmt_info,
                              bool vectype_maybe_set_p,
-                             poly_uint64 *vf,
-                             vec<stmt_vec_info > *mask_producers)
+                             poly_uint64 *vf)
 {
   gimple *stmt = stmt_info->stmt;
 
@@ -192,8 +191,6 @@ vect_determine_vf_for_stmt_1 (stmt_vec_info stmt_info,
        gcc_assert ((STMT_VINFO_DATA_REF (stmt_info)
                     || vectype_maybe_set_p)
                    && STMT_VINFO_VECTYPE (stmt_info) == stmt_vectype);
-      else if (stmt_vectype == boolean_type_node)
-       mask_producers->safe_push (stmt_info);
       else
        STMT_VINFO_VECTYPE (stmt_info) = stmt_vectype;
     }
@@ -206,21 +203,17 @@ vect_determine_vf_for_stmt_1 (stmt_vec_info stmt_info,
 
 /* Subroutine of vect_determine_vectorization_factor.  Set the vector
    types of STMT_INFO and all attached pattern statements and update
-   the vectorization factor VF accordingly.  If some of the statements
-   produce a mask result whose vector type can only be calculated later,
-   add them to MASK_PRODUCERS.  Return true on success or false if
-   something prevented vectorization.  */
+   the vectorization factor VF accordingly.  Return true on success
+   or false if something prevented vectorization.  */
 
 static opt_result
-vect_determine_vf_for_stmt (stmt_vec_info stmt_info, poly_uint64 *vf,
-                           vec<stmt_vec_info > *mask_producers)
+vect_determine_vf_for_stmt (stmt_vec_info stmt_info, poly_uint64 *vf)
 {
   vec_info *vinfo = stmt_info->vinfo;
   if (dump_enabled_p ())
     dump_printf_loc (MSG_NOTE, vect_location, "==> examining statement: %G",
                     stmt_info->stmt);
-  opt_result res
-    = vect_determine_vf_for_stmt_1 (stmt_info, false, vf, mask_producers);
+  opt_result res = vect_determine_vf_for_stmt_1 (stmt_info, false, vf);
   if (!res)
     return res;
 
@@ -239,10 +232,7 @@ vect_determine_vf_for_stmt (stmt_vec_info stmt_info, poly_uint64 *vf,
            dump_printf_loc (MSG_NOTE, vect_location,
                             "==> examining pattern def stmt: %G",
                             def_stmt_info->stmt);
-         if (!vect_determine_vf_for_stmt_1 (def_stmt_info, true,
-                                            vf, mask_producers))
-         res = vect_determine_vf_for_stmt_1 (def_stmt_info, true,
-                                             vf, mask_producers);
+         res = vect_determine_vf_for_stmt_1 (def_stmt_info, true, vf);
          if (!res)
            return res;
        }
@@ -251,7 +241,7 @@ vect_determine_vf_for_stmt (stmt_vec_info stmt_info, poly_uint64 *vf,
        dump_printf_loc (MSG_NOTE, vect_location,
                         "==> examining pattern statement: %G",
                         stmt_info->stmt);
-      res = vect_determine_vf_for_stmt_1 (stmt_info, true, vf, mask_producers);
+      res = vect_determine_vf_for_stmt_1 (stmt_info, true, vf);
       if (!res)
        return res;
     }
@@ -296,7 +286,6 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
   tree vectype;
   stmt_vec_info stmt_info;
   unsigned i;
-  auto_vec<stmt_vec_info> mask_producers;
 
   DUMP_VECT_SCOPE ("vect_determine_vectorization_factor");
 
@@ -354,8 +343,7 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
        {
          stmt_info = loop_vinfo->lookup_stmt (gsi_stmt (si));
          opt_result res
-           = vect_determine_vf_for_stmt (stmt_info, &vectorization_factor,
-                                         &mask_producers);
+           = vect_determine_vf_for_stmt (stmt_info, &vectorization_factor);
          if (!res)
            return res;
         }
@@ -373,16 +361,6 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
     return opt_result::failure_at (vect_location,
                                   "not vectorized: unsupported data-type\n");
   LOOP_VINFO_VECT_FACTOR (loop_vinfo) = vectorization_factor;
-
-  for (i = 0; i < mask_producers.length (); i++)
-    {
-      stmt_info = mask_producers[i];
-      opt_tree mask_type = vect_get_mask_type_for_stmt (stmt_info);
-      if (!mask_type)
-       return opt_result::propagate_failure (mask_type);
-      STMT_VINFO_VECTYPE (stmt_info) = mask_type;
-    }
-
   return opt_result::success ();
 }
 
index e3fd0e903a43adb6fbe9afd22d2256a7df038c4e..0d420e44bb0d977c9bc38bc6a7e0b875facfd2eb 100644 (file)
@@ -925,17 +925,6 @@ vect_build_slp_tree_1 (unsigned char *swap,
              || rhs_code == LROTATE_EXPR
              || rhs_code == RROTATE_EXPR)
            {
-             if (vectype == boolean_type_node)
-               {
-                 if (dump_enabled_p ())
-                   dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
-                                    "Build SLP failed: shift of a"
-                                    " boolean.\n");
-                 /* Fatal mismatch.  */
-                 matches[0] = false;
-                 return false;
-               }
-
              vec_mode = TYPE_MODE (vectype);
 
              /* First see if we have a vector/vector shift.  */
@@ -1157,9 +1146,8 @@ vect_build_slp_tree_1 (unsigned char *swap,
   if (alt_stmt_code != ERROR_MARK
       && TREE_CODE_CLASS (alt_stmt_code) != tcc_reference)
     {
-      if (vectype == boolean_type_node
-         || !vect_two_operations_perm_ok_p (stmts, group_size,
-                                            vectype, alt_stmt_code))
+      if (!vect_two_operations_perm_ok_p (stmts, group_size,
+                                         vectype, alt_stmt_code))
        {
          for (i = 0; i < group_size; ++i)
            if (gimple_assign_rhs_code (stmts[i]->stmt) == alt_stmt_code)
@@ -2751,25 +2739,6 @@ vect_slp_analyze_node_operations_1 (vec_info *vinfo, slp_tree node,
   stmt_vec_info stmt_info = SLP_TREE_SCALAR_STMTS (node)[0];
   gcc_assert (STMT_SLP_TYPE (stmt_info) != loop_vect);
 
-  /* For BB vectorization vector types are assigned here.
-     Memory accesses already got their vector type assigned
-     in vect_analyze_data_refs.  */
-  bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
-  if (bb_vinfo && STMT_VINFO_VECTYPE (stmt_info) == boolean_type_node)
-    {
-      unsigned int group_size = SLP_TREE_SCALAR_STMTS (node).length ();
-      tree vectype = vect_get_mask_type_for_stmt (stmt_info, group_size);
-      if (!vectype)
-       /* vect_get_mask_type_for_stmt has already explained the
-          failure.  */
-       return false;
-
-      stmt_vec_info sstmt_info;
-      unsigned int i;
-      FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, sstmt_info)
-       STMT_VINFO_VECTYPE (sstmt_info) = vectype;
-    }
-
   /* Calculate the number of vector statements to be created for the
      scalar stmts in this node.  For SLP reductions it is equal to the
      number of vector statements in the children (which has already been
index f1e2ff4117f7506f7061383ab4eba387b79a59db..2cb6b1544ea1216640220f0b4808406f94f8ae49 100644 (file)
@@ -3325,6 +3325,15 @@ vectorizable_call (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
       return false;
     }
 
+  if (VECTOR_BOOLEAN_TYPE_P (vectype_out)
+      != VECTOR_BOOLEAN_TYPE_P (vectype_in))
+    {
+      if (dump_enabled_p ())
+       dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+                        "mixed mask and nonmask vector types\n");
+      return false;
+    }
+
   /* FORNOW */
   nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in);
   nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out);
@@ -5982,7 +5991,8 @@ vectorizable_operation (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
 
   /* Most operations cannot handle bit-precision types without extra
      truncations.  */
-  if (!VECTOR_BOOLEAN_TYPE_P (vectype_out)
+  bool mask_op_p = VECTOR_BOOLEAN_TYPE_P (vectype_out);
+  if (!mask_op_p
       && !type_has_mode_precision_p (TREE_TYPE (scalar_dest))
       /* Exception are bitwise binary operations.  */
       && code != BIT_IOR_EXPR
@@ -6044,10 +6054,11 @@ vectorizable_operation (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
   if (maybe_ne (nunits_out, nunits_in))
     return false;
 
+  tree vectype2 = NULL_TREE, vectype3 = NULL_TREE;
   if (op_type == binary_op || op_type == ternary_op)
     {
       op1 = gimple_assign_rhs2 (stmt);
-      if (!vect_is_simple_use (op1, vinfo, &dt[1]))
+      if (!vect_is_simple_use (op1, vinfo, &dt[1], &vectype2))
        {
          if (dump_enabled_p ())
            dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -6058,7 +6069,7 @@ vectorizable_operation (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
   if (op_type == ternary_op)
     {
       op2 = gimple_assign_rhs3 (stmt);
-      if (!vect_is_simple_use (op2, vinfo, &dt[2]))
+      if (!vect_is_simple_use (op2, vinfo, &dt[2], &vectype3))
        {
          if (dump_enabled_p ())
            dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -6083,6 +6094,21 @@ vectorizable_operation (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
 
   gcc_assert (ncopies >= 1);
 
+  /* Reject attempts to combine mask types with nonmask types, e.g. if
+     we have an AND between a (nonmask) boolean loaded from memory and
+     a (mask) boolean result of a comparison.
+
+     TODO: We could easily fix these cases up using pattern statements.  */
+  if (VECTOR_BOOLEAN_TYPE_P (vectype) != mask_op_p
+      || (vectype2 && VECTOR_BOOLEAN_TYPE_P (vectype2) != mask_op_p)
+      || (vectype3 && VECTOR_BOOLEAN_TYPE_P (vectype3) != mask_op_p))
+    {
+      if (dump_enabled_p ())
+       dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+                        "mixed mask and nonmask vector types\n");
+      return false;
+    }
+
   /* Supportable by target?  */
 
   vec_mode = TYPE_MODE (vectype);
@@ -12026,9 +12052,6 @@ vect_gen_while_not (gimple_seq *seq, tree mask_type, tree start_index,
 
    - Set *STMT_VECTYPE_OUT to:
      - NULL_TREE if the statement doesn't need to be vectorized;
-     - boolean_type_node if the statement is a boolean operation whose
-       vector type can only be determined once all the other vector types
-       are known; and
      - the equivalent of STMT_VINFO_VECTYPE otherwise.
 
    - Set *NUNITS_VECTYPE_OUT to the vector type that contains the maximum
@@ -12085,11 +12108,22 @@ vect_get_vector_types_for_stmt (stmt_vec_info stmt_info,
   tree scalar_type = NULL_TREE;
   if (group_size == 0 && STMT_VINFO_VECTYPE (stmt_info))
     {
-      *stmt_vectype_out = vectype = STMT_VINFO_VECTYPE (stmt_info);
+      vectype = STMT_VINFO_VECTYPE (stmt_info);
       if (dump_enabled_p ())
        dump_printf_loc (MSG_NOTE, vect_location,
                         "precomputed vectype: %T\n", vectype);
     }
+  else if (vect_use_mask_type_p (stmt_info))
+    {
+      unsigned int precision = stmt_info->mask_precision;
+      scalar_type = build_nonstandard_integer_type (precision, 1);
+      vectype = get_mask_type_for_scalar_type (vinfo, scalar_type, group_size);
+      if (!vectype)
+       return opt_result::failure_at (stmt, "not vectorized: unsupported"
+                                      " data-type %T\n", scalar_type);
+      if (dump_enabled_p ())
+       dump_printf_loc (MSG_NOTE, vect_location, "vectype: %T\n", vectype);
+    }
   else
     {
       if (data_reference *dr = STMT_VINFO_DATA_REF (stmt_info))
@@ -12099,28 +12133,6 @@ vect_get_vector_types_for_stmt (stmt_vec_info stmt_info,
       else
        scalar_type = TREE_TYPE (gimple_get_lhs (stmt));
 
-      /* Pure bool ops don't participate in number-of-units computation.
-        For comparisons use the types being compared.  */
-      if (!STMT_VINFO_DATA_REF (stmt_info)
-         && VECT_SCALAR_BOOLEAN_TYPE_P (scalar_type)
-         && is_gimple_assign (stmt)
-         && gimple_assign_rhs_code (stmt) != COND_EXPR)
-       {
-         *stmt_vectype_out = boolean_type_node;
-
-         tree rhs1 = gimple_assign_rhs1 (stmt);
-         if (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) == tcc_comparison
-             && !VECT_SCALAR_BOOLEAN_TYPE_P (TREE_TYPE (rhs1)))
-           scalar_type = TREE_TYPE (rhs1);
-         else
-           {
-             if (dump_enabled_p ())
-               dump_printf_loc (MSG_NOTE, vect_location,
-                                "pure bool operation.\n");
-             return opt_result::success ();
-           }
-       }
-
       if (dump_enabled_p ())
        {
          if (group_size)
@@ -12138,18 +12150,15 @@ vect_get_vector_types_for_stmt (stmt_vec_info stmt_info,
                                       " unsupported data-type %T\n",
                                       scalar_type);
 
-      if (!*stmt_vectype_out)
-       *stmt_vectype_out = vectype;
-
       if (dump_enabled_p ())
        dump_printf_loc (MSG_NOTE, vect_location, "vectype: %T\n", vectype);
     }
+  *stmt_vectype_out = vectype;
 
   /* Don't try to compute scalar types if the stmt produces a boolean
      vector; use the existing vector type instead.  */
   tree nunits_vectype = vectype;
-  if (!VECTOR_BOOLEAN_TYPE_P (vectype)
-      && *stmt_vectype_out != boolean_type_node)
+  if (!VECTOR_BOOLEAN_TYPE_P (vectype))
     {
       /* The number of units is set according to the smallest scalar
         type (or the largest vector size, but we only support one
@@ -12174,9 +12183,8 @@ vect_get_vector_types_for_stmt (stmt_vec_info stmt_info,
        }
     }
 
-  gcc_assert (*stmt_vectype_out == boolean_type_node
-             || multiple_p (TYPE_VECTOR_SUBPARTS (nunits_vectype),
-                            TYPE_VECTOR_SUBPARTS (*stmt_vectype_out)));
+  gcc_assert (multiple_p (TYPE_VECTOR_SUBPARTS (nunits_vectype),
+                         TYPE_VECTOR_SUBPARTS (*stmt_vectype_out)));
 
   if (dump_enabled_p ())
     {
@@ -12188,84 +12196,3 @@ vect_get_vector_types_for_stmt (stmt_vec_info stmt_info,
   *nunits_vectype_out = nunits_vectype;
   return opt_result::success ();
 }
-
-/* Try to determine the correct vector type for STMT_INFO, which is a
-   statement that produces a scalar boolean result.  Return the vector
-   type on success, otherwise return NULL_TREE.  If GROUP_SIZE is nonzero
-   and we're performing BB vectorization, make sure that the number of
-   elements in the vector is no bigger than GROUP_SIZE.  */
-
-opt_tree
-vect_get_mask_type_for_stmt (stmt_vec_info stmt_info, unsigned int group_size)
-{
-  vec_info *vinfo = stmt_info->vinfo;
-  gimple *stmt = stmt_info->stmt;
-  tree mask_type = NULL;
-  tree vectype, scalar_type;
-
-  if (is_gimple_assign (stmt)
-      && TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) == tcc_comparison
-      && !VECT_SCALAR_BOOLEAN_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt))))
-    {
-      scalar_type = TREE_TYPE (gimple_assign_rhs1 (stmt));
-      mask_type = get_mask_type_for_scalar_type (vinfo, scalar_type,
-                                                group_size);
-
-      if (!mask_type)
-       return opt_tree::failure_at (stmt,
-                                    "not vectorized: unsupported mask\n");
-    }
-  else
-    {
-      tree rhs;
-      ssa_op_iter iter;
-      enum vect_def_type dt;
-
-      FOR_EACH_SSA_TREE_OPERAND (rhs, stmt, iter, SSA_OP_USE)
-       {
-         if (!vect_is_simple_use (rhs, stmt_info->vinfo, &dt, &vectype))
-           return opt_tree::failure_at (stmt,
-                                        "not vectorized:can't compute mask"
-                                        " type for statement, %G", stmt);
-
-         /* No vectype probably means external definition.
-            Allow it in case there is another operand which
-            allows to determine mask type.  */
-         if (!vectype)
-           continue;
-
-         if (!mask_type)
-           mask_type = vectype;
-         else if (maybe_ne (TYPE_VECTOR_SUBPARTS (mask_type),
-                            TYPE_VECTOR_SUBPARTS (vectype)))
-           return opt_tree::failure_at (stmt,
-                                        "not vectorized: different sized mask"
-                                        " types in statement, %T and %T\n",
-                                        mask_type, vectype);
-         else if (VECTOR_BOOLEAN_TYPE_P (mask_type)
-                  != VECTOR_BOOLEAN_TYPE_P (vectype))
-           return opt_tree::failure_at (stmt,
-                                        "not vectorized: mixed mask and "
-                                        "nonmask vector types in statement, "
-                                        "%T and %T\n",
-                                        mask_type, vectype);
-       }
-
-      /* We may compare boolean value loaded as vector of integers.
-        Fix mask_type in such case.  */
-      if (mask_type
-         && !VECTOR_BOOLEAN_TYPE_P (mask_type)
-         && gimple_code (stmt) == GIMPLE_ASSIGN
-         && TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) == tcc_comparison)
-       mask_type = truth_type_for (mask_type);
-    }
-
-  /* No mask_type should mean loop invariant predicate.
-     This is probably a subject for optimization in if-conversion.  */
-  if (!mask_type)
-    return opt_tree::failure_at (stmt,
-                                "not vectorized: can't compute mask type "
-                                "for statement: %G", stmt);
-
-  return opt_tree::success (mask_type);
-}