https://gcc.gnu.org/g:c6fff0b1709f2a7d665ffadce96d6deb07ce62ae
commit r16-5394-gc6fff0b1709f2a7d665ffadce96d6deb07ce62ae Author: Christophe Lyon <[email protected]> Date: Thu Sep 18 23:16:32 2025 +0000 arm: [MVE intrinsics] Avoid warnings when floating-point is not supported [PR 117814] If the target does not support floating-point, we register FP vector types as 'void' (see register_vector_type). This 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. This happens for instance in gcc.target/arm/pr112337.c, depending on how GCC is built (I didn't notice the warnings because arm_mve.h is considered as a system include in my environment, and the warning is not emitted, but CI reported it). 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 cannot appear and disappear withing a single TU, they have to be available in all 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). The patch now enforces -mfp16-format=none if the option was used. 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 apply -mfp16-format=none where we used to default to ieee 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. The patch removes gcc.target/arm/fp16-compile-none-1.c which tests that using __fp16 produces an error with -mfp16-format=none, since it is no longer the case. 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-opts.h (arm_fp16_format_type): Add ARM_FP16_FORMAT_DEFAULT. * config/arm/arm.cc (arm_vector_mode_supported_p): Accept floating-point vector modes even if TARGET_HAVE_MVE_FLOAT is false. (arm_option_reconfigure_globals): Apply ARM_FP16_FORMAT_NONE if requested. * config/arm/arm.opt (mfp16-format): Default to ARM_FP16_FORMAT_DEFAULT. * config/arm/arm_mve_types.h (float16_t, float32_t): Define unconditionally. * doc/sourcebuild.texi (ARM-specific attributes): Document arm_v8_1m_mve_nofp_ok. 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. * gcc.target/arm/fp16-compile-none-1.c: Delete. * g++.target/arm/mve/general-c++/nomve_fp_1.c: Fix expected error message. * lib/target-supports.exp (check_effective_target_arm_v8_1m_mve_nofp_ok_nocache): New. (check_effective_target_arm_v8_1m_mve_nofp_ok): New. (add_options_for_arm_v8_1m_mve_nofp): New. Diff: --- gcc/config/arm/arm-builtins.cc | 4 +- gcc/config/arm/arm-mve-builtins.cc | 22 +-------- gcc/config/arm/arm-opts.h | 1 + gcc/config/arm/arm.cc | 14 +++--- gcc/config/arm/arm.opt | 2 +- gcc/config/arm/arm_mve_types.h | 2 - gcc/doc/sourcebuild.texi | 6 +++ .../g++.target/arm/mve/general-c++/nomve_fp_1.c | 2 +- gcc/testsuite/gcc.target/arm/fp16-compile-none-1.c | 7 --- .../gcc.target/arm/mve/intrinsics/pr117814-2-f16.c | 30 ++++++++++++ .../gcc.target/arm/mve/intrinsics/pr117814-2-f32.c | 30 ++++++++++++ .../gcc.target/arm/mve/intrinsics/pr117814-3-f16.c | 21 +++++++++ .../gcc.target/arm/mve/intrinsics/pr117814-3-f32.c | 21 +++++++++ .../gcc.target/arm/mve/intrinsics/pr117814-4-f16.c | 23 +++++++++ .../gcc.target/arm/mve/intrinsics/pr117814-f16.c | 22 +++++++++ .../gcc.target/arm/mve/intrinsics/pr117814-f32.c | 22 +++++++++ gcc/testsuite/lib/target-supports.exp | 54 ++++++++++++++++++++++ 17 files changed, 242 insertions(+), 41 deletions(-) diff --git a/gcc/config/arm/arm-builtins.cc b/gcc/config/arm/arm-builtins.cc index 3bb2566f9a2f..b0bbb32644c5 100644 --- a/gcc/config/arm/arm-builtins.cc +++ b/gcc/config/arm/arm-builtins.cc @@ -1685,9 +1685,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 42b53cc05e77..b37c91c541bc 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-opts.h b/gcc/config/arm/arm-opts.h index 5c543bf52466..d2384edb542b 100644 --- a/gcc/config/arm/arm-opts.h +++ b/gcc/config/arm/arm-opts.h @@ -35,6 +35,7 @@ */ enum arm_fp16_format_type { + ARM_FP16_FORMAT_DEFAULT = -1, ARM_FP16_FORMAT_NONE = 0, ARM_FP16_FORMAT_IEEE = 1, ARM_FP16_FORMAT_ALTERNATIVE = 2 diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc index 9dbc3f9befaf..07d24d1f67ed 100644 --- a/gcc/config/arm/arm.cc +++ b/gcc/config/arm/arm.cc @@ -3923,13 +3923,19 @@ arm_option_reconfigure_globals (void) arm_arch_bf16 = bitmap_bit_p (arm_active_target.isa, isa_bit_bf16); arm_fp16_inst = bitmap_bit_p (arm_active_target.isa, isa_bit_fp16); - if (arm_fp16_inst) + + /* Set arm_fp16_format to IEEE if the target has fp16 support unless user + forced ARM_FP16_FORMAT_NONE. */ + if (arm_fp16_inst && (arm_fp16_format != ARM_FP16_FORMAT_NONE)) { if (arm_fp16_format == ARM_FP16_FORMAT_ALTERNATIVE) error ("selected fp16 options are incompatible"); arm_fp16_format = ARM_FP16_FORMAT_IEEE; } + if (arm_fp16_format == ARM_FP16_FORMAT_DEFAULT) + arm_fp16_format = ARM_FP16_FORMAT_NONE; + arm_arch_cde = 0; arm_arch_cde_coproc = 0; int cde_bits[] = {isa_bit_cdecp0, isa_bit_cdecp1, isa_bit_cdecp2, @@ -29639,11 +29645,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.opt b/gcc/config/arm/arm.opt index d5eeeae7eaef..caa08d120cef 100644 --- a/gcc/config/arm/arm.opt +++ b/gcc/config/arm/arm.opt @@ -139,7 +139,7 @@ Target Var(TARGET_FLIP_THUMB) Undocumented Switch ARM/Thumb modes on alternating functions for compiler testing. mfp16-format= -Target RejectNegative Joined Enum(arm_fp16_format_type) Var(arm_fp16_format) Init(ARM_FP16_FORMAT_NONE) +Target RejectNegative Joined Enum(arm_fp16_format_type) Var(arm_fp16_format) Init(ARM_FP16_FORMAT_DEFAULT) Specify the __fp16 floating-point format. Enum diff --git a/gcc/config/arm/arm_mve_types.h b/gcc/config/arm/arm_mve_types.h index 42e74666e80b..d1889c68ac53 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/sourcebuild.texi b/gcc/doc/sourcebuild.texi index fc1d52c42c9e..c51c8f3c4424 100644 --- a/gcc/doc/sourcebuild.texi +++ b/gcc/doc/sourcebuild.texi @@ -2219,6 +2219,12 @@ the Half-precision floating-point instructions (HP), Floating-point Extension (FP) along with M-Profile Vector Extension (MVE). Some multilibs may be incompatible with these options. +@item arm_v8_1m_mve_nofp_ok +ARM target supports options to generate instructions from ARMv8.1-M +with the M-Profile Vector Extension (MVE) but without the +Half-precision floating-point instructions (HP) and Floating-point +Extension (FP). Some multilibs may be incompatible with these options. + @item arm_mve_hw Test system supports executing MVE instructions. 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 fd8c05b0eed4..4b91e0c6327b 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/fp16-compile-none-1.c b/gcc/testsuite/gcc.target/arm/fp16-compile-none-1.c deleted file mode 100644 index 9472249e2e2a..000000000000 --- a/gcc/testsuite/gcc.target/arm/fp16-compile-none-1.c +++ /dev/null @@ -1,7 +0,0 @@ -/* { dg-do compile } */ -/* { dg-require-effective-target arm_fp16_none_ok } */ -/* { dg-options "-mfp16-format=none" } */ - -/* __fp16 type name is not recognized unless you explicitly enable it - by selecting -mfp16-format=ieee or -mfp16-format=alternative. */ -__fp16 xx = 0.0; /* { dg-error "unknown type name" } */ 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 000000000000..046cad030d7c --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/pr117814-2-f16.c @@ -0,0 +1,30 @@ +/* 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_nofp_ok } */ +/* { dg-add-options arm_v8_1m_mve_nofp } */ +/* { 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 000000000000..6856e8e6a085 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/pr117814-2-f32.c @@ -0,0 +1,30 @@ +/* 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_nofp_ok } */ +/* { dg-add-options arm_v8_1m_mve_nofp } */ +/* { 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 000000000000..bcb0dd654163 --- /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 000000000000..7e02816d5055 --- /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 000000000000..b266f1b94e0c --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/pr117814-4-f16.c @@ -0,0 +1,23 @@ +/* Check that -mfp16-format=none works. */ + +/* { 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 + +/* { dg-final { scan-assembler-not {eabi_attribute 38,} } } */ 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 000000000000..88930c1a3eb6 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/pr117814-f16.c @@ -0,0 +1,22 @@ +/* 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_nofp_ok } */ +/* { dg-add-options arm_v8_1m_mve_nofp } */ +/* { 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 000000000000..814e781fa5d8 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/pr117814-f32.c @@ -0,0 +1,22 @@ +/* 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_nofp_ok } */ +/* { dg-add-options arm_v8_1m_mve_nofp } */ +/* { 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 diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 67f1a3c82303..b00e11e2ae52 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -6963,6 +6963,60 @@ proc add_options_for_arm_v8_1m_mve { flags } { return "$flags $et_arm_v8_1m_mve_flags" } +# Return 1 if the target supports ARMv8.1-M MVE without floating point +# instructions, 0 otherwise. The test is valid for ARM. +# Record the command line options needed. + +proc check_effective_target_arm_v8_1m_mve_nofp_ok_nocache { } { + global et_arm_v8_1m_mve_nofp_flags + set et_arm_v8_1m_mve_nofp_flags "" + + if { ![istarget arm*-*-*] } { + return 0; + } + + # Iterate through sets of options to find the compiler flags that + # need to be added to the -march option. + foreach flags { + "" + "-mfloat-abi=softfp" + "-mfpu=auto -mcpu=unset -march=armv8.1-m.main+mve" + "-mfpu=auto -mcpu=unset -march=armv8.1-m.main+mve -mfloat-abi=softfp" + } { + if { [check_no_compiler_messages_nocache \ + arm_v8_1m_mve_ok object { + #if !defined (__ARM_FEATURE_MVE) + #error "__ARM_FEATURE_MVE not defined" + #endif + #if (__ARM_FEATURE_MVE & 2) + #error "__ARM_FEATURE_MVE for floating point defined" + #endif + #if __ARM_BIG_ENDIAN + #error "MVE intrinsics are not supported in Big-Endian mode." + #endif + #include <arm_mve.h> + } "$flags -mthumb"] } { + set et_arm_v8_1m_mve_nofp_flags "$flags -mthumb --save-temps" + return 1 + } + } + + return 0; +} + +proc check_effective_target_arm_v8_1m_mve_nofp_ok { } { + return [check_cached_effective_target arm_v8_1m_mve_nofp_ok \ + check_effective_target_arm_v8_1m_mve_nofp_ok_nocache] +} + +proc add_options_for_arm_v8_1m_mve_nofp { flags } { + if { ! [check_effective_target_arm_v8_1m_mve_nofp_ok] } { + return "$flags" + } + global et_arm_v8_1m_mve_nofp_flags + return "$flags $et_arm_v8_1m_mve_nofp_flags" +} + proc check_effective_target_arm_v8_2a_dotprod_neon_ok { } { return [check_cached_effective_target arm_v8_2a_dotprod_neon_ok \ check_effective_target_arm_v8_2a_dotprod_neon_ok_nocache]
