+2017-09-05 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * machmode.h (mode_for_vector): Return an opt_mode.
+ * stor-layout.c (mode_for_vector): Likewise.
+ (mode_for_int_vector): Update accordingly.
+ (layout_type): Likewise.
+ * config/i386/i386.c (emit_memmov): Likewise.
+ (ix86_expand_set_or_movmem): Likewise.
+ (ix86_expand_vector_init): Likewise.
+ (ix86_get_mask_mode): Likewise.
+ * config/powerpcspe/powerpcspe.c (rs6000_expand_vec_perm_const_1):
+ Likewise.
+ * config/rs6000/rs6000.c (rs6000_expand_vec_perm_const_1): Likewise.
+ * expmed.c (extract_bit_field_1): Likewise.
+ * expr.c (expand_expr_real_2): Likewise.
+ * optabs-query.c (can_vec_perm_p): Likewise.
+ (can_vec_mask_load_store_p): Likewise.
+ * optabs.c (expand_vec_perm): Likewise.
+ * targhooks.c (default_get_mask_mode): Likewise.
+ * tree-vect-stmts.c (vectorizable_store): Likewise.
+ (vectorizable_load): Likewise.
+ (get_vectype_for_scalar_type_and_size): Likewise.
+
2017-09-05 Richard Sandiford <richard.sandiford@linaro.org>
* machmode.h (mode_for_int_vector): New function.
if (GET_MODE_SIZE (move_mode) > GET_MODE_SIZE (word_mode))
{
int nunits = GET_MODE_SIZE (move_mode) / GET_MODE_SIZE (word_mode);
- move_mode = mode_for_vector (word_mode, nunits);
- code = optab_handler (mov_optab, move_mode);
- if (code == CODE_FOR_nothing)
+ if (!mode_for_vector (word_mode, nunits).exists (&move_mode)
+ || (code = optab_handler (mov_optab, move_mode)) == CODE_FOR_nothing)
{
move_mode = word_mode;
piece_size = GET_MODE_SIZE (move_mode);
if (GET_MODE_SIZE (move_mode) > GET_MODE_SIZE (word_mode))
{
int nunits = GET_MODE_SIZE (move_mode) / GET_MODE_SIZE (word_mode);
- move_mode = mode_for_vector (word_mode, nunits);
- if (optab_handler (mov_optab, move_mode) == CODE_FOR_nothing)
+ if (!mode_for_vector (word_mode, nunits).exists (&move_mode)
+ || optab_handler (mov_optab, move_mode) == CODE_FOR_nothing)
move_mode = word_mode;
}
gcc_assert (optab_handler (mov_optab, move_mode) != CODE_FOR_nothing);
rtx ops[2] = { XVECEXP (vals, 0, 0), XVECEXP (vals, 0, 1) };
if (inner_mode == QImode || inner_mode == HImode)
{
- mode = mode_for_vector (SImode,
- n_elts * GET_MODE_SIZE (inner_mode) / 4);
- inner_mode
- = mode_for_vector (SImode,
- n_elts * GET_MODE_SIZE (inner_mode) / 8);
+ unsigned int n_bits = n_elts * GET_MODE_SIZE (inner_mode);
+ mode = mode_for_vector (SImode, n_bits / 4).require ();
+ inner_mode = mode_for_vector (SImode, n_bits / 8).require ();
ops[0] = gen_lowpart (inner_mode, ops[0]);
ops[1] = gen_lowpart (inner_mode, ops[1]);
subtarget = gen_reg_rtx (mode);
gcc_assert (elem_size * nunits == vector_size);
- return mode_for_vector (elem_mode, nunits);
+ return mode_for_vector (elem_mode, nunits).else_blk ();
}
\f
vmode = GET_MODE (target);
gcc_assert (GET_MODE_NUNITS (vmode) == 2);
- dmode = mode_for_vector (GET_MODE_INNER (vmode), 4);
+ dmode = mode_for_vector (GET_MODE_INNER (vmode), 4).require ();
x = gen_rtx_VEC_CONCAT (dmode, op0, op1);
v = gen_rtvec (2, GEN_INT (perm0), GEN_INT (perm1));
x = gen_rtx_VEC_SELECT (vmode, x, gen_rtx_PARALLEL (VOIDmode, v));
vmode = GET_MODE (target);
gcc_assert (GET_MODE_NUNITS (vmode) == 2);
- dmode = mode_for_vector (GET_MODE_INNER (vmode), 4);
+ dmode = mode_for_vector (GET_MODE_INNER (vmode), 4).require ();
x = gen_rtx_VEC_CONCAT (dmode, op0, op1);
v = gen_rtvec (2, GEN_INT (perm0), GEN_INT (perm1));
x = gen_rtx_VEC_SELECT (vmode, x, gen_rtx_PARALLEL (VOIDmode, v));
machine_mode new_mode = GET_MODE (op0);
if (GET_MODE_INNER (new_mode) != GET_MODE_INNER (tmode))
{
- new_mode = mode_for_vector (GET_MODE_INNER (tmode),
- GET_MODE_BITSIZE (GET_MODE (op0))
- / GET_MODE_UNIT_BITSIZE (tmode));
- if (!VECTOR_MODE_P (new_mode)
+ scalar_mode inner_mode = GET_MODE_INNER (tmode);
+ unsigned int nunits = (GET_MODE_BITSIZE (GET_MODE (op0))
+ / GET_MODE_UNIT_BITSIZE (tmode));
+ if (!mode_for_vector (inner_mode, nunits).exists (&new_mode)
+ || !VECTOR_MODE_P (new_mode)
|| GET_MODE_SIZE (new_mode) != GET_MODE_SIZE (GET_MODE (op0))
|| GET_MODE_INNER (new_mode) != GET_MODE_INNER (tmode)
|| !targetm.vector_mode_supported_p (new_mode))
tree sel_type = TREE_TYPE (treeop2);
machine_mode vmode
= mode_for_vector (SCALAR_TYPE_MODE (TREE_TYPE (sel_type)),
- TYPE_VECTOR_SUBPARTS (sel_type));
+ TYPE_VECTOR_SUBPARTS (sel_type)).require ();
gcc_assert (GET_MODE_CLASS (vmode) == MODE_VECTOR_INT);
op2 = simplify_subreg (vmode, op2, TYPE_MODE (sel_type), 0);
gcc_assert (op2 && GET_CODE (op2) == CONST_VECTOR);
(mode_for_size (size, MODE_DECIMAL_FLOAT, 0));
}
-/* Similar to mode_for_size, but find the smallest mode for a given width. */
-
extern machine_mode smallest_mode_for_size (unsigned int, enum mode_class);
/* Find the narrowest integer mode that contains at least SIZE bits.
return as_a <scalar_int_mode> (smallest_mode_for_size (size, MODE_INT));
}
-/* Return an integer mode of exactly the same size as the input mode. */
-
extern opt_scalar_int_mode int_mode_for_mode (machine_mode);
-
extern machine_mode bitwise_mode_for_mode (machine_mode);
-
-/* Return a mode that is suitable for representing a vector,
- or BLKmode on failure. */
-
-extern machine_mode mode_for_vector (scalar_mode, unsigned);
-
+extern opt_machine_mode mode_for_vector (scalar_mode, unsigned);
extern opt_machine_mode mode_for_int_vector (unsigned int, unsigned int);
/* Return the integer vector equivalent of MODE, if one exists. In other
return true;
/* We allow fallback to a QI vector mode, and adjust the mask. */
- if (GET_MODE_INNER (mode) == QImode)
- return false;
- qimode = mode_for_vector (QImode, GET_MODE_SIZE (mode));
- if (!VECTOR_MODE_P (qimode))
+ if (GET_MODE_INNER (mode) == QImode
+ || !mode_for_vector (QImode, GET_MODE_SIZE (mode)).exists (&qimode)
+ || !VECTOR_MODE_P (qimode))
return false;
/* ??? For completeness, we ought to check the QImode version of
vector_sizes &= ~cur;
if (cur <= GET_MODE_SIZE (smode))
continue;
- vmode = mode_for_vector (smode, cur / GET_MODE_SIZE (smode));
- mask_mode = targetm.vectorize.get_mask_mode (GET_MODE_NUNITS (vmode),
- cur);
- if (VECTOR_MODE_P (vmode)
- && convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing)
- return true;
+ unsigned int nunits = cur / GET_MODE_SIZE (smode);
+ if (mode_for_vector (smode, nunits).exists (&vmode)
+ && VECTOR_MODE_P (vmode))
+ {
+ mask_mode = targetm.vectorize.get_mask_mode (nunits, cur);
+ if (convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing)
+ return true;
+ }
}
return false;
}
/* Set QIMODE to a different vector mode with byte elements.
If no such mode, or if MODE already has byte elements, use VOIDmode. */
- qimode = VOIDmode;
- if (GET_MODE_INNER (mode) != QImode)
- {
- qimode = mode_for_vector (QImode, w);
- if (!VECTOR_MODE_P (qimode))
- qimode = VOIDmode;
- }
+ if (GET_MODE_INNER (mode) == QImode
+ || !mode_for_vector (QImode, w).exists (&qimode)
+ || !VECTOR_MODE_P (qimode))
+ qimode = VOIDmode;
/* If the input is a constant, expand it specially. */
gcc_assert (GET_MODE_CLASS (GET_MODE (sel)) == MODE_VECTOR_INT);
return inner_type;
}
-/* Find a mode that is suitable for representing a vector with
- NUNITS elements of mode INNERMODE. Returns BLKmode if there
- is no suitable mode. */
+/* Find a mode that is suitable for representing a vector with NUNITS
+ elements of mode INNERMODE, if one exists. The returned mode can be
+ either an integer mode or a vector mode. */
-machine_mode
+opt_machine_mode
mode_for_vector (scalar_mode innermode, unsigned nunits)
{
machine_mode mode;
FOR_EACH_MODE_FROM (mode, mode)
if (GET_MODE_NUNITS (mode) == nunits
&& GET_MODE_INNER (mode) == innermode)
- break;
+ return mode;
/* For integers, try mapping it to a same-sized scalar mode. */
- if (mode == VOIDmode
- && GET_MODE_CLASS (innermode) == MODE_INT)
+ if (GET_MODE_CLASS (innermode) == MODE_INT)
{
unsigned int nbits = nunits * GET_MODE_BITSIZE (innermode);
- mode = int_mode_for_size (nbits, 0).else_blk ();
+ if (int_mode_for_size (nbits, 0).exists (&mode)
+ && have_regs_of_mode[mode])
+ return mode;
}
- if (mode == VOIDmode
- || (GET_MODE_CLASS (mode) == MODE_INT
- && !have_regs_of_mode[mode]))
- return BLKmode;
-
- return mode;
+ return opt_machine_mode ();
}
/* Return the mode for a vector that has NUNITS integer elements of
mode_for_int_vector (unsigned int int_bits, unsigned int nunits)
{
scalar_int_mode int_mode;
- if (int_mode_for_size (int_bits, 0).exists (&int_mode))
- {
- machine_mode vec_mode = mode_for_vector (int_mode, nunits);
- if (vec_mode != BLKmode)
- return vec_mode;
- }
+ machine_mode vec_mode;
+ if (int_mode_for_size (int_bits, 0).exists (&int_mode)
+ && mode_for_vector (int_mode, nunits).exists (&vec_mode))
+ return vec_mode;
return opt_machine_mode ();
}
if (TYPE_MODE (type) == VOIDmode)
SET_TYPE_MODE (type,
mode_for_vector (SCALAR_TYPE_MODE (innertype),
- nunits));
+ nunits).else_blk ());
TYPE_SATURATING (type) = TYPE_SATURATING (TREE_TYPE (type));
TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TREE_TYPE (type));
gcc_assert (elem_size * nunits == vector_size);
- vector_mode = mode_for_vector (elem_mode, nunits);
- if (!VECTOR_MODE_P (vector_mode)
+ if (!mode_for_vector (elem_mode, nunits).exists (&vector_mode)
+ || !VECTOR_MODE_P (vector_mode)
|| !targetm.vector_mode_supported_p (vector_mode))
vector_mode = BLKmode;
/* First check if vec_extract optab doesn't support extraction
of vector elts directly. */
scalar_mode elmode = SCALAR_TYPE_MODE (elem_type);
- machine_mode vmode = mode_for_vector (elmode, group_size);
- if (! VECTOR_MODE_P (vmode)
+ machine_mode vmode;
+ if (!mode_for_vector (elmode, group_size).exists (&vmode)
+ || !VECTOR_MODE_P (vmode)
|| (convert_optab_handler (vec_extract_optab,
TYPE_MODE (vectype), vmode)
== CODE_FOR_nothing))
unsigned lsize
= group_size * GET_MODE_BITSIZE (elmode);
elmode = int_mode_for_size (lsize, 0).require ();
- vmode = mode_for_vector (elmode, nunits / group_size);
/* If we can't construct such a vector fall back to
element extracts from the original vector type and
element size stores. */
- if (VECTOR_MODE_P (vmode)
+ if (mode_for_vector (elmode,
+ nunits / group_size).exists (&vmode)
+ && VECTOR_MODE_P (vmode)
&& (convert_optab_handler (vec_extract_optab,
vmode, elmode)
!= CODE_FOR_nothing))
/* First check if vec_init optab supports construction from
vector elts directly. */
scalar_mode elmode = SCALAR_TYPE_MODE (TREE_TYPE (vectype));
- machine_mode vmode = mode_for_vector (elmode, group_size);
- if (VECTOR_MODE_P (vmode)
+ machine_mode vmode;
+ if (mode_for_vector (elmode, group_size).exists (&vmode)
+ && VECTOR_MODE_P (vmode)
&& (convert_optab_handler (vec_init_optab,
TYPE_MODE (vectype), vmode)
!= CODE_FOR_nothing))
unsigned lsize
= group_size * TYPE_PRECISION (TREE_TYPE (vectype));
elmode = int_mode_for_size (lsize, 0).require ();
- vmode = mode_for_vector (elmode, nunits / group_size);
/* If we can't construct such a vector fall back to
element loads of the original vector type. */
- if (VECTOR_MODE_P (vmode)
+ if (mode_for_vector (elmode,
+ nunits / group_size).exists (&vmode)
+ && VECTOR_MODE_P (vmode)
&& (convert_optab_handler (vec_init_optab, vmode, elmode)
!= CODE_FOR_nothing))
{
lookup a vector mode of the specified size. */
if (size == 0)
simd_mode = targetm.vectorize.preferred_simd_mode (inner_mode);
- else
- simd_mode = mode_for_vector (inner_mode, size / nbytes);
+ else if (!mode_for_vector (inner_mode, size / nbytes).exists (&simd_mode))
+ return NULL_TREE;
nunits = GET_MODE_SIZE (simd_mode) / nbytes;
/* NOTE: nunits == 1 is allowed to support single element vector types. */
if (nunits < 1)