Message ID | 20151002135921.GE26618@msticlxl57.ims.intel.com |
---|---|
State | New |
Headers | show |
On 10/02/2015 07:59 AM, Ilya Enkovich wrote: > 2015-10-02 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. > > > diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi > index eb495a8..098213e 100644 > --- a/gcc/doc/tm.texi > +++ b/gcc/doc/tm.texi > @@ -5688,6 +5688,11 @@ 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. > +@end deftypefn Does it make sense to indicate the default used if the target does not provide a definition for this hook? > 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? > 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. 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
On Fri, Oct 9, 2015 at 10:43 PM, Jeff Law <law@redhat.com> wrote: > On 10/02/2015 07:59 AM, Ilya Enkovich wrote: >> >> 2015-10-02 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. >> >> >> diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi >> index eb495a8..098213e 100644 >> --- a/gcc/doc/tm.texi >> +++ b/gcc/doc/tm.texi >> @@ -5688,6 +5688,11 @@ 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. >> +@end deftypefn > > Does it make sense to indicate the default used if the target does not > provide a definition for this hook? > > > > >> 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? Probably not because of TYPE_MODE interfering for vector types. But... +/* 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); do we really need differing _precision_ boolean types? I think we only need differing size (aka mode) boolean types, no? Thus, keep precision == 1 but "only" adjust the mode (possibly by simply setting precision to 1 after fixup_unsigned_type ...)? Richard. > >> 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. > > > 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
2015-10-13 16:17 GMT+03:00 Richard Biener <richard.guenther@gmail.com>: > On Fri, Oct 9, 2015 at 10:43 PM, Jeff Law <law@redhat.com> wrote: >> On 10/02/2015 07:59 AM, Ilya Enkovich wrote: >>> >>> 2015-10-02 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. >>> >>> >>> diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi >>> index eb495a8..098213e 100644 >>> --- a/gcc/doc/tm.texi >>> +++ b/gcc/doc/tm.texi >>> @@ -5688,6 +5688,11 @@ 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. >>> +@end deftypefn >> >> Does it make sense to indicate the default used if the target does not >> provide a definition for this hook? >> >> >> >> >>> 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? > > Probably not because of TYPE_MODE interfering for vector types. Seems I need to roll it back then. I don't think I want scalar mode to be used for cases when proper integer vector mode is unsupported by target but returned by default get_mask_mode hook. Such cases just should be lowered into scalars. > > But... > > +/* 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); > > do we really need differing _precision_ boolean types? I think we only > need differing size (aka mode) boolean types, no? Thus, keep precision == 1 > but "only" adjust the mode (possibly by simply setting precision to 1 after > fixup_unsigned_type ...)? The reason for that was -1 value of a proper size which may be used as vector element value. I'm not sure if something breaks in the compiler if I set 1 precision for all created boolean types, but I assumed it's reasonable to match precision and actually stored values. Ilya > > Richard. > >> >>> 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. >> >> >> 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
FAIL: gcc.c-torture/compile/pr54713-1.c -O0 (internal compiler error) $ gcc/xgcc -Bgcc/ -w -c ../gcc/testsuite/gcc.c-torture/compile/pr54713-1.c ../gcc/testsuite/gcc.c-torture/compile/pr54713-1.c: In function ‘f4’: ../gcc/testsuite/gcc.c-torture/compile/pr54713-1.c:31:1: error: position plus size exceeds size of referenced object in BIT_FIELD_REF f4 (V *p, V *q) ^ BIT_FIELD_REF <_8, 32, 64> ../gcc/testsuite/gcc.c-torture/compile/pr54713-1.c:33:18: note: in statement *p = (*p ^ *q) == *q; ^ _47 = BIT_FIELD_REF <_8, 32, 64>; ../gcc/testsuite/gcc.c-torture/compile/pr54713-1.c:31:1: error: position plus size exceeds size of referenced object in BIT_FIELD_REF f4 (V *p, V *q) ^ BIT_FIELD_REF <_8, 32, 96> ../gcc/testsuite/gcc.c-torture/compile/pr54713-1.c:33:18: note: in statement *p = (*p ^ *q) == *q; ^ _50 = BIT_FIELD_REF <_8, 32, 96>; ../gcc/testsuite/gcc.c-torture/compile/pr54713-1.c:31:1: error: position plus size exceeds size of referenced object in BIT_FIELD_REF f4 (V *p, V *q) ^ BIT_FIELD_REF <_8, 32, 128> ../gcc/testsuite/gcc.c-torture/compile/pr54713-1.c:33:18: note: in statement *p = (*p ^ *q) == *q; ^ _53 = BIT_FIELD_REF <_8, 32, 128>; ../gcc/testsuite/gcc.c-torture/compile/pr54713-1.c:31:1: error: position plus size exceeds size of referenced object in BIT_FIELD_REF f4 (V *p, V *q) ^ BIT_FIELD_REF <_8, 32, 160> ../gcc/testsuite/gcc.c-torture/compile/pr54713-1.c:33:18: note: in statement *p = (*p ^ *q) == *q; ^ _56 = BIT_FIELD_REF <_8, 32, 160>; ../gcc/testsuite/gcc.c-torture/compile/pr54713-1.c:31:1: error: position plus size exceeds size of referenced object in BIT_FIELD_REF f4 (V *p, V *q) ^ BIT_FIELD_REF <_8, 32, 192> ../gcc/testsuite/gcc.c-torture/compile/pr54713-1.c:33:18: note: in statement *p = (*p ^ *q) == *q; ^ _59 = BIT_FIELD_REF <_8, 32, 192>; ../gcc/testsuite/gcc.c-torture/compile/pr54713-1.c:31:1: error: position plus size exceeds size of referenced object in BIT_FIELD_REF f4 (V *p, V *q) ^ BIT_FIELD_REF <_8, 32, 224> ../gcc/testsuite/gcc.c-torture/compile/pr54713-1.c:33:18: note: in statement *p = (*p ^ *q) == *q; ^ _62 = BIT_FIELD_REF <_8, 32, 224>; ../gcc/testsuite/gcc.c-torture/compile/pr54713-1.c:31:1: internal compiler error: verify_gimple failed f4 (V *p, V *q) ^ 0xa7b98b verify_gimple_in_cfg(function*, bool) ../../gcc/tree-cfg.c:5093 0x97f63f execute_function_todo ../../gcc/passes.c:1976 0x97fffb execute_todo ../../gcc/passes.c:2033 Andreas.
2015-10-22 13:13 GMT+03:00 Andreas Schwab <schwab@suse.de>:
> FAIL: gcc.c-torture/compile/pr54713-1.c -O0 (internal compiler error)
Can't reproduce it on i386. What's config used?
Ilya
Ilya Enkovich <enkovich.gnu@gmail.com> writes: > 2015-10-22 13:13 GMT+03:00 Andreas Schwab <schwab@suse.de>: >> FAIL: gcc.c-torture/compile/pr54713-1.c -O0 (internal compiler error) > > Can't reproduce it on i386. What's config used? http://gcc.gnu.org/ml/gcc-testresults/2015-10/msg02350.html http://gcc.gnu.org/ml/gcc-testresults/2015-10/msg02361.html http://gcc.gnu.org/ml/gcc-testresults/2015-10/msg02396.html Andreas.
On Fri, Oct 02, 2015 at 02:59:21PM +0100, Ilya Enkovich wrote: > Hi, > > This patch starts the first series to introduce vec<bool> as a vector > comparison type. This series introduces the new vec<bool> type and force its > usage for all vector comparisons. This series doesn't intoroduce any new > vectorization features. I split it into five small patches but will commit > in a single chunk. Patch series was bootstrapped and tested on > x86_64-unknown-linux-gnu. > > The first patch introduces a target hook and functions to produce new vector > type. Hi, This patch (or whatever combination of patches became r229129) caused an ICE to show up in my random testing of the AArch64 arm_neon.h intrinsics. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68134 I've tried reproducing the failure on other targets but I can't seem to get it to trigger elsewhere. Thanks, James --- random-test.c:10:42: internal compiler error: in prepare_cmp_insn, at optabs.c:3820 uint64x1_t result = (uint64x1_t) (arg1 == arg2); ^ 0x996e40 prepare_cmp_insn ..../src/gcc/gcc/optabs.c:3820 0x997396 emit_cmp_and_jump_insns(rtx_def*, rtx_def*, rtx_code, rtx_def*, machine_mode, int, rtx_def*, int) ..../src/gcc/gcc/optabs.c:3967 0x72e934 do_compare_rtx_and_jump(rtx_def*, rtx_def*, rtx_code, int, machine_mode, rtx_def*, rtx_code_label*, rtx_code_label*, int) ..../src/gcc/gcc/dojump.c:1149 0x72f52a do_compare_and_jump ..../src/gcc/gcc/dojump.c:1228 0x73134f do_jump_1(tree_code, tree_node*, tree_node*, rtx_code_label*, rtx_code_label*, int) ..../src/gcc/gcc/dojump.c:240 0x731c68 jumpifnot_1(tree_code, tree_node*, tree_node*, rtx_code_label*, int) ..../src/gcc/gcc/dojump.c:148 0x7c6e47 expand_expr_real_2(separate_ops*, rtx_def*, machine_mode, expand_modifier) ..../src/gcc/gcc/expr.c:9030 0x6c5ad9 expand_gimple_stmt_1 ..../src/gcc/gcc/cfgexpand.c:3617 0x6c5ad9 expand_gimple_stmt ..../src/gcc/gcc/cfgexpand.c:3677 0x6c8316 expand_gimple_basic_block ..../src/gcc/gcc/cfgexpand.c:5681 0x6cb8c4 execute ..../src/gcc/gcc/cfgexpand.c:6293 Please submit a full bug report, with preprocessed source if appropriate. Please include the complete backtrace with any bug report. See <http://gcc.gnu.org/bugs.html> for instructions.
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index eb495a8..098213e 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -5688,6 +5688,11 @@ 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. +@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 92835c1..92cfa1d 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..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 f330709..b96fd51 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -1789,6 +1789,15 @@ 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.", + 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 5ae991d..cc7263f 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 cb9e7e8..2ff2827 100644 --- a/gcc/tree-vect-stmts.c +++ b/gcc/tree-vect-stmts.c @@ -8201,6 +8201,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 84fd34d..0cb8361 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -8005,6 +8005,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. */ @@ -9755,8 +9783,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); @@ -10581,6 +10610,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 @@ -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))); } else return boolean_type_node; diff --git a/gcc/tree.h b/gcc/tree.h index e500151..a85e9a7 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -469,6 +469,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. */ @@ -3820,6 +3826,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); @@ -4540,6 +4548,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 *);