Give the target more control over ARRAY_TYPE modes
authorRichard Sandiford <richard.sandiford@linaro.org>
Sat, 13 Jan 2018 17:57:25 +0000 (17:57 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Sat, 13 Jan 2018 17:57:25 +0000 (17:57 +0000)
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

gcc/ChangeLog
gcc/doc/tm.texi
gcc/doc/tm.texi.in
gcc/hooks.c
gcc/hooks.h
gcc/stor-layout.c
gcc/target.def
gcc/tree-vect-data-refs.c

index d965d8fbb3a1e70e6e092383fa806a5c8064c5e4..ed20d31774b1f28ec02172efbd54ce7c9e21ef98 100644 (file)
@@ -1,3 +1,17 @@
+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>
index 4cd8dcea3951990289ee8efd7776f1abc12c923a..25b0a1b21230058ed2d41a1dce1308f439a8ece4 100644 (file)
@@ -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}.
index 3a2c2f26141711c66b31d8704380d99b88d97073..b0ac8b2fd8fbebf2c20b5ee4f052f0638000ce46 100644 (file)
@@ -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
index 90d74bbebd339fe75e86232fa5896e9192f9dad3..61719606a36db15a91215f14e35ca0585fffab42 100644 (file)
@@ -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 ();
+}
index d6c894f5b70d322c55bd42f7dea5dbc5d46e09eb..8caedd429a6964bdf23b7fc0f939a430c4031a1c 100644 (file)
@@ -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
index 58ebd6cfcfcf9716c942e7dedc81d721cc74f022..0f65e166411dab479291b0ad4ab431516d0271a1 100644 (file)
@@ -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 ();
index 0a4f5fe6ef6d625ee34b35764357c6408da111e8..783ac99980910047c90a70d715a2283cd2be4ef3 100644 (file)
@@ -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
index eb82594259807060c3f20483c3a3171c940b3533..759c1e30edffaad705392d744ac0a926f0f95aa4 100644 (file)
@@ -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)