aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/doc/tm.texi14
-rw-r--r--gcc/doc/tm.texi.in2
-rw-r--r--gcc/hooks.c8
-rw-r--r--gcc/hooks.h3
-rw-r--r--gcc/stor-layout.c19
-rw-r--r--gcc/target.def16
-rw-r--r--gcc/tree-vect-data-refs.c23
8 files changed, 81 insertions, 18 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d965d8f..ed20d31 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -2,6 +2,20 @@
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>
+
* 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 4cd8dce..25b0a1b 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 3a2c2f2..b0ac8b2 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 90d74bb..6171960 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 d6c894f..8caedd4 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 58ebd6c..0f65e16 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 0a4f5fe..783ac99 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 eb82594..759c1e3 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)