aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIlya Enkovich <enkovich.gnu@gmail.com>2015-10-21 16:01:43 +0000
committerIlya Enkovich <ienkovich@gcc.gnu.org>2015-10-21 16:01:43 +0000
commit9f47c7e5cf3f69d34ad09c97a729649d18dfb3a6 (patch)
treec0078faec62f54a6b5b518102c489b0e7cd1f459
parent6f9045f4e16df8791ae67e0508b61accc4c982c2 (diff)
downloadgcc-9f47c7e5cf3f69d34ad09c97a729649d18dfb3a6.zip
gcc-9f47c7e5cf3f69d34ad09c97a729649d18dfb3a6.tar.gz
gcc-9f47c7e5cf3f69d34ad09c97a729649d18dfb3a6.tar.bz2
tm.texi: Regenerated.
gcc/ * 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. From-SVN: r229128
-rw-r--r--gcc/ChangeLog40
-rw-r--r--gcc/c/ChangeLog7
-rw-r--r--gcc/c/c-typeck.c32
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/call.c15
-rw-r--r--gcc/cp/typeck.c16
-rw-r--r--gcc/doc/tm.texi6
-rw-r--r--gcc/doc/tm.texi.in2
-rw-r--r--gcc/optabs.c5
-rw-r--r--gcc/stor-layout.c14
-rw-r--r--gcc/target.def10
-rw-r--r--gcc/targhooks.c14
-rw-r--r--gcc/targhooks.h1
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/ext/vector22.C1
-rw-r--r--gcc/tree-cfg.c21
-rw-r--r--gcc/tree-vect-generic.c57
-rw-r--r--gcc/tree-vect-stmts.c8
-rw-r--r--gcc/tree.c74
-rw-r--r--gcc/tree.h9
20 files changed, 287 insertions, 56 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2971405..d5296ae 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index c1dbde6..34aafc2 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -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.
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index bc43602..6b32781 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -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;
}
+/* 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
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 9f282d8..2a9e873 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index f8db2df..55b3c8c 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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);
}
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 9e6f949..3147609 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 731e630..4a12ad6 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -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
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 0b52250d..6f0c252 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -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
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 223daf7..82a1ee6 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -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));
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 938e54b..58ecd7b 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -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.
diff --git a/gcc/target.def b/gcc/target.def
index 694e455..93478e8 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -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,
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index 5077ec9..01aaed07 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -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. */
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index 77c284a..e13e087 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -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,
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ed725ee..3f325b9 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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>
diff --git a/gcc/testsuite/g++.dg/ext/vector22.C b/gcc/testsuite/g++.dg/ext/vector22.C
index daf4e19..5d28637 100644
--- a/gcc/testsuite/g++.dg/ext/vector22.C
+++ b/gcc/testsuite/g++.dg/ext/vector22.C
@@ -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" } } */
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 5bf546e..8e3e810 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -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;
diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c
index dad38a2..a20b9af 100644
--- a/gcc/tree-vect-generic.c
+++ b/gcc/tree-vect-generic.c
@@ -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
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 3896e5c..19f62d0 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -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)));
}
diff --git a/gcc/tree.c b/gcc/tree.c
index 9d0e9de..6c75699 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -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;
diff --git a/gcc/tree.h b/gcc/tree.h
index f62cd27..300077c 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -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 *);