This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [Boolean Vector, patch 1/5] Introduce boolean vector to be used as a vector comparison type
- From: Ilya Enkovich <enkovich dot gnu at gmail dot com>
- To: Jeff Law <law at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Tue, 13 Oct 2015 16:16:22 +0300
- Subject: Re: [Boolean Vector, patch 1/5] Introduce boolean vector to be used as a vector comparison type
- Authentication-results: sourceware.org; auth=none
- References: <20151002135921 dot GE26618 at msticlxl57 dot ims dot intel dot com> <561826D6 dot 3050101 at redhat dot com>
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.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.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 *);