This patch allows the target to override MAX_FIXED_MODE_SIZE for
specific kinds of array.  We can then give a non-BLK mode to things
like uint32x2x4_t, which in turn allows them to be stored in registers.

The patch is a backport of:

    http://gcc.gnu.org/ml/gcc-patches/2011-03/msg02192.html

which Richard Guenther approved in principle, but which can't be
applied yet because of 4/5.  The only difference in the 4.5 version
is that 4.5 still uses the old target hook definition scheme,
rather than 4.7's target.def.

Richard


gcc/
        * hooks.h (hook_bool_mode_uhwi_false): Declare.
        * hooks.c (hook_bool_mode_uhwi_false): New function.
        * doc/tm.texi (TARGET_ARRAY_MODE_SUPPORTED_P): Document.
        * target.h (array_mode_supported_p): New hook.
        * target-def.h (TARGET_ARRAY_MODE_SUPPORTED_P): Define if undefined.
        (TARGET_INITIALIZER): Include it.
        * 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.

Index: gcc/hooks.h
===================================================================
--- gcc/hooks.h 2011-04-19 14:14:01.000000000 +0000
+++ gcc/hooks.h 2011-04-19 16:19:06.000000000 +0000
@@ -32,6 +32,8 @@ extern bool hook_bool_const_int_const_in
 extern bool hook_bool_mode_false (enum machine_mode);
 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_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);
Index: gcc/hooks.c
===================================================================
--- gcc/hooks.c 2011-04-19 14:14:01.000000000 +0000
+++ gcc/hooks.c 2011-04-19 16:19:06.000000000 +0000
@@ -86,6 +86,15 @@ hook_bool_mode_const_rtx_true (enum mach
   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)
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi     2011-04-19 14:14:01.000000000 +0000
+++ gcc/doc/tm.texi     2011-04-19 16:38:08.000000000 +0000
@@ -4367,6 +4367,34 @@ insns involving vector mode @var{mode}.
 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
+
 @node Scalar Return
 @subsection How Scalar Function Values Are Returned
 @cindex return values in registers
Index: gcc/target.h
===================================================================
--- gcc/target.h        2011-04-19 14:14:01.000000000 +0000
+++ gcc/target.h        2011-04-19 16:38:08.000000000 +0000
@@ -764,6 +764,9 @@ struct gcc_target
      for further details.  */
   bool (* vector_mode_supported_p) (enum machine_mode mode);
 
+  /* See tm.texi.  */
+  bool (* array_mode_supported_p) (enum machine_mode, unsigned HOST_WIDE_INT);
+
   /* Compute a (partial) cost for rtx X.  Return true if the complete
      cost has been computed, and false if subexpressions should be
      scanned.  In either case, *TOTAL contains the cost result.  */
Index: gcc/target-def.h
===================================================================
--- gcc/target-def.h    2011-04-19 14:14:01.000000000 +0000
+++ gcc/target-def.h    2011-04-19 16:38:08.000000000 +0000
@@ -553,6 +553,10 @@ #define TARGET_FIXED_POINT_SUPPORTED_P d
 #define TARGET_VECTOR_MODE_SUPPORTED_P hook_bool_mode_false
 #endif
 
+#ifndef TARGET_ARRAY_MODE_SUPPORTED_P
+#define TARGET_ARRAY_MODE_SUPPORTED_P hook_bool_mode_uhwi_false
+#endif
+
 /* In hooks.c.  */
 #define TARGET_CANNOT_MODIFY_JUMPS_P hook_bool_void_false
 #define TARGET_BRANCH_TARGET_REGISTER_CLASS \
@@ -985,6 +989,7 @@ #define TARGET_INITIALIZER                  \
   TARGET_ADDR_SPACE_HOOKS,                     \
   TARGET_SCALAR_MODE_SUPPORTED_P,              \
   TARGET_VECTOR_MODE_SUPPORTED_P,               \
+  TARGET_ARRAY_MODE_SUPPORTED_P,               \
   TARGET_RTX_COSTS,                            \
   TARGET_ADDRESS_COST,                         \
   TARGET_ALLOCATE_INITIAL_VALUE,               \
Index: gcc/stor-layout.c
===================================================================
--- gcc/stor-layout.c   2011-04-19 14:14:01.000000000 +0000
+++ gcc/stor-layout.c   2011-04-19 14:14:03.000000000 +0000
@@ -507,6 +507,34 @@ get_mode_alignment (enum machine_mode mo
   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.  */
@@ -2044,14 +2072,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)))
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c        2011-04-19 14:14:01.000000000 +0000
+++ gcc/config/arm/arm.c        2011-04-19 16:38:08.000000000 +0000
@@ -222,6 +222,8 @@ static const char *arm_invalid_return_ty
 static tree arm_promoted_type (const_tree t);
 static tree arm_convert_to_type (tree type, tree expr);
 static bool arm_scalar_mode_supported_p (enum machine_mode);
+static bool arm_array_mode_supported_p (enum machine_mode,
+                                       unsigned HOST_WIDE_INT);
 static bool arm_frame_pointer_required (void);
 static bool arm_can_eliminate (const int, const int);
 static void arm_asm_trampoline_template (FILE *);
@@ -355,6 +357,8 @@ #define TARGET_ADDRESS_COST arm_address_
 #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_MACHINE_DEPENDENT_REORG
 #define TARGET_MACHINE_DEPENDENT_REORG arm_reorg
@@ -22435,6 +22439,20 @@ arm_vector_mode_supported_p (enum machin
     return true;
 
   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;
 }
 
 /* Implement TARGET_SHIFT_TRUNCATION_MASK.  SImode shifts use normal

_______________________________________________
linaro-toolchain mailing list
linaro-toolchain@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-toolchain

Reply via email to