From 0f6d54f720796f2ebcb15764ac0d0b174529367d Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Tue, 3 May 2011 07:46:10 +0000 Subject: [PATCH] hooks.h (hook_bool_mode_uhwi_false): Declare. gcc/ * hooks.h (hook_bool_mode_uhwi_false): Declare. * hooks.c (hook_bool_mode_uhwi_false): New function. * target.def (array_mode_supported_p): New hook. * doc/tm.texi.in (TARGET_ARRAY_MODE_SUPPORTED_P): Add @hook. * doc/tm.texi: Regenerate. * stor-layout.c (mode_for_array): New function. (layout_type): Use it. * config/arm/arm.c (arm_array_mode_supported_p): New function. (TARGET_ARRAY_MODE_SUPPORTED_P): Define. From-SVN: r173290 --- gcc/ChangeLog | 12 ++++++++++++ gcc/config/arm/arm.c | 18 ++++++++++++++++++ gcc/doc/tm.texi | 28 ++++++++++++++++++++++++++++ gcc/doc/tm.texi.in | 2 ++ gcc/hooks.c | 9 +++++++++ gcc/hooks.h | 2 ++ gcc/stor-layout.c | 38 ++++++++++++++++++++++++++++++-------- gcc/target.def | 32 ++++++++++++++++++++++++++++++++ 8 files changed, 133 insertions(+), 8 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 043f73aa7f2..f67a0db60d9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2011-05-03 Richard Sandiford + + * hooks.h (hook_bool_mode_uhwi_false): Declare. + * hooks.c (hook_bool_mode_uhwi_false): New function. + * target.def (array_mode_supported_p): New hook. + * doc/tm.texi.in (TARGET_ARRAY_MODE_SUPPORTED_P): Add @hook. + * doc/tm.texi: Regenerate. + * stor-layout.c (mode_for_array): New function. + (layout_type): Use it. + * config/arm/arm.c (arm_array_mode_supported_p): New function. + (TARGET_ARRAY_MODE_SUPPORTED_P): Define. + 2011-05-03 Eric Botcazou PR target/48723 diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 1affbd38cf2..4f9c2aa7063 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -243,6 +243,8 @@ static rtx arm_pic_static_addr (rtx orig, rtx reg); static bool cortex_a9_sched_adjust_cost (rtx, rtx, rtx, int *); static bool xscale_sched_adjust_cost (rtx, rtx, rtx, int *); static bool fa726te_sched_adjust_cost (rtx, rtx, rtx, int *); +static bool arm_array_mode_supported_p (enum machine_mode, + unsigned HOST_WIDE_INT); static enum machine_mode arm_preferred_simd_mode (enum machine_mode); static bool arm_class_likely_spilled_p (reg_class_t); static bool arm_vector_alignment_reachable (const_tree type, bool is_packed); @@ -399,6 +401,8 @@ static const struct default_options arm_option_optimization_table[] = #define TARGET_SHIFT_TRUNCATION_MASK arm_shift_truncation_mask #undef TARGET_VECTOR_MODE_SUPPORTED_P #define TARGET_VECTOR_MODE_SUPPORTED_P arm_vector_mode_supported_p +#undef TARGET_ARRAY_MODE_SUPPORTED_P +#define TARGET_ARRAY_MODE_SUPPORTED_P arm_array_mode_supported_p #undef TARGET_VECTORIZE_PREFERRED_SIMD_MODE #define TARGET_VECTORIZE_PREFERRED_SIMD_MODE arm_preferred_simd_mode #undef TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_SIZES @@ -22453,6 +22457,20 @@ arm_vector_mode_supported_p (enum machine_mode mode) return false; } +/* Implements target hook array_mode_supported_p. */ + +static bool +arm_array_mode_supported_p (enum machine_mode mode, + unsigned HOST_WIDE_INT nelems) +{ + if (TARGET_NEON + && (VALID_NEON_DREG_MODE (mode) || VALID_NEON_QREG_MODE (mode)) + && (nelems >= 2 && nelems <= 4)) + return true; + + return false; +} + /* Use the option -mvectorize-with-neon-quad to override the use of doubleword registers when autovectorizing for Neon, at least until multiple vector widths are supported properly by the middle-end. */ diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index a89d0ecc83d..7351e8338b8 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -4277,6 +4277,34 @@ insns involving vector mode @var{mode}. At the very least, it must have move patterns for this mode. @end deftypefn +@deftypefn {Target Hook} bool TARGET_ARRAY_MODE_SUPPORTED_P (enum 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}. +Returning true here overrides the usual @code{MAX_FIXED_MODE} limit +and allows GCC to use any defined integer mode. + +One use of this hook is to support vector load and store operations +that operate on several homogeneous vectors. For example, ARM NEON +has operations like: + +@smallexample +int8x8x3_t vld3_s8 (const int8_t *) +@end smallexample + +where the return type is defined as: + +@smallexample +typedef struct int8x8x3_t +@{ + int8x8_t val[3]; +@} int8x8x3_t; +@end smallexample + +If this hook allows @code{val} to have a scalar mode, then +@code{int8x8x3_t} can have the same mode. GCC can then store +@code{int8x8x3_t}s in registers rather than forcing them onto the stack. +@end deftypefn + @deftypefn {Target Hook} bool TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P (enum machine_mode @var{mode}) Define this to return nonzero for machine modes for which the port has small register classes. If this target hook returns nonzero for a given diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 4637088a819..45d5982eb7b 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -4263,6 +4263,8 @@ insns involving vector mode @var{mode}. At the very least, it must have move patterns for this mode. @end deftypefn +@hook TARGET_ARRAY_MODE_SUPPORTED_P + @hook TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P Define this to return nonzero for machine modes for which the port has small register classes. If this target hook returns nonzero for a given diff --git a/gcc/hooks.c b/gcc/hooks.c index 7791a14fbee..9dfde822a5f 100644 --- a/gcc/hooks.c +++ b/gcc/hooks.c @@ -117,6 +117,15 @@ hook_bool_mode_rtx_true (enum machine_mode mode ATTRIBUTE_UNUSED, return true; } +/* Generic hook that takes (enum machine_mode, unsigned HOST_WIDE_INT) + and returns false. */ +bool +hook_bool_mode_uhwi_false (enum machine_mode mode ATTRIBUTE_UNUSED, + unsigned HOST_WIDE_INT value ATTRIBUTE_UNUSED) +{ + return false; +} + /* Generic hook that takes (FILE *, const char *) and does nothing. */ void hook_void_FILEptr_constcharptr (FILE *a ATTRIBUTE_UNUSED, const char *b ATTRIBUTE_UNUSED) diff --git a/gcc/hooks.h b/gcc/hooks.h index 11dd7a9d816..a1b011203d5 100644 --- a/gcc/hooks.h +++ b/gcc/hooks.h @@ -36,6 +36,8 @@ extern bool hook_bool_mode_const_rtx_false (enum machine_mode, const_rtx); extern bool hook_bool_mode_const_rtx_true (enum machine_mode, const_rtx); extern bool hook_bool_mode_rtx_false (enum machine_mode, rtx); extern bool hook_bool_mode_rtx_true (enum machine_mode, rtx); +extern bool hook_bool_mode_uhwi_false (enum machine_mode, + unsigned HOST_WIDE_INT); extern bool hook_bool_tree_false (tree); extern bool hook_bool_const_tree_false (const_tree); extern bool hook_bool_tree_true (tree); diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index ea0d44d64d2..62de10de54a 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -546,6 +546,34 @@ get_mode_alignment (enum machine_mode mode) return MIN (BIGGEST_ALIGNMENT, MAX (1, mode_base_align[mode]*BITS_PER_UNIT)); } +/* Return the natural mode of an array, given that it is SIZE bytes in + total and has elements of type ELEM_TYPE. */ + +static enum machine_mode +mode_for_array (tree elem_type, tree size) +{ + tree elem_size; + unsigned HOST_WIDE_INT int_size, int_elem_size; + bool limit_p; + + /* One-element arrays get the component type's mode. */ + elem_size = TYPE_SIZE (elem_type); + if (simple_cst_equal (size, elem_size)) + return TYPE_MODE (elem_type); + + limit_p = true; + if (host_integerp (size, 1) && host_integerp (elem_size, 1)) + { + int_size = tree_low_cst (size, 1); + int_elem_size = tree_low_cst (elem_size, 1); + 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)) + limit_p = false; + } + return mode_for_size_tree (size, MODE_INT, limit_p); +} /* Subroutine of layout_decl: Force alignment required for the data type. But if the decl itself wants greater alignment, don't override that. */ @@ -2040,14 +2068,8 @@ layout_type (tree type) && (TYPE_MODE (TREE_TYPE (type)) != BLKmode || TYPE_NO_FORCE_BLK (TREE_TYPE (type)))) { - /* One-element arrays get the component type's mode. */ - if (simple_cst_equal (TYPE_SIZE (type), - TYPE_SIZE (TREE_TYPE (type)))) - SET_TYPE_MODE (type, TYPE_MODE (TREE_TYPE (type))); - else - SET_TYPE_MODE (type, mode_for_size_tree (TYPE_SIZE (type), - MODE_INT, 1)); - + SET_TYPE_MODE (type, mode_for_array (TREE_TYPE (type), + TYPE_SIZE (type))); if (TYPE_MODE (type) != BLKmode && STRICT_ALIGNMENT && TYPE_ALIGN (type) < BIGGEST_ALIGNMENT && TYPE_ALIGN (type) < GET_MODE_ALIGNMENT (TYPE_MODE (type))) diff --git a/gcc/target.def b/gcc/target.def index ea4d3e95aec..754713fe493 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -1565,6 +1565,38 @@ DEFHOOK bool, (enum machine_mode mode), hook_bool_mode_false) +/* True if we should try to use a scalar mode to represent an array, + overriding the usual MAX_FIXED_MODE limit. */ +DEFHOOK +(array_mode_supported_p, + "Return true if GCC should try to use a scalar mode to store an array\n\ +of @var{nelems} elements, given that each element has mode @var{mode}.\n\ +Returning true here overrides the usual @code{MAX_FIXED_MODE} limit\n\ +and allows GCC to use any defined integer mode.\n\ +\n\ +One use of this hook is to support vector load and store operations\n\ +that operate on several homogeneous vectors. For example, ARM NEON\n\ +has operations like:\n\ +\n\ +@smallexample\n\ +int8x8x3_t vld3_s8 (const int8_t *)\n\ +@end smallexample\n\ +\n\ +where the return type is defined as:\n\ +\n\ +@smallexample\n\ +typedef struct int8x8x3_t\n\ +@{\n\ + int8x8_t val[3];\n\ +@} int8x8x3_t;\n\ +@end smallexample\n\ +\n\ +If this hook allows @code{val} to have a scalar mode, then\n\ +@code{int8x8x3_t} can have the same mode. GCC can then store\n\ +@code{int8x8x3_t}s in registers rather than forcing them onto the stack.", + bool, (enum machine_mode mode, unsigned HOST_WIDE_INT nelems), + hook_bool_mode_uhwi_false) + /* Compute cost of moving data from a register of class FROM to one of TO, using MODE. */ DEFHOOK -- 2.30.2