This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[ARM] Enable __fp16 as a function parameter and return type.


Hello,

The ARM target supports the half-precision floating point type __fp16
but does not allow its use as a function return or parameter type. This
patch removes that restriction and defines the ACLE macro
__ARM_FP16_ARGS to indicate this. The code generated for passing __fp16
values into and out of functions depends on the level of hardware
support but conforms to the AAPCS (see
http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042f/IHI0042F_aapcs.pdf).

This patch enables data movement for HF-mode values using VFP registers,
when they are available, to support passing arguments and return values
through the registers.

This patch also fixes the definition of TARGET_NEON_FP16 which used to
require both neon and fp16 features to be enabled. This was
inadvertently weakened, when the macro definition was changed to use
ARM_FPU_FSET_HAS, to only require one of neon or fp16 to be
enabled. This patch returns to the original
requirements. TARGET_NEON_FP16 is only used in instruction selection for
HF-mode data moves.

Tested for arm-none-eabi with cross-compiled check-gcc and for
arm-none-linux-gnueabihf with native bootstrap and make check.

Ok for trunk?
Matthew

gcc/
2016-04-27  Matthew Wahab  <matthew.wahab@arm.com>
	    Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
	    Jiong Wang  <jiong.wang@arm.com>

	* config/arm/arm-c.c (arm_cpu_builtins): Use def_or_undef_macro
	for __ARM_FP16_FORMAT_IEEE and __ARM_FP16_FORMAT_ALTERNATIVE.
	Define __ARM_FP16_ARGS when appropriate.
	* config/arm/arm.c (arm_invalid_parameter_type): Remove
	declaration.
	(arm_invalid_return_type): Likewise.
	(TARGET_INVALID_PARAMETER_TYPE): Remove.
	(TARGET_INVALID_RETURN_TYPE): Remove.
	(aapcs_vfp_sub_candidate): Allow HFmode.
	(aapcs_vfp_allocate): Add comment.  Support HFmode.
	(aapcs_vfp_allocate_return_reg): Likewise.
	(struct aapcs_cp_arg_layout): Slightly reword comments for
	is_return_candidate and allocate_return_reg.
	(output_mov_vfp): Update assert.
	(arm_hard_regno_mode_ok): Remove comment, update HF-mode
	condition.
	(arm_invalid_parameter_type): Remove.
	(amr_invalid_return_type): Remove.
	* config/arm/arm.h (TARGET_NEON_FP16): Fix definition.
	* config/arm/arm.md (*arm32_movhf): Disable for TARGET_VFP.
	* config/arm/vfp.md (*movhf_vfp): Enable for TARGET_VFP.

gcc/testsuite/
2016-04-27  Matthew Wahab  <matthew.wahab@arm.com>

	* g++.dg/ext/arm-fp16/fp16-param-1.c: Update expected output.  Add
	test for __ARM_FP16_ARGS.
	* g++.dg/ext/arm-fp16/fp16-return-1.c: Update expected output.
	* gcc.target/arm/aapcs/neon-vect10.c: New.
	* gcc.target/arm/aapcs/neon-vect9.c: New.
	* gcc.target/arm/aapcs/vfp18.c: New.
	* gcc.target/arm/aapcs/vfp19.c: New.
	* gcc.target/arm/aapcs/vfp20.c: New.
	* gcc.target/arm/aapcs/vfp21.c: New.
	* gcc.target/arm/fp16-aapcs-1.c: New.
	* g++.target/arm/fp16-param-1.c: Update expected output.  Add
	test for __ARM_FP16_ARGS.
	* g++.target/arm/fp16-return-1.c: Update expected output.
[PATCH] [ARM] Enable __fp16 as a function parameter and return type.

The ARM target supports the half-precision floating point type __fp16
but does not allow its use as a function return or parameter type. This
patch removes that restriction and defines the ACLE macro
__ARM_FP16_ARGS to indicate this. The code generated for passing __fp16
values into and out of functions depends on the level of hardware
support but conforms to the AAPCS (see
http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042f/IHI0042F_aapcs.pdf).

This patch enables data movement for HF-mode values using VFP registers,
when they are available, to support passing arguments and return values
through the register.

This patch also fixes the definition of TARGET_NEON_FP16 which used to
require both neon and fp16 features to be enabled. This was
inadvertently weakened, when the macro definition was changed to use
ARM_FPU_FSET_HAS, to only require one of neon or fp16 to be
enabled. This patch returns to the original
requirements. TARGET_NEON_FP16 is only used in instruction selection for
HF-mode data moves.

Tested for arm-none-eabi with cross-compiled check-gcc and for
arm-none-linux-gnueabihf with native bootstrap and make check.

gcc/
2016-04-27  Matthew Wahab  <matthew.wahab@arm.com>
	    Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
	    Jiong Wang  <jiong.wang@arm.com>

	* config/arm/arm-c.c (arm_cpu_builtins): Use def_or_undef_macro
	for __ARM_FP16_FORMAT_IEEE and __ARM_FP16_FORMAT_ALTERNATIVE.
	Define __ARM_FP16_ARGS when appropriate.
	* config/arm/arm.c (arm_invalid_parameter_type): Remove
	declaration.
	(arm_invalid_return_type): Likewise.
	(TARGET_INVALID_PARAMETER_TYPE): Remove.
	(TARGET_INVALID_RETURN_TYPE): Remove.
	(aapcs_vfp_sub_candidate): Allow HFmode.
	(aapcs_vfp_allocate): Add comment.  Support HFmode.
	(aapcs_vfp_allocate_return_reg): Likewise.
	(struct aapcs_cp_arg_layout): Slightly reword comments for
	is_return_candidate and allocate_return_reg.
	(output_mov_vfp): Update assert.
	(arm_hard_regno_mode_ok): Remove comment, update HF-mode
	condition.
	(arm_invalid_parameter_type): Remove.
	(amr_invalid_return_type): Remove.
	* config/arm/arm.h (TARGET_NEON_FP16): Fix definition.
	* config/arm/arm.md (*arm32_movhf): Disable for TARGET_VFP.
	* config/arm/vfp.md (*movhf_vfp): Enable for TARGET_VFP.

gcc/testsuite/
2016-04-27  Matthew Wahab  <matthew.wahab@arm.com>

	* g++.dg/ext/arm-fp16/fp16-param-1.c: Update expected output.  Add
	test for __ARM_FP16_ARGS.
	* g++.dg/ext/arm-fp16/fp16-return-1.c: Update expected output.
	* gcc.target/arm/aapcs/neon-vect10.c: New.
	* gcc.target/arm/aapcs/neon-vect9.c: New.
	* gcc.target/arm/aapcs/vfp18.c: New.
	* gcc.target/arm/aapcs/vfp19.c: New.
	* gcc.target/arm/aapcs/vfp20.c: New.
	* gcc.target/arm/aapcs/vfp21.c: New.
	* gcc.target/arm/fp16-aapcs-1.c: New.
	* g++.target/arm/fp16-param-1.c: Update expected output.  Add
	test for __ARM_FP16_ARGS.
	* g++.target/arm/fp16-return-1.c: Update expected output.
---
 gcc/config/arm/arm-c.c                            | 10 ++--
 gcc/config/arm/arm.c                              | 57 +++++++----------------
 gcc/config/arm/arm.h                              |  3 +-
 gcc/config/arm/arm.md                             |  2 +-
 gcc/config/arm/vfp.md                             |  3 +-
 gcc/testsuite/g++.dg/ext/arm-fp16/fp16-param-1.C  | 12 +++--
 gcc/testsuite/g++.dg/ext/arm-fp16/fp16-return-1.C |  7 ++-
 gcc/testsuite/gcc.target/arm/aapcs/neon-vect10.c  | 31 ++++++++++++
 gcc/testsuite/gcc.target/arm/aapcs/neon-vect9.c   | 23 +++++++++
 gcc/testsuite/gcc.target/arm/aapcs/vfp18.c        | 27 +++++++++++
 gcc/testsuite/gcc.target/arm/aapcs/vfp19.c        | 29 ++++++++++++
 gcc/testsuite/gcc.target/arm/aapcs/vfp20.c        | 21 +++++++++
 gcc/testsuite/gcc.target/arm/aapcs/vfp21.c        | 25 ++++++++++
 gcc/testsuite/gcc.target/arm/fp16-aapcs-1.c       | 17 +++++++
 gcc/testsuite/gcc.target/arm/fp16-param-1.c       | 12 +++--
 gcc/testsuite/gcc.target/arm/fp16-return-1.c      |  7 ++-
 16 files changed, 224 insertions(+), 62 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/arm/aapcs/neon-vect10.c
 create mode 100644 gcc/testsuite/gcc.target/arm/aapcs/neon-vect9.c
 create mode 100644 gcc/testsuite/gcc.target/arm/aapcs/vfp18.c
 create mode 100644 gcc/testsuite/gcc.target/arm/aapcs/vfp19.c
 create mode 100644 gcc/testsuite/gcc.target/arm/aapcs/vfp20.c
 create mode 100644 gcc/testsuite/gcc.target/arm/aapcs/vfp21.c
 create mode 100644 gcc/testsuite/gcc.target/arm/fp16-aapcs-1.c

diff --git a/gcc/config/arm/arm-c.c b/gcc/config/arm/arm-c.c
index 4fbdfc5..b98470f 100644
--- a/gcc/config/arm/arm-c.c
+++ b/gcc/config/arm/arm-c.c
@@ -135,10 +135,12 @@ arm_cpu_builtins (struct cpp_reader* pfile)
   else
     cpp_undef (pfile, "__ARM_FP");
 
-  if (arm_fp16_format == ARM_FP16_FORMAT_IEEE)
-    builtin_define ("__ARM_FP16_FORMAT_IEEE");
-  if (arm_fp16_format == ARM_FP16_FORMAT_ALTERNATIVE)
-    builtin_define ("__ARM_FP16_FORMAT_ALTERNATIVE");
+  def_or_undef_macro (pfile, "__ARM_FP16_FORMAT_IEEE",
+		      arm_fp16_format == ARM_FP16_FORMAT_IEEE);
+  def_or_undef_macro (pfile, "__ARM_FP16_FORMAT_ALTERNATIVE",
+		      arm_fp16_format == ARM_FP16_FORMAT_ALTERNATIVE);
+  def_or_undef_macro (pfile, "__ARM_FP16_ARGS",
+		      arm_fp16_format != ARM_FP16_FORMAT_NONE);
 
   def_or_undef_macro (pfile, "__ARM_FEATURE_FMA", TARGET_FMA);
   def_or_undef_macro (pfile, "__ARM_NEON__", TARGET_NEON);
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 71b5143..e1e311f 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -249,8 +249,6 @@ static void arm_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED;
 static bool arm_output_addr_const_extra (FILE *, rtx);
 static bool arm_allocate_stack_slots_for_args (void);
 static bool arm_warn_func_return (tree);
-static const char *arm_invalid_parameter_type (const_tree t);
-static const char *arm_invalid_return_type (const_tree t);
 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 (machine_mode);
@@ -654,12 +652,6 @@ static const struct attribute_spec arm_attribute_table[] =
 #undef TARGET_PREFERRED_RELOAD_CLASS
 #define TARGET_PREFERRED_RELOAD_CLASS arm_preferred_reload_class
 
-#undef TARGET_INVALID_PARAMETER_TYPE
-#define TARGET_INVALID_PARAMETER_TYPE arm_invalid_parameter_type
-
-#undef TARGET_INVALID_RETURN_TYPE
-#define TARGET_INVALID_RETURN_TYPE arm_invalid_return_type
-
 #undef TARGET_PROMOTED_TYPE
 #define TARGET_PROMOTED_TYPE arm_promoted_type
 
@@ -5549,7 +5541,7 @@ aapcs_vfp_sub_candidate (const_tree type, machine_mode *modep)
     {
     case REAL_TYPE:
       mode = TYPE_MODE (type);
-      if (mode != DFmode && mode != SFmode)
+      if (mode != DFmode && mode != SFmode && mode != HFmode)
 	return -1;
 
       if (*modep == VOIDmode)
@@ -5797,11 +5789,16 @@ aapcs_vfp_is_call_candidate (CUMULATIVE_ARGS *pcum, machine_mode mode,
 						&pcum->aapcs_vfp_rcount);
 }
 
+/* Implement the allocate field in aapcs_cp_arg_layout.  See the comment there
+   for the behaviour of this function.  */
+
 static bool
 aapcs_vfp_allocate (CUMULATIVE_ARGS *pcum, machine_mode mode,
 		    const_tree type  ATTRIBUTE_UNUSED)
 {
-  int shift = GET_MODE_SIZE (pcum->aapcs_vfp_rmode) / GET_MODE_SIZE (SFmode);
+  int rmode_size
+    = MAX (GET_MODE_SIZE (pcum->aapcs_vfp_rmode), GET_MODE_SIZE (SFmode));
+  int shift = rmode_size / GET_MODE_SIZE (SFmode);
   unsigned mask = (1 << (shift * pcum->aapcs_vfp_rcount)) - 1;
   int regno;
 
@@ -5850,6 +5847,9 @@ aapcs_vfp_allocate (CUMULATIVE_ARGS *pcum, machine_mode mode,
   return false;
 }
 
+/* Implement the allocate_return_reg field in aapcs_cp_arg_layout.  See the
+   comment there for the behaviour of this function.  */
+
 static rtx
 aapcs_vfp_allocate_return_reg (enum arm_pcs pcs_variant ATTRIBUTE_UNUSED,
 			       machine_mode mode,
@@ -5940,13 +5940,13 @@ static struct
      required for a return from FUNCTION_ARG.  */
   bool (*allocate) (CUMULATIVE_ARGS *, machine_mode, const_tree);
 
-  /* Return true if a result of mode MODE (or type TYPE if MODE is
-     BLKmode) is can be returned in this co-processor's registers.  */
+  /* Return true if a result of mode MODE (or type TYPE if MODE is BLKmode) can
+     be returned in this co-processor's registers.  */
   bool (*is_return_candidate) (enum arm_pcs, machine_mode, const_tree);
 
-  /* Allocate and return an RTX element to hold the return type of a
-     call, this routine must not fail and will only be called if
-     is_return_candidate returned true with the same parameters.  */
+  /* Allocate and return an RTX element to hold the return type of a call.  This
+     routine must not fail and will only be called if is_return_candidate
+     returned true with the same parameters.  */
   rtx (*allocate_return_reg) (enum arm_pcs, machine_mode, const_tree);
 
   /* Finish processing this argument and prepare to start processing
@@ -18608,7 +18608,8 @@ output_move_vfp (rtx *operands)
 
   gcc_assert (REG_P (reg));
   gcc_assert (IS_VFP_REGNUM (REGNO (reg)));
-  gcc_assert (mode == SFmode
+  gcc_assert ((mode == HFmode && TARGET_HARD_FLOAT && TARGET_VFP)
+	      || mode == SFmode
 	      || mode == DFmode
 	      || mode == SImode
 	      || mode == DImode
@@ -23397,10 +23398,8 @@ arm_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
       if (mode == DFmode)
 	return VFP_REGNO_OK_FOR_DOUBLE (regno);
 
-      /* VFP registers can hold HFmode values, but there is no point in
-	 putting them there unless we have hardware conversion insns. */
       if (mode == HFmode)
-	return TARGET_FP16 && VFP_REGNO_OK_FOR_SINGLE (regno);
+	return VFP_REGNO_OK_FOR_SINGLE (regno);
 
       if (TARGET_NEON)
         return (VALID_NEON_DREG_MODE (mode) && VFP_REGNO_OK_FOR_DOUBLE (regno))
@@ -23604,26 +23603,6 @@ arm_debugger_arg_offset (int value, rtx addr)
   return value;
 }
 
-/* Implement TARGET_INVALID_PARAMETER_TYPE.  */
-
-static const char *
-arm_invalid_parameter_type (const_tree t)
-{
-  if (SCALAR_FLOAT_TYPE_P (t) && TYPE_PRECISION (t) == 16)
-    return N_("function parameters cannot have __fp16 type");
-  return NULL;
-}
-
-/* Implement TARGET_INVALID_PARAMETER_TYPE.  */
-
-static const char *
-arm_invalid_return_type (const_tree t)
-{
-  if (SCALAR_FLOAT_TYPE_P (t) && TYPE_PRECISION (t) == 16)
-    return N_("functions cannot return __fp16 type");
-  return NULL;
-}
-
 /* Implement TARGET_PROMOTED_TYPE.  */
 
 static tree
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index ad123dd..5b1a030 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -194,7 +194,8 @@ extern void (*arm_lang_output_object_attributes_hook)(void);
 /* FPU supports half-precision floating-point with NEON element load/store.  */
 #define TARGET_NEON_FP16						\
   (TARGET_VFP								\
-   && ARM_FPU_FSET_HAS (TARGET_FPU_FEATURES, FPU_FL_NEON | FPU_FL_FP16))
+   && ARM_FPU_FSET_HAS (TARGET_FPU_FEATURES, FPU_FL_NEON)		\
+   && ARM_FPU_FSET_HAS (TARGET_FPU_FEATURES, FPU_FL_FP16))
 
 /* FPU supports VFP half-precision floating-point.  */
 #define TARGET_FP16							\
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 47171b9..adae7cc 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -6547,7 +6547,7 @@
 (define_insn "*arm32_movhf"
   [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
 	(match_operand:HF 1 "general_operand"	   " m,r,r,F"))]
-  "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16)
+  "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_VFP)
    && (	  s_register_operand (operands[0], HFmode)
        || s_register_operand (operands[1], HFmode))"
   "*
diff --git a/gcc/config/arm/vfp.md b/gcc/config/arm/vfp.md
index ac5f3b8..5e4d96a 100644
--- a/gcc/config/arm/vfp.md
+++ b/gcc/config/arm/vfp.md
@@ -268,7 +268,8 @@
 (define_insn "*movhf_vfp"
   [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,t,r,t,r,r")
 	(match_operand:HF 1 "general_operand"	   " m,r,t,r,r,t,F"))]
-  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FP16 && !TARGET_NEON_FP16
+  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP
+   && !TARGET_NEON_FP16
    && (   s_register_operand (operands[0], HFmode)
        || s_register_operand (operands[1], HFmode))"
   "*
diff --git a/gcc/testsuite/g++.dg/ext/arm-fp16/fp16-param-1.C b/gcc/testsuite/g++.dg/ext/arm-fp16/fp16-param-1.C
index 03feb1a..e89da15 100644
--- a/gcc/testsuite/g++.dg/ext/arm-fp16/fp16-param-1.C
+++ b/gcc/testsuite/g++.dg/ext/arm-fp16/fp16-param-1.C
@@ -1,10 +1,14 @@
 /* { dg-do compile { target arm*-*-* } } */
 /* { dg-options "-mfp16-format=ieee" } */
 
-/* Functions cannot have parameters of type __fp16.  */
-extern void f (__fp16);		/* { dg-error "parameters cannot have __fp16 type" } */
-extern void (*pf) (__fp16);	/* { dg-error "parameters cannot have __fp16 type" } */
+/* Test that the ACLE macro is defined.  */
+#if __ARM_FP16_ARGS != 1
+#error Unexpected value for __ARM_FP16_ARGS
+#endif
+
+/* Test that __fp16 is supported as a parameter type.  */
+extern void f (__fp16);
+extern void (*pf) (__fp16);
 
-/* These should be OK.  */
 extern void g (__fp16 *);
 extern void (*pg) (__fp16 *);
diff --git a/gcc/testsuite/g++.dg/ext/arm-fp16/fp16-return-1.C b/gcc/testsuite/g++.dg/ext/arm-fp16/fp16-return-1.C
index 406dfac..b96532d 100644
--- a/gcc/testsuite/g++.dg/ext/arm-fp16/fp16-return-1.C
+++ b/gcc/testsuite/g++.dg/ext/arm-fp16/fp16-return-1.C
@@ -1,10 +1,9 @@
 /* { dg-do compile { target arm*-*-* } } */
 /* { dg-options "-mfp16-format=ieee" } */
 
-/* Functions cannot return type __fp16.  */
-extern __fp16 f (void);		/* { dg-error "cannot return __fp16" } */
-extern __fp16 (*pf) (void);	/* { dg-error "cannot return __fp16" } */
+/* Test that __fp16 is supported as a return type.  */
+extern __fp16 f (void);
+extern __fp16 (*pf) (void);
 
-/* These should be OK.  */
 extern __fp16 *g (void);
 extern __fp16 *(*pg) (void);
diff --git a/gcc/testsuite/gcc.target/arm/aapcs/neon-vect10.c b/gcc/testsuite/gcc.target/arm/aapcs/neon-vect10.c
new file mode 100644
index 0000000..680a3b5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/aapcs/neon-vect10.c
@@ -0,0 +1,31 @@
+/* Test AAPCS layout (VFP variant for Neon types) */
+
+/* { dg-do run { target arm_eabi } } */
+/* { dg-require-effective-target arm_neon_fp16_ok } */
+/* { dg-add-options arm_neon_fp16 } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define NEON
+#define TESTFILE "neon-vect10.c"
+#include "neon-constants.h"
+
+#include "abitest.h"
+#else
+
+ARG (int32x4_t, i32x4_constvec2, Q0) /* D0, D1.  */
+#if defined (__ARM_BIG_ENDIAN)
+ARG (__fp16, 3.0f, S4 + 2) /* D2, Q1.  */
+#else
+ARG (__fp16, 3.0f, S4) /* D2, Q1.  */
+#endif
+ARG (int32x4x2_t, i32x4x2_constvec1, Q2) /* Q2, Q3 - D4-D6 , s5-s12.  */
+ARG (double, 12.0, D3) /* Backfill this particular argument.  */
+#if defined (__ARM_BIG_ENDIAN)
+ARG (__fp16, 5.0f, S5 + 2) /* Backfill in S5.  */
+#else
+ARG (__fp16, 5.0f, S5) /* Backfill in S5.  */
+#endif
+ARG (int32x4x2_t, i32x4x2_constvec2, STACK)
+LAST_ARG (int, 3, R0)
+#endif
diff --git a/gcc/testsuite/gcc.target/arm/aapcs/neon-vect9.c b/gcc/testsuite/gcc.target/arm/aapcs/neon-vect9.c
new file mode 100644
index 0000000..fc2b13b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/aapcs/neon-vect9.c
@@ -0,0 +1,23 @@
+/* Test AAPCS layout (VFP variant for Neon types) */
+
+/* { dg-do run { target arm_eabi } } */
+/* { dg-require-effective-target arm_neon_fp16_ok } */
+/* { dg-add-options arm_neon_fp16 } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define NEON
+#define TESTFILE "neon-vect9.c"
+#include "neon-constants.h"
+
+#include "abitest.h"
+#else
+
+ARG (int32x4_t, i32x4_constvec2, Q0) /* D0, D1.  */
+#if defined (__ARM_BIG_ENDIAN)
+ARG (__fp16, 3.0f, S4 + 2) /* D2, Q1 occupied.  */
+#else
+ARG (__fp16, 3.0f, S4) /* D2, Q1 occupied.  */
+#endif
+LAST_ARG (int, 3, R0)
+#endif
diff --git a/gcc/testsuite/gcc.target/arm/aapcs/vfp18.c b/gcc/testsuite/gcc.target/arm/aapcs/vfp18.c
new file mode 100644
index 0000000..225e9ce
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/aapcs/vfp18.c
@@ -0,0 +1,27 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target arm_eabi } }  */
+/* { dg-require-effective-target arm_neon_fp16_ok } */
+/* { dg-options "-O -mfpu=vfp -mfloat-abi=hard -mfp16-format=ieee" } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define TESTFILE "vfp18.c"
+#include "abitest.h"
+
+#else
+#if defined (__ARM_BIG_ENDIAN)
+ARG (__fp16, 1.0f, S0 + 2)
+#else
+ARG (__fp16, 1.0f, S0)
+#endif
+ARG (float, 2.0f, S1)
+ARG (double, 4.0, D1)
+ARG (float, 2.0f, S4)
+#if defined (__ARM_BIG_ENDIAN)
+ARG (__fp16, 1.0f, S5 + 2)
+#else
+ARG (__fp16, 1.0f, S5)
+#endif
+LAST_ARG (int, 3, R0)
+#endif
diff --git a/gcc/testsuite/gcc.target/arm/aapcs/vfp19.c b/gcc/testsuite/gcc.target/arm/aapcs/vfp19.c
new file mode 100644
index 0000000..8928b15
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/aapcs/vfp19.c
@@ -0,0 +1,29 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target arm_eabi } } */
+/* { dg-require-effective-target arm_neon_fp16_ok } */
+/* { dg-options "-O -mfpu=vfp -mfloat-abi=hard -mfp16-format=ieee" } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define TESTFILE "vfp19.c"
+
+__complex__ x = 1.0+2.0i;
+
+#include "abitest.h"
+#else
+#if defined (__ARM_BIG_ENDIAN)
+ARG (__fp16, 1.0f, S0 + 2)
+#else
+ARG (__fp16, 1.0f, S0)
+#endif
+ARG (float, 2.0f, S1)
+ARG (__complex__ double, x, D1)
+ARG (float, 3.0f, S6)
+#if defined (__ARM_BIG_ENDIAN)
+ARG (__fp16, 2.0f, S7 + 2)
+#else
+ARG (__fp16, 2.0f, S7)
+#endif
+LAST_ARG (int, 3, R0)
+#endif
diff --git a/gcc/testsuite/gcc.target/arm/aapcs/vfp20.c b/gcc/testsuite/gcc.target/arm/aapcs/vfp20.c
new file mode 100644
index 0000000..61f0704
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/aapcs/vfp20.c
@@ -0,0 +1,21 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target arm_eabi } } */
+/* { dg-require-effective-target arm_neon_fp16_ok } */
+/* { dg-options "-O -mfpu=vfp -mfloat-abi=hard -mfp16-format=ieee" } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define TESTFILE "vfp20.c"
+
+#define PCSATTR __attribute__((pcs("aapcs")))
+
+#include "abitest.h"
+#else
+ARG (float, 1.0f, R0)
+ARG (double, 2.0, R2)
+ARG (float, 3.0f, STACK)
+ARG (__fp16, 2.0f, STACK+4)
+LAST_ARG (double, 4.0, STACK+8)
+#endif
+
diff --git a/gcc/testsuite/gcc.target/arm/aapcs/vfp21.c b/gcc/testsuite/gcc.target/arm/aapcs/vfp21.c
new file mode 100644
index 0000000..15dff7d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/aapcs/vfp21.c
@@ -0,0 +1,25 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target arm_eabi } } */
+/* { dg-require-effective-target arm_neon_fp16_ok } */
+/* { dg-options "-O -mfpu=vfp -mfloat-abi=hard -mfp16-format=ieee" } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define TESTFILE "vfp21.c"
+
+#define PCSATTR __attribute__((pcs("aapcs")))
+
+#include "abitest.h"
+#else
+#if defined (__ARM_BIG_ENDIAN)
+ARG (__fp16, 1.0f, R0 + 2)
+#else
+ARG (__fp16, 1.0f, R0)
+#endif
+ARG (double, 2.0, R2)
+ARG (__fp16, 3.0f, STACK)
+ARG (float, 2.0f, STACK+4)
+LAST_ARG (double, 4.0, STACK+8)
+#endif
+
diff --git a/gcc/testsuite/gcc.target/arm/fp16-aapcs-1.c b/gcc/testsuite/gcc.target/arm/fp16-aapcs-1.c
new file mode 100644
index 0000000..5eab3e2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/fp16-aapcs-1.c
@@ -0,0 +1,17 @@
+/* { dg-do compile }  */
+/* { dg-require-effective-target arm_fp16_ok } */
+/* { dg-options "-mfp16-format=ieee -O2" }  */
+/* { dg-add-options arm_fp16 } */
+
+/* Test __fp16 arguments and return value in registers.  */
+
+__fp16 F (__fp16 a, __fp16 b, __fp16 c)
+{
+  if (a == b)
+    return c;
+  return a;
+}
+
+/* { dg-final { scan-assembler-times {vcvtb\.f32\.f16\ts[0-9]+, s0} 1 } }  */
+/* { dg-final { scan-assembler-times {vcvtb\.f32\.f16\ts[0-9]+, s1} 1 } }  */
+/* { dg-final { scan-assembler-times {vmov\ts0, r[0-9]+} 1 } }  */
diff --git a/gcc/testsuite/gcc.target/arm/fp16-param-1.c b/gcc/testsuite/gcc.target/arm/fp16-param-1.c
index af4845f..9c52730 100644
--- a/gcc/testsuite/gcc.target/arm/fp16-param-1.c
+++ b/gcc/testsuite/gcc.target/arm/fp16-param-1.c
@@ -1,10 +1,14 @@
 /* { dg-do compile } */
 /* { dg-options "-mfp16-format=ieee" } */
 
-/* Functions cannot have parameters of type __fp16.  */
-extern void f (__fp16);		/* { dg-error "parameters cannot have __fp16 type" } */
-extern void (*pf) (__fp16);	/* { dg-error "parameters cannot have __fp16 type" } */
+/* Test that the ACLE macro is defined.  */
+#if __ARM_FP16_ARGS != 1
+#error Unexpected value for __ARM_FP16_ARGS
+#endif
+
+/* Test that __fp16 is supported as a parameter type.  */
+extern void f (__fp16);
+extern void (*pf) (__fp16);
 
-/* These should be OK.  */
 extern void g (__fp16 *);
 extern void (*pg) (__fp16 *);
diff --git a/gcc/testsuite/gcc.target/arm/fp16-return-1.c b/gcc/testsuite/gcc.target/arm/fp16-return-1.c
index f763941..f97a8d7 100644
--- a/gcc/testsuite/gcc.target/arm/fp16-return-1.c
+++ b/gcc/testsuite/gcc.target/arm/fp16-return-1.c
@@ -1,10 +1,9 @@
 /* { dg-do compile } */
 /* { dg-options "-mfp16-format=ieee" } */
 
-/* Functions cannot return type __fp16.  */
-extern __fp16 f (void);		/* { dg-error "cannot return __fp16" } */
-extern __fp16 (*pf) (void);	/* { dg-error "cannot return __fp16" } */
+/* Test that __fp16 is supported as a return type.  */
+extern __fp16 f (void);
+extern __fp16 (*pf) (void);
 
-/* These should be OK.  */
 extern __fp16 *g (void);
 extern __fp16 *(*pg) (void);
-- 
2.1.4


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]