commit c2ed018d10328c5cf93aa56b00ba4caf5dace539 Author: Ramana Radhakrishnan Date: Fri Nov 11 21:39:22 2022 +0000 [Patch Arm] Fix PR92999 PR target/92999 is a case where the VFP PCS implementation is incorrectly considering homogenous floating point aggregates with FP16 and BF16 values. Can someone help me with a bootstrap and regression test on an armhf environment ? Signed-off-by: Ramana Radhakrishnan Tested-by: Alex Coplan Reviewed-by: Richard Earnshaw PR target/92999 gcc/ChangeLog: * config/arm/arm.cc (aapcs_vfp_is_invalid_scalar_in_ha): New (aapcs_vfp_sub_candidate): Adjust. gcc/testsuite/ChangeLog: * gcc.target/arm/pr92999.c: New test. diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc index 2eb4d51e4a3..cd3e1ffe777 100644 --- a/gcc/config/arm/arm.cc +++ b/gcc/config/arm/arm.cc @@ -6281,6 +6281,31 @@ const unsigned int WARN_PSABI_EMPTY_CXX17_BASE = 1U << 0; const unsigned int WARN_PSABI_NO_UNIQUE_ADDRESS = 1U << 1; const unsigned int WARN_PSABI_ZERO_WIDTH_BITFIELD = 1U << 2; + +/* The AAPCS VFP ABI allows homogenous aggregates with scalar + FP32 and FP64 members. + Return + true if this is a scalar that is not a proper candidate + false if this is a scalar that is an acceptable scalar data + type in a homogenous aggregate or if this is not a scalar allowing + the tree walk in aapcs_vfp_sub_candidate to continue. + */ +static bool +aapcs_vfp_is_invalid_scalar_in_ha (const_tree inner_type) +{ + + machine_mode mode = TYPE_MODE (inner_type); + if (TREE_CODE (inner_type) == REAL_TYPE) + { + if (mode == DFmode && mode == SFmode) + return false; + else + return true; + } + else + return false; +} + /* Walk down the type tree of TYPE counting consecutive base elements. If *MODEP is VOIDmode, then set it to the first valid floating point type. If a non-floating point type is found, or if a floating point @@ -6372,6 +6397,10 @@ aapcs_vfp_sub_candidate (const_tree type, machine_mode *modep, || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) return -1; + /* We ignore HFA's of FP16 and BF16. */ + if (aapcs_vfp_is_invalid_scalar_in_ha (TREE_TYPE (type))) + return -1; + count = aapcs_vfp_sub_candidate (TREE_TYPE (type), modep, warn_psabi_flags); if (count == -1 @@ -6455,6 +6484,10 @@ aapcs_vfp_sub_candidate (const_tree type, machine_mode *modep, } } + /* We ignore HA's of FP16 and BF16. */ + if (aapcs_vfp_is_invalid_scalar_in_ha (TREE_TYPE (field))) + return -1; + sub_count = aapcs_vfp_sub_candidate (TREE_TYPE (field), modep, warn_psabi_flags); if (sub_count < 0) @@ -6489,6 +6522,10 @@ aapcs_vfp_sub_candidate (const_tree type, machine_mode *modep, if (TREE_CODE (field) != FIELD_DECL) continue; + /* We ignore HA's of FP16 and BF16. */ + if (aapcs_vfp_is_invalid_scalar_in_ha (TREE_TYPE (field))) + return -1; + sub_count = aapcs_vfp_sub_candidate (TREE_TYPE (field), modep, warn_psabi_flags); if (sub_count < 0) diff --git a/gcc/testsuite/gcc.target/arm/pr92999.c b/gcc/testsuite/gcc.target/arm/pr92999.c new file mode 100644 index 00000000000..faa21fdb7d2 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pr92999.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ +/* { dg-options "-mfp16-format=ieee" } */ + +// +// Compile with gcc -mfp16-format=ieee +// Any optimization level is fine. +// +// Correct output should be +// "y.first = 1, y.second = -99" +// +// Buggy output is +// "y.first = -99, y.second = -99" +// +#include +struct phalf { + __fp16 first; + __fp16 second; +}; + +struct phalf phalf_copy(struct phalf* src) __attribute__((noinline)); +struct phalf phalf_copy(struct phalf* src) { + return *src; +} + +int main() { + struct phalf x = { 1.0, -99.0}; + struct phalf y = phalf_copy(&x); + if (y.first != 1.0 && y.second != -99.0) + abort(); + return 0; +}