On Tue, 14 Jan 2025 at 14:11, Christophe Lyon <christophe.l...@linaro.org> wrote: > > If the target does not support floating-point, we register FP vector > types as 'void' (see register_vector_type). > > The leads to warnings about 'pure attribute on function returning > void' when we declare the various load intrinsics because their > call_properties say CP_READ_MEMORY (thus giving them the 'pure' > attribute), but their return type is void. > > To avoid such warnings, declare floating-point scalar and vector types > even if the target does not have an FPU. > > Note that since an FPU can be activated via #pragma GCC target > ("arch=armv8.1-m.main+mve.fp") for instance, it means that such types > must cannot appear and disappear withing a single TU, they have to be > available in both contexts. This implies a noteworthy change for > __fp16: it not longer depends on using -mfp16-format=ieee or > alternative. Also note that if the target ISA has the fp16 bit set, > we already silently activate -mfp16-format=ieee (with an error if > -mfp16-format=alternative was supplied). > > In arm-mve-builtins.cc (register_builtin_types, register_vector_type, > register_builtin_tuple_types), this means simply removing the early > exits. However, for this to work, we need to update > arm_vector_mode_supported_p, so that vector floating-point types are > always defined, and __fp16 must always be registered by > arm_init_fp16_builtins (as it is the base type for vectors of > float16_t. Another side effect is that the declaration of float16_t > and float32_t typedefs is now unconditional. > > The new tests verify that: > - we emit an error if the code tries to use floating-point intrinsics > and the target does not have the floating-point extension > - we emit the expected code when activating the floating-point > expected via a pragma > - we emit the expected code when the target supports floating-point > (no pragma needed) > - we ignore -mfp16-format=none > > An update is needed in g++.target/arm/mve/general-c++/nomve_fp_1.c, > because the error message now correctly uses float16x8_t instead of > void as return type. > > gcc/ChangeLog: > > PR target/117814 > * config/arm/arm-builtins.cc (arm_init_fp16_builtins): Always > register __fp16 type. > * config/arm/arm-mve-builtins.cc (register_builtin_tuple_types): > Remove special handling when TARGET_HAVE_MVE_FLOAT is false. > (register_vector_type): Likewise. > (register_builtin_tuple_types): Likewise. > * config/arm/arm.cc (arm_vector_mode_supported_p): Accept > floating-point vector modes even if TARGET_HAVE_MVE_FLOAT is > false. > * config/arm/arm_mve_types.h (float16_t, float32_t): Define > unconditionally. > * doc/extend.texi (Half-precision Floating-point): __fp16 is now > always available on arm. More x86 paragraph closer to the rest of > the x86 information. > > gcc/testsuite/ChangeLog: > > PR target/117814 > * gcc.target/arm/mve/intrinsics/pr117814-f16.c: New test. > * gcc.target/arm/mve/intrinsics/pr117814-2-f16.c: New test. > * gcc.target/arm/mve/intrinsics/pr117814-3-f16.c: New test. > * gcc.target/arm/mve/intrinsics/pr117814-4-f16.c: New test. > * gcc.target/arm/mve/intrinsics/pr117814-f32.c: New test. > * gcc.target/arm/mve/intrinsics/pr117814-2-f32.c: New test. > * gcc.target/arm/mve/intrinsics/pr117814-3-f32.c: New test. > * g++.target/arm/mve/general-c++/nomve_fp_1.c: Fix expected error > message.
CI complains because I forgot to remove fp16-compile-none-1.c (we no longer emit an error when using __fp16 with -mfp16-format=none). fp16-compile-none-2.c still passes because we do not enable HF mode in arm_scalar_mode_supported_p. That still seems a bit inconsistent... Maybe we should handle arm_fp16_format a bit differently, such that we can make a difference between no option and explicit -mfp16-format=none? Thanks, Christophe > --- > gcc/config/arm/arm-builtins.cc | 4 +-- > gcc/config/arm/arm-mve-builtins.cc | 22 +----------- > gcc/config/arm/arm.cc | 6 +--- > gcc/config/arm/arm_mve_types.h | 2 -- > gcc/doc/extend.texi | 29 +++++++++------ > .../arm/mve/general-c++/nomve_fp_1.c | 2 +- > .../arm/mve/intrinsics/pr117814-2-f16.c | 36 +++++++++++++++++++ > .../arm/mve/intrinsics/pr117814-2-f32.c | 36 +++++++++++++++++++ > .../arm/mve/intrinsics/pr117814-3-f16.c | 21 +++++++++++ > .../arm/mve/intrinsics/pr117814-3-f32.c | 21 +++++++++++ > .../arm/mve/intrinsics/pr117814-4-f16.c | 21 +++++++++++ > .../arm/mve/intrinsics/pr117814-f16.c | 28 +++++++++++++++ > .../arm/mve/intrinsics/pr117814-f32.c | 28 +++++++++++++++ > 13 files changed, 213 insertions(+), 43 deletions(-) > create mode 100644 > gcc/testsuite/gcc.target/arm/mve/intrinsics/pr117814-2-f16.c > create mode 100644 > gcc/testsuite/gcc.target/arm/mve/intrinsics/pr117814-2-f32.c > create mode 100644 > gcc/testsuite/gcc.target/arm/mve/intrinsics/pr117814-3-f16.c > create mode 100644 > gcc/testsuite/gcc.target/arm/mve/intrinsics/pr117814-3-f32.c > create mode 100644 > gcc/testsuite/gcc.target/arm/mve/intrinsics/pr117814-4-f16.c > create mode 100644 gcc/testsuite/gcc.target/arm/mve/intrinsics/pr117814-f16.c > create mode 100644 gcc/testsuite/gcc.target/arm/mve/intrinsics/pr117814-f32.c > > diff --git a/gcc/config/arm/arm-builtins.cc b/gcc/config/arm/arm-builtins.cc > index e860607686c..8f0aae4cff1 100644 > --- a/gcc/config/arm/arm-builtins.cc > +++ b/gcc/config/arm/arm-builtins.cc > @@ -2443,9 +2443,7 @@ arm_init_fp16_builtins (void) > arm_fp16_type_node = make_node (REAL_TYPE); > TYPE_PRECISION (arm_fp16_type_node) = GET_MODE_PRECISION (HFmode); > layout_type (arm_fp16_type_node); > - if (arm_fp16_format) > - (*lang_hooks.types.register_builtin_type) (arm_fp16_type_node, > - "__fp16"); > + (*lang_hooks.types.register_builtin_type) (arm_fp16_type_node, "__fp16"); > } > > void > diff --git a/gcc/config/arm/arm-mve-builtins.cc > b/gcc/config/arm/arm-mve-builtins.cc > index 42b53cc05e7..b37c91c541b 100644 > --- a/gcc/config/arm/arm-mve-builtins.cc > +++ b/gcc/config/arm/arm-mve-builtins.cc > @@ -410,8 +410,6 @@ register_builtin_types () > #include "arm-mve-builtins.def" > for (unsigned int i = 0; i < NUM_VECTOR_TYPES; ++i) > { > - if (vector_types[i].requires_float && !TARGET_HAVE_MVE_FLOAT) > - continue; > tree eltype = scalar_types[i]; > tree vectype; > if (eltype == boolean_type_node) > @@ -433,18 +431,6 @@ register_builtin_types () > static void > register_vector_type (vector_type_index type) > { > - > - /* If the target does not have the mve.fp extension, but the type requires > - it, then it needs to be assigned a non-dummy type so that functions > - with those types in their signature can be registered. This allows for > - diagnostics about the missing extension, rather than about a missing > - function definition. */ > - if (vector_types[type].requires_float && !TARGET_HAVE_MVE_FLOAT) > - { > - acle_vector_types[0][type] = void_type_node; > - return; > - } > - > tree vectype = abi_vector_types[type]; > tree id = get_identifier (vector_types[type].acle_name); > tree decl = build_decl (input_location, TYPE_DECL, id, vectype); > @@ -470,13 +456,7 @@ register_builtin_tuple_types (vector_type_index type) > { > const vector_type_info* info = &vector_types[type]; > > - /* If the target does not have the mve.fp extension, but the type requires > - it, then it needs to be assigned a non-dummy type so that functions > - with those types in their signature can be registered. This allows for > - diagnostics about the missing extension, rather than about a missing > - function definition. */ > - if (scalar_types[type] == boolean_type_node > - || (info->requires_float && !TARGET_HAVE_MVE_FLOAT)) > + if (scalar_types[type] == boolean_type_node) > { > for (unsigned int num_vectors = 2; num_vectors <= 4; num_vectors += 2) > acle_vector_types[num_vectors >> 1][type] = void_type_node; > diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc > index 5649986868b..2a0c6b2e1d8 100644 > --- a/gcc/config/arm/arm.cc > +++ b/gcc/config/arm/arm.cc > @@ -29804,11 +29804,7 @@ arm_vector_mode_supported_p (machine_mode mode) > return true; > > if (TARGET_HAVE_MVE > - && (VALID_MVE_SI_MODE (mode) || VALID_MVE_PRED_MODE (mode))) > - return true; > - > - if (TARGET_HAVE_MVE_FLOAT > - && (mode == V2DFmode || mode == V4SFmode || mode == V8HFmode)) > + && (VALID_MVE_MODE (mode) || VALID_MVE_PRED_MODE (mode))) > return true; > > return false; > diff --git a/gcc/config/arm/arm_mve_types.h b/gcc/config/arm/arm_mve_types.h > index 42e74666e80..d1889c68ac5 100644 > --- a/gcc/config/arm/arm_mve_types.h > +++ b/gcc/config/arm/arm_mve_types.h > @@ -26,10 +26,8 @@ > #ifndef _GCC_ARM_MVE_TYPES_H > #define _GCC_ARM_MVE_TYPES_H > > -#if (__ARM_FEATURE_MVE & 2) /* MVE Floating point. */ > typedef __fp16 float16_t; > typedef float float32_t; > -#endif > > #pragma GCC arm "arm_mve_types.h" > > diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi > index 1e1b4cc837d..2a542233c70 100644 > --- a/gcc/doc/extend.texi > +++ b/gcc/doc/extend.texi > @@ -1170,17 +1170,18 @@ typedef _Complex float __attribute__((mode(IC))) > _Complex_ibm128; > @cindex @code{__fp16} data type > @cindex @code{__Float16} data type > > -On ARM and AArch64 targets, GCC supports half-precision (16-bit) floating > -point via the @code{__fp16} type defined in the ARM C Language Extensions. > -On ARM systems, you must enable this type explicitly with the > -@option{-mfp16-format} command-line option in order to use it. > -On x86 targets with SSE2 enabled, GCC supports half-precision (16-bit) > -floating point via the @code{_Float16} type. For C++, x86 provides a builtin > -type named @code{_Float16} which contains same data format as C. > - > -ARM targets support two incompatible representations for half-precision > -floating-point values. You must choose one of the representations and > -use it consistently in your program. > +On ARM and AArch64 targets, GCC supports half-precision (16-bit) > +floating point via the @code{__fp16} type defined in the ARM C > +Language Extensions. On ARM systems, the @option{-mfp16-format} > +command-line option selects which format to use when the target > +supports several of them. > + > +Most ARM targets support two incompatible representations for > +half-precision floating-point values. You must choose one of the > +representations and use it consistently in your program, unless your > +target only supports IEEE 754-2008 format (for instance > +@code{armv8.2-a+fp16} and @code{armv8.1-m.main+mve.fp}) in which case > +it is the default and only acceptable setting. > > Specifying @option{-mfp16-format=ieee} selects the IEEE 754-2008 format. > This format can represent normalized values in the range of @math{2^{-14}} > to 65504. > @@ -1220,6 +1221,12 @@ calls. > It is recommended that portable code use the @code{_Float16} type defined > by ISO/IEC TS 18661-3:2015. @xref{Floating Types}. > > + > +On x86 targets with SSE2 enabled, GCC supports half-precision (16-bit) > +floating point via the @code{_Float16} type. For C++, x86 provides a > +builtin type named @code{_Float16} which contains same data format as > +C. > + > On x86 targets with SSE2 enabled, without @option{-mavx512fp16}, > all operations will be emulated by software emulation and the @code{float} > instructions. The default behavior for @code{FLT_EVAL_METHOD} is to keep the > diff --git a/gcc/testsuite/g++.target/arm/mve/general-c++/nomve_fp_1.c > b/gcc/testsuite/g++.target/arm/mve/general-c++/nomve_fp_1.c > index fd8c05b0eed..4b91e0c6327 100644 > --- a/gcc/testsuite/g++.target/arm/mve/general-c++/nomve_fp_1.c > +++ b/gcc/testsuite/g++.target/arm/mve/general-c++/nomve_fp_1.c > @@ -12,6 +12,6 @@ > void > f1 (uint8x16_t v) > { > - vreinterpretq_f16 (v); /* { dg-error {ACLE function 'void > vreinterpretq_f16\(uint8x16_t\)' requires ISA extension 'mve.fp'} } */ > + vreinterpretq_f16 (v); /* { dg-error {ACLE function 'float16x8_t > vreinterpretq_f16\(uint8x16_t\)' requires ISA extension 'mve.fp'} } */ > /* { dg-message {note: you can enable mve.fp by using the command-line > option '-march', or by using the 'target' attribute or pragma} "" {target > *-*-*} .-1 } */ > } > diff --git a/gcc/testsuite/gcc.target/arm/mve/intrinsics/pr117814-2-f16.c > b/gcc/testsuite/gcc.target/arm/mve/intrinsics/pr117814-2-f16.c > new file mode 100644 > index 00000000000..d16c04e2ee4 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/pr117814-2-f16.c > @@ -0,0 +1,36 @@ > +/* Check that we can compile if the target does not support floating-point, > but > + we use a pragma to enable FP support locally. */ > + > +/* { dg-require-effective-target arm_v8_1m_mve_ok } */ > +/* { dg-require-effective-target arm_fp_ok } */ > +/* Do not use dg-add-options arm_v8_1m_mve, because this might expand to "", > + which could imply mve+fp depending on the user settings. We want to make > + sure the '+fp' extension is not enabled. */ > +/* { dg-options "-mfpu=auto -march=armv8.1-m.main+mve" } */ > +/* We need arm_fp to get the proper -mfloat-abi=XXX, if needed. */ > +/* { dg-add-options arm_fp } */ > +/* { dg-additional-options "-O2" } */ > + > +#include "arm_mve.h" > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +#pragma GCC target ("arch=armv8.1-m.main+mve.fp") > + > +/* > +**foo: > +** ... > +** vldrh.16 q[0-9]+, \[(?:ip|fp|r[0-9]+)\](?: @.*|) > +** ... > +*/ > +float16x8_t > +foo (float16_t const *base) > +{ > + return vld1q_f16 (base); > +} > + > +#ifdef __cplusplus > +} > +#endif > diff --git a/gcc/testsuite/gcc.target/arm/mve/intrinsics/pr117814-2-f32.c > b/gcc/testsuite/gcc.target/arm/mve/intrinsics/pr117814-2-f32.c > new file mode 100644 > index 00000000000..2b2f6f2ab13 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/pr117814-2-f32.c > @@ -0,0 +1,36 @@ > +/* Check that we can compile if the target does not support floating-point, > but > + we use a pragma to enable FP support locally. */ > + > +/* { dg-require-effective-target arm_v8_1m_mve_ok } */ > +/* { dg-require-effective-target arm_fp_ok } */ > +/* Do not use dg-add-options arm_v8_1m_mve, because this might expand to "", > + which could imply mve+fp depending on the user settings. We want to make > + sure the '+fp' extension is not enabled. */ > +/* { dg-options "-mfpu=auto -march=armv8.1-m.main+mve" } */ > +/* We need arm_fp to get the proper -mfloat-abi=XXX, if needed. */ > +/* { dg-add-options arm_fp } */ > +/* { dg-additional-options "-O2" } */ > + > +#include "arm_mve.h" > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +#pragma GCC target ("arch=armv8.1-m.main+mve.fp") > + > +/* > +**foo: > +** ... > +** vldrw.32 q[0-9]+, \[(?:ip|fp|r[0-9]+)\](?: @.*|) > +** ... > +*/ > +float32x4_t > +foo (float32_t const *base) > +{ > + return vld1q_f32 (base); > +} > + > +#ifdef __cplusplus > +} > +#endif > diff --git a/gcc/testsuite/gcc.target/arm/mve/intrinsics/pr117814-3-f16.c > b/gcc/testsuite/gcc.target/arm/mve/intrinsics/pr117814-3-f16.c > new file mode 100644 > index 00000000000..bcb0dd65416 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/pr117814-3-f16.c > @@ -0,0 +1,21 @@ > +/* Check that we can compile if the target supports floating-point. */ > + > +/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */ > +/* { dg-add-options arm_v8_1m_mve_fp } */ > +/* { dg-additional-options "-O2" } */ > + > +#include "arm_mve.h" > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +float16x8_t > +foo (float16_t const *base) > +{ > + return vld1q_f16 (base); > +} > + > +#ifdef __cplusplus > +} > +#endif > diff --git a/gcc/testsuite/gcc.target/arm/mve/intrinsics/pr117814-3-f32.c > b/gcc/testsuite/gcc.target/arm/mve/intrinsics/pr117814-3-f32.c > new file mode 100644 > index 00000000000..7e02816d505 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/pr117814-3-f32.c > @@ -0,0 +1,21 @@ > +/* Check that we can compile if the target supports floating-point. */ > + > +/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */ > +/* { dg-add-options arm_v8_1m_mve_fp } */ > +/* { dg-additional-options "-O2" } */ > + > +#include "arm_mve.h" > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +float32x4_t > +foo (float32_t const *base) > +{ > + return vld1q_f32 (base); > +} > + > +#ifdef __cplusplus > +} > +#endif > diff --git a/gcc/testsuite/gcc.target/arm/mve/intrinsics/pr117814-4-f16.c > b/gcc/testsuite/gcc.target/arm/mve/intrinsics/pr117814-4-f16.c > new file mode 100644 > index 00000000000..0757d5a549b > --- /dev/null > +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/pr117814-4-f16.c > @@ -0,0 +1,21 @@ > +/* Check that -mfp16-format=none is silently ignored. */ > + > +/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */ > +/* { dg-add-options arm_v8_1m_mve_fp } */ > +/* { dg-additional-options "-O2 -mfp16-format=none" } */ > + > +#include "arm_mve.h" > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +float16x8_t > +foo (float16_t const *base) > +{ > + return vld1q_f16 (base); > +} > + > +#ifdef __cplusplus > +} > +#endif > diff --git a/gcc/testsuite/gcc.target/arm/mve/intrinsics/pr117814-f16.c > b/gcc/testsuite/gcc.target/arm/mve/intrinsics/pr117814-f16.c > new file mode 100644 > index 00000000000..c25506bd034 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/pr117814-f16.c > @@ -0,0 +1,28 @@ > +/* Check that we get an error if the target does not support floating-point: > we > + force +mve to cancel a possible implicit +mve.fp. */ > + > +/* { dg-require-effective-target arm_v8_1m_mve_ok } */ > +/* { dg-require-effective-target arm_fp_ok } */ > +/* Do not use dg-add-options arm_v8_1m_mve, because this might expand to "", > + which could imply mve+fp depending on the user settings. We want to make > + sure the '+fp' extension is not enabled. */ > +/* { dg-options "-mfpu=auto -march=armv8.1-m.main+mve" } */ > +/* We need arm_fp to get the proper -mfloat-abi=XXX, if needed. */ > +/* { dg-add-options arm_fp } */ > +/* { dg-additional-options "-O2" } */ > + > +#include "arm_mve.h" > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +float16x8_t > +foo (float16_t const *base) > +{ > + return vld1q_f16 (base); /* { dg-error {ACLE function '.*vld1q_f16.*' > requires ISA extension 'mve.fp'} } */ > +} > + > +#ifdef __cplusplus > +} > +#endif > diff --git a/gcc/testsuite/gcc.target/arm/mve/intrinsics/pr117814-f32.c > b/gcc/testsuite/gcc.target/arm/mve/intrinsics/pr117814-f32.c > new file mode 100644 > index 00000000000..91a5e192986 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/pr117814-f32.c > @@ -0,0 +1,28 @@ > +/* Check that we get an error if the target does not support floating-point: > we > + force +mve to cancel a possible implicit +mve.fp. */ > + > +/* { dg-require-effective-target arm_v8_1m_mve_ok } */ > +/* { dg-require-effective-target arm_fp_ok } */ > +/* Do not use dg-add-options arm_v8_1m_mve, because this might expand to "", > + which could imply mve+fp depending on the user settings. We want to make > + sure the '+fp' extension is not enabled. */ > +/* { dg-options "-mfpu=auto -march=armv8.1-m.main+mve" } */ > +/* We need arm_fp to get the proper -mfloat-abi=XXX, if needed. */ > +/* { dg-add-options arm_fp } */ > +/* { dg-additional-options "-O2" } */ > + > +#include "arm_mve.h" > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +float32x4_t > +foo (float32_t const *base) > +{ > + return vld1q_f32 (base); /* { dg-error {ACLE function '.*vld1q_f32.*' > requires ISA extension 'mve.fp'} } */ > +} > + > +#ifdef __cplusplus > +} > +#endif > -- > 2.34.1 >