So far we've used integer modes for LD[234] and ST[234] arrays.
That doesn't scale well to SVE, since the sizes aren't fixed at
compile time (and even if they were, we wouldn't want integers
to be so wide).
This patch lets the target use double-, triple- and quadruple-length
vectors instead.
2018-01-13 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
gcc/
* target.def (array_mode): New target hook.
* doc/tm.texi.in (TARGET_ARRAY_MODE): New hook.
* doc/tm.texi: Regenerate.
* hooks.h (hook_optmode_mode_uhwi_none): Declare.
* hooks.c (hook_optmode_mode_uhwi_none): New function.
* tree-vect-data-refs.c (vect_lanes_optab_supported_p): Use
targetm.array_mode.
* stor-layout.c (mode_for_array): Likewise. Support polynomial
type sizes.
Co-Authored-By: Alan Hayward <alan.hayward@arm.com>
Co-Authored-By: David Sherwood <david.sherwood@arm.com>
From-SVN: r256617
+2018-01-13 Richard Sandiford <richard.sandiford@linaro.org>
+ Alan Hayward <alan.hayward@arm.com>
+ David Sherwood <david.sherwood@arm.com>
+
+ * target.def (array_mode): New target hook.
+ * doc/tm.texi.in (TARGET_ARRAY_MODE): New hook.
+ * doc/tm.texi: Regenerate.
+ * hooks.h (hook_optmode_mode_uhwi_none): Declare.
+ * hooks.c (hook_optmode_mode_uhwi_none): New function.
+ * tree-vect-data-refs.c (vect_lanes_optab_supported_p): Use
+ targetm.array_mode.
+ * stor-layout.c (mode_for_array): Likewise. Support polynomial
+ type sizes.
+
2018-01-13 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
must have move patterns for this mode.
@end deftypefn
+@deftypefn {Target Hook} opt_machine_mode TARGET_ARRAY_MODE (machine_mode @var{mode}, unsigned HOST_WIDE_INT @var{nelems})
+Return the mode that GCC should use for an array that has
+@var{nelems} elements, with each element having mode @var{mode}.
+Return no mode if the target has no special requirements. In the
+latter case, GCC looks for an integer mode of the appropriate size
+if available and uses BLKmode otherwise. Usually the search for the
+integer mode is limited to @code{MAX_FIXED_MODE_SIZE}, but the
+@code{TARGET_ARRAY_MODE_SUPPORTED_P} hook allows a larger mode to be
+used in specific cases.
+
+The main use of this hook is to specify that an array of vectors should
+also have a vector mode. The default implementation returns no mode.
+@end deftypefn
+
@deftypefn {Target Hook} bool TARGET_ARRAY_MODE_SUPPORTED_P (machine_mode @var{mode}, unsigned HOST_WIDE_INT @var{nelems})
Return true if GCC should try to use a scalar mode to store an array
of @var{nelems} elements, given that each element has mode @var{mode}.
@hook TARGET_VECTOR_MODE_SUPPORTED_P
+@hook TARGET_ARRAY_MODE
+
@hook TARGET_ARRAY_MODE_SUPPORTED_P
@hook TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P
return false;
}
+/* Generic hook that takes a mode and an unsigned HOST_WIDE_INT and
+ returns no mode. */
+
+opt_machine_mode
+hook_optmode_mode_uhwi_none (machine_mode, unsigned HOST_WIDE_INT)
+{
+ return opt_machine_mode ();
+}
extern const char *hook_constcharptr_const_tree_const_tree_null (const_tree, const_tree);
extern const char *hook_constcharptr_int_const_tree_null (int, const_tree);
extern const char *hook_constcharptr_int_const_tree_const_tree_null (int, const_tree, const_tree);
+
+extern opt_machine_mode hook_optmode_mode_uhwi_none (machine_mode,
+ unsigned HOST_WIDE_INT);
#endif
mode_for_array (tree elem_type, tree size)
{
tree elem_size;
- unsigned HOST_WIDE_INT int_size, int_elem_size;
+ poly_uint64 int_size, int_elem_size;
+ unsigned HOST_WIDE_INT num_elems;
bool limit_p;
/* One-element arrays get the component type's mode. */
return TYPE_MODE (elem_type);
limit_p = true;
- if (tree_fits_uhwi_p (size) && tree_fits_uhwi_p (elem_size))
+ if (poly_int_tree_p (size, &int_size)
+ && poly_int_tree_p (elem_size, &int_elem_size)
+ && maybe_ne (int_elem_size, 0U)
+ && constant_multiple_p (int_size, int_elem_size, &num_elems))
{
- int_size = tree_to_uhwi (size);
- int_elem_size = tree_to_uhwi (elem_size);
- if (int_elem_size > 0
- && int_size % int_elem_size == 0
- && targetm.array_mode_supported_p (TYPE_MODE (elem_type),
- int_size / int_elem_size))
+ machine_mode elem_mode = TYPE_MODE (elem_type);
+ machine_mode mode;
+ if (targetm.array_mode (elem_mode, num_elems).exists (&mode))
+ return mode;
+ if (targetm.array_mode_supported_p (elem_mode, num_elems))
limit_p = false;
}
return mode_for_size_tree (size, MODE_INT, limit_p).else_blk ();
HOST_WIDE_INT, (const_tree type),
default_vector_alignment)
+DEFHOOK
+(array_mode,
+ "Return the mode that GCC should use for an array that has\n\
+@var{nelems} elements, with each element having mode @var{mode}.\n\
+Return no mode if the target has no special requirements. In the\n\
+latter case, GCC looks for an integer mode of the appropriate size\n\
+if available and uses BLKmode otherwise. Usually the search for the\n\
+integer mode is limited to @code{MAX_FIXED_MODE_SIZE}, but the\n\
+@code{TARGET_ARRAY_MODE_SUPPORTED_P} hook allows a larger mode to be\n\
+used in specific cases.\n\
+\n\
+The main use of this hook is to specify that an array of vectors should\n\
+also have a vector mode. The default implementation returns no mode.",
+ opt_machine_mode, (machine_mode mode, unsigned HOST_WIDE_INT nelems),
+ hook_optmode_mode_uhwi_none)
+
/* True if we should try to use a scalar mode to represent an array,
overriding the usual MAX_FIXED_MODE limit. */
DEFHOOK
vect_lanes_optab_supported_p (const char *name, convert_optab optab,
tree vectype, unsigned HOST_WIDE_INT count)
{
- machine_mode mode;
- scalar_int_mode array_mode;
+ machine_mode mode, array_mode;
bool limit_p;
mode = TYPE_MODE (vectype);
- limit_p = !targetm.array_mode_supported_p (mode, count);
- if (!int_mode_for_size (count * GET_MODE_BITSIZE (mode),
- limit_p).exists (&array_mode))
+ if (!targetm.array_mode (mode, count).exists (&array_mode))
{
- if (dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "no array mode for %s[" HOST_WIDE_INT_PRINT_DEC "]\n",
- GET_MODE_NAME (mode), count);
- return false;
+ poly_uint64 bits = count * GET_MODE_BITSIZE (mode);
+ limit_p = !targetm.array_mode_supported_p (mode, count);
+ if (!int_mode_for_size (bits, limit_p).exists (&array_mode))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "no array mode for %s["
+ HOST_WIDE_INT_PRINT_DEC "]\n",
+ GET_MODE_NAME (mode), count);
+ return false;
+ }
}
if (convert_optab_handler (optab, array_mode, mode) == CODE_FOR_nothing)