Add support for MODE_VECTOR_BOOL

This patch adds a new mode class to represent vectors of booleans.
GET_MODE_BITSIZE (m) / GET_MODE_NUNITS (m) determines the number
of bits that are used to represent each boolean; this can be 1
for a fully-packed representation or greater than 1 for an unpacked
representation.  In the latter case, the value of bits other than
the lowest is not significant.

These are used by the SVE port to represent predicates.

2018-01-03  Richard Sandiford  <richard.sandiford@linaro.org>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

gcc/
	* mode-classes.def (MODE_VECTOR_BOOL): New mode class.
	* machmode.h (INTEGRAL_MODE_P, VECTOR_MODE_P): Return true
	for MODE_VECTOR_BOOL.
	* machmode.def (VECTOR_BOOL_MODE): Document.
	* genmodes.c (VECTOR_BOOL_MODE): New macro.
	(make_vector_bool_mode): New function.
	(complete_mode, emit_mode_wider, emit_mode_adjustments): Handle
	MODE_VECTOR_BOOL.
	* lto-streamer-in.c (lto_input_mode_table): Likewise.
	* rtx-vector-builder.c (rtx_vector_builder::find_cached_value):
	Likewise.
	* stor-layout.c (int_mode_for_mode): Likewise.
	* tree.c (build_vector_type_for_mode): Likewise.
	* varasm.c (output_constant_pool_2): Likewise.
	* emit-rtl.c (init_emit_once): Make sure that CONST1_RTX (BImode) and
	CONSTM1_RTX (BImode) are the same thing.  Initialize const_tiny_rtx
	for MODE_VECTOR_BOOL.
	* expr.c (expand_expr_real_1): Use VECTOR_MODE_P instead of a list
	of mode class checks.
	* tree-vect-generic.c (expand_vector_operation): Use VECTOR_MODE_P
	instead of a list of mode class checks.
	(expand_vector_scalar_condition): Likewise.
	(type_for_widest_vector_mode): Handle BImode as an inner mode.

gcc/c-family/
	* c-common.c (c_common_type_for_mode): Handle MODE_VECTOR_BOOL.

gcc/fortran/
	* trans-types.c (gfc_type_for_mode): Handle MODE_VECTOR_BOOL.

gcc/go/
	* go-lang.c (go_langhook_type_for_mode): Handle MODE_VECTOR_BOOL.

gcc/lto/
	* lto-lang.c (lto_type_for_mode): Handle MODE_VECTOR_BOOL.

Co-Authored-By: Alan Hayward <alan.hayward@arm.com>
Co-Authored-By: David Sherwood <david.sherwood@arm.com>

From-SVN: r256202
This commit is contained in:
Richard Sandiford 2018-01-03 21:43:02 +00:00 committed by Richard Sandiford
parent cf098191e4
commit 5c0caeb37f
21 changed files with 195 additions and 28 deletions

View File

@ -1,3 +1,31 @@
2018-01-03 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
* mode-classes.def (MODE_VECTOR_BOOL): New mode class.
* machmode.h (INTEGRAL_MODE_P, VECTOR_MODE_P): Return true
for MODE_VECTOR_BOOL.
* machmode.def (VECTOR_BOOL_MODE): Document.
* genmodes.c (VECTOR_BOOL_MODE): New macro.
(make_vector_bool_mode): New function.
(complete_mode, emit_mode_wider, emit_mode_adjustments): Handle
MODE_VECTOR_BOOL.
* lto-streamer-in.c (lto_input_mode_table): Likewise.
* rtx-vector-builder.c (rtx_vector_builder::find_cached_value):
Likewise.
* stor-layout.c (int_mode_for_mode): Likewise.
* tree.c (build_vector_type_for_mode): Likewise.
* varasm.c (output_constant_pool_2): Likewise.
* emit-rtl.c (init_emit_once): Make sure that CONST1_RTX (BImode) and
CONSTM1_RTX (BImode) are the same thing. Initialize const_tiny_rtx
for MODE_VECTOR_BOOL.
* expr.c (expand_expr_real_1): Use VECTOR_MODE_P instead of a list
of mode class checks.
* tree-vect-generic.c (expand_vector_operation): Use VECTOR_MODE_P
instead of a list of mode class checks.
(expand_vector_scalar_condition): Likewise.
(type_for_widest_vector_mode): Handle BImode as an inner mode.
2018-01-03 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>

View File

@ -1,3 +1,9 @@
2018-01-03 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
* c-common.c (c_common_type_for_mode): Handle MODE_VECTOR_BOOL.
2018-01-03 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>

View File

@ -2279,6 +2279,14 @@ c_common_type_for_mode (machine_mode mode, int unsignedp)
if (inner_type != NULL_TREE)
return build_complex_type (inner_type);
}
else if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL
&& valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
{
unsigned int elem_bits = vector_element_size (GET_MODE_BITSIZE (mode),
GET_MODE_NUNITS (mode));
tree bool_type = build_nonstandard_boolean_type (elem_bits);
return build_vector_type_for_mode (bool_type, mode);
}
else if (VECTOR_MODE_P (mode)
&& valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
{

View File

@ -6268,6 +6268,12 @@ init_emit_once (void)
FOR_EACH_MODE_IN_CLASS (mode, MODE_INT)
const_tiny_rtx[3][(int) mode] = constm1_rtx;
/* For BImode, 1 and -1 are unsigned and signed interpretations
of the same value. */
const_tiny_rtx[0][(int) BImode] = const0_rtx;
const_tiny_rtx[1][(int) BImode] = const_true_rtx;
const_tiny_rtx[3][(int) BImode] = const_true_rtx;
for (mode = MIN_MODE_PARTIAL_INT;
mode <= MAX_MODE_PARTIAL_INT;
mode = (machine_mode)((int)(mode) + 1))
@ -6285,6 +6291,15 @@ init_emit_once (void)
const_tiny_rtx[0][(int) mode] = gen_rtx_CONCAT (mode, inner, inner);
}
/* As for BImode, "all 1" and "all -1" are unsigned and signed
interpretations of the same value. */
FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_BOOL)
{
const_tiny_rtx[0][(int) mode] = gen_const_vector (mode, 0);
const_tiny_rtx[3][(int) mode] = gen_const_vector (mode, 3);
const_tiny_rtx[1][(int) mode] = const_tiny_rtx[3][(int) mode];
}
FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_INT)
{
const_tiny_rtx[0][(int) mode] = gen_const_vector (mode, 0);
@ -6386,10 +6401,6 @@ init_emit_once (void)
if (GET_MODE_CLASS ((machine_mode) i) == MODE_CC)
const_tiny_rtx[0][i] = const0_rtx;
const_tiny_rtx[0][(int) BImode] = const0_rtx;
if (STORE_FLAG_VALUE == 1)
const_tiny_rtx[1][(int) BImode] = const1_rtx;
FOR_EACH_MODE_IN_CLASS (smode_iter, MODE_POINTER_BOUNDS)
{
scalar_mode smode = smode_iter.require ();

View File

@ -10082,12 +10082,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
case VECTOR_CST:
{
tree tmp = NULL_TREE;
if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT
|| GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT
|| GET_MODE_CLASS (mode) == MODE_VECTOR_FRACT
|| GET_MODE_CLASS (mode) == MODE_VECTOR_UFRACT
|| GET_MODE_CLASS (mode) == MODE_VECTOR_ACCUM
|| GET_MODE_CLASS (mode) == MODE_VECTOR_UACCUM)
if (VECTOR_MODE_P (mode))
return const_vector_from_tree (exp);
scalar_int_mode int_mode;
if (is_int_mode (mode, &int_mode))

View File

@ -1,3 +1,9 @@
2018-01-03 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
* trans-types.c (gfc_type_for_mode): Handle MODE_VECTOR_BOOL.
2018-01-03 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>

View File

@ -3185,6 +3185,14 @@ gfc_type_for_mode (machine_mode mode, int unsignedp)
tree type = gfc_type_for_size (GET_MODE_PRECISION (int_mode), unsignedp);
return type != NULL_TREE && mode == TYPE_MODE (type) ? type : NULL_TREE;
}
else if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL
&& valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
{
unsigned int elem_bits = vector_element_size (GET_MODE_BITSIZE (mode),
GET_MODE_NUNITS (mode));
tree bool_type = build_nonstandard_boolean_type (elem_bits);
return build_vector_type_for_mode (bool_type, mode);
}
else if (VECTOR_MODE_P (mode)
&& valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
{

View File

@ -375,6 +375,10 @@ complete_mode (struct mode_data *m)
m->bytesize = 2 * m->component->bytesize;
break;
case MODE_VECTOR_BOOL:
validate_mode (m, UNSET, SET, SET, SET, UNSET);
break;
case MODE_VECTOR_INT:
case MODE_VECTOR_FLOAT:
case MODE_VECTOR_FRACT:
@ -526,6 +530,28 @@ make_vector_modes (enum mode_class cl, unsigned int width,
}
}
/* Create a vector of booleans called NAME with COUNT elements and
BYTESIZE bytes in total. */
#define VECTOR_BOOL_MODE(NAME, COUNT, BYTESIZE) \
make_vector_bool_mode (#NAME, COUNT, BYTESIZE, __FILE__, __LINE__)
static void ATTRIBUTE_UNUSED
make_vector_bool_mode (const char *name, unsigned int count,
unsigned int bytesize, const char *file,
unsigned int line)
{
struct mode_data *m = find_mode ("BI");
if (!m)
{
error ("%s:%d: no mode \"BI\"", file, line);
return;
}
struct mode_data *v = new_mode (MODE_VECTOR_BOOL, name, file, line);
v->component = m;
v->ncomponents = count;
v->bytesize = bytesize;
}
/* Input. */
#define _SPECIAL_MODE(C, N) \
@ -1438,7 +1464,8 @@ emit_mode_wider (void)
/* For vectors we want twice the number of components,
with the same element type. */
if (m->cl == MODE_VECTOR_INT
if (m->cl == MODE_VECTOR_BOOL
|| m->cl == MODE_VECTOR_INT
|| m->cl == MODE_VECTOR_FLOAT
|| m->cl == MODE_VECTOR_FRACT
|| m->cl == MODE_VECTOR_UFRACT
@ -1657,6 +1684,7 @@ emit_mode_adjustments (void)
printf ("\n /* %s:%d */\n", a->file, a->line);
switch (a->mode->cl)
{
case MODE_VECTOR_BOOL:
case MODE_VECTOR_INT:
case MODE_VECTOR_FLOAT:
case MODE_VECTOR_FRACT:
@ -1688,6 +1716,10 @@ emit_mode_adjustments (void)
m->name);
break;
case MODE_VECTOR_BOOL:
/* Changes to BImode should not affect vector booleans. */
break;
case MODE_VECTOR_INT:
case MODE_VECTOR_FLOAT:
case MODE_VECTOR_FRACT:
@ -1728,6 +1760,10 @@ emit_mode_adjustments (void)
printf (" mode_base_align[E_%smode] = s;\n", m->name);
break;
case MODE_VECTOR_BOOL:
/* Changes to BImode should not affect vector booleans. */
break;
case MODE_VECTOR_INT:
case MODE_VECTOR_FLOAT:
case MODE_VECTOR_FRACT:

View File

@ -1,3 +1,9 @@
2018-01-03 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
* go-lang.c (go_langhook_type_for_mode): Handle MODE_VECTOR_BOOL.
2018-01-03 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>

View File

@ -377,8 +377,16 @@ go_langhook_type_for_mode (machine_mode mode, int unsignedp)
make sense for the middle-end to ask the frontend for a type
which the frontend does not support. However, at least for now
it is required. See PR 46805. */
if (VECTOR_MODE_P (mode)
if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL
&& valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
{
unsigned int elem_bits = vector_element_size (GET_MODE_BITSIZE (mode),
GET_MODE_NUNITS (mode));
tree bool_type = build_nonstandard_boolean_type (elem_bits);
return build_vector_type_for_mode (bool_type, mode);
}
else if (VECTOR_MODE_P (mode)
&& valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
{
tree inner;

View File

@ -1675,6 +1675,7 @@ lto_input_mode_table (struct lto_file_decl_data *file_data)
{
switch (mclass)
{
case MODE_VECTOR_BOOL:
case MODE_VECTOR_INT:
case MODE_VECTOR_FLOAT:
case MODE_VECTOR_FRACT:

View File

@ -1,3 +1,9 @@
2018-01-03 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
* lto-lang.c (lto_type_for_mode): Handle MODE_VECTOR_BOOL.
2018-01-03 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>

View File

@ -1012,6 +1012,14 @@ lto_type_for_mode (machine_mode mode, int unsigned_p)
if (inner_type != NULL_TREE)
return build_complex_type (inner_type);
}
else if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL
&& valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
{
unsigned int elem_bits = vector_element_size (GET_MODE_BITSIZE (mode),
GET_MODE_NUNITS (mode));
tree bool_type = build_nonstandard_boolean_type (elem_bits);
return build_vector_type_for_mode (bool_type, mode);
}
else if (VECTOR_MODE_P (mode)
&& valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
{

View File

@ -142,6 +142,13 @@ along with GCC; see the file COPYING3. If not see
than two bytes (if CLASS is FLOAT). CLASS must be INT or
FLOAT. The names follow the same rule as VECTOR_MODE uses.
VECTOR_BOOL_MODE (NAME, COUNT, BYTESIZE)
Create a vector mode called NAME that contains COUNT boolean
elements and occupies BYTESIZE bytes in total. Each boolean
element occupies (COUNT * BITS_PER_UNIT) / BYTESIZE bits, with
the element at index 0 occupying the lsb of the first byte in
memory. Only the lowest bit of each element is significant.
COMPLEX_MODES (CLASS);
For all modes presently declared in class CLASS, construct
corresponding complex modes. Modes smaller than one byte

View File

@ -108,6 +108,7 @@ extern const unsigned char mode_class[NUM_MACHINE_MODES];
(GET_MODE_CLASS (MODE) == MODE_INT \
|| GET_MODE_CLASS (MODE) == MODE_PARTIAL_INT \
|| GET_MODE_CLASS (MODE) == MODE_COMPLEX_INT \
|| GET_MODE_CLASS (MODE) == MODE_VECTOR_BOOL \
|| GET_MODE_CLASS (MODE) == MODE_VECTOR_INT)
/* Nonzero if MODE is a floating-point mode. */
@ -123,8 +124,9 @@ extern const unsigned char mode_class[NUM_MACHINE_MODES];
|| GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT)
/* Nonzero if MODE is a vector mode. */
#define VECTOR_MODE_P(MODE) \
(GET_MODE_CLASS (MODE) == MODE_VECTOR_INT \
#define VECTOR_MODE_P(MODE) \
(GET_MODE_CLASS (MODE) == MODE_VECTOR_BOOL \
|| GET_MODE_CLASS (MODE) == MODE_VECTOR_INT \
|| GET_MODE_CLASS (MODE) == MODE_VECTOR_FLOAT \
|| GET_MODE_CLASS (MODE) == MODE_VECTOR_FRACT \
|| GET_MODE_CLASS (MODE) == MODE_VECTOR_UFRACT \

View File

@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see
DEF_MODE_CLASS (MODE_DECIMAL_FLOAT), /* decimal floating point */ \
DEF_MODE_CLASS (MODE_COMPLEX_INT), /* complex numbers */ \
DEF_MODE_CLASS (MODE_COMPLEX_FLOAT), \
DEF_MODE_CLASS (MODE_VECTOR_BOOL), /* vectors of single bits */ \
DEF_MODE_CLASS (MODE_VECTOR_INT), /* SIMD vectors */ \
DEF_MODE_CLASS (MODE_VECTOR_FRACT), /* SIMD vectors */ \
DEF_MODE_CLASS (MODE_VECTOR_UFRACT), /* SIMD vectors */ \

View File

@ -88,6 +88,16 @@ rtx_vector_builder::find_cached_value ()
rtx elt = (*this)[0];
if (GET_MODE_CLASS (m_mode) == MODE_VECTOR_BOOL)
{
if (elt == const1_rtx || elt == constm1_rtx)
return CONST1_RTX (m_mode);
else if (elt == const0_rtx)
return CONST0_RTX (m_mode);
else
gcc_unreachable ();
}
/* We can be called before the global vector constants are set up,
but in that case we'll just return null. */
scalar_mode inner_mode = GET_MODE_INNER (m_mode);

View File

@ -379,12 +379,13 @@ int_mode_for_mode (machine_mode mode)
case MODE_COMPLEX_FLOAT:
case MODE_FLOAT:
case MODE_DECIMAL_FLOAT:
case MODE_VECTOR_INT:
case MODE_VECTOR_FLOAT:
case MODE_FRACT:
case MODE_ACCUM:
case MODE_UFRACT:
case MODE_UACCUM:
case MODE_VECTOR_BOOL:
case MODE_VECTOR_INT:
case MODE_VECTOR_FLOAT:
case MODE_VECTOR_FRACT:
case MODE_VECTOR_ACCUM:
case MODE_VECTOR_UFRACT:

View File

@ -981,12 +981,7 @@ expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type
/* If the compute mode is not a vector mode (hence we are not decomposing
a BLKmode vector to smaller, hardware-supported vectors), we may want
to expand the operations in parallel. */
if (GET_MODE_CLASS (compute_mode) != MODE_VECTOR_INT
&& GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FLOAT
&& GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FRACT
&& GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UFRACT
&& GET_MODE_CLASS (compute_mode) != MODE_VECTOR_ACCUM
&& GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UACCUM)
if (!VECTOR_MODE_P (compute_mode))
switch (code)
{
case PLUS_EXPR:
@ -1175,6 +1170,8 @@ type_for_widest_vector_mode (tree type, optab op)
mode = MIN_MODE_VECTOR_ACCUM;
else if (SCALAR_UACCUM_MODE_P (inner_mode))
mode = MIN_MODE_VECTOR_UACCUM;
else if (inner_mode == BImode)
mode = MIN_MODE_VECTOR_BOOL;
else
mode = MIN_MODE_VECTOR_INT;
@ -1537,12 +1534,7 @@ expand_vector_scalar_condition (gimple_stmt_iterator *gsi)
/* If the compute mode is not a vector mode (hence we are not decomposing
a BLKmode vector to smaller, hardware-supported vectors), we may want
to expand the operations in parallel. */
if (GET_MODE_CLASS (compute_mode) != MODE_VECTOR_INT
&& GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FLOAT
&& GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FRACT
&& GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UFRACT
&& GET_MODE_CLASS (compute_mode) != MODE_VECTOR_ACCUM
&& GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UACCUM)
if (!VECTOR_MODE_P (compute_mode))
new_rhs = expand_vector_parallel (gsi, do_cond, type, rhs2, rhs3,
COND_EXPR);
else

View File

@ -10509,6 +10509,7 @@ build_vector_type_for_mode (tree innertype, machine_mode mode)
switch (GET_MODE_CLASS (mode))
{
case MODE_VECTOR_BOOL:
case MODE_VECTOR_INT:
case MODE_VECTOR_FLOAT:
case MODE_VECTOR_FRACT:

View File

@ -3918,6 +3918,32 @@ output_constant_pool_2 (fixed_size_mode mode, rtx x, unsigned int align)
assemble_integer (x, GET_MODE_SIZE (mode), align, 1);
break;
case MODE_VECTOR_BOOL:
{
gcc_assert (GET_CODE (x) == CONST_VECTOR);
/* Pick the smallest integer mode that contains at least one
whole element. Often this is byte_mode and contains more
than one element. */
unsigned int nelts = GET_MODE_NUNITS (mode);
unsigned int elt_bits = GET_MODE_BITSIZE (mode) / nelts;
unsigned int int_bits = MAX (elt_bits, BITS_PER_UNIT);
scalar_int_mode int_mode = int_mode_for_size (int_bits, 0).require ();
/* Build the constant up one integer at a time. */
unsigned int elts_per_int = int_bits / elt_bits;
for (unsigned int i = 0; i < nelts; i += elts_per_int)
{
unsigned HOST_WIDE_INT value = 0;
unsigned int limit = MIN (nelts - i, elts_per_int);
for (unsigned int j = 0; j < limit; ++j)
if (INTVAL (CONST_VECTOR_ELT (x, i + j)) != 0)
value |= 1 << (j * elt_bits);
output_constant_pool_2 (int_mode, gen_int_mode (value, int_mode),
i != 0 ? MIN (align, int_bits) : align);
}
break;
}
case MODE_VECTOR_FLOAT:
case MODE_VECTOR_INT:
case MODE_VECTOR_FRACT: