On 09 Oct 14:43, Jeff Law wrote: > On 10/02/2015 07:59 AM, Ilya Enkovich wrote: > >+This hook returns mode to be used for a mask to be used for a vector > >+of specified @var{length} with @var{nunits} elements. > >+@end deftypefn > Does it make sense to indicate the default used if the target does not > provide a definition for this hook? > >
Sure > > > >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)); > Shouldn't this be TYPE_MODE rather than accessing the internals of the tree > node directly? Previous version of this patch had changes in vector_type_mode and seems I copy-pasted this field access from there. Will fix it here. > > > >diff --git a/gcc/tree.c b/gcc/tree.c > >index 84fd34d..0cb8361 100644 > >--- a/gcc/tree.c > >+++ b/gcc/tree.c > >@@ -11067,9 +11130,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))); > Presumably you're not building an opaque type anymore because you want > warnings if somethings tries to do a conversion? I'm going to assume this > was intentional. Right. I don't expect front-end to cast boolean vector to anything. Its usage should be limited by VEC_COND_EXPR. > > > With the doc update and the fix to use TYPE_MODE (assuming there's not a > good reason to be looking at the underlying type directly) this is OK. > > jeff Here is an updated version. Thanks, Ilya -- 2015-10-13 Ilya Enkovich <enkovich....@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. diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 33939ec..914cfea 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/stor-layout.c b/gcc/stor-layout.c index 938e54b..d2289d9 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_MODE (type))); + 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 d29aad5..f166fbb 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 7238c8f..ac01d57 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/tree-vect-stmts.c b/gcc/tree-vect-stmts.c index 0073ddb..df08926 100644 --- a/gcc/tree-vect-stmts.c +++ b/gcc/tree-vect-stmts.c @@ -8190,6 +8190,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 02f0a7a..6eeb13d 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -8015,6 +8015,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. */ @@ -9765,8 +9793,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); @@ -10591,6 +10620,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 @@ -11077,9 +11140,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 a776b89..0ee3dce 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. */ @@ -3826,6 +3832,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); @@ -4546,6 +4554,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 *);