diff mbox

[Boolean,Vector,1/5] Introduce boolean vector to be used as a vector comparison type

Message ID 20151002135921.GE26618@msticlxl57.ims.intel.com
State New
Headers show

Commit Message

Ilya Enkovich Oct. 2, 2015, 1:59 p.m. UTC
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.

Thanks,
Ilya
--
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.

Comments

Jeff Law Oct. 9, 2015, 8:43 p.m. UTC | #1
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
Richard Biener Oct. 13, 2015, 1:17 p.m. UTC | #2
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
Ilya Enkovich Oct. 13, 2015, 1:35 p.m. UTC | #3
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
Andreas Schwab Oct. 22, 2015, 10:13 a.m. UTC | #4
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.
Ilya Enkovich Oct. 22, 2015, 10:27 a.m. UTC | #5
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
Andreas Schwab Oct. 22, 2015, 10:37 a.m. UTC | #6
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.
James Greenhalgh Oct. 28, 2015, 2:51 p.m. UTC | #7
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 mbox

Patch

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 *);