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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@256202
138bc75d-0d04-0410-961f-
82ee72b054a4
+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>
+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>
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)))
{
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))
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);
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 ();
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))
+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>
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)))
{
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:
}
}
+/* 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) \
/* 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
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:
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:
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:
+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>
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;
{
switch (mclass)
{
+ case MODE_VECTOR_BOOL:
case MODE_VECTOR_INT:
case MODE_VECTOR_FLOAT:
case MODE_VECTOR_FRACT:
+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>
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)))
{
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
(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. */
|| 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 \
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 */ \
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);
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:
/* 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:
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;
/* 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
switch (GET_MODE_CLASS (mode))
{
+ case MODE_VECTOR_BOOL:
case MODE_VECTOR_INT:
case MODE_VECTOR_FLOAT:
case MODE_VECTOR_FRACT:
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: