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.wa...@arm.com> Ramana Radhakrishnan <ramana.radhakrish...@arm.com> Jiong Wang <jiong.w...@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.wa...@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.wa...@arm.com> Ramana Radhakrishnan <ramana.radhakrish...@arm.com> Jiong Wang <jiong.w...@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.wa...@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