Hi!

useless_type_conversion_p says that precision 1 unsigned BOOLEAN_TYPE
conversion to/from precision 1 unsigned integral type is useless,
but apparently the vectorizer heavily relies on the BOOLEAN_TYPE vs.
unsigned integral:1 distinction (uses VECTOR_BOOLEAN_TYPE_P types
only for real BOOLEAN_TYPE).  As the conversion is useless, we can end up
as in the following testcase with e.g. binary operations which have boolean
on one side and unsigned int:1 on another.

The following patch replaces all explicit BOOLEAN_TYPE checks in the
vectorizer with a new macro that handles unsigned integral:1 the same
as BOOLEAN_TYPE.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2017-01-31  Jakub Jelinek  <ja...@redhat.com>

        PR tree-optimization/79284
        * tree.h (INTEGRAL_BOOLEAN_TYPE_P): Define.
        * tree-vect-stmts.c (vect_get_vec_def_for_operand,
        vectorizable_mask_load_store, vectorizable_operation,
        vect_is_simple_cond, get_same_sized_vectype): Use it instead
        of comparing TREE_CODE of a type against BOOLEAN_TYPE.
        * tree-vect-patterns.c (check_bool_pattern, search_type_for_mask_1,
        vect_recog_bool_pattern, vect_recog_mask_conversion_pattern): Likewise.
        * tree-vect-slp.c (vect_get_constant_vectors): Likewise.
        * tree-vect-loop.c (vect_determine_vectorization_factor): Likewise.
testsuite/
        * gcc.c-torture/compile/pr79284.c: New test.

--- gcc/tree.h.jj       2017-01-23 23:57:41.000000000 +0100
+++ gcc/tree.h  2017-01-31 16:16:28.969224648 +0100
@@ -532,6 +532,16 @@ extern void omp_clause_range_check_faile
         || VECTOR_TYPE_P (TYPE))               \
        && INTEGRAL_TYPE_P (TREE_TYPE (TYPE))))
 
+/* Nonzero if TYPE represents a (scalar) boolean type or type
+   in the middle-end compatible with it.  */
+
+#define INTEGRAL_BOOLEAN_TYPE_P(TYPE) \
+  (TREE_CODE (TYPE) == BOOLEAN_TYPE            \
+   || ((TREE_CODE (TYPE) == INTEGER_TYPE       \
+       || TREE_CODE (TYPE) == ENUMERAL_TYPE)   \
+       && TYPE_PRECISION (TYPE) == 1           \
+       && TYPE_UNSIGNED (TYPE)))
+
 /* Nonzero if TYPE represents a non-saturating fixed-point type.  */
 
 #define NON_SAT_FIXED_POINT_TYPE_P(TYPE) \
--- gcc/tree-vect-stmts.c.jj    2017-01-09 12:44:14.000000000 +0100
+++ gcc/tree-vect-stmts.c       2017-01-31 16:18:51.855369244 +0100
@@ -1420,7 +1420,7 @@ vect_get_vec_def_for_operand (tree op, g
 
       if (vectype)
        vector_type = vectype;
-      else if (TREE_CODE (TREE_TYPE (op)) == BOOLEAN_TYPE
+      else if (INTEGRAL_BOOLEAN_TYPE_P (TREE_TYPE (op))
               && VECTOR_BOOLEAN_TYPE_P (stmt_vectype))
        vector_type = build_same_sized_truth_vector_type (stmt_vectype);
       else
@@ -2029,7 +2029,7 @@ vectorizable_mask_load_store (gimple *st
 
   mask = gimple_call_arg (stmt, 2);
 
-  if (TREE_CODE (TREE_TYPE (mask)) != BOOLEAN_TYPE)
+  if (!INTEGRAL_BOOLEAN_TYPE_P (TREE_TYPE (mask)))
     return false;
 
   /* FORNOW. This restriction should be relaxed.  */
@@ -5275,9 +5275,9 @@ vectorizable_operation (gimple *stmt, gi
         of booleans or vector of integers).  We use output
         vectype because operations on boolean don't change
         type.  */
-      if (TREE_CODE (TREE_TYPE (op0)) == BOOLEAN_TYPE)
+      if (INTEGRAL_BOOLEAN_TYPE_P (TREE_TYPE (op0)))
        {
-         if (TREE_CODE (TREE_TYPE (scalar_dest)) != BOOLEAN_TYPE)
+         if (!INTEGRAL_BOOLEAN_TYPE_P (TREE_TYPE (scalar_dest)))
            {
              if (dump_enabled_p ())
                dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -7666,7 +7666,7 @@ vect_is_simple_cond (tree cond, vec_info
 
   /* Mask case.  */
   if (TREE_CODE (cond) == SSA_NAME
-      && TREE_CODE (TREE_TYPE (cond)) == BOOLEAN_TYPE)
+      && INTEGRAL_BOOLEAN_TYPE_P (TREE_TYPE (cond)))
     {
       gimple *lhs_def_stmt = SSA_NAME_DEF_STMT (cond);
       if (!vect_is_simple_use (cond, vinfo, &lhs_def_stmt,
@@ -9059,7 +9059,7 @@ get_mask_type_for_scalar_type (tree scal
 tree
 get_same_sized_vectype (tree scalar_type, tree vector_type)
 {
-  if (TREE_CODE (scalar_type) == BOOLEAN_TYPE)
+  if (INTEGRAL_BOOLEAN_TYPE_P (scalar_type))
     return build_same_sized_truth_vector_type (vector_type);
 
   return get_vectype_for_scalar_type_and_size
--- gcc/tree-vect-patterns.c.jj 2017-01-01 12:45:37.000000000 +0100
+++ gcc/tree-vect-patterns.c    2017-01-31 16:17:48.082197351 +0100
@@ -3158,9 +3158,7 @@ check_bool_pattern (tree var, vec_info *
       break;
 
     CASE_CONVERT:
-      if ((TYPE_PRECISION (TREE_TYPE (rhs1)) != 1
-          || !TYPE_UNSIGNED (TREE_TYPE (rhs1)))
-         && TREE_CODE (TREE_TYPE (rhs1)) != BOOLEAN_TYPE)
+      if (!INTEGRAL_BOOLEAN_TYPE_P (TREE_TYPE (rhs1)))
        return false;
       if (! check_bool_pattern (rhs1, vinfo, stmts))
        return false;
@@ -3474,9 +3472,7 @@ search_type_for_mask_1 (tree var, vec_in
   if (TREE_CODE (var) != SSA_NAME)
     return NULL_TREE;
 
-  if ((TYPE_PRECISION (TREE_TYPE (var)) != 1
-       || !TYPE_UNSIGNED (TREE_TYPE (var)))
-      && TREE_CODE (TREE_TYPE (var)) != BOOLEAN_TYPE)
+  if (!INTEGRAL_BOOLEAN_TYPE_P (TREE_TYPE (var)))
     return NULL_TREE;
 
   if (!vect_is_simple_use (var, vinfo, &def_stmt, &dt))
@@ -3518,7 +3514,7 @@ search_type_for_mask_1 (tree var, vec_in
        {
          tree comp_vectype, mask_type;
 
-         if (TREE_CODE (TREE_TYPE (rhs1)) == BOOLEAN_TYPE)
+         if (INTEGRAL_BOOLEAN_TYPE_P (TREE_TYPE (rhs1)))
            {
              res = search_type_for_mask_1 (rhs1, vinfo, cache);
              res2 = search_type_for_mask_1 (gimple_assign_rhs2 (def_stmt),
@@ -3637,9 +3633,7 @@ vect_recog_bool_pattern (vec<gimple *> *
   var = gimple_assign_rhs1 (last_stmt);
   lhs = gimple_assign_lhs (last_stmt);
 
-  if ((TYPE_PRECISION (TREE_TYPE (var)) != 1
-       || !TYPE_UNSIGNED (TREE_TYPE (var)))
-      && TREE_CODE (TREE_TYPE (var)) != BOOLEAN_TYPE)
+  if (!INTEGRAL_BOOLEAN_TYPE_P (TREE_TYPE (var)))
     return NULL;
 
   hash_set<gimple *> bool_stmts;
@@ -4023,7 +4017,7 @@ vect_recog_mask_conversion_pattern (vec<
 
   /* Now check for binary boolean operations requiring conversion for
      one of operands.  */
-  if (TREE_CODE (TREE_TYPE (lhs)) != BOOLEAN_TYPE)
+  if (!INTEGRAL_BOOLEAN_TYPE_P (TREE_TYPE (lhs)))
     return NULL;
 
   if (rhs_code != BIT_IOR_EXPR
--- gcc/tree-vect-slp.c.jj      2017-01-09 11:35:04.000000000 +0100
+++ gcc/tree-vect-slp.c 2017-01-31 16:17:36.243351080 +0100
@@ -2949,7 +2949,7 @@ vect_get_constant_vectors (tree op, slp_
   gimple_seq ctor_seq = NULL;
 
   /* Check if vector type is a boolean vector.  */
-  if (TREE_CODE (TREE_TYPE (op)) == BOOLEAN_TYPE
+  if (INTEGRAL_BOOLEAN_TYPE_P (TREE_TYPE (op))
       && vect_mask_constant_operand_p (stmt, op_num))
     vector_type
       = build_same_sized_truth_vector_type (STMT_VINFO_VECTYPE (stmt_vinfo));
--- gcc/tree-vect-loop.c.jj     2017-01-05 11:43:11.000000000 +0100
+++ gcc/tree-vect-loop.c        2017-01-31 16:18:17.593814137 +0100
@@ -433,7 +433,7 @@ vect_determine_vectorization_factor (loo
              /* Bool ops don't participate in vectorization factor
                 computation.  For comparison use compared types to
                 compute a factor.  */
-             if (TREE_CODE (scalar_type) == BOOLEAN_TYPE
+             if (INTEGRAL_BOOLEAN_TYPE_P (scalar_type)
                  && is_gimple_assign (stmt)
                  && gimple_assign_rhs_code (stmt) != COND_EXPR)
                {
@@ -445,8 +445,8 @@ vect_determine_vectorization_factor (loo
                  if (gimple_code (stmt) == GIMPLE_ASSIGN
                      && TREE_CODE_CLASS (gimple_assign_rhs_code (stmt))
                         == tcc_comparison
-                     && TREE_CODE (TREE_TYPE (gimple_assign_rhs1 (stmt)))
-                        != BOOLEAN_TYPE)
+                     && !INTEGRAL_BOOLEAN_TYPE_P
+                           (TREE_TYPE (gimple_assign_rhs1 (stmt))))
                    scalar_type = TREE_TYPE (gimple_assign_rhs1 (stmt));
                  else
                    {
@@ -587,7 +587,7 @@ vect_determine_vectorization_factor (loo
 
       if (gimple_code (stmt) == GIMPLE_ASSIGN
          && TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) == tcc_comparison
-         && TREE_CODE (TREE_TYPE (gimple_assign_rhs1 (stmt))) != BOOLEAN_TYPE)
+         && !INTEGRAL_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 (scalar_type);
--- gcc/testsuite/gcc.c-torture/compile/pr79284.c.jj    2017-01-31 
16:05:43.103547991 +0100
+++ gcc/testsuite/gcc.c-torture/compile/pr79284.c       2017-01-31 
16:05:30.000000000 +0100
@@ -0,0 +1,13 @@
+/* PR tree-optimization/79284 */
+
+struct S { unsigned a : 1; } b;
+int c[64];
+
+int
+foo (int x)
+{ 
+  char e, f;
+  for (e = 63; e; e--)
+    f = (c[e] && ~0) != b.a;
+  return f;
+}

        Jakub

Reply via email to