gcc/
authorienkovich <ienkovich@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 21 Oct 2015 16:01:43 +0000 (16:01 +0000)
committerienkovich <ienkovich@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 21 Oct 2015 16:01:43 +0000 (16:01 +0000)
* doc/tm.texi: Regenerated.
* doc/tm.texi.in (TARGET_VECTORIZE_GET_MASK_MODE): New.
* stor-layout.c (layout_type): Use mode to get vector mask size.
* target.def (get_mask_mode): New.
* targhooks.c (default_get_mask_mode): New.
* targhooks.h (default_get_mask_mode): New.
* gcc/tree-vect-stmts.c (get_same_sized_vectype): Add special case
for boolean vector.
* tree.c (MAX_BOOL_CACHED_PREC): New.
(nonstandard_boolean_type_cache): New.
(build_nonstandard_boolean_type): New.
(make_vector_type): Vector mask has no canonical type.
(build_truth_vector_type): New.
(build_same_sized_truth_vector_type): New.
(truth_type_for): Support vector masks.
* tree.h (VECTOR_BOOLEAN_TYPE_P): New.
(build_truth_vector_type): New.
(build_same_sized_truth_vector_type): New.
(build_nonstandard_boolean_type): New.
* tree-cfg.c (verify_gimple_comparison) Require boolean
vector type for vector comparison.
(verify_gimple_assign_ternary): Likewise.
* optabs.c (expand_vec_cond_expr): Accept boolean vector as
condition operand.
* tree-vect-stmts.c (vectorizable_condition): Use boolean
vector type for vector comparison.
* tree-vect-generic.c (elem_op_func): Add new operand to hold
vector type.
(do_unop): Adjust to modified function type.
(do_binop): Likewise.
(do_plus_minus): Likewise.
(do_negate); Likewise.
(expand_vector_piecewise): Likewise.
(do_cond): Likewise.
(do_compare): Use comparison instead of condition.
(expand_vector_divmod): Use boolean vector type for comparison.
(expand_vector_operations_1): Skip scalar mask operations.

gcc/c

* c-typeck.c (build_conditional_expr): Use boolean vector
type for vector comparison.
(build_vec_cmp): New.
(build_binary_op): Use build_vec_cmp for comparison.

gcc/cp

* call.c (build_conditional_expr_1): Use boolean vector
type for vector comparison.
* typeck.c (build_vec_cmp): New.
(cp_build_binary_op): Use build_vec_cmp for comparison.

gcc/testsuite/

* g++.dg/ext/vector22.C: Allow VEC_COND_EXPR.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@229128 138bc75d-0d04-0410-961f-82ee72b054a4

20 files changed:
gcc/ChangeLog
gcc/c/ChangeLog
gcc/c/c-typeck.c
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/typeck.c
gcc/doc/tm.texi
gcc/doc/tm.texi.in
gcc/optabs.c
gcc/stor-layout.c
gcc/target.def
gcc/targhooks.c
gcc/targhooks.h
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ext/vector22.C
gcc/tree-cfg.c
gcc/tree-vect-generic.c
gcc/tree-vect-stmts.c
gcc/tree.c
gcc/tree.h

index 2971405..d5296ae 100644 (file)
@@ -1,5 +1,45 @@
 2015-10-21  Ilya Enkovich  <enkovich.gnu@gmail.com>
 
+       * doc/tm.texi: Regenerated.
+       * doc/tm.texi.in (TARGET_VECTORIZE_GET_MASK_MODE): New.
+       * stor-layout.c (layout_type): Use mode to get vector mask size.
+       * target.def (get_mask_mode): New.
+       * targhooks.c (default_get_mask_mode): New.
+       * targhooks.h (default_get_mask_mode): New.
+       * gcc/tree-vect-stmts.c (get_same_sized_vectype): Add special case
+       for boolean vector.
+       * tree.c (MAX_BOOL_CACHED_PREC): New.
+       (nonstandard_boolean_type_cache): New.
+       (build_nonstandard_boolean_type): New.
+       (make_vector_type): Vector mask has no canonical type.
+       (build_truth_vector_type): New.
+       (build_same_sized_truth_vector_type): New.
+       (truth_type_for): Support vector masks.
+       * tree.h (VECTOR_BOOLEAN_TYPE_P): New.
+       (build_truth_vector_type): New.
+       (build_same_sized_truth_vector_type): New.
+       (build_nonstandard_boolean_type): New.
+       * tree-cfg.c (verify_gimple_comparison) Require boolean
+       vector type for vector comparison.
+       (verify_gimple_assign_ternary): Likewise.
+       * optabs.c (expand_vec_cond_expr): Accept boolean vector as
+       condition operand.
+       * tree-vect-stmts.c (vectorizable_condition): Use boolean
+       vector type for vector comparison.
+       * tree-vect-generic.c (elem_op_func): Add new operand to hold
+       vector type.
+       (do_unop): Adjust to modified function type.
+       (do_binop): Likewise.
+       (do_plus_minus): Likewise.
+       (do_negate); Likewise.
+       (expand_vector_piecewise): Likewise.
+       (do_cond): Likewise.
+       (do_compare): Use comparison instead of condition.
+       (expand_vector_divmod): Use boolean vector type for comparison.
+       (expand_vector_operations_1): Skip scalar mask operations.
+
+2015-10-21  Ilya Enkovich  <enkovich.gnu@gmail.com>
+
        * omp-low.c (simd_clone_create): Set in_other_partition
        for created clones.
 
index c1dbde6..34aafc2 100644 (file)
@@ -1,3 +1,10 @@
+2015-10-21  Ilya Enkovich  <enkovich.gnu@gmail.com>
+
+       * c-typeck.c (build_conditional_expr): Use boolean vector
+       type for vector comparison.
+       (build_vec_cmp): New.
+       (build_binary_op): Use build_vec_cmp for comparison.
+
 2015-10-20  Marek Polacek  <polacek@redhat.com>
 
        * c-parser.c (is_cilkplus_vector_p): Don't define here.
index bc43602..6b32781 100644 (file)
@@ -4771,6 +4771,18 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
                       && TREE_CODE (orig_op2) == INTEGER_CST
                       && !TREE_OVERFLOW (orig_op2)));
     }
+
+  /* Need to convert condition operand into a vector mask.  */
+  if (VECTOR_TYPE_P (TREE_TYPE (ifexp)))
+    {
+      tree vectype = TREE_TYPE (ifexp);
+      tree elem_type = TREE_TYPE (vectype);
+      tree zero = build_int_cst (elem_type, 0);
+      tree zero_vec = build_vector_from_val (vectype, zero);
+      tree cmp_type = build_same_sized_truth_vector_type (vectype);
+      ifexp = build2 (NE_EXPR, cmp_type, ifexp, zero_vec);
+    }
+
   if (int_const || (ifexp_bcp && TREE_CODE (ifexp) == INTEGER_CST))
     ret = fold_build3_loc (colon_loc, COND_EXPR, result_type, ifexp, op1, op2);
   else
@@ -10237,6 +10249,20 @@ push_cleanup (tree decl, tree cleanup, bool eh_only)
   STATEMENT_LIST_STMT_EXPR (list) = stmt_expr;
 }
 \f
+/* Build a vector comparison of ARG0 and ARG1 using CODE opcode
+   into a value of TYPE type.  Comparison is done via VEC_COND_EXPR.  */
+
+static tree
+build_vec_cmp (tree_code code, tree type,
+              tree arg0, tree arg1)
+{
+  tree zero_vec = build_zero_cst (type);
+  tree minus_one_vec = build_minus_one_cst (type);
+  tree cmp_type = build_same_sized_truth_vector_type (type);
+  tree cmp = build2 (code, cmp_type, arg0, arg1);
+  return build3 (VEC_COND_EXPR, type, cmp, minus_one_vec, zero_vec);
+}
+
 /* Build a binary-operation expression without default conversions.
    CODE is the kind of expression to build.
    LOCATION is the operator's location.
@@ -10803,7 +10829,8 @@ build_binary_op (location_t location, enum tree_code code,
           result_type = build_opaque_vector_type (intt,
                                                  TYPE_VECTOR_SUBPARTS (type0));
           converted = 1;
-          break;
+         ret = build_vec_cmp (resultcode, result_type, op0, op1);
+         goto return_build_binary_op;
         }
       if (FLOAT_TYPE_P (type0) || FLOAT_TYPE_P (type1))
        warning_at (location,
@@ -10955,7 +10982,8 @@ build_binary_op (location_t location, enum tree_code code,
           result_type = build_opaque_vector_type (intt,
                                                  TYPE_VECTOR_SUBPARTS (type0));
           converted = 1;
-          break;
+         ret = build_vec_cmp (resultcode, result_type, op0, op1);
+         goto return_build_binary_op;
         }
       build_type = integer_type_node;
       if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
index 9f282d8..2a9e873 100644 (file)
@@ -1,3 +1,10 @@
+2015-10-21  Ilya Enkovich  <enkovich.gnu@gmail.com>
+
+       * call.c (build_conditional_expr_1): Use boolean vector
+       type for vector comparison.
+       * typeck.c (build_vec_cmp): New.
+       (cp_build_binary_op): Use build_vec_cmp for comparison.
+
 2015-10-20  Jason Merrill  <jason@redhat.com>
 
        PR c++/66583
index f8db2df..55b3c8c 100644 (file)
@@ -4627,6 +4627,15 @@ build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3,
 
   if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (arg1)))
     {
+      /* If arg1 is another cond_expr choosing between -1 and 0,
+        then we can use its comparison.  It may help to avoid
+        additional comparison, produce more accurate diagnostics
+        and enables folding.  */
+      if (TREE_CODE (arg1) == VEC_COND_EXPR
+         && integer_minus_onep (TREE_OPERAND (arg1, 1))
+         && integer_zerop (TREE_OPERAND (arg1, 2)))
+       arg1 = TREE_OPERAND (arg1, 0);
+
       arg1 = force_rvalue (arg1, complain);
       arg2 = force_rvalue (arg2, complain);
       arg3 = force_rvalue (arg3, complain);
@@ -4739,8 +4748,10 @@ build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3,
        }
 
       if (!COMPARISON_CLASS_P (arg1))
-       arg1 = cp_build_binary_op (loc, NE_EXPR, arg1,
-                                  build_zero_cst (arg1_type), complain);
+       {
+         tree cmp_type = build_same_sized_truth_vector_type (arg1_type);
+         arg1 = build2 (NE_EXPR, cmp_type, arg1, build_zero_cst (arg1_type));
+       }
       return fold_build3 (VEC_COND_EXPR, arg2_type, arg1, arg2, arg3);
     }
 
index 9e6f949..3147609 100644 (file)
@@ -3916,6 +3916,20 @@ build_binary_op (location_t location, enum tree_code code, tree op0, tree op1,
   return cp_build_binary_op (location, code, op0, op1, tf_warning_or_error);
 }
 
+/* Build a vector comparison of ARG0 and ARG1 using CODE opcode
+   into a value of TYPE type.  Comparison is done via VEC_COND_EXPR.  */
+
+static tree
+build_vec_cmp (tree_code code, tree type,
+              tree arg0, tree arg1)
+{
+  tree zero_vec = build_zero_cst (type);
+  tree minus_one_vec = build_minus_one_cst (type);
+  tree cmp_type = build_same_sized_truth_vector_type(type);
+  tree cmp = build2 (code, cmp_type, arg0, arg1);
+  cmp = fold_if_not_in_template (cmp);
+  return build3 (VEC_COND_EXPR, type, cmp, minus_one_vec, zero_vec);
+}
 
 /* Build a binary-operation expression without default conversions.
    CODE is the kind of expression to build.
@@ -4785,7 +4799,7 @@ cp_build_binary_op (location_t location,
          result_type = build_opaque_vector_type (intt,
                                                  TYPE_VECTOR_SUBPARTS (type0));
          converted = 1;
-         break;
+         return build_vec_cmp (resultcode, result_type, op0, op1);
        }
       build_type = boolean_type_node;
       if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
index 731e630..4a12ad6 100644 (file)
@@ -5688,6 +5688,12 @@ mode returned by @code{TARGET_VECTORIZE_PREFERRED_SIMD_MODE}.
 The default is zero which means to not iterate over other vector sizes.
 @end deftypefn
 
+@deftypefn {Target Hook} machine_mode TARGET_VECTORIZE_GET_MASK_MODE (unsigned @var{nunits}, unsigned @var{length})
+This hook returns mode to be used for a mask to be used for a vector
+of specified @var{length} with @var{nunits} elements.  By default an integer
+vector mode of a proper size is returned.
+@end deftypefn
+
 @deftypefn {Target Hook} {void *} TARGET_VECTORIZE_INIT_COST (struct loop *@var{loop_info})
 This hook should initialize target-specific data structures in preparation for modeling the costs of vectorizing a loop or basic block.  The default allocates three unsigned integers for accumulating costs for the prologue, body, and epilogue of the loop or basic block.  If @var{loop_info} is non-NULL, it identifies the loop being vectorized; otherwise a single block is being vectorized.
 @end deftypefn
index 0b52250..6f0c252 100644 (file)
@@ -4225,6 +4225,8 @@ address;  but often a machine-dependent strategy can generate better code.
 
 @hook TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_SIZES
 
+@hook TARGET_VECTORIZE_GET_MASK_MODE
+
 @hook TARGET_VECTORIZE_INIT_COST
 
 @hook TARGET_VECTORIZE_ADD_STMT_COST
index 223daf7..82a1ee6 100644 (file)
@@ -5365,16 +5365,17 @@ expand_vec_cond_expr (tree vec_cond_type, tree op0, tree op1, tree op2,
       op0a = TREE_OPERAND (op0, 0);
       op0b = TREE_OPERAND (op0, 1);
       tcode = TREE_CODE (op0);
+      unsignedp = TYPE_UNSIGNED (TREE_TYPE (op0a));
     }
   else
     {
       /* Fake op0 < 0.  */
-      gcc_assert (!TYPE_UNSIGNED (TREE_TYPE (op0)));
+      gcc_assert (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (op0)));
       op0a = op0;
       op0b = build_zero_cst (TREE_TYPE (op0));
       tcode = LT_EXPR;
+      unsignedp = false;
     }
-  unsignedp = TYPE_UNSIGNED (TREE_TYPE (op0a));
   cmp_op_mode = TYPE_MODE (TREE_TYPE (op0a));
 
 
index 938e54b..58ecd7b 100644 (file)
@@ -2184,10 +2184,16 @@ layout_type (tree type)
 
        TYPE_SATURATING (type) = TYPE_SATURATING (TREE_TYPE (type));
         TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TREE_TYPE (type));
-       TYPE_SIZE_UNIT (type) = int_const_binop (MULT_EXPR,
-                                                TYPE_SIZE_UNIT (innertype),
-                                                size_int (nunits));
-       TYPE_SIZE (type) = int_const_binop (MULT_EXPR, TYPE_SIZE (innertype),
+       /* Several boolean vector elements may fit in a single unit.  */
+       if (VECTOR_BOOLEAN_TYPE_P (type))
+         TYPE_SIZE_UNIT (type)
+           = size_int (GET_MODE_SIZE (type->type_common.mode));
+       else
+         TYPE_SIZE_UNIT (type) = int_const_binop (MULT_EXPR,
+                                                  TYPE_SIZE_UNIT (innertype),
+                                                  size_int (nunits));
+       TYPE_SIZE (type) = int_const_binop (MULT_EXPR,
+                                           TYPE_SIZE (innertype),
                                            bitsize_int (nunits));
 
        /* For vector types, we do not default to the mode's alignment.
index 694e455..93478e8 100644 (file)
@@ -1810,6 +1810,16 @@ The default is zero which means to not iterate over other vector sizes.",
  (void),
  default_autovectorize_vector_sizes)
 
+/* Function to get a target mode for a vector mask.  */
+DEFHOOK
+(get_mask_mode,
+ "This hook returns mode to be used for a mask to be used for a vector\n\
+of specified @var{length} with @var{nunits} elements.  By default an integer\n\
+vector mode of a proper size is returned.",
+ machine_mode,
+ (unsigned nunits, unsigned length),
+ default_get_mask_mode)
+
 /* Target builtin that implements vector gather operation.  */
 DEFHOOK
 (builtin_gather,
index 5077ec9..01aaed0 100644 (file)
@@ -1087,6 +1087,20 @@ default_autovectorize_vector_sizes (void)
   return 0;
 }
 
+/* By defaults a vector of integers is used as a mask.  */
+
+machine_mode
+default_get_mask_mode (unsigned nunits, unsigned vector_size)
+{
+  unsigned elem_size = vector_size / nunits;
+  machine_mode elem_mode
+    = smallest_mode_for_size (elem_size * BITS_PER_UNIT, MODE_INT);
+
+  gcc_assert (elem_size * nunits == vector_size);
+
+  return mode_for_vector (elem_mode, nunits);
+}
+
 /* By default, the cost model accumulates three separate costs (prologue,
    loop body, and epilogue) for a vectorized loop or block.  So allocate an
    array of three unsigned ints, set it to zero, and return its address.  */
index 77c284a..e13e087 100644 (file)
@@ -100,6 +100,7 @@ default_builtin_support_vector_misalignment (machine_mode mode,
                                             int, bool);
 extern machine_mode default_preferred_simd_mode (machine_mode mode);
 extern unsigned int default_autovectorize_vector_sizes (void);
+extern machine_mode default_get_mask_mode (unsigned, unsigned);
 extern void *default_init_cost (struct loop *);
 extern unsigned default_add_stmt_cost (void *, int, enum vect_cost_for_stmt,
                                       struct _stmt_vec_info *, int,
index ed725ee..3f325b9 100644 (file)
@@ -1,5 +1,9 @@
 2015-10-21  Ilya Enkovich  <enkovich.gnu@gmail.com>
 
+       * g++.dg/ext/vector22.C: Allow VEC_COND_EXPR.
+
+2015-10-21  Ilya Enkovich  <enkovich.gnu@gmail.com>
+
        * gcc.dg/lto/simd-function_0.c: New test.
 
 2015-10-21  Uros Bizjak  <ubizjak@gmail.com>
index daf4e19..5d28637 100644 (file)
@@ -18,4 +18,3 @@ void h(vec*a){
 }
 
 /* { dg-final { scan-tree-dump-not "~" "gimple" } } */
-/* { dg-final { scan-tree-dump-not "VEC_COND_EXPR" "gimple" } } */
index 5bf546e..8e3e810 100644 (file)
@@ -3465,10 +3465,10 @@ verify_gimple_comparison (tree type, tree op0, tree op1)
           return true;
         }
     }
-  /* Or an integer vector type with the same size and element count
+  /* Or a boolean vector type with the same element count
      as the comparison operand types.  */
   else if (TREE_CODE (type) == VECTOR_TYPE
-          && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE)
+          && TREE_CODE (TREE_TYPE (type)) == BOOLEAN_TYPE)
     {
       if (TREE_CODE (op0_type) != VECTOR_TYPE
          || TREE_CODE (op1_type) != VECTOR_TYPE)
@@ -3479,12 +3479,7 @@ verify_gimple_comparison (tree type, tree op0, tree op1)
           return true;
         }
 
-      if (TYPE_VECTOR_SUBPARTS (type) != TYPE_VECTOR_SUBPARTS (op0_type)
-         || (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (type)))
-             != GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0_type))))
-         /* The result of a vector comparison is of signed
-            integral type.  */
-         || TYPE_UNSIGNED (TREE_TYPE (type)))
+      if (TYPE_VECTOR_SUBPARTS (type) != TYPE_VECTOR_SUBPARTS (op0_type))
         {
           error ("invalid vector comparison resulting type");
           debug_generic_expr (type);
@@ -3971,15 +3966,13 @@ verify_gimple_assign_ternary (gassign *stmt)
       break;
 
     case VEC_COND_EXPR:
-      if (!VECTOR_INTEGER_TYPE_P (rhs1_type)
-         || TYPE_SIGN (rhs1_type) != SIGNED
-         || TYPE_SIZE (rhs1_type) != TYPE_SIZE (lhs_type)
+      if (!VECTOR_BOOLEAN_TYPE_P (rhs1_type)
          || TYPE_VECTOR_SUBPARTS (rhs1_type)
             != TYPE_VECTOR_SUBPARTS (lhs_type))
        {
-         error ("the first argument of a VEC_COND_EXPR must be of a signed "
-                "integral vector type of the same size and number of "
-                "elements as the result");
+         error ("the first argument of a VEC_COND_EXPR must be of a "
+                "boolean vector type of the same number of elements "
+                "as the result");
          debug_generic_expr (lhs_type);
          debug_generic_expr (rhs1_type);
          return true;
index dad38a2..a20b9af 100644 (file)
@@ -105,14 +105,27 @@ build_word_mode_vector_type (int nunits)
 }
 
 typedef tree (*elem_op_func) (gimple_stmt_iterator *,
-                             tree, tree, tree, tree, tree, enum tree_code);
+                             tree, tree, tree, tree, tree, enum tree_code,
+                             tree);
 
 static inline tree
 tree_vec_extract (gimple_stmt_iterator *gsi, tree type,
                  tree t, tree bitsize, tree bitpos)
 {
   if (bitpos)
-    return gimplify_build3 (gsi, BIT_FIELD_REF, type, t, bitsize, bitpos);
+    {
+      if (TREE_CODE (type) == BOOLEAN_TYPE)
+       {
+         tree itype
+           = build_nonstandard_integer_type (tree_to_uhwi (bitsize), 0);
+         tree field = gimplify_build3 (gsi, BIT_FIELD_REF, itype, t,
+                                       bitsize, bitpos);
+         return gimplify_build2 (gsi, NE_EXPR, type, field,
+                                 build_zero_cst (itype));
+       }
+      else
+       return gimplify_build3 (gsi, BIT_FIELD_REF, type, t, bitsize, bitpos);
+    }
   else
     return gimplify_build1 (gsi, VIEW_CONVERT_EXPR, type, t);
 }
@@ -120,7 +133,7 @@ tree_vec_extract (gimple_stmt_iterator *gsi, tree type,
 static tree
 do_unop (gimple_stmt_iterator *gsi, tree inner_type, tree a,
         tree b ATTRIBUTE_UNUSED, tree bitpos, tree bitsize,
-        enum tree_code code)
+        enum tree_code code, tree type ATTRIBUTE_UNUSED)
 {
   a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
   return gimplify_build1 (gsi, code, inner_type, a);
@@ -128,7 +141,8 @@ do_unop (gimple_stmt_iterator *gsi, tree inner_type, tree a,
 
 static tree
 do_binop (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
-         tree bitpos, tree bitsize, enum tree_code code)
+         tree bitpos, tree bitsize, enum tree_code code,
+         tree type ATTRIBUTE_UNUSED)
 {
   if (TREE_CODE (TREE_TYPE (a)) == VECTOR_TYPE)
     a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
@@ -145,20 +159,12 @@ do_binop (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
    size equal to the size of INNER_TYPE.  */
 static tree
 do_compare (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
-         tree bitpos, tree bitsize, enum tree_code code)
+           tree bitpos, tree bitsize, enum tree_code code, tree type)
 {
-  tree comp_type;
-
   a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
   b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
 
-  comp_type = build_nonstandard_integer_type
-                     (GET_MODE_BITSIZE (TYPE_MODE (inner_type)), 0);
-
-  return gimplify_build3 (gsi, COND_EXPR, comp_type,
-                         fold_build2 (code, boolean_type_node, a, b),
-                         build_int_cst (comp_type, -1),
-                         build_int_cst (comp_type, 0));
+  return gimplify_build2 (gsi, code, TREE_TYPE (type), a, b);
 }
 
 /* Expand vector addition to scalars.  This does bit twiddling
@@ -177,7 +183,7 @@ do_compare (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
 static tree
 do_plus_minus (gimple_stmt_iterator *gsi, tree word_type, tree a, tree b,
               tree bitpos ATTRIBUTE_UNUSED, tree bitsize ATTRIBUTE_UNUSED,
-              enum tree_code code)
+              enum tree_code code, tree type ATTRIBUTE_UNUSED)
 {
   tree inner_type = TREE_TYPE (TREE_TYPE (a));
   unsigned HOST_WIDE_INT max;
@@ -209,7 +215,8 @@ static tree
 do_negate (gimple_stmt_iterator *gsi, tree word_type, tree b,
           tree unused ATTRIBUTE_UNUSED, tree bitpos ATTRIBUTE_UNUSED,
           tree bitsize ATTRIBUTE_UNUSED,
-          enum tree_code code ATTRIBUTE_UNUSED)
+          enum tree_code code ATTRIBUTE_UNUSED,
+          tree type ATTRIBUTE_UNUSED)
 {
   tree inner_type = TREE_TYPE (TREE_TYPE (b));
   HOST_WIDE_INT max;
@@ -255,7 +262,7 @@ expand_vector_piecewise (gimple_stmt_iterator *gsi, elem_op_func f,
   for (i = 0; i < nunits;
        i += delta, index = int_const_binop (PLUS_EXPR, index, part_width))
     {
-      tree result = f (gsi, inner_type, a, b, index, part_width, code);
+      tree result = f (gsi, inner_type, a, b, index, part_width, code, type);
       constructor_elt ce = {NULL_TREE, result};
       v->quick_push (ce);
     }
@@ -298,7 +305,7 @@ expand_vector_parallel (gimple_stmt_iterator *gsi, elem_op_func f, tree type,
       /* Use a single scalar operation with a mode no wider than word_mode.  */
       mode = mode_for_size (tree_to_uhwi (TYPE_SIZE (type)), MODE_INT, 0);
       compute_type = lang_hooks.types.type_for_mode (mode, 1);
-      result = f (gsi, compute_type, a, b, NULL_TREE, NULL_TREE, code);
+      result = f (gsi, compute_type, a, b, NULL_TREE, NULL_TREE, code, type);
       warning_at (loc, OPT_Wvector_operation_performance,
                  "vector operation will be expanded with a "
                  "single scalar operation");
@@ -615,11 +622,12 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
          if (addend == NULL_TREE
              && expand_vec_cond_expr_p (type, type))
            {
-             tree zero, cst, cond;
+             tree zero, cst, cond, mask_type;
              gimple *stmt;
 
+             mask_type = build_same_sized_truth_vector_type (type);
              zero = build_zero_cst (type);
-             cond = build2 (LT_EXPR, type, op0, zero);
+             cond = build2 (LT_EXPR, mask_type, op0, zero);
              for (i = 0; i < nunits; i++)
                vec[i] = build_int_cst (TREE_TYPE (type),
                                        ((unsigned HOST_WIDE_INT) 1
@@ -1386,7 +1394,8 @@ count_type_subparts (tree type)
 
 static tree
 do_cond (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
-        tree bitpos, tree bitsize, enum tree_code code)
+        tree bitpos, tree bitsize, enum tree_code code,
+        tree type ATTRIBUTE_UNUSED)
 {
   if (TREE_CODE (TREE_TYPE (a)) == VECTOR_TYPE)
     a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
@@ -1496,6 +1505,12 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi)
   if (TREE_CODE (type) != VECTOR_TYPE)
     return;
 
+  /* A scalar operation pretending to be a vector one.  */
+  if (VECTOR_BOOLEAN_TYPE_P (type)
+      && !VECTOR_MODE_P (TYPE_MODE (type))
+      && TYPE_MODE (type) != BLKmode)
+    return;
+
   if (CONVERT_EXPR_CODE_P (code)
       || code == FLOAT_EXPR
       || code == FIX_TRUNC_EXPR
index 3896e5c..19f62d0 100644 (file)
@@ -7254,10 +7254,7 @@ vectorizable_condition (gimple *stmt, gimple_stmt_iterator *gsi,
   if (!vect_is_simple_use (else_clause, stmt_info->vinfo, &def_stmt, &dt))
     return false;
 
-  unsigned int prec = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (vectype)));
-  /* The result of a vector comparison should be signed type.  */
-  tree cmp_type = build_nonstandard_integer_type (prec, 0);
-  vec_cmp_type = get_same_sized_vectype (cmp_type, vectype);
+  vec_cmp_type = build_same_sized_truth_vector_type (comp_vectype);
   if (vec_cmp_type == NULL_TREE)
     return false;
 
@@ -8067,6 +8064,9 @@ get_vectype_for_scalar_type (tree scalar_type)
 tree
 get_same_sized_vectype (tree scalar_type, tree vector_type)
 {
+  if (TREE_CODE (scalar_type) == BOOLEAN_TYPE)
+    return build_same_sized_truth_vector_type (vector_type);
+
   return get_vectype_for_scalar_type_and_size
           (scalar_type, GET_MODE_SIZE (TYPE_MODE (vector_type)));
 }
index 9d0e9de..6c75699 100644 (file)
@@ -8041,6 +8041,34 @@ build_nonstandard_integer_type (unsigned HOST_WIDE_INT precision,
   return ret;
 }
 
+#define MAX_BOOL_CACHED_PREC \
+  (HOST_BITS_PER_WIDE_INT > 64 ? HOST_BITS_PER_WIDE_INT : 64)
+static GTY(()) tree nonstandard_boolean_type_cache[MAX_BOOL_CACHED_PREC + 1];
+
+/* Builds a boolean type of precision PRECISION.
+   Used for boolean vectors to choose proper vector element size.  */
+tree
+build_nonstandard_boolean_type (unsigned HOST_WIDE_INT precision)
+{
+  tree type;
+
+  if (precision <= MAX_BOOL_CACHED_PREC)
+    {
+      type = nonstandard_boolean_type_cache[precision];
+      if (type)
+       return type;
+    }
+
+  type = make_node (BOOLEAN_TYPE);
+  TYPE_PRECISION (type) = precision;
+  fixup_unsigned_type (type);
+
+  if (precision <= MAX_INT_CACHED_PREC)
+    nonstandard_boolean_type_cache[precision] = type;
+
+  return type;
+}
+
 /* Create a range of some discrete type TYPE (an INTEGER_TYPE, ENUMERAL_TYPE
    or BOOLEAN_TYPE) with low bound LOWVAL and high bound HIGHVAL.  If SHARED
    is true, reuse such a type that has already been constructed.  */
@@ -9791,8 +9819,9 @@ make_vector_type (tree innertype, int nunits, machine_mode mode)
 
   if (TYPE_STRUCTURAL_EQUALITY_P (innertype))
     SET_TYPE_STRUCTURAL_EQUALITY (t);
-  else if (TYPE_CANONICAL (innertype) != innertype
-          || mode != VOIDmode)
+  else if ((TYPE_CANONICAL (innertype) != innertype
+           || mode != VOIDmode)
+          && !VECTOR_BOOLEAN_TYPE_P (t))
     TYPE_CANONICAL (t)
       = make_vector_type (TYPE_CANONICAL (innertype), nunits, VOIDmode);
 
@@ -10617,6 +10646,40 @@ build_vector_type (tree innertype, int nunits)
   return make_vector_type (innertype, nunits, VOIDmode);
 }
 
+/* Build truth vector with specified length and number of units.  */
+
+tree
+build_truth_vector_type (unsigned nunits, unsigned vector_size)
+{
+  machine_mode mask_mode = targetm.vectorize.get_mask_mode (nunits,
+                                                           vector_size);
+
+  gcc_assert (mask_mode != VOIDmode);
+
+  unsigned HOST_WIDE_INT esize = GET_MODE_BITSIZE (mask_mode) / nunits;
+  gcc_assert (esize * nunits == GET_MODE_BITSIZE (mask_mode));
+
+  tree bool_type = build_nonstandard_boolean_type (esize);
+
+  return make_vector_type (bool_type, nunits, mask_mode);
+}
+
+/* Returns a vector type corresponding to a comparison of VECTYPE.  */
+
+tree
+build_same_sized_truth_vector_type (tree vectype)
+{
+  if (VECTOR_BOOLEAN_TYPE_P (vectype))
+    return vectype;
+
+  unsigned HOST_WIDE_INT size = GET_MODE_SIZE (TYPE_MODE (vectype));
+
+  if (!size)
+    size = tree_to_uhwi (TYPE_SIZE_UNIT (vectype));
+
+  return build_truth_vector_type (TYPE_VECTOR_SUBPARTS (vectype), size);
+}
+
 /* Similarly, but builds a variant type with TYPE_VECTOR_OPAQUE set.  */
 
 tree
@@ -11103,9 +11166,10 @@ truth_type_for (tree type)
 {
   if (TREE_CODE (type) == VECTOR_TYPE)
     {
-      tree elem = lang_hooks.types.type_for_size
-        (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (type))), 0);
-      return build_opaque_vector_type (elem, TYPE_VECTOR_SUBPARTS (type));
+      if (VECTOR_BOOLEAN_TYPE_P (type))
+       return type;
+      return build_truth_vector_type (TYPE_VECTOR_SUBPARTS (type),
+                                     GET_MODE_SIZE (TYPE_MODE (type)));
     }
   else
     return boolean_type_node;
index f62cd27..300077c 100644 (file)
@@ -470,6 +470,12 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
 
 #define VECTOR_TYPE_P(TYPE) (TREE_CODE (TYPE) == VECTOR_TYPE)
 
+/* Nonzero if TYPE represents a vector of booleans.  */
+
+#define VECTOR_BOOLEAN_TYPE_P(TYPE)                            \
+  (TREE_CODE (TYPE) == VECTOR_TYPE                     \
+   && TREE_CODE (TREE_TYPE (TYPE)) == BOOLEAN_TYPE)
+
 /* Nonzero if TYPE represents an integral type.  Note that we do not
    include COMPLEX types here.  Keep these checks in ascending code
    order.  */
@@ -3895,6 +3901,8 @@ extern tree build_reference_type_for_mode (tree, machine_mode, bool);
 extern tree build_reference_type (tree);
 extern tree build_vector_type_for_mode (tree, machine_mode);
 extern tree build_vector_type (tree innertype, int nunits);
+extern tree build_truth_vector_type (unsigned, unsigned);
+extern tree build_same_sized_truth_vector_type (tree vectype);
 extern tree build_opaque_vector_type (tree innertype, int nunits);
 extern tree build_index_type (tree);
 extern tree build_array_type (tree, tree);
@@ -4615,6 +4623,7 @@ extern void init_ttree (void);
 extern void build_common_tree_nodes (bool, bool);
 extern void build_common_builtin_nodes (void);
 extern tree build_nonstandard_integer_type (unsigned HOST_WIDE_INT, int);
+extern tree build_nonstandard_boolean_type (unsigned HOST_WIDE_INT);
 extern tree build_range_type (tree, tree, tree);
 extern tree build_nonshared_range_type (tree, tree, tree);
 extern bool subrange_type_for_debug_p (const_tree, tree *, tree *);