This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[ARM] Enable __fp16 as a function parameter and return type.
- From: Matthew Wahab <matthew dot wahab at foss dot arm dot com>
- To: gcc-patches <gcc-patches at gcc dot gnu dot org>
- Date: Thu, 28 Apr 2016 10:20:01 +0100
- Subject: [ARM] Enable __fp16 as a function parameter and return type.
- Authentication-results: sourceware.org; auth=none
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