From 30d26b1cadb152b462086b79c16cbdd276690541 Mon Sep 17 00:00:00 2001 From: rsandifo Date: Sat, 13 Jan 2018 17:57:25 +0000 Subject: [PATCH] Give the target more control over ARRAY_TYPE modes 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 Alan Hayward David Sherwood 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@256617 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 14 ++++++++++++++ gcc/doc/tm.texi | 14 ++++++++++++++ gcc/doc/tm.texi.in | 2 ++ gcc/hooks.c | 8 ++++++++ gcc/hooks.h | 3 +++ gcc/stor-layout.c | 19 +++++++++++-------- gcc/target.def | 16 ++++++++++++++++ gcc/tree-vect-data-refs.c | 23 +++++++++++++---------- 8 files changed, 81 insertions(+), 18 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d965d8fbb3a..ed20d31774b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -2,6 +2,20 @@ Alan Hayward David Sherwood + * 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 + Alan Hayward + David Sherwood + * fold-const.c (fold_binary_loc): Check the argument types rather than the result type when testing for a vector operation. diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 4cd8dcea395..25b0a1b2123 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -4250,6 +4250,20 @@ insns involving vector mode @var{mode}. At the very least, it 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}. diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 3a2c2f26141..b0ac8b2fd8f 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -3329,6 +3329,8 @@ stack. @hook TARGET_VECTOR_MODE_SUPPORTED_P +@hook TARGET_ARRAY_MODE + @hook TARGET_ARRAY_MODE_SUPPORTED_P @hook TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P diff --git a/gcc/hooks.c b/gcc/hooks.c index 90d74bbebd3..61719606a36 100644 --- a/gcc/hooks.c +++ b/gcc/hooks.c @@ -525,3 +525,11 @@ hook_bool_mode_reg_class_t_reg_class_t_false (machine_mode, reg_class_t, 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 (); +} diff --git a/gcc/hooks.h b/gcc/hooks.h index d6c894f5b70..8caedd429a6 100644 --- a/gcc/hooks.h +++ b/gcc/hooks.h @@ -124,4 +124,7 @@ extern const char *hook_constcharptr_const_rtx_insn_null (const rtx_insn *); 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 diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index 58ebd6cfcfc..0f65e166411 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -546,7 +546,8 @@ static machine_mode 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. */ @@ -555,14 +556,16 @@ mode_for_array (tree elem_type, tree size) 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 (); diff --git a/gcc/target.def b/gcc/target.def index 0a4f5fe6ef6..783ac999809 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -3426,6 +3426,22 @@ the vector element type.", 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 diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c index eb825942598..759c1e30edf 100644 --- a/gcc/tree-vect-data-refs.c +++ b/gcc/tree-vect-data-refs.c @@ -61,20 +61,23 @@ static bool 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) -- 2.11.4.GIT