This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[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: gcc-patches at gcc dot gnu dot org
- Date: Fri, 2 Oct 2015 16:59:21 +0300
- Subject: [Boolean Vector, patch 1/5] Introduce boolean vector to be used as a vector comparison type
- Authentication-results: sourceware.org; auth=none
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.
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 *);