From 8a1360e72d6c6056606aa5edd8c906c50f26de59 Mon Sep 17 00:00:00 2001 From: Stam Markianos-Wright Date: Mon, 16 Jan 2023 11:40:40 +0000 Subject: [PATCH] arm: Split up MVE _Generic associations to prevent type clashes [PR107515] With these previous patches: https://gcc.gnu.org/pipermail/gcc-patches/2022-November/606586.html https://gcc.gnu.org/pipermail/gcc-patches/2022-November/606587.html we enabled the MVE overloaded _Generic associations to handle more scalar types, however at PR 107515 we found a new regression that wasn't detected in our testing: With glibc's posix/types.h: ``` typedef signed int __int32_t; ... typedef __int32_t int32_t; ``` We would get a `error: '_Generic' specifies two compatible types` from `__ARM_mve_coerce3` because of `type: param`, when `type` is `int` and `int32_t: param` both being the same under the hood. The same did not happen with Newlib's header sys/_stdint.h: ``` typedef long int __int32_t; ... typedef __int32_t int32_t ; ``` which worked fine, because it uses `long int`. The same could feasibly happen in `__ARM_mve_coerce2` between `__fp16` and `float16_t`. The solution here is to break the _Generic down so that the similar types don't appear at the same level, as is done in `__ARM_mve_typeid` gcc/ChangeLog: PR target/96795 PR target/107515 * config/arm/arm_mve.h (__ARM_mve_coerce2): Split types. (__ARM_mve_coerce3): Likewise. gcc/testsuite/ChangeLog: PR target/96795 PR target/107515 * gcc.target/arm/mve/intrinsics/mve_intrinsic_type_overloads-fp.c: New test. * gcc.target/arm/mve/intrinsics/mve_intrinsic_type_overloads-int.c: New test. --- gcc/config/arm/arm_mve.h | 4 +- .../intrinsics/mve_intrinsic_type_overloads-fp.c | 65 ++++++++++++++++++++++ .../intrinsics/mve_intrinsic_type_overloads-int.c | 45 +++++++++++++++ 3 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_intrinsic_type_overloads-fp.c create mode 100644 gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_intrinsic_type_overloads-int.c diff --git a/gcc/config/arm/arm_mve.h b/gcc/config/arm/arm_mve.h index 00fb42a..13bdb60 100644 --- a/gcc/config/arm/arm_mve.h +++ b/gcc/config/arm/arm_mve.h @@ -35659,9 +35659,9 @@ extern void *__ARM_undef; #define __ARM_mve_coerce1(param, type) \ _Generic(param, type: param, const type: param, default: *(type *)__ARM_undef) #define __ARM_mve_coerce2(param, type) \ - _Generic(param, type: param, float16_t: param, float32_t: param, default: *(type *)__ARM_undef) + _Generic(param, type: param, __fp16: param, default: _Generic (param, _Float16: param, float16_t: param, float32_t: param, default: *(type *)__ARM_undef)) #define __ARM_mve_coerce3(param, type) \ - _Generic(param, type: param, int8_t: param, int16_t: param, int32_t: param, int64_t: param, uint8_t: param, uint16_t: param, uint32_t: param, uint64_t: param, default: *(type *)__ARM_undef) + _Generic(param, type: param, default: _Generic (param, int8_t: param, int16_t: param, int32_t: param, int64_t: param, uint8_t: param, uint16_t: param, uint32_t: param, uint64_t: param, default: *(type *)__ARM_undef)) #if (__ARM_FEATURE_MVE & 2) /* MVE Floating point. */ diff --git a/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_intrinsic_type_overloads-fp.c b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_intrinsic_type_overloads-fp.c new file mode 100644 index 0000000..7492e9b --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_intrinsic_type_overloads-fp.c @@ -0,0 +1,65 @@ +/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */ +/* { dg-add-options arm_v8_1m_mve_fp } */ +/* { dg-additional-options "-O2 -Wno-pedantic -Wno-long-long" } */ +#include "arm_mve.h" + +float f1; +double f2; +float16_t f3; +float32_t f4; +__fp16 f5; +_Float16 f6; + +int i1; +short i2; +long i3; +long long i4; +int8_t i5; +int16_t i6; +int32_t i7; +int64_t i8; + +const int ci1; +const short ci2; +const long ci3; +const long long ci4; +const int8_t ci5; +const int16_t ci6; +const int32_t ci7; +const int64_t ci8; + +float16x8_t floatvec; +int16x8_t intvec; + +void test(void) +{ + /* Test a few different supported ways of passing an int value. The + intrinsic vmulq was chosen arbitrarily, but it is representative of + all intrinsics that take a non-const scalar value. */ + intvec = vmulq(intvec, 2); + intvec = vmulq(intvec, (int32_t) 2); + intvec = vmulq(intvec, (short) 2); + intvec = vmulq(intvec, i1); + intvec = vmulq(intvec, i2); + intvec = vmulq(intvec, i3); + intvec = vmulq(intvec, i4); + intvec = vmulq(intvec, i5); + intvec = vmulq(intvec, i6); + intvec = vmulq(intvec, i7); + intvec = vmulq(intvec, i8); + + /* Test a few different supported ways of passing a float value. */ + floatvec = vmulq(floatvec, 0.5); + floatvec = vmulq(floatvec, 0.5f); + floatvec = vmulq(floatvec, (__fp16) 0.5); + floatvec = vmulq(floatvec, f1); + floatvec = vmulq(floatvec, f2); + floatvec = vmulq(floatvec, f3); + floatvec = vmulq(floatvec, f4); + floatvec = vmulq(floatvec, f5); + floatvec = vmulq(floatvec, f6); + floatvec = vmulq(floatvec, 0.15f16); + floatvec = vmulq(floatvec, (_Float16) 0.15); +} + +/* { dg-final { scan-assembler-not "__ARM_undef" } } */ diff --git a/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_intrinsic_type_overloads-int.c b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_intrinsic_type_overloads-int.c new file mode 100644 index 0000000..9a921bf --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_intrinsic_type_overloads-int.c @@ -0,0 +1,45 @@ +/* { dg-require-effective-target arm_v8_1m_mve_ok } */ +/* { dg-add-options arm_v8_1m_mve } */ +/* { dg-additional-options "-O2 -Wno-pedantic -Wno-long-long" } */ + +#include "arm_mve.h" + +int i1; +short i2; +long i3; +long long i4; +int8_t i5; +int16_t i6; +int32_t i7; +int64_t i8; + +const int ci1; +const short ci2; +const long ci3; +const long long ci4; +const int8_t ci5; +const int16_t ci6; +const int32_t ci7; +const int64_t ci8; + +int16x8_t intvec; + +void test(void) +{ + /* Test a few different supported ways of passing an int value. The + intrinsic vmulq was chosen arbitrarily, but it is representative of + all intrinsics that take a non-const scalar value. */ + intvec = vmulq(intvec, 2); + intvec = vmulq(intvec, (int32_t) 2); + intvec = vmulq(intvec, (short) 2); + intvec = vmulq(intvec, i1); + intvec = vmulq(intvec, i2); + intvec = vmulq(intvec, i3); + intvec = vmulq(intvec, i4); + intvec = vmulq(intvec, i5); + intvec = vmulq(intvec, i6); + intvec = vmulq(intvec, i7); + intvec = vmulq(intvec, i8); +} + +/* { dg-final { scan-assembler-not "__ARM_undef" } } */ -- 2.7.4