https://gcc.gnu.org/g:efbc7fbb70d875ec1ff628f0e4b3bcfc80bcb9e6
commit r17-2018-gefbc7fbb70d875ec1ff628f0e4b3bcfc80bcb9e6 Author: Karl Meakin <[email protected]> Date: Fri Feb 20 15:38:46 2026 +0000 aarch64: Port NEON add intrinsics to pragma-based framework Add all the necessary infrastructure for defining NEON intrinsics using the pragma-based framework, and port the `vadd` family of functions to demonstrate that it works. gcc/ChangeLog: * config/aarch64/aarch64-neon-builtins-base.cc: New file. * config/aarch64/aarch64-neon-builtins-base.def: New file. * config/aarch64/aarch64-neon-builtins-base.h: New file. * config/aarch64/aarch64-neon-builtins-functions.h: New file. * config/aarch64/aarch64-neon-builtins-shapes.cc: New file. * config/aarch64/aarch64-neon-builtins-shapes.h: New file. * config/aarch64/aarch64-neon-builtins.def: New file. * config.gcc (extra_headers, extra_objs): Add new files and reformat for readability. * config/aarch64/t-aarch64: Add recipes for new files. * config/aarch64/aarch64-protos.h (handle_arm_neon_h): Rename to `init_arm_neon_builtins`. * config/aarch64/aarch64-builtins.cc (handle_arm_neon_h): Likewise. * config/aarch64/aarch64-c.cc (aarch64_pragma_aarch64): Call `aarch64_acle::handle_arm_neon_h`. * config/aarch64/aarch64-acle-builtins.cc (TYPES_*): Move to aarch64-acle-builtins.h (NONSTREAMING_SVE, SVE_AND_SME, SSVE): Likewise. (neon_function_groups): New variable. (arm_neon_h_handled): Likewise. (handle_arm_neon_h): New function. * config/aarch64/aarch64-sve-builtins-shapes.cc: (gimple_folder::fold): Allow folding if `TARGET_SVE` is false but `TARGET_SIMD` is true. * config/aarch64/aarch64-sve-builtins.def (p8, p16, p64, 128): New type suffixes. * config/aarch64/aarch64-acle-builtins.h (enum handle_pragma_index): New enum member `arm_neon_handle`. (enum type_class_index): New enum member `TYPE_poly`. (TYPES_*): Moved from `aarch64-acle-builtins.cc`. (NONSTREAMING_SVE, SVE_AND_SME, SSVE): Likewise. * config/aarch64/arm_neon.h (vadd_s8, vadd_s16, vadd_s32, vadd_f32, vadd_f64, vadd_u8, vadd_u16, vadd_u32, vadd_s64, vadd_u64, vaddq_s8, vaddq_s16, vaddq_s32, vaddq_s64, vaddq_f32, vaddq_f64, vaddq_u8, vaddq_u16, vaddq_u32, vaddq_u64, vadd_f16, vaddq_f16, vadd_p8, vadd_p16, vadd_p64, vaddq_p8, vaddq_p16, vaddq_p64, vaddq_p128, vaddd_u64, vaddd_s64): Delete function definitions. gcc/testsuite/ChangeLog: * g++.target/aarch64/pr103147-6.C: Fix tests. * g++.target/aarch64/pr117048.C: Fix tests. * gcc.target/aarch64/pr103147-6.c: Fix tests. * gcc.target/aarch64/neon/aarch64-neon.exp: New test. * gcc.target/aarch64/neon/arm_neon_test.h: New test. * gcc.target/aarch64/neon/vadd.c: New test. Diff: --- gcc/config.gcc | 2 + gcc/config/aarch64/aarch64-acle-builtins.cc | 895 ++------------------- gcc/config/aarch64/aarch64-acle-builtins.h | 831 +++++++++++++++++++ gcc/config/aarch64/aarch64-builtins.cc | 11 +- gcc/config/aarch64/aarch64-c.cc | 2 +- gcc/config/aarch64/aarch64-neon-builtins-base.cc | 106 +++ gcc/config/aarch64/aarch64-neon-builtins-base.def | 33 + gcc/config/aarch64/aarch64-neon-builtins-base.h | 29 + .../aarch64/aarch64-neon-builtins-functions.h | 29 + gcc/config/aarch64/aarch64-neon-builtins-shapes.cc | 69 ++ gcc/config/aarch64/aarch64-neon-builtins-shapes.h | 29 + gcc/config/aarch64/aarch64-neon-builtins.def | 40 + gcc/config/aarch64/aarch64-protos.h | 3 +- gcc/config/aarch64/aarch64-sve-builtins-shapes.cc | 16 +- gcc/config/aarch64/aarch64-sve-builtins.def | 11 + gcc/config/aarch64/arm_neon.h | 204 ----- gcc/config/aarch64/t-aarch64 | 29 + gcc/testsuite/g++.target/aarch64/pr103147-6.C | 1 + gcc/testsuite/g++.target/aarch64/pr117048.C | 2 +- .../gcc.target/aarch64/neon/aarch64-neon.exp | 43 + .../gcc.target/aarch64/neon/arm_neon_test.h | 22 + gcc/testsuite/gcc.target/aarch64/neon/vadd.c | 203 +++++ gcc/testsuite/gcc.target/aarch64/pr103147-6.c | 1 + 23 files changed, 1579 insertions(+), 1032 deletions(-) diff --git a/gcc/config.gcc b/gcc/config.gcc index 94189b9b0e26..07400cb23e0f 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -392,6 +392,8 @@ aarch64*-*-*) extra_objs="${extra_objs} aarch64-json-tunings-printer.o" extra_objs="${extra_objs} aarch64-json-tunings-parser.o" extra_objs="${extra_objs} aarch64-narrow-gp-writes.o" + extra_objs="${extra_objs} aarch64-neon-builtins-base.o" + extra_objs="${extra_objs} aarch64-neon-builtins-shapes.o" target_gtfiles="${target_gtfiles} \$(srcdir)/config/aarch64/aarch64-protos.h" target_gtfiles="${target_gtfiles} \$(srcdir)/config/aarch64/aarch64-builtins.h" diff --git a/gcc/config/aarch64/aarch64-acle-builtins.cc b/gcc/config/aarch64/aarch64-acle-builtins.cc index 03a8ba2efd35..d065457c0118 100644 --- a/gcc/config/aarch64/aarch64-acle-builtins.cc +++ b/gcc/config/aarch64/aarch64-acle-builtins.cc @@ -54,6 +54,8 @@ #include "aarch64-sve-builtins-sve2.h" #include "aarch64-sve-builtins-sme.h" #include "aarch64-sve-builtins-shapes.h" +#include "aarch64-neon-builtins-shapes.h" +#include "aarch64-neon-builtins-base.h" #include "aarch64-builtins.h" using namespace aarch64; @@ -180,819 +182,21 @@ CONSTEXPR const group_suffix_info group_suffixes[] = { { "", 0, 1 } }; -/* Define a TYPES_<combination> macro for each combination of type - suffixes that an ACLE function can have, where <combination> is the - name used in DEF_SVE_FUNCTION entries. - - Use S (T) for single type suffix T and D (T1, T2) for a pair of type - suffixes T1 and T2. Use commas to separate the suffixes. - - Although the order shouldn't matter, the convention is to sort the - suffixes lexicographically after dividing suffixes into a type - class ("b", "f", etc.) and a numerical bit count. */ - -/* _b8 _b16 _b32 _b64. */ -#define TYPES_all_pred(S, D, T) \ - S (b8), S (b16), S (b32), S (b64) - -/* _c8 _c16 _c32 _c64. */ -#define TYPES_all_count(S, D, T) \ - S (c8), S (c16), S (c32), S (c64) - -/* _b8 _b16 _b32 _b64 - _c8 _c16 _c32 _c64. */ -#define TYPES_all_pred_count(S, D, T) \ - TYPES_all_pred (S, D, T), \ - TYPES_all_count (S, D, T) - -/* _f16 _f32 _f64. */ -#define TYPES_all_float(S, D, T) \ - S (f16), S (f32), S (f64) - -/* _f32 _f64. */ -#define TYPES_sd_float(S, D, T) \ - S (f32), S (f64) - -/* _s8 _s16 _s32 _s64. */ -#define TYPES_all_signed(S, D, T) \ - S (s8), S (s16), S (s32), S (s64) - -/* _f16 _f32 _f64 - _s8 _s16 _s32 _s64. */ -#define TYPES_all_float_and_signed(S, D, T) \ - TYPES_all_float (S, D, T), TYPES_all_signed (S, D, T) - -/* _u8 _u16 _u32 _u64. */ -#define TYPES_all_unsigned(S, D, T) \ - S (u8), S (u16), S (u32), S (u64) - -/* _s8 _s16 _s32 _s64 - _u8 _u16 _u32 _u64. */ -#define TYPES_all_integer(S, D, T) \ - TYPES_all_signed (S, D, T), TYPES_all_unsigned (S, D, T) - -/* _f16 _f32 _f64 - _s8 _s16 _s32 _s64 - _u8 _u16 _u32 _u64. */ -#define TYPES_all_arith(S, D, T) \ - TYPES_all_float (S, D, T), TYPES_all_integer (S, D, T) - -#define TYPES_all_data(S, D, T) \ - TYPES_b_data (S, D, T), \ - TYPES_h_data (S, D, T), \ - TYPES_s_data (S, D, T), \ - TYPES_d_data (S, D, T) - -/* _b only. */ -#define TYPES_b(S, D, T) \ - S (b) - -/* _c only. */ -#define TYPES_c(S, D, T) \ - S (c) - -/* _u8. */ -#define TYPES_b_unsigned(S, D, T) \ - S (u8) - -/* _s8 - _u8. */ -#define TYPES_b_integer(S, D, T) \ - S (s8), TYPES_b_unsigned (S, D, T) - -/* _mf8 - _s8 - _u8. */ -#define TYPES_b_data(S, D, T) \ - S (mf8), TYPES_b_integer (S, D, T) - -/* _s8 _s16 - _u8 _u16. */ -#define TYPES_bh_integer(S, D, T) \ - S (s8), S (s16), S (u8), S (u16) - -/* _u8 _u32. */ -#define TYPES_bs_unsigned(S, D, T) \ - S (u8), S (u32) - -/* _s8 _s16 _s32. */ -#define TYPES_bhs_signed(S, D, T) \ - S (s8), S (s16), S (s32) - -/* _u8 _u16 _u32. */ -#define TYPES_bhs_unsigned(S, D, T) \ - S (u8), S (u16), S (u32) - -/* _s8 _s16 _s32 - _u8 _u16 _u32. */ -#define TYPES_bhs_integer(S, D, T) \ - TYPES_bhs_signed (S, D, T), TYPES_bhs_unsigned (S, D, T) - -#define TYPES_bh_data(S, D, T) \ - TYPES_b_data (S, D, T), \ - TYPES_h_data (S, D, T) - -#define TYPES_bhs_data(S, D, T) \ - TYPES_b_data (S, D, T), \ - TYPES_h_data (S, D, T), \ - TYPES_s_data (S, D, T) - -/* _s16_s8 _s32_s16 _s64_s32 - _u16_u8 _u32_u16 _u64_u32. */ -#define TYPES_bhs_widen(S, D, T) \ - D (s16, s8), D (s32, s16), D (s64, s32), \ - D (u16, u8), D (u32, u16), D (u64, u32) - -/* _bf16. */ -#define TYPES_h_bfloat(S, D, T) \ - S (bf16) - -/* _f16. */ -#define TYPES_h_float(S, D, T) \ - S (f16) - -/* _s16 - _u16. */ -#define TYPES_h_integer(S, D, T) \ - S (s16), S (u16) - -/* _bf16 - _f16 - _s16 - _u16. */ -#define TYPES_h_data(S, D, T) \ - S (bf16), S (f16), TYPES_h_integer (S, D, T) - -/* _s16 _s32. */ -#define TYPES_hs_signed(S, D, T) \ - S (s16), S (s32) - -/* _s16 _s32 - _u16 _u32. */ -#define TYPES_hs_integer(S, D, T) \ - TYPES_hs_signed (S, D, T), S (u16), S (u32) - -/* _f16 _f32. */ -#define TYPES_hs_float(S, D, T) \ - S (f16), S (f32) - -#define TYPES_hs_data(S, D, T) \ - TYPES_h_data (S, D, T), \ - TYPES_s_data (S, D, T) - -/* _u16 _u64. */ -#define TYPES_hd_unsigned(S, D, T) \ - S (u16), S (u64) - -/* _s16 _s32 _s64. */ -#define TYPES_hsd_signed(S, D, T) \ - S (s16), S (s32), S (s64) - -/* _s16 _s32 _s64 - _u16 _u32 _u64. */ -#define TYPES_hsd_integer(S, D, T) \ - TYPES_hsd_signed (S, D, T), S (u16), S (u32), S (u64) - -#define TYPES_hsd_data(S, D, T) \ - TYPES_h_data (S, D, T), \ - TYPES_s_data (S, D, T), \ - TYPES_d_data (S, D, T) - -/* _f16_mf8. */ -#define TYPES_h_float_mf8(S, D, T) \ - D (f16, mf8) - -/* _f32. */ -#define TYPES_s_float(S, D, T) \ - S (f32) - -/* _f32_mf8. */ -#define TYPES_s_float_mf8(S, D, T) \ - D (f32, mf8) - -/* _f32 - _s16 _s32 _s64 - _u16 _u32 _u64. */ -#define TYPES_s_float_hsd_integer(S, D, T) \ - TYPES_s_float (S, D, T), TYPES_hsd_integer (S, D, T) - -/* _f32 - _s32 _s64 - _u32 _u64. */ -#define TYPES_s_float_sd_integer(S, D, T) \ - TYPES_s_float (S, D, T), TYPES_sd_integer (S, D, T) - -/* _s32. */ -#define TYPES_s_signed(S, D, T) \ - S (s32) - -/* _u32. */ -#define TYPES_s_unsigned(S, D, T) \ - S (u32) - -/* _s32 - _u32. */ -#define TYPES_s_integer(S, D, T) \ - TYPES_s_signed (S, D, T), TYPES_s_unsigned (S, D, T) - -/* _f32 - _s32 - _u32. */ -#define TYPES_s_data(S, D, T) \ - TYPES_s_float (S, D, T), TYPES_s_integer (S, D, T) - -/* _s32 _s64. */ -#define TYPES_sd_signed(S, D, T) \ - S (s32), S (s64) - -/* _u32 _u64. */ -#define TYPES_sd_unsigned(S, D, T) \ - S (u32), S (u64) - -/* _s32 _s64 - _u32 _u64. */ -#define TYPES_sd_integer(S, D, T) \ - TYPES_sd_signed (S, D, T), TYPES_sd_unsigned (S, D, T) - -#define TYPES_sd_data(S, D, T) \ - TYPES_s_data (S, D, T), \ - TYPES_d_data (S, D, T) - -/* _f16 _f32 _f64 - _s32 _s64 - _u32 _u64. */ -#define TYPES_all_float_and_sd_integer(S, D, T) \ - TYPES_all_float (S, D, T), TYPES_sd_integer (S, D, T) - -/* _f64. */ -#define TYPES_d_float(S, D, T) \ - S (f64) - -/* _u64. */ -#define TYPES_d_unsigned(S, D, T) \ - S (u64) - -/* _s64 - _u64. */ -#define TYPES_d_integer(S, D, T) \ - S (s64), TYPES_d_unsigned (S, D, T) - -/* _f64 - _s64 - _u64. */ -#define TYPES_d_data(S, D, T) \ - TYPES_d_float (S, D, T), TYPES_d_integer (S, D, T) - -/* All the type combinations allowed by svcvt. */ -#define TYPES_cvt(S, D, T) \ - D (f16, f32), D (f16, f64), \ - D (f16, s16), D (f16, s32), D (f16, s64), \ - D (f16, u16), D (f16, u32), D (f16, u64), \ - \ - D (f32, f16), D (f32, f64), \ - D (f32, s32), D (f32, s64), \ - D (f32, u32), D (f32, u64), \ - \ - D (f64, f16), D (f64, f32), \ - D (f64, s32), D (f64, s64), \ - D (f64, u32), D (f64, u64), \ - \ - D (s16, f16), \ - D (s32, f16), D (s32, f32), D (s32, f64), \ - D (s64, f16), D (s64, f32), D (s64, f64), \ - \ - D (u16, f16), \ - D (u32, f16), D (u32, f32), D (u32, f64), \ - D (u64, f16), D (u64, f32), D (u64, f64) - -/* _bf16_f32. */ -#define TYPES_cvt_bfloat(S, D, T) \ - D (bf16, f32) - -/* { _bf16 _f16 } x _f32. */ -#define TYPES_cvt_h_s_float(S, D, T) \ - D (bf16, f32), D (f16, f32) - -/* _f32_f16. */ -#define TYPES_cvt_f32_f16(S, D, T) \ - D (f32, f16) - -/* _f32_f16 - _f64_f32. */ -#define TYPES_cvt_long(S, D, T) \ - D (f32, f16), D (f64, f32) - -/* _f32_f64. */ -#define TYPES_cvt_narrow_s(S, D, T) \ - D (f32, f64) - -/* _f16_f32 - _f32_f64. */ -#define TYPES_cvt_narrow(S, D, T) \ - D (f16, f32), TYPES_cvt_narrow_s (S, D, T) - -/* { _s32 _u32 } x _f32 - - _f32 x { _s32 _u32 }. */ -#define TYPES_cvt_s_s(S, D, T) \ - D (s32, f32), \ - D (u32, f32), \ - D (f32, s32), \ - D (f32, u32) - -/* _f16_mf8 - _bf16_mf8. */ -#define TYPES_cvt_mf8(S, D, T) \ - D (f16, mf8), D (bf16, mf8) - -/* _mf8_f16 - _mf8_bf16. */ -#define TYPES_cvtn_mf8(S, D, T) \ - D (mf8, f16), D (mf8, bf16) - -/* _mf8_f32. */ -#define TYPES_cvtnx_mf8(S, D, T) \ - D (mf8, f32) - -/* { _s32 _s64 } x { _b8 _b16 _b32 _b64 } - { _u32 _u64 }. */ -#define TYPES_inc_dec_n1(D, A) \ - D (A, b8), D (A, b16), D (A, b32), D (A, b64) -#define TYPES_inc_dec_n(S, D, T) \ - TYPES_inc_dec_n1 (D, s32), \ - TYPES_inc_dec_n1 (D, s64), \ - TYPES_inc_dec_n1 (D, u32), \ - TYPES_inc_dec_n1 (D, u64) - -/* { _s16 _u16 } x _s32 - - { _u16 } x _u32. */ -#define TYPES_qcvt_x2(S, D, T) \ - D (s16, s32), \ - D (u16, u32), \ - D (u16, s32) - -/* { _s8 _u8 } x _s32 - - { _u8 } x _u32 - - { _s16 _u16 } x _s64 - - { _u16 } x _u64. */ -#define TYPES_qcvt_x4(S, D, T) \ - D (s8, s32), \ - D (u8, u32), \ - D (u8, s32), \ - D (s16, s64), \ - D (u16, u64), \ - D (u16, s64) - -/* _s16_s32 - _u16_u32. */ -#define TYPES_qrshr_x2(S, D, T) \ - D (s16, s32), \ - D (u16, u32) - -/* _u16_s32. */ -#define TYPES_qrshru_x2(S, D, T) \ - D (u16, s32) - -/* _s8_s32 - _s16_s64 - _u8_u32 - _u16_u64. */ -#define TYPES_qrshr_x4(S, D, T) \ - D (s8, s32), \ - D (s16, s64), \ - D (u8, u32), \ - D (u16, u64) - -/* _u8_s32 - _u16_s64. */ -#define TYPES_qrshru_x4(S, D, T) \ - D (u8, s32), \ - D (u16, s64) - -/* { _mf8 _bf16 } { _mf8 _bf16 } - { _f16 _f32 _f64 } { _f16 _f32 _f64 } - { _s8 _s16 _s32 _s64 } x { _s8 _s16 _s32 _s64 } - { _u8 _u16 _u32 _u64 } { _u8 _u16 _u32 _u64 }. */ -#define TYPES_reinterpret1(D, A) \ - D (A, mf8), \ - D (A, bf16), \ - D (A, f16), D (A, f32), D (A, f64), \ - D (A, s8), D (A, s16), D (A, s32), D (A, s64), \ - D (A, u8), D (A, u16), D (A, u32), D (A, u64) -#define TYPES_reinterpret(S, D, T) \ - TYPES_reinterpret1 (D, mf8), \ - TYPES_reinterpret1 (D, bf16), \ - TYPES_reinterpret1 (D, f16), \ - TYPES_reinterpret1 (D, f32), \ - TYPES_reinterpret1 (D, f64), \ - TYPES_reinterpret1 (D, s8), \ - TYPES_reinterpret1 (D, s16), \ - TYPES_reinterpret1 (D, s32), \ - TYPES_reinterpret1 (D, s64), \ - TYPES_reinterpret1 (D, u8), \ - TYPES_reinterpret1 (D, u16), \ - TYPES_reinterpret1 (D, u32), \ - TYPES_reinterpret1 (D, u64) - -/* _b_c - _c_b. */ -#define TYPES_reinterpret_b(S, D, T) \ - D (b, c), \ - D (c, b) - -/* { _b8 _b16 _b32 _b64 } x { _s32 _s64 } - { _u32 _u64 } */ -#define TYPES_while1(D, bn) \ - D (bn, s32), D (bn, s64), D (bn, u32), D (bn, u64) -#define TYPES_while(S, D, T) \ - TYPES_while1 (D, b8), \ - TYPES_while1 (D, b16), \ - TYPES_while1 (D, b32), \ - TYPES_while1 (D, b64) - -/* { _b8 _b16 _b32 _b64 } x { _s64 } - { _u64 } */ -#define TYPES_while_x(S, D, T) \ - D (b8, s64), D (b8, u64), \ - D (b16, s64), D (b16, u64), \ - D (b32, s64), D (b32, u64), \ - D (b64, s64), D (b64, u64) - -/* { _c8 _c16 _c32 _c64 } x { _s64 } - { _u64 } */ -#define TYPES_while_x_c(S, D, T) \ - D (c8, s64), D (c8, u64), \ - D (c16, s64), D (c16, u64), \ - D (c32, s64), D (c32, u64), \ - D (c64, s64), D (c64, u64) - -/* _f32_f16 - _s32_s16 - _u32_u16. */ -#define TYPES_s_narrow_fsu(S, D, T) \ - D (f32, f16), D (s32, s16), D (u32, u16) - -/* _za8 _za16 _za32 _za64 _za128. */ -#define TYPES_all_za(S, D, T) \ - S (za8), S (za16), S (za32), S (za64), S (za128) - -/* _za64. */ -#define TYPES_d_za(S, D, T) \ - S (za64) - -/* { _za8 } x { _mf8 _s8 _u8 } - - { _za16 } x { _bf16 _f16 _s16 _u16 } - - { _za32 } x { _f32 _s32 _u32 } - - { _za64 } x { _f64 _s64 _u64 }. */ -#define TYPES_za_bhsd_data(S, D, T) \ - D (za8, mf8), D (za8, s8), D (za8, u8), \ - D (za16, bf16), D (za16, f16), D (za16, s16), D (za16, u16), \ - D (za32, f32), D (za32, s32), D (za32, u32), \ - D (za64, f64), D (za64, s64), D (za64, u64) - -/* Likewise, plus: - - { _za128 } x { _bf16 } - { _f16 _f32 _f64 } - { _s8 _s16 _s32 _s64 } - { _u8 _u16 _u32 _u64 }. */ - -#define TYPES_za_all_data(S, D, T) \ - TYPES_za_bhsd_data (S, D, T), \ - TYPES_reinterpret1 (D, za128) - -/* _za16_mf8. */ -#define TYPES_za_h_mf8(S, D, T) \ - D (za16, mf8) - -/* { _za_16 _za_32 } x _mf8. */ -#define TYPES_za_hs_mf8(S, D, T) \ - D (za16, mf8), D (za32, mf8) - -/* _za16_bf16. */ -#define TYPES_za_h_bfloat(S, D, T) \ - D (za16, bf16) - -/* _za16_f16. */ -#define TYPES_za_h_float(S, D, T) \ - D (za16, f16) - -/* _za32_s8. */ -#define TYPES_za_s_b_signed(S, D, T) \ - D (za32, s8) - -/* _za32_u8. */ -#define TYPES_za_s_b_unsigned(S, D, T) \ - D (za32, u8) - -/* _za32 x { _s8 _u8 }. */ -#define TYPES_za_s_b_integer(S, D, T) \ - D (za32, s8), D (za32, u8) - -/* _za32 x { _s16 _u16 }. */ -#define TYPES_za_s_h_integer(S, D, T) \ - D (za32, s16), D (za32, u16) - -/* _za32 x { _bf16 _f16 _s16 _u16 }. */ -#define TYPES_za_s_h_data(S, D, T) \ - D (za32, bf16), D (za32, f16), D (za32, s16), D (za32, u16) - -/* _za32_u32. */ -#define TYPES_za_s_unsigned(S, D, T) \ - D (za32, u32) - -/* _za32 x { _s32 _u32 }. */ -#define TYPES_za_s_integer(S, D, T) \ - D (za32, s32), D (za32, u32) - -/* _za32_mf8. */ -#define TYPES_za_s_mf8(S, D, T) \ - D (za32, mf8) - -/* _za32_f32. */ -#define TYPES_za_s_float(S, D, T) \ - D (za32, f32) - -/* _za32 x { _f32 _s32 _u32 }. */ -#define TYPES_za_s_data(S, D, T) \ - D (za32, f32), D (za32, s32), D (za32, u32) - -/* _za64 x { _s16 _u16 }. */ -#define TYPES_za_d_h_integer(S, D, T) \ - D (za64, s16), D (za64, u16) - -/* _za64_f64. */ -#define TYPES_za_d_float(S, D, T) \ - D (za64, f64) - -/* _za64 x { _s64 _u64 }. */ -#define TYPES_za_d_integer(S, D, T) \ - D (za64, s64), D (za64, u64) - -/* _za32 x { _s8 _u8 _bf16 _f16 _f32 }. */ -#define TYPES_mop_base(S, D, T) \ - D (za32, s8), D (za32, u8), D (za32, bf16), D (za32, f16), D (za32, f32) - -/* _za32_s8. */ -#define TYPES_mop_base_signed(S, D, T) \ - D (za32, s8) - -/* _za32_u8. */ -#define TYPES_mop_base_unsigned(S, D, T) \ - D (za32, u8) - -/* _za64 x { _s16 _u16 }. */ -#define TYPES_mop_i16i64(S, D, T) \ - D (za64, s16), D (za64, u16) - -/* _za64_s16. */ -#define TYPES_mop_i16i64_signed(S, D, T) \ - D (za64, s16) - -/* _za64_u16. */ -#define TYPES_mop_i16i64_unsigned(S, D, T) \ - D (za64, u16) - -/* _za. */ -#define TYPES_za(S, D, T) \ - S (za) - -/* Describe a tuple of type suffixes in which only the first is used. */ -#define DEF_VECTOR_TYPE(X) \ - { TYPE_SUFFIX_ ## X, NUM_TYPE_SUFFIXES, NUM_TYPE_SUFFIXES } - -/* Describe a tuple of type suffixes in which only the first two are used. */ -#define DEF_DOUBLE_TYPE(X, Y) \ - { TYPE_SUFFIX_ ## X, TYPE_SUFFIX_ ## Y, NUM_TYPE_SUFFIXES } - -/* Describe a tuple of type suffixes in which three elements are used. */ -#define DEF_TRIPLE_TYPE(X, Y, Z) \ - { TYPE_SUFFIX_ ## X, TYPE_SUFFIX_ ## Y, TYPE_SUFFIX_ ## Z } - -/* Create an array that can be used in aarch64-sve-builtins.def to - select the type suffixes in TYPES_<NAME>. */ -#define DEF_SVE_TYPES_ARRAY(NAME) \ - static const type_suffix_triple types_##NAME[] = { \ - TYPES_##NAME (DEF_VECTOR_TYPE, DEF_DOUBLE_TYPE, DEF_TRIPLE_TYPE), \ - { NUM_TYPE_SUFFIXES, NUM_TYPE_SUFFIXES, NUM_TYPE_SUFFIXES } \ - } - -/* For functions that don't take any type suffixes. */ -static const type_suffix_triple types_none[] = { - { NUM_TYPE_SUFFIXES, NUM_TYPE_SUFFIXES, NUM_TYPE_SUFFIXES }, - { NUM_TYPE_SUFFIXES, NUM_TYPE_SUFFIXES, NUM_TYPE_SUFFIXES } -}; - -/* Create an array for each TYPES_<combination> macro above. */ -DEF_SVE_TYPES_ARRAY (all_pred); -DEF_SVE_TYPES_ARRAY (all_count); -DEF_SVE_TYPES_ARRAY (all_pred_count); -DEF_SVE_TYPES_ARRAY (all_float); -DEF_SVE_TYPES_ARRAY (all_signed); -DEF_SVE_TYPES_ARRAY (all_float_and_signed); -DEF_SVE_TYPES_ARRAY (all_unsigned); -DEF_SVE_TYPES_ARRAY (all_integer); -DEF_SVE_TYPES_ARRAY (all_arith); -DEF_SVE_TYPES_ARRAY (all_data); -DEF_SVE_TYPES_ARRAY (b); -DEF_SVE_TYPES_ARRAY (b_unsigned); -DEF_SVE_TYPES_ARRAY (b_integer); -DEF_SVE_TYPES_ARRAY (bh_integer); -DEF_SVE_TYPES_ARRAY (bs_unsigned); -DEF_SVE_TYPES_ARRAY (bhs_signed); -DEF_SVE_TYPES_ARRAY (bhs_unsigned); -DEF_SVE_TYPES_ARRAY (bhs_integer); -DEF_SVE_TYPES_ARRAY (bh_data); -DEF_SVE_TYPES_ARRAY (bhs_data); -DEF_SVE_TYPES_ARRAY (bhs_widen); -DEF_SVE_TYPES_ARRAY (c); -DEF_SVE_TYPES_ARRAY (h_bfloat); -DEF_SVE_TYPES_ARRAY (h_float); -DEF_SVE_TYPES_ARRAY (h_float_mf8); -DEF_SVE_TYPES_ARRAY (h_integer); -DEF_SVE_TYPES_ARRAY (h_data); -DEF_SVE_TYPES_ARRAY (hs_signed); -DEF_SVE_TYPES_ARRAY (hs_integer); -DEF_SVE_TYPES_ARRAY (hs_float); -DEF_SVE_TYPES_ARRAY (hs_data); -DEF_SVE_TYPES_ARRAY (hd_unsigned); -DEF_SVE_TYPES_ARRAY (hsd_signed); -DEF_SVE_TYPES_ARRAY (hsd_integer); -DEF_SVE_TYPES_ARRAY (hsd_data); -DEF_SVE_TYPES_ARRAY (s_float); -DEF_SVE_TYPES_ARRAY (s_float_hsd_integer); -DEF_SVE_TYPES_ARRAY (s_float_mf8); -DEF_SVE_TYPES_ARRAY (s_float_sd_integer); -DEF_SVE_TYPES_ARRAY (s_signed); -DEF_SVE_TYPES_ARRAY (s_unsigned); -DEF_SVE_TYPES_ARRAY (s_integer); -DEF_SVE_TYPES_ARRAY (s_data); -DEF_SVE_TYPES_ARRAY (sd_float); -DEF_SVE_TYPES_ARRAY (sd_signed); -DEF_SVE_TYPES_ARRAY (sd_unsigned); -DEF_SVE_TYPES_ARRAY (sd_integer); -DEF_SVE_TYPES_ARRAY (sd_data); -DEF_SVE_TYPES_ARRAY (all_float_and_sd_integer); -DEF_SVE_TYPES_ARRAY (d_float); -DEF_SVE_TYPES_ARRAY (d_unsigned); -DEF_SVE_TYPES_ARRAY (d_integer); -DEF_SVE_TYPES_ARRAY (d_data); -DEF_SVE_TYPES_ARRAY (cvt); -DEF_SVE_TYPES_ARRAY (cvt_bfloat); -DEF_SVE_TYPES_ARRAY (cvt_h_s_float); -DEF_SVE_TYPES_ARRAY (cvt_f32_f16); -DEF_SVE_TYPES_ARRAY (cvt_long); -DEF_SVE_TYPES_ARRAY (cvt_mf8); -DEF_SVE_TYPES_ARRAY (cvt_narrow_s); -DEF_SVE_TYPES_ARRAY (cvt_narrow); -DEF_SVE_TYPES_ARRAY (cvt_s_s); -DEF_SVE_TYPES_ARRAY (cvtn_mf8); -DEF_SVE_TYPES_ARRAY (cvtnx_mf8); -DEF_SVE_TYPES_ARRAY (inc_dec_n); -DEF_SVE_TYPES_ARRAY (qcvt_x2); -DEF_SVE_TYPES_ARRAY (qcvt_x4); -DEF_SVE_TYPES_ARRAY (qrshr_x2); -DEF_SVE_TYPES_ARRAY (qrshr_x4); -DEF_SVE_TYPES_ARRAY (qrshru_x2); -DEF_SVE_TYPES_ARRAY (qrshru_x4); -DEF_SVE_TYPES_ARRAY (reinterpret); -DEF_SVE_TYPES_ARRAY (reinterpret_b); -DEF_SVE_TYPES_ARRAY (while); -DEF_SVE_TYPES_ARRAY (while_x); -DEF_SVE_TYPES_ARRAY (while_x_c); -DEF_SVE_TYPES_ARRAY (s_narrow_fsu); -DEF_SVE_TYPES_ARRAY (all_za); -DEF_SVE_TYPES_ARRAY (d_za); -DEF_SVE_TYPES_ARRAY (za_bhsd_data); -DEF_SVE_TYPES_ARRAY (za_all_data); -DEF_SVE_TYPES_ARRAY (za_h_mf8); -DEF_SVE_TYPES_ARRAY (za_h_bfloat); -DEF_SVE_TYPES_ARRAY (za_h_float); -DEF_SVE_TYPES_ARRAY (za_s_b_signed); -DEF_SVE_TYPES_ARRAY (za_s_b_unsigned); -DEF_SVE_TYPES_ARRAY (za_s_b_integer); -DEF_SVE_TYPES_ARRAY (za_s_h_integer); -DEF_SVE_TYPES_ARRAY (za_s_h_data); -DEF_SVE_TYPES_ARRAY (za_s_unsigned); -DEF_SVE_TYPES_ARRAY (za_s_integer); -DEF_SVE_TYPES_ARRAY (za_s_mf8); -DEF_SVE_TYPES_ARRAY (za_hs_mf8); -DEF_SVE_TYPES_ARRAY (za_s_float); -DEF_SVE_TYPES_ARRAY (za_s_data); -DEF_SVE_TYPES_ARRAY (za_d_h_integer); -DEF_SVE_TYPES_ARRAY (za_d_float); -DEF_SVE_TYPES_ARRAY (za_d_integer); -DEF_SVE_TYPES_ARRAY (mop_base); -DEF_SVE_TYPES_ARRAY (mop_base_signed); -DEF_SVE_TYPES_ARRAY (mop_base_unsigned); -DEF_SVE_TYPES_ARRAY (mop_i16i64); -DEF_SVE_TYPES_ARRAY (mop_i16i64_signed); -DEF_SVE_TYPES_ARRAY (mop_i16i64_unsigned); -DEF_SVE_TYPES_ARRAY (za); - -static const group_suffix_index groups_none[] = { - GROUP_none, NUM_GROUP_SUFFIXES -}; - -static const group_suffix_index groups_x2[] = { GROUP_x2, NUM_GROUP_SUFFIXES }; - -static const group_suffix_index groups_x12[] = { - GROUP_none, GROUP_x2, NUM_GROUP_SUFFIXES -}; - -static const group_suffix_index groups_x4[] = { GROUP_x4, NUM_GROUP_SUFFIXES }; - -static const group_suffix_index groups_x24[] = { - GROUP_x2, GROUP_x4, NUM_GROUP_SUFFIXES -}; - -static const group_suffix_index groups_x124[] = { - GROUP_none, GROUP_x2, GROUP_x4, NUM_GROUP_SUFFIXES -}; - -static const group_suffix_index groups_x1234[] = { - GROUP_none, GROUP_x2, GROUP_x3, GROUP_x4, NUM_GROUP_SUFFIXES -}; - -static const group_suffix_index groups_vg1x2[] = { - GROUP_vg1x2, NUM_GROUP_SUFFIXES -}; - -static const group_suffix_index groups_vg1x4[] = { - GROUP_vg1x4, NUM_GROUP_SUFFIXES -}; - -static const group_suffix_index groups_vg1x24[] = { - GROUP_vg1x2, GROUP_vg1x4, NUM_GROUP_SUFFIXES -}; - -static const group_suffix_index groups_vg2[] = { - GROUP_vg2x1, GROUP_vg2x2, GROUP_vg2x4, NUM_GROUP_SUFFIXES -}; - -static const group_suffix_index groups_vg4[] = { - GROUP_vg4x1, GROUP_vg4x2, GROUP_vg4x4, NUM_GROUP_SUFFIXES -}; - -static const group_suffix_index groups_vg24[] = { - GROUP_vg2, GROUP_vg4, NUM_GROUP_SUFFIXES -}; - -/* Used by functions that have no governing predicate. */ -static const predication_index preds_none[] = { PRED_none, NUM_PREDS }; - -/* Used by functions that have a governing predicate but do not have an - explicit suffix. */ -static const predication_index preds_implicit[] = { PRED_implicit, NUM_PREDS }; - -/* Used by functions that only support "_m" predication. */ -static const predication_index preds_m[] = { PRED_m, NUM_PREDS }; - -/* Used by functions that allow merging and "don't care" predication, - but are not suitable for predicated MOVPRFX. */ -static const predication_index preds_mx[] = { - PRED_m, PRED_x, NUM_PREDS -}; - -/* Used by functions that allow merging, zeroing and "don't care" - predication. */ -static const predication_index preds_mxz[] = { - PRED_m, PRED_x, PRED_z, NUM_PREDS +constexpr const aarch64_acle::function_group_info neon_function_groups[] = { +#define DEF_NEON_FUNCTION(NAME, TYPES, SHAPE_ARGS) \ + { \ + /* .base_name = */ #NAME, \ + /* .base = */ &aarch64_acle::functions::NAME, \ + /* .shape = */ &aarch64_acle::shapes::SHAPE_NAME (NAME, TYPES),\ + /* .types = */ aarch64_acle::types_##TYPES, \ + /* .groups = */ aarch64_acle::groups_none, \ + /* .preds = */ aarch64_acle::preds_none, \ + /* .extensions = */ aarch64_required_extensions::REQUIRED_EXTENSIONS,\ + /* .fpm_mode = */ aarch64_acle::FPM_unused, \ + }, +#include "aarch64-neon-builtins.def" }; -/* Used by functions that have the mxz predicated forms above, and in addition - have an unpredicated form. */ -static const predication_index preds_mxz_or_none[] = { - PRED_m, PRED_x, PRED_z, PRED_none, NUM_PREDS -}; - -/* Used by functions that allow merging and zeroing predication but have - no "_x" form. */ -static const predication_index preds_mz[] = { PRED_m, PRED_z, NUM_PREDS }; - -/* Used by functions that have an unpredicated form and a _z predicated - form. */ -static const predication_index preds_z_or_none[] = { - PRED_z, PRED_none, NUM_PREDS -}; - -/* Used by (mostly predicate) functions that only support "_z" predication. */ -static const predication_index preds_z[] = { PRED_z, NUM_PREDS }; - -/* Used by SME instructions that always merge into ZA. */ -static const predication_index preds_za_m[] = { PRED_za_m, NUM_PREDS }; - -#define NONSTREAMING_SVE(X) nonstreaming_only (AARCH64_FL_SVE | (X)) -#define SVE_AND_SME(X, Y) streaming_compatible (AARCH64_FL_SVE | (X), (Y)) -#define SSVE(X) SVE_AND_SME (X, X) - /* A list of all arm_sve.h functions. */ static CONSTEXPR const function_group_info function_groups[] = { #define DEF_SVE_FUNCTION_GS_FPM(NAME, SHAPE, TYPES, GROUPS, PREDS, FPM_MODE) \ @@ -1351,6 +555,9 @@ function_builder::function_builder (handle_pragma_index pragma_index, m_function_nulls = function_nulls; gcc_obstack_init (&m_string_obstack); + + if (!function_table) + function_table = hash_table<registered_function_hasher>::create_ggc (1023); } function_builder::~function_builder () @@ -3864,9 +3071,9 @@ gimple_folder::fold_to_stmt_vops (gimple *g) gimple * gimple_folder::fold () { - /* Don't fold anything when SVE is disabled; emit an error during + /* Don't fold anything when NEON/SVE are disabled; emit an error during expansion instead. */ - if (!TARGET_SVE) + if (!TARGET_SIMD && !TARGET_SVE) return NULL; /* Punt if the function has a return type and no result location is @@ -4777,6 +3984,7 @@ init_builtins () register_builtin_types (); if (in_lto_p) { + aarch64_acle::handle_arm_neon_h (false); handle_arm_sve_h (false); handle_arm_sme_h (false); handle_arm_neon_sve_bridge_h (false); @@ -4879,13 +4087,50 @@ register_svprfop () "svprfop", &values); } +static bool arm_neon_h_handled = false; + +static bool arm_sve_h_handled = false; +static location_t arm_sve_h_location; + +static bool arm_sme_h_handled = false; +static location_t arm_sme_h_location; + +static bool arm_neon_sve_bridge_h_handled = false; +static location_t arm_neon_sve_bridge_h_location; + +/* Implement #pragma GCC aarch64 "arm_neon.h". */ +void +handle_arm_neon_h (bool function_nulls_p) +{ + if (arm_neon_h_handled) + return; + + /* FIXME: Remove once all NEON intrinsics have been ported to the pragma-based + framework. */ + init_arm_neon_builtins (); + + aarch64_target_switcher switcher; + aarch64_acle::function_builder builder (aarch64_acle::arm_neon_handle, + function_nulls_p); + + for (auto &group : neon_function_groups) + builder.register_function_group (group); + + arm_neon_h_handled = true; +} + /* Implement #pragma GCC aarch64 "arm_sve.h". */ void handle_arm_sve_h (bool function_nulls_p) { - if (function_table) + if (!aarch64_acle::arm_neon_h_handled) + aarch64_acle::handle_arm_neon_h (false); + + if (arm_sve_h_handled) { error ("duplicate definition of %qs", "arm_sve.h"); + inform (arm_sve_h_location, "previous definition of %qs here", + "arm_sve.h"); return; } @@ -4908,25 +4153,38 @@ handle_arm_sve_h (bool function_nulls_p) register_svprfop (); /* Define the functions. */ - function_table = hash_table<registered_function_hasher>::create_ggc (1023); function_builder builder (arm_sve_handle, function_nulls_p); for (unsigned int i = 0; i < ARRAY_SIZE (function_groups); ++i) builder.register_function_group (function_groups[i]); + + arm_sve_h_handled = true; + arm_sve_h_location = input_location; } /* Implement #pragma GCC aarch64 "arm_neon_sve_bridge.h". */ void handle_arm_neon_sve_bridge_h (bool function_nulls_p) { - if (initial_indexes[arm_sme_handle] == 0) + if (!arm_sme_h_handled) handle_arm_sme_h (true); + if (arm_neon_sve_bridge_h_handled) + { + error ("duplicate definition of %qs", "arm_neon_sve_bridge.h"); + inform (arm_neon_sve_bridge_h_location, "previous definition of %qs here", + "arm_neon_sve_bridge.h"); + return; + } + aarch64_target_switcher switcher; /* Define the functions. */ function_builder builder (arm_neon_sve_handle, function_nulls_p); for (unsigned int i = 0; i < ARRAY_SIZE (neon_sve_function_groups); ++i) builder.register_function_group (neon_sve_function_groups[i]); + + arm_neon_sve_bridge_h_handled = true; + arm_neon_sve_bridge_h_location = input_location; } /* Return the function decl with SVE function subcode CODE, or error_mark_node @@ -4943,7 +4201,7 @@ builtin_decl (unsigned int code, bool) void handle_arm_sme_h (bool function_nulls_p) { - if (!function_table) + if (!arm_sve_h_handled) { error ("%qs defined without first defining %qs", "arm_sme.h", "arm_sve.h"); @@ -4955,6 +4213,9 @@ handle_arm_sme_h (bool function_nulls_p) function_builder builder (arm_sme_handle, function_nulls_p); for (unsigned int i = 0; i < ARRAY_SIZE (sme_function_groups); ++i) builder.register_function_group (sme_function_groups[i]); + + arm_sme_h_handled = true; + arm_sme_h_location = input_location; } /* If we're implementing manual overloading, check whether the SVE diff --git a/gcc/config/aarch64/aarch64-acle-builtins.h b/gcc/config/aarch64/aarch64-acle-builtins.h index 20152aaea6a2..5e90ba21bf39 100644 --- a/gcc/config/aarch64/aarch64-acle-builtins.h +++ b/gcc/config/aarch64/aarch64-acle-builtins.h @@ -129,6 +129,7 @@ enum units_index /* Enumerates the pragma handlers. */ enum handle_pragma_index { + arm_neon_handle, arm_sve_handle, arm_sme_handle, arm_neon_sve_handle, @@ -187,6 +188,7 @@ enum type_class_index TYPE_mfloat, TYPE_signed, TYPE_unsigned, + TYPE_poly, NUM_TYPE_CLASSES }; @@ -1172,6 +1174,835 @@ function_expander::result_mode () const return TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))); } +/* Define a TYPES_<combination> macro for each combination of type + suffixes that an ACLE function can have, where <combination> is the + name used in DEF_SVE_FUNCTION entries. + + Use S (T) for single type suffix T and D (T1, T2) for a pair of type + suffixes T1 and T2. Use commas to separate the suffixes. + + Although the order shouldn't matter, the convention is to sort the + suffixes lexicographically after dividing suffixes into a type + class ("b", "f", etc.) and a numerical bit count. */ + +/* _b8 _b16 _b32 _b64. */ +#define TYPES_all_pred(S, D, T) \ + S (b8), S (b16), S (b32), S (b64) + +/* _c8 _c16 _c32 _c64. */ +#define TYPES_all_count(S, D, T) \ + S (c8), S (c16), S (c32), S (c64) + +/* _b8 _b16 _b32 _b64 + _c8 _c16 _c32 _c64. */ +#define TYPES_all_pred_count(S, D, T) \ + TYPES_all_pred (S, D, T), \ + TYPES_all_count (S, D, T) + +/* _f16 _f32 _f64. */ +#define TYPES_all_float(S, D, T) \ + S (f16), S (f32), S (f64) + +/* _f32 _f64. */ +#define TYPES_sd_float(S, D, T) \ + S (f32), S (f64) + +/* _s8 _s16 _s32 _s64. */ +#define TYPES_all_signed(S, D, T) \ + S (s8), S (s16), S (s32), S (s64) + +/* _f16 _f32 _f64 + _s8 _s16 _s32 _s64. */ +#define TYPES_all_float_and_signed(S, D, T) \ + TYPES_all_float (S, D, T), TYPES_all_signed (S, D, T) + +/* _u8 _u16 _u32 _u64. */ +#define TYPES_all_unsigned(S, D, T) \ + S (u8), S (u16), S (u32), S (u64) + +/* _s8 _s16 _s32 _s64 + _u8 _u16 _u32 _u64. */ +#define TYPES_all_integer(S, D, T) \ + TYPES_all_signed (S, D, T), TYPES_all_unsigned (S, D, T) + +/* _f16 _f32 _f64 + _s8 _s16 _s32 _s64 + _u8 _u16 _u32 _u64. */ +#define TYPES_all_arith(S, D, T) \ + TYPES_all_float (S, D, T), TYPES_all_integer (S, D, T) + +/* _f32 _f64 + _s8 _s16 _s32 _s64 + _u8 _u16 _u32 _u64. */ +#define TYPES_all_arith_no_fp16(S, D, T) \ + S (f32), S (f64), \ + TYPES_all_integer (S, D, T) + +#define TYPES_all_data(S, D, T) \ + TYPES_b_data (S, D, T), \ + TYPES_h_data (S, D, T), \ + TYPES_s_data (S, D, T), \ + TYPES_d_data (S, D, T) + +/* _b only. */ +#define TYPES_b(S, D, T) \ + S (b) + +/* _c only. */ +#define TYPES_c(S, D, T) \ + S (c) + +/* _u8. */ +#define TYPES_b_unsigned(S, D, T) \ + S (u8) + +/* _s8 + _u8. */ +#define TYPES_b_integer(S, D, T) \ + S (s8), TYPES_b_unsigned (S, D, T) + +/* _mf8 + _s8 + _u8. */ +#define TYPES_b_data(S, D, T) \ + S (mf8), TYPES_b_integer (S, D, T) + +/* _s8 _s16 + _u8 _u16. */ +#define TYPES_bh_integer(S, D, T) \ + S (s8), S (s16), S (u8), S (u16) + +/* _u8 _u32. */ +#define TYPES_bs_unsigned(S, D, T) \ + S (u8), S (u32) + +/* _s8 _s16 _s32. */ +#define TYPES_bhs_signed(S, D, T) \ + S (s8), S (s16), S (s32) + +/* _u8 _u16 _u32. */ +#define TYPES_bhs_unsigned(S, D, T) \ + S (u8), S (u16), S (u32) + +/* _s8 _s16 _s32 + _u8 _u16 _u32. */ +#define TYPES_bhs_integer(S, D, T) \ + TYPES_bhs_signed (S, D, T), TYPES_bhs_unsigned (S, D, T) + +#define TYPES_bh_data(S, D, T) \ + TYPES_b_data (S, D, T), \ + TYPES_h_data (S, D, T) + +#define TYPES_bhs_data(S, D, T) \ + TYPES_b_data (S, D, T), \ + TYPES_h_data (S, D, T), \ + TYPES_s_data (S, D, T) + +/* _s16_s8 _s32_s16 _s64_s32 + _u16_u8 _u32_u16 _u64_u32. */ +#define TYPES_bhs_widen(S, D, T) \ + D (s16, s8), D (s32, s16), D (s64, s32), \ + D (u16, u8), D (u32, u16), D (u64, u32) + +/* _bf16. */ +#define TYPES_h_bfloat(S, D, T) \ + S (bf16) + +/* _f16. */ +#define TYPES_h_float(S, D, T) \ + S (f16) + +/* _s16 + _u16. */ +#define TYPES_h_integer(S, D, T) \ + S (s16), S (u16) + +/* _bf16 + _f16 + _s16 + _u16. */ +#define TYPES_h_data(S, D, T) \ + S (bf16), S (f16), TYPES_h_integer (S, D, T) + +/* _s16 _s32. */ +#define TYPES_hs_signed(S, D, T) \ + S (s16), S (s32) + +/* _s16 _s32 + _u16 _u32. */ +#define TYPES_hs_integer(S, D, T) \ + TYPES_hs_signed (S, D, T), S (u16), S (u32) + +/* _f16 _f32. */ +#define TYPES_hs_float(S, D, T) \ + S (f16), S (f32) + +#define TYPES_hs_data(S, D, T) \ + TYPES_h_data (S, D, T), \ + TYPES_s_data (S, D, T) + +/* _u16 _u64. */ +#define TYPES_hd_unsigned(S, D, T) \ + S (u16), S (u64) + +/* _s16 _s32 _s64. */ +#define TYPES_hsd_signed(S, D, T) \ + S (s16), S (s32), S (s64) + +/* _s16 _s32 _s64 + _u16 _u32 _u64. */ +#define TYPES_hsd_integer(S, D, T) \ + TYPES_hsd_signed (S, D, T), S (u16), S (u32), S (u64) + +#define TYPES_hsd_data(S, D, T) \ + TYPES_h_data (S, D, T), \ + TYPES_s_data (S, D, T), \ + TYPES_d_data (S, D, T) + +/* _f16_mf8. */ +#define TYPES_h_float_mf8(S, D, T) \ + D (f16, mf8) + +/* _f32. */ +#define TYPES_s_float(S, D, T) \ + S (f32) + +/* _f32_mf8. */ +#define TYPES_s_float_mf8(S, D, T) \ + D (f32, mf8) + +/* _f32 + _s16 _s32 _s64 + _u16 _u32 _u64. */ +#define TYPES_s_float_hsd_integer(S, D, T) \ + TYPES_s_float (S, D, T), TYPES_hsd_integer (S, D, T) + +/* _f32 + _s32 _s64 + _u32 _u64. */ +#define TYPES_s_float_sd_integer(S, D, T) \ + TYPES_s_float (S, D, T), TYPES_sd_integer (S, D, T) + +/* _s32. */ +#define TYPES_s_signed(S, D, T) \ + S (s32) + +/* _u32. */ +#define TYPES_s_unsigned(S, D, T) \ + S (u32) + +/* _s32 + _u32. */ +#define TYPES_s_integer(S, D, T) \ + TYPES_s_signed (S, D, T), TYPES_s_unsigned (S, D, T) + +/* _f32 + _s32 + _u32. */ +#define TYPES_s_data(S, D, T) \ + TYPES_s_float (S, D, T), TYPES_s_integer (S, D, T) + +/* _s32 _s64. */ +#define TYPES_sd_signed(S, D, T) \ + S (s32), S (s64) + +/* _u32 _u64. */ +#define TYPES_sd_unsigned(S, D, T) \ + S (u32), S (u64) + +/* _s32 _s64 + _u32 _u64. */ +#define TYPES_sd_integer(S, D, T) \ + TYPES_sd_signed (S, D, T), TYPES_sd_unsigned (S, D, T) + +#define TYPES_sd_data(S, D, T) \ + TYPES_s_data (S, D, T), \ + TYPES_d_data (S, D, T) + +/* _f16 _f32 _f64 + _s32 _s64 + _u32 _u64. */ +#define TYPES_all_float_and_sd_integer(S, D, T) \ + TYPES_all_float (S, D, T), TYPES_sd_integer (S, D, T) + +/* _f64. */ +#define TYPES_d_float(S, D, T) \ + S (f64) + +/* _u64. */ +#define TYPES_d_unsigned(S, D, T) \ + S (u64) + +/* _s64 + _u64. */ +#define TYPES_d_integer(S, D, T) \ + S (s64), TYPES_d_unsigned (S, D, T) + +/* _f64 + _s64 + _u64. */ +#define TYPES_d_data(S, D, T) \ + TYPES_d_float (S, D, T), TYPES_d_integer (S, D, T) + +/* All the type combinations allowed by svcvt. */ +#define TYPES_cvt(S, D, T) \ + D (f16, f32), D (f16, f64), \ + D (f16, s16), D (f16, s32), D (f16, s64), \ + D (f16, u16), D (f16, u32), D (f16, u64), \ + \ + D (f32, f16), D (f32, f64), \ + D (f32, s32), D (f32, s64), \ + D (f32, u32), D (f32, u64), \ + \ + D (f64, f16), D (f64, f32), \ + D (f64, s32), D (f64, s64), \ + D (f64, u32), D (f64, u64), \ + \ + D (s16, f16), \ + D (s32, f16), D (s32, f32), D (s32, f64), \ + D (s64, f16), D (s64, f32), D (s64, f64), \ + \ + D (u16, f16), \ + D (u32, f16), D (u32, f32), D (u32, f64), \ + D (u64, f16), D (u64, f32), D (u64, f64) + +/* _bf16_f32. */ +#define TYPES_cvt_bfloat(S, D, T) \ + D (bf16, f32) + +/* { _bf16 _f16 } x _f32. */ +#define TYPES_cvt_h_s_float(S, D, T) \ + D (bf16, f32), D (f16, f32) + +/* _f32_f16. */ +#define TYPES_cvt_f32_f16(S, D, T) \ + D (f32, f16) + +/* _f32_f16 + _f64_f32. */ +#define TYPES_cvt_long(S, D, T) \ + D (f32, f16), D (f64, f32) + +/* _f32_f64. */ +#define TYPES_cvt_narrow_s(S, D, T) \ + D (f32, f64) + +/* _f16_f32 + _f32_f64. */ +#define TYPES_cvt_narrow(S, D, T) \ + D (f16, f32), TYPES_cvt_narrow_s (S, D, T) + +/* { _s32 _u32 } x _f32 + + _f32 x { _s32 _u32 }. */ +#define TYPES_cvt_s_s(S, D, T) \ + D (s32, f32), \ + D (u32, f32), \ + D (f32, s32), \ + D (f32, u32) + +/* _f16_mf8 + _bf16_mf8. */ +#define TYPES_cvt_mf8(S, D, T) \ + D (f16, mf8), D (bf16, mf8) + +/* _mf8_f16 + _mf8_bf16. */ +#define TYPES_cvtn_mf8(S, D, T) \ + D (mf8, f16), D (mf8, bf16) + +/* _mf8_f32. */ +#define TYPES_cvtnx_mf8(S, D, T) \ + D (mf8, f32) + +/* { _s32 _s64 } x { _b8 _b16 _b32 _b64 } + { _u32 _u64 }. */ +#define TYPES_inc_dec_n1(D, A) \ + D (A, b8), D (A, b16), D (A, b32), D (A, b64) +#define TYPES_inc_dec_n(S, D, T) \ + TYPES_inc_dec_n1 (D, s32), \ + TYPES_inc_dec_n1 (D, s64), \ + TYPES_inc_dec_n1 (D, u32), \ + TYPES_inc_dec_n1 (D, u64) + +/* { _s16 _u16 } x _s32 + + { _u16 } x _u32. */ +#define TYPES_qcvt_x2(S, D, T) \ + D (s16, s32), \ + D (u16, u32), \ + D (u16, s32) + +/* { _s8 _u8 } x _s32 + + { _u8 } x _u32 + + { _s16 _u16 } x _s64 + + { _u16 } x _u64. */ +#define TYPES_qcvt_x4(S, D, T) \ + D (s8, s32), \ + D (u8, u32), \ + D (u8, s32), \ + D (s16, s64), \ + D (u16, u64), \ + D (u16, s64) + +/* _s16_s32 + _u16_u32. */ +#define TYPES_qrshr_x2(S, D, T) \ + D (s16, s32), \ + D (u16, u32) + +/* _u16_s32. */ +#define TYPES_qrshru_x2(S, D, T) \ + D (u16, s32) + +/* _s8_s32 + _s16_s64 + _u8_u32 + _u16_u64. */ +#define TYPES_qrshr_x4(S, D, T) \ + D (s8, s32), \ + D (s16, s64), \ + D (u8, u32), \ + D (u16, u64) + +/* _u8_s32 + _u16_s64. */ +#define TYPES_qrshru_x4(S, D, T) \ + D (u8, s32), \ + D (u16, s64) + +/* { _mf8 _bf16 } { _mf8 _bf16 } + { _f16 _f32 _f64 } { _f16 _f32 _f64 } + { _s8 _s16 _s32 _s64 } x { _s8 _s16 _s32 _s64 } + { _u8 _u16 _u32 _u64 } { _u8 _u16 _u32 _u64 }. */ +#define TYPES_reinterpret1(D, A) \ + D (A, mf8), \ + D (A, bf16), \ + D (A, f16), D (A, f32), D (A, f64), \ + D (A, s8), D (A, s16), D (A, s32), D (A, s64), \ + D (A, u8), D (A, u16), D (A, u32), D (A, u64) +#define TYPES_reinterpret(S, D, T) \ + TYPES_reinterpret1 (D, mf8), \ + TYPES_reinterpret1 (D, bf16), \ + TYPES_reinterpret1 (D, f16), \ + TYPES_reinterpret1 (D, f32), \ + TYPES_reinterpret1 (D, f64), \ + TYPES_reinterpret1 (D, s8), \ + TYPES_reinterpret1 (D, s16), \ + TYPES_reinterpret1 (D, s32), \ + TYPES_reinterpret1 (D, s64), \ + TYPES_reinterpret1 (D, u8), \ + TYPES_reinterpret1 (D, u16), \ + TYPES_reinterpret1 (D, u32), \ + TYPES_reinterpret1 (D, u64) + +/* _b_c + _c_b. */ +#define TYPES_reinterpret_b(S, D, T) \ + D (b, c), \ + D (c, b) + +/* { _b8 _b16 _b32 _b64 } x { _s32 _s64 } + { _u32 _u64 } */ +#define TYPES_while1(D, bn) \ + D (bn, s32), D (bn, s64), D (bn, u32), D (bn, u64) +#define TYPES_while(S, D, T) \ + TYPES_while1 (D, b8), \ + TYPES_while1 (D, b16), \ + TYPES_while1 (D, b32), \ + TYPES_while1 (D, b64) + +/* { _b8 _b16 _b32 _b64 } x { _s64 } + { _u64 } */ +#define TYPES_while_x(S, D, T) \ + D (b8, s64), D (b8, u64), \ + D (b16, s64), D (b16, u64), \ + D (b32, s64), D (b32, u64), \ + D (b64, s64), D (b64, u64) + +/* { _c8 _c16 _c32 _c64 } x { _s64 } + { _u64 } */ +#define TYPES_while_x_c(S, D, T) \ + D (c8, s64), D (c8, u64), \ + D (c16, s64), D (c16, u64), \ + D (c32, s64), D (c32, u64), \ + D (c64, s64), D (c64, u64) + +/* _f32_f16 + _s32_s16 + _u32_u16. */ +#define TYPES_s_narrow_fsu(S, D, T) \ + D (f32, f16), D (s32, s16), D (u32, u16) + +/* _za8 _za16 _za32 _za64 _za128. */ +#define TYPES_all_za(S, D, T) \ + S (za8), S (za16), S (za32), S (za64), S (za128) + +/* _za64. */ +#define TYPES_d_za(S, D, T) \ + S (za64) + +/* { _za8 } x { _mf8 _s8 _u8 } + { _za16 } x { _bf16 _f16 _s16 _u16 } + { _za32 } x { _f32 _s32 _u32 } + { _za64 } x { _f64 _s64 _u64 }. */ +#define TYPES_za_bhsd_data(S, D, T) \ + D (za8, mf8), D (za8, s8), D (za8, u8), \ + D (za16, bf16), D (za16, f16), D (za16, s16), D (za16, u16), \ + D (za32, f32), D (za32, s32), D (za32, u32), \ + D (za64, f64), D (za64, s64), D (za64, u64) + +/* Likewise, plus: + + { _za128 } x { _bf16 } + { _f16 _f32 _f64 } + { _s8 _s16 _s32 _s64 } + { _u8 _u16 _u32 _u64 }. */ + +#define TYPES_za_all_data(S, D, T) \ + TYPES_za_bhsd_data (S, D, T), \ + TYPES_reinterpret1 (D, za128) + +/* _za16_mf8. */ +#define TYPES_za_h_mf8(S, D, T) \ + D (za16, mf8) + +/* { _za_16 _za_32 } x _mf8. */ +#define TYPES_za_hs_mf8(S, D, T) \ + D (za16, mf8), D (za32, mf8) + +/* _za16_bf16. */ +#define TYPES_za_h_bfloat(S, D, T) \ + D (za16, bf16) + +/* _za16_f16. */ +#define TYPES_za_h_float(S, D, T) \ + D (za16, f16) + +/* _za32_s8. */ +#define TYPES_za_s_b_signed(S, D, T) \ + D (za32, s8) + +/* _za32_u8. */ +#define TYPES_za_s_b_unsigned(S, D, T) \ + D (za32, u8) + +/* _za32 x { _s8 _u8 }. */ +#define TYPES_za_s_b_integer(S, D, T) \ + D (za32, s8), D (za32, u8) + +/* _za32 x { _s16 _u16 }. */ +#define TYPES_za_s_h_integer(S, D, T) \ + D (za32, s16), D (za32, u16) + +/* _za32 x { _bf16 _f16 _s16 _u16 }. */ +#define TYPES_za_s_h_data(S, D, T) \ + D (za32, bf16), D (za32, f16), D (za32, s16), D (za32, u16) + +/* _za32_u32. */ +#define TYPES_za_s_unsigned(S, D, T) \ + D (za32, u32) + +/* _za32 x { _s32 _u32 }. */ +#define TYPES_za_s_integer(S, D, T) \ + D (za32, s32), D (za32, u32) + +/* _za32_mf8. */ +#define TYPES_za_s_mf8(S, D, T) \ + D (za32, mf8) + +/* _za32_f32. */ +#define TYPES_za_s_float(S, D, T) \ + D (za32, f32) + +/* _za32 x { _f32 _s32 _u32 }. */ +#define TYPES_za_s_data(S, D, T) \ + D (za32, f32), D (za32, s32), D (za32, u32) + +/* _za64 x { _s16 _u16 }. */ +#define TYPES_za_d_h_integer(S, D, T) \ + D (za64, s16), D (za64, u16) + +/* _za64_f64. */ +#define TYPES_za_d_float(S, D, T) \ + D (za64, f64) + +/* _za64 x { _s64 _u64 }. */ +#define TYPES_za_d_integer(S, D, T) \ + D (za64, s64), D (za64, u64) + +/* _za32 x { _s8 _u8 _bf16 _f16 _f32 }. */ +#define TYPES_mop_base(S, D, T) \ + D (za32, s8), D (za32, u8), D (za32, bf16), D (za32, f16), D (za32, f32) + +/* _za32_s8. */ +#define TYPES_mop_base_signed(S, D, T) \ + D (za32, s8) + +/* _za32_u8. */ +#define TYPES_mop_base_unsigned(S, D, T) \ + D (za32, u8) + +/* _za64 x { _s16 _u16 }. */ +#define TYPES_mop_i16i64(S, D, T) \ + D (za64, s16), D (za64, u16) + +/* _za64_s16. */ +#define TYPES_mop_i16i64_signed(S, D, T) \ + D (za64, s16) + +/* _za64_u16. */ +#define TYPES_mop_i16i64_unsigned(S, D, T) \ + D (za64, u16) + +/* _za. */ +#define TYPES_za(S, D, T) \ + S (za) + +/* _p8 _p16 _p64. */ +#define TYPES_bhd_poly(S, D, T) \ + S (p8), S (p16), S (p64) + +/* _p8 _p16 _p64 _p128. */ +#define TYPES_bhdq_poly(S, D, T) \ + S (p8), S (p16), S (p64), S (p128) + +/* Describe a tuple of type suffixes in which only the first is used. */ +#define DEF_VECTOR_TYPE(X) \ + { TYPE_SUFFIX_ ## X, NUM_TYPE_SUFFIXES, NUM_TYPE_SUFFIXES } + +/* Describe a tuple of type suffixes in which only the first two are used. */ +#define DEF_DOUBLE_TYPE(X, Y) \ + { TYPE_SUFFIX_ ## X, TYPE_SUFFIX_ ## Y, NUM_TYPE_SUFFIXES } + +/* Describe a tuple of type suffixes in which three elements are used. */ +#define DEF_TRIPLE_TYPE(X, Y, Z) \ + { TYPE_SUFFIX_ ## X, TYPE_SUFFIX_ ## Y, TYPE_SUFFIX_ ## Z } + +/* Create an array that can be used in aarch64-sve-builtins.def to + select the type suffixes in TYPES_<NAME>. */ +#define DEF_SVE_TYPES_ARRAY(NAME) \ + static const type_suffix_triple types_##NAME[] = { \ + TYPES_##NAME (DEF_VECTOR_TYPE, DEF_DOUBLE_TYPE, DEF_TRIPLE_TYPE), \ + { NUM_TYPE_SUFFIXES, NUM_TYPE_SUFFIXES, NUM_TYPE_SUFFIXES } \ + } + +/* For functions that don't take any type suffixes. */ +static const type_suffix_triple types_none[] = { + { NUM_TYPE_SUFFIXES, NUM_TYPE_SUFFIXES, NUM_TYPE_SUFFIXES }, + { NUM_TYPE_SUFFIXES, NUM_TYPE_SUFFIXES, NUM_TYPE_SUFFIXES } +}; + +/* Create an array for each TYPES_<combination> macro above. */ +DEF_SVE_TYPES_ARRAY (all_pred); +DEF_SVE_TYPES_ARRAY (all_count); +DEF_SVE_TYPES_ARRAY (all_pred_count); +DEF_SVE_TYPES_ARRAY (all_float); +DEF_SVE_TYPES_ARRAY (sd_float); +DEF_SVE_TYPES_ARRAY (all_signed); +DEF_SVE_TYPES_ARRAY (all_float_and_signed); +DEF_SVE_TYPES_ARRAY (all_unsigned); +DEF_SVE_TYPES_ARRAY (all_integer); +DEF_SVE_TYPES_ARRAY (all_arith); +DEF_SVE_TYPES_ARRAY (all_arith_no_fp16); +DEF_SVE_TYPES_ARRAY (all_data); +DEF_SVE_TYPES_ARRAY (b); +DEF_SVE_TYPES_ARRAY (b_unsigned); +DEF_SVE_TYPES_ARRAY (b_integer); +DEF_SVE_TYPES_ARRAY (bh_integer); +DEF_SVE_TYPES_ARRAY (bs_unsigned); +DEF_SVE_TYPES_ARRAY (bhs_signed); +DEF_SVE_TYPES_ARRAY (bhs_unsigned); +DEF_SVE_TYPES_ARRAY (bhs_integer); +DEF_SVE_TYPES_ARRAY (bh_data); +DEF_SVE_TYPES_ARRAY (bhs_data); +DEF_SVE_TYPES_ARRAY (bhs_widen); +DEF_SVE_TYPES_ARRAY (c); +DEF_SVE_TYPES_ARRAY (h_bfloat); +DEF_SVE_TYPES_ARRAY (h_float); +DEF_SVE_TYPES_ARRAY (h_float_mf8); +DEF_SVE_TYPES_ARRAY (h_integer); +DEF_SVE_TYPES_ARRAY (h_data); +DEF_SVE_TYPES_ARRAY (hs_signed); +DEF_SVE_TYPES_ARRAY (hs_integer); +DEF_SVE_TYPES_ARRAY (hs_float); +DEF_SVE_TYPES_ARRAY (hs_data); +DEF_SVE_TYPES_ARRAY (hd_unsigned); +DEF_SVE_TYPES_ARRAY (hsd_signed); +DEF_SVE_TYPES_ARRAY (hsd_integer); +DEF_SVE_TYPES_ARRAY (hsd_data); +DEF_SVE_TYPES_ARRAY (s_float); +DEF_SVE_TYPES_ARRAY (s_float_hsd_integer); +DEF_SVE_TYPES_ARRAY (s_float_mf8); +DEF_SVE_TYPES_ARRAY (s_float_sd_integer); +DEF_SVE_TYPES_ARRAY (s_signed); +DEF_SVE_TYPES_ARRAY (s_unsigned); +DEF_SVE_TYPES_ARRAY (s_integer); +DEF_SVE_TYPES_ARRAY (s_data); +DEF_SVE_TYPES_ARRAY (sd_signed); +DEF_SVE_TYPES_ARRAY (sd_unsigned); +DEF_SVE_TYPES_ARRAY (sd_integer); +DEF_SVE_TYPES_ARRAY (sd_data); +DEF_SVE_TYPES_ARRAY (all_float_and_sd_integer); +DEF_SVE_TYPES_ARRAY (d_float); +DEF_SVE_TYPES_ARRAY (d_unsigned); +DEF_SVE_TYPES_ARRAY (d_integer); +DEF_SVE_TYPES_ARRAY (d_data); +DEF_SVE_TYPES_ARRAY (cvt); +DEF_SVE_TYPES_ARRAY (cvt_bfloat); +DEF_SVE_TYPES_ARRAY (cvt_h_s_float); +DEF_SVE_TYPES_ARRAY (cvt_f32_f16); +DEF_SVE_TYPES_ARRAY (cvt_long); +DEF_SVE_TYPES_ARRAY (cvt_mf8); +DEF_SVE_TYPES_ARRAY (cvt_narrow_s); +DEF_SVE_TYPES_ARRAY (cvt_narrow); +DEF_SVE_TYPES_ARRAY (cvt_s_s); +DEF_SVE_TYPES_ARRAY (cvtn_mf8); +DEF_SVE_TYPES_ARRAY (cvtnx_mf8); +DEF_SVE_TYPES_ARRAY (inc_dec_n); +DEF_SVE_TYPES_ARRAY (qcvt_x2); +DEF_SVE_TYPES_ARRAY (qcvt_x4); +DEF_SVE_TYPES_ARRAY (qrshr_x2); +DEF_SVE_TYPES_ARRAY (qrshr_x4); +DEF_SVE_TYPES_ARRAY (qrshru_x2); +DEF_SVE_TYPES_ARRAY (qrshru_x4); +DEF_SVE_TYPES_ARRAY (reinterpret); +DEF_SVE_TYPES_ARRAY (reinterpret_b); +DEF_SVE_TYPES_ARRAY (while); +DEF_SVE_TYPES_ARRAY (while_x); +DEF_SVE_TYPES_ARRAY (while_x_c); +DEF_SVE_TYPES_ARRAY (s_narrow_fsu); +DEF_SVE_TYPES_ARRAY (all_za); +DEF_SVE_TYPES_ARRAY (d_za); +DEF_SVE_TYPES_ARRAY (za_bhsd_data); +DEF_SVE_TYPES_ARRAY (za_all_data); +DEF_SVE_TYPES_ARRAY (za_h_mf8); +DEF_SVE_TYPES_ARRAY (za_h_bfloat); +DEF_SVE_TYPES_ARRAY (za_h_float); +DEF_SVE_TYPES_ARRAY (za_s_b_signed); +DEF_SVE_TYPES_ARRAY (za_s_b_unsigned); +DEF_SVE_TYPES_ARRAY (za_s_b_integer); +DEF_SVE_TYPES_ARRAY (za_s_h_integer); +DEF_SVE_TYPES_ARRAY (za_s_h_data); +DEF_SVE_TYPES_ARRAY (za_s_unsigned); +DEF_SVE_TYPES_ARRAY (za_s_integer); +DEF_SVE_TYPES_ARRAY (za_s_mf8); +DEF_SVE_TYPES_ARRAY (za_hs_mf8); +DEF_SVE_TYPES_ARRAY (za_s_float); +DEF_SVE_TYPES_ARRAY (za_s_data); +DEF_SVE_TYPES_ARRAY (za_d_h_integer); +DEF_SVE_TYPES_ARRAY (za_d_float); +DEF_SVE_TYPES_ARRAY (za_d_integer); +DEF_SVE_TYPES_ARRAY (mop_base); +DEF_SVE_TYPES_ARRAY (mop_base_signed); +DEF_SVE_TYPES_ARRAY (mop_base_unsigned); +DEF_SVE_TYPES_ARRAY (mop_i16i64); +DEF_SVE_TYPES_ARRAY (mop_i16i64_signed); +DEF_SVE_TYPES_ARRAY (mop_i16i64_unsigned); +DEF_SVE_TYPES_ARRAY (za); + +DEF_SVE_TYPES_ARRAY (bhd_poly); +DEF_SVE_TYPES_ARRAY (bhdq_poly); + +static const group_suffix_index groups_none[] = { + GROUP_none, NUM_GROUP_SUFFIXES +}; + +static const group_suffix_index groups_x2[] = { GROUP_x2, NUM_GROUP_SUFFIXES }; + +static const group_suffix_index groups_x12[] = { + GROUP_none, GROUP_x2, NUM_GROUP_SUFFIXES +}; + +static const group_suffix_index groups_x4[] = { GROUP_x4, NUM_GROUP_SUFFIXES }; + +static const group_suffix_index groups_x24[] = { + GROUP_x2, GROUP_x4, NUM_GROUP_SUFFIXES +}; + +static const group_suffix_index groups_x124[] = { + GROUP_none, GROUP_x2, GROUP_x4, NUM_GROUP_SUFFIXES +}; + +static const group_suffix_index groups_x1234[] = { + GROUP_none, GROUP_x2, GROUP_x3, GROUP_x4, NUM_GROUP_SUFFIXES +}; + +static const group_suffix_index groups_vg1x2[] = { + GROUP_vg1x2, NUM_GROUP_SUFFIXES +}; + +static const group_suffix_index groups_vg1x4[] = { + GROUP_vg1x4, NUM_GROUP_SUFFIXES +}; + +static const group_suffix_index groups_vg1x24[] = { + GROUP_vg1x2, GROUP_vg1x4, NUM_GROUP_SUFFIXES +}; + +static const group_suffix_index groups_vg2[] = { + GROUP_vg2x1, GROUP_vg2x2, GROUP_vg2x4, NUM_GROUP_SUFFIXES +}; + +static const group_suffix_index groups_vg4[] = { + GROUP_vg4x1, GROUP_vg4x2, GROUP_vg4x4, NUM_GROUP_SUFFIXES +}; + +static const group_suffix_index groups_vg24[] = { + GROUP_vg2, GROUP_vg4, NUM_GROUP_SUFFIXES +}; + +/* Used by functions that have no governing predicate. */ +static const predication_index preds_none[] = { PRED_none, NUM_PREDS }; + +/* Used by functions that have a governing predicate but do not have an + explicit suffix. */ +static const predication_index preds_implicit[] = { PRED_implicit, NUM_PREDS }; + +/* Used by functions that only support "_m" predication. */ +static const predication_index preds_m[] = { PRED_m, NUM_PREDS }; + +/* Used by functions that allow merging and "don't care" predication, + but are not suitable for predicated MOVPRFX. */ +static const predication_index preds_mx[] = { + PRED_m, PRED_x, NUM_PREDS +}; + +/* Used by functions that allow merging, zeroing and "don't care" + predication. */ +static const predication_index preds_mxz[] = { + PRED_m, PRED_x, PRED_z, NUM_PREDS +}; + +/* Used by functions that have the mxz predicated forms above, and in addition + have an unpredicated form. */ +static const predication_index preds_mxz_or_none[] = { + PRED_m, PRED_x, PRED_z, PRED_none, NUM_PREDS +}; + +/* Used by functions that allow merging and zeroing predication but have + no "_x" form. */ +static const predication_index preds_mz[] = { PRED_m, PRED_z, NUM_PREDS }; + +/* Used by functions that have an unpredicated form and a _z predicated + form. */ +static const predication_index preds_z_or_none[] = { + PRED_z, PRED_none, NUM_PREDS +}; + +/* Used by (mostly predicate) functions that only support "_z" predication. */ +static const predication_index preds_z[] = { PRED_z, NUM_PREDS }; + +/* Used by SME instructions that always merge into ZA. */ +static const predication_index preds_za_m[] = { PRED_za_m, NUM_PREDS }; + +void build_all (function_builder &b, const char *signature, + const function_group_info &group, + mode_suffix_index mode_suffix_id, + bool force_direct_overloads = false); } #endif diff --git a/gcc/config/aarch64/aarch64-builtins.cc b/gcc/config/aarch64/aarch64-builtins.cc index f9bb6227e7e1..e34fa4a59d8e 100644 --- a/gcc/config/aarch64/aarch64-builtins.cc +++ b/gcc/config/aarch64/aarch64-builtins.cc @@ -1940,12 +1940,11 @@ aarch64_target_switcher::~aarch64_target_switcher () sizeof (have_regs_of_mode)); } -/* Implement #pragma GCC aarch64 "arm_neon.h". - - The types and functions defined here need to be available internally - during LTO as well. */ +/* Initialize NEON builtins using the old framework. + Delete once NEON all intrinsics have been ported to the pragma-based + framework. */ void -handle_arm_neon_h (void) +init_arm_neon_builtins (void) { aarch64_target_switcher switcher (AARCH64_FL_SIMD); @@ -1973,7 +1972,7 @@ aarch64_init_simd_builtins (void) aarch64_init_simd_builtin_functions (false); if (in_lto_p) - handle_arm_neon_h (); + init_arm_neon_builtins (); /* Initialize the remaining fcmla_laneq intrinsics. */ aarch64_init_fcmla_laneq_builtins (); diff --git a/gcc/config/aarch64/aarch64-c.cc b/gcc/config/aarch64/aarch64-c.cc index b3c5d05099ca..b809dbea51ae 100644 --- a/gcc/config/aarch64/aarch64-c.cc +++ b/gcc/config/aarch64/aarch64-c.cc @@ -416,7 +416,7 @@ aarch64_pragma_aarch64 (cpp_reader *) else if (strcmp (name, "arm_sme.h") == 0) aarch64_acle::handle_arm_sme_h (false); else if (strcmp (name, "arm_neon.h") == 0) - handle_arm_neon_h (); + aarch64_acle::handle_arm_neon_h (false); else if (strcmp (name, "arm_acle.h") == 0) handle_arm_acle_h (); else if (strcmp (name, "arm_neon_sve_bridge.h") == 0) diff --git a/gcc/config/aarch64/aarch64-neon-builtins-base.cc b/gcc/config/aarch64/aarch64-neon-builtins-base.cc new file mode 100644 index 000000000000..379c89e714d6 --- /dev/null +++ b/gcc/config/aarch64/aarch64-neon-builtins-base.cc @@ -0,0 +1,106 @@ +/* ACLE support for AArch64 NEON (__ARM_FEATURE_SIMD intrinsics) + Copyright (C) 2026-2026 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "tree.h" +#include "rtl.h" +#include "tm_p.h" +#include "memmodel.h" +#include "insn-codes.h" +#include "optabs.h" +#include "recog.h" +#include "expr.h" +#include "basic-block.h" +#include "function.h" +#include "fold-const.h" +#include "gimple.h" +#include "gimple-iterator.h" +#include "gimplify.h" +#include "explow.h" +#include "tree-vector-builder.h" +#include "rtx-vector-builder.h" +#include "vec-perm-indices.h" +#include "aarch64-acle-builtins.h" +#include "aarch64-neon-builtins-base.h" +#include "aarch64-neon-builtins-functions.h" +#include "gimple-fold.h" + +namespace aarch64_acle { +/* Base class for all function expanders. + At least one of `expand` or `fold` must be overriden by derived classes. */ +class gimple_function_base : public function_base +{ + rtx expand (function_expander &) const override { gcc_unreachable (); } + gimple *fold (gimple_folder &) const override { gcc_unreachable (); } +}; + +/* For intrinsics that map to a single GIMPLE expression with no argument + preparation necessary. */ +class gimple_expr : public gimple_function_base +{ + tree_code m_int_code; + tree_code m_float_code; + tree_code m_poly_code; + +public: + constexpr gimple_expr (tree_code code) + : m_int_code (code), + m_float_code (code), + m_poly_code (code) + {} + + constexpr gimple_expr (tree_code int_code, + tree_code float_code, + tree_code poly_code) + : m_int_code (int_code), + m_float_code (float_code), + m_poly_code (poly_code) + {} + + gimple *fold (gimple_folder &f) const override + { + auto nargs = gimple_call_num_args (f.call); + auto arg0 = nargs >= 1 ? gimple_call_arg (f.call, 0) : nullptr; + auto arg1 = nargs >= 2 ? gimple_call_arg (f.call, 1) : nullptr; + auto arg2 = nargs >= 3 ? gimple_call_arg (f.call, 2) : nullptr; + + auto type_class = f.type_suffix (0).tclass; + switch (type_class) + { + case TYPE_signed: + case TYPE_unsigned: + return gimple_build_assign (f.lhs, m_int_code, arg0, arg1, arg2); + case TYPE_float: + return gimple_build_assign (f.lhs, m_float_code, arg0, arg1, arg2); + case TYPE_poly: + return gimple_build_assign (f.lhs, m_poly_code, arg0, arg1, arg2); + default: + gcc_unreachable (); + } + } +}; + +// Lanewise arithmetic +NEON_FUNCTION (vaddd, gimple_expr, (PLUS_EXPR)) +NEON_FUNCTION (vadd, gimple_expr, (PLUS_EXPR, PLUS_EXPR, BIT_XOR_EXPR)) +NEON_FUNCTION (vaddq, gimple_expr, (PLUS_EXPR, PLUS_EXPR, BIT_XOR_EXPR)) +} diff --git a/gcc/config/aarch64/aarch64-neon-builtins-base.def b/gcc/config/aarch64/aarch64-neon-builtins-base.def new file mode 100644 index 000000000000..1291e2164535 --- /dev/null +++ b/gcc/config/aarch64/aarch64-neon-builtins-base.def @@ -0,0 +1,33 @@ +/* ACLE support for AArch64 NEON (__ARM_FEATURE_SIMD intrinsics) + Copyright (C) 2026-2026 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +// Lanewise arithmetic +#define REQUIRED_EXTENSIONS nonstreaming_only (AARCH64_FL_SIMD) +DEF_NEON_FUNCTION (vaddd, d_integer, ("s0,s0,s0")) +DEF_NEON_FUNCTION (vadd, all_arith_no_fp16, ("D0,D0,D0")) +DEF_NEON_FUNCTION (vadd, bhd_poly, ("D0,D0,D0")) +DEF_NEON_FUNCTION (vaddq, all_arith_no_fp16, ("Q0,Q0,Q0")) +DEF_NEON_FUNCTION (vaddq, bhdq_poly, ("Q0,Q0,Q0")) +#undef REQUIRED_EXTENSIONS + +// Lanewise arithmetic (FP16) +#define REQUIRED_EXTENSIONS nonstreaming_only (AARCH64_FL_SIMD | AARCH64_FL_F16) +DEF_NEON_FUNCTION (vadd, h_float, ("D0,D0,D0")) +DEF_NEON_FUNCTION (vaddq, h_float, ("Q0,Q0,Q0")) +#undef REQUIRED_EXTENSIONS diff --git a/gcc/config/aarch64/aarch64-neon-builtins-base.h b/gcc/config/aarch64/aarch64-neon-builtins-base.h new file mode 100644 index 000000000000..9612bef42f26 --- /dev/null +++ b/gcc/config/aarch64/aarch64-neon-builtins-base.h @@ -0,0 +1,29 @@ +/* ACLE support for AArch64 NEON (__ARM_FEATURE_SIMD intrinsics) + Copyright (C) 2026-2026 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#ifndef GCC_AARCH64_NEON_BUILTINS_BASE_H +#define GCC_AARCH64_NEON_BUILTINS_BASE_H + +namespace aarch64_acle::functions { +#define DEF_NEON_FUNCTION(NAME, ...) \ + extern const aarch64_acle::function_base *const NAME; +#include "aarch64-neon-builtins.def" +} + +#endif diff --git a/gcc/config/aarch64/aarch64-neon-builtins-functions.h b/gcc/config/aarch64/aarch64-neon-builtins-functions.h new file mode 100644 index 000000000000..58a631ac54e0 --- /dev/null +++ b/gcc/config/aarch64/aarch64-neon-builtins-functions.h @@ -0,0 +1,29 @@ +/* ACLE support for AArch64 NEON (function_base classes) + Copyright (C) 2026-2026 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#ifndef GCC_AARCH64_NEON_BUILTINS_FUNCTIONS_H +#define GCC_AARCH64_NEON_BUILTINS_FUNCTIONS_H + +/* Declare the global function base NAME, creating it from an instance + of class CLASS with constructor arguments ARGS. */ +#define NEON_FUNCTION(NAME, CLASS, ARGS) \ + namespace { static constexpr const CLASS NAME##_obj ARGS; } \ + const function_base *const aarch64_acle::functions::NAME = &NAME##_obj; + +#endif diff --git a/gcc/config/aarch64/aarch64-neon-builtins-shapes.cc b/gcc/config/aarch64/aarch64-neon-builtins-shapes.cc new file mode 100644 index 000000000000..7946a7675eb5 --- /dev/null +++ b/gcc/config/aarch64/aarch64-neon-builtins-shapes.cc @@ -0,0 +1,69 @@ +/* ACLE support for AArch64 NEON (function shapes) + Copyright (C) 2026-2026 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#define INCLUDE_ALGORITHM +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "basic-block.h" +#include "tree.h" +#include "function.h" +#include "gimple.h" +#include "rtl.h" +#include "tm_p.h" +#include "memmodel.h" +#include "insn-codes.h" +#include "optabs.h" +#include "aarch64-acle-builtins.h" +#include "aarch64-sve-builtins-shapes.h" +#include "aarch64-builtins.h" + +using namespace aarch64_acle; + +/* All NEON functions are non-overloaded, so we don't need bespoke + function shapes. Instead, we can just use a single shape for all NEON + functions, parameterised by a signature. */ +struct neon_shape : public function_shape +{ + constexpr neon_shape (const char *signature) + : m_signature (signature) + {} + + const char *m_signature; + + void build (function_builder &b, + const function_group_info &group) const override + { + aarch64_acle::build_all (b, this->m_signature, group, MODE_none); + } + + bool check (function_checker &) const override { return true; } + + bool explicit_type_suffix_p (unsigned int) const override { return true; } + tree resolve (function_resolver &) const override { gcc_unreachable (); } +}; + +namespace aarch64_acle::shapes { +#define DEF_NEON_FUNCTION(NAME, TYPES, SHAPE_ARGS) \ + static constexpr const neon_shape OBJ_NAME (NAME, TYPES) SHAPE_ARGS; \ + const aarch64_acle::function_shape *SHAPE_NAME (NAME, TYPES) \ + = &OBJ_NAME (NAME, TYPES); +#include "aarch64-neon-builtins.def" +} diff --git a/gcc/config/aarch64/aarch64-neon-builtins-shapes.h b/gcc/config/aarch64/aarch64-neon-builtins-shapes.h new file mode 100644 index 000000000000..c94f4c994643 --- /dev/null +++ b/gcc/config/aarch64/aarch64-neon-builtins-shapes.h @@ -0,0 +1,29 @@ +/* ACLE support for AArch64 NEON (function shapes) + Copyright (C) 2026-2026 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#ifndef GCC_AARCH64_NEON_BUILTINS_SHAPES_H +#define GCC_AARCH64_NEON_BUILTINS_SHAPES_H + +namespace aarch64_acle::shapes { +#define DEF_NEON_FUNCTION(NAME, TYPES, SHAPE_ARGS) \ + extern const aarch64_acle::function_shape *const SHAPE_NAME (NAME, TYPES); +#include "aarch64-neon-builtins.def" +} + +#endif diff --git a/gcc/config/aarch64/aarch64-neon-builtins.def b/gcc/config/aarch64/aarch64-neon-builtins.def new file mode 100644 index 000000000000..58630eebe489 --- /dev/null +++ b/gcc/config/aarch64/aarch64-neon-builtins.def @@ -0,0 +1,40 @@ +/* ACLE support for AArch64 NEON (__ARM_FEATURE_SIMD intrinsics) + Copyright (C) 2026-2026 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +/* Code organization: See block comment at the top of + aarch64-sve-builtins.def. */ + +/* Define a new function group. */ +#ifndef DEF_NEON_FUNCTION +#define DEF_NEON_FUNCTION(NAME, TYPES, SHAPE_ARGS) +#endif + +/* Helper for generating the name of the function_group's corresponding + neon_shape instance. */ +#define OBJ_NAME(NAME, TYPES) NAME ## _ ## TYPES ## _obj + +/* Helper for generating the name of the function_group's corresponding + function_shape. */ +#define SHAPE_NAME(NAME, TYPES) NAME ## _ ## TYPES ## _shape + +#include "aarch64-neon-builtins-base.def" + +#undef DEF_NEON_FUNCTION +#undef OBJ_NAME +#undef SHAPE_NAME diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index fb255316dfbf..5580f3148d6d 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -1157,7 +1157,7 @@ tree aarch64_general_builtin_decl (unsigned, bool); tree aarch64_general_builtin_rsqrt (unsigned int); void aarch64_ms_variadic_abi_init_builtins (void); void handle_arm_acle_h (void); -void handle_arm_neon_h (void); +void init_arm_neon_builtins (void); bool aarch64_check_required_extensions (location_t, tree, aarch64_required_extensions); @@ -1184,6 +1184,7 @@ namespace aarch64_acle { void handle_arm_sve_h (bool); void handle_arm_sme_h (bool); void handle_arm_neon_sve_bridge_h (bool); + void handle_arm_neon_h (bool); tree builtin_decl (unsigned, bool); bool builtin_type_p (const_tree); bool builtin_type_p (const_tree, unsigned int *, unsigned int *); diff --git a/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc b/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc index 74e05d48b6ca..0290c2ecc469 100644 --- a/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc +++ b/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc @@ -277,6 +277,18 @@ parse_type (const function_instance &instance, const char *&format) if (ch == 's') { type_suffix_index suffix = parse_element_type (instance, format); + + // HACK: remove once all NEON intrinsics have been ported to the + // pragma-based framework. + if (suffix == TYPE_SUFFIX_p8) + return aarch64_simd_types_trees[Poly8_t].eltype; + if (suffix == TYPE_SUFFIX_p16) + return aarch64_simd_types_trees[Poly16_t].eltype; + if (suffix == TYPE_SUFFIX_p64) + return aarch64_simd_types_trees[Poly64_t].eltype; + if (suffix == TYPE_SUFFIX_p128) + return aarch64_simd_types_trees[Poly128_t].eltype; + return scalar_types[type_suffixes[suffix].vector_type]; } @@ -530,10 +542,10 @@ build_vs_offset (function_builder &b, const char *signature, predicate. FORCE_DIRECT_OVERLOADS is true if there is a one-to-one mapping between "short" and "full" names, and if standard overload resolution therefore isn't necessary. */ -static void +void build_all (function_builder &b, const char *signature, const function_group_info &group, mode_suffix_index mode_suffix_id, - bool force_direct_overloads = false) + bool force_direct_overloads) { for (unsigned int pi = 0; group.preds[pi] != NUM_PREDS; ++pi) for (unsigned int gi = 0; group.groups[gi] != NUM_GROUP_SUFFIXES; ++gi) diff --git a/gcc/config/aarch64/aarch64-sve-builtins.def b/gcc/config/aarch64/aarch64-sve-builtins.def index 6ad257643b69..6df8d41d7f63 100644 --- a/gcc/config/aarch64/aarch64-sve-builtins.def +++ b/gcc/config/aarch64/aarch64-sve-builtins.def @@ -26,6 +26,8 @@ - aarch64-sve-builtins.def for common data types, groups, and other supporting definitions used across all files. + - aarch64-neon-builtins-base.def for any AdvSIMD intrinsic that is + enabled by the +simd extension. - aarch64-sve-builtins-base.def for the baseline SVE intrinsics which predate SVE2 and SME. - aarch64-sve-builtins-sve2.def for any scalable SIMD intrinsic that is @@ -159,6 +161,15 @@ DEF_SVE_NEON_TYPE_SUFFIX (u32, svuint32_t, unsigned, 32, VNx4SImode, DEF_SVE_NEON_TYPE_SUFFIX (u64, svuint64_t, unsigned, 64, VNx2DImode, Uint64x1_t, Uint64x2_t) +DEF_SVE_NEON_TYPE_SUFFIX (p8, svuint8_t, poly, 8, VNx16QImode, + Poly8x8_t, Poly8x16_t) +DEF_SVE_NEON_TYPE_SUFFIX (p16, svuint16_t, poly, 16, VNx8HImode, + Poly16x4_t, Poly16x8_t) +DEF_SVE_NEON_TYPE_SUFFIX (p64, svuint64_t, poly, 64, VNx2DImode, + Poly64x1_t, Poly64x2_t) +DEF_SVE_NEON_TYPE_SUFFIX (p128, svuint64_t, poly, 128, TImode, + Poly128_t, Poly128_t) + /* Associate _za with bytes. This is needed for svldr_vnum_za and svstr_vnum_za, whose ZA offset can be in the range [0, 15], as for za8. */ DEF_SME_ZA_SUFFIX (za, 8, VNx16QImode) diff --git a/gcc/config/aarch64/arm_neon.h b/gcc/config/aarch64/arm_neon.h index d7505a16edb5..b45f53663ba8 100644 --- a/gcc/config/aarch64/arm_neon.h +++ b/gcc/config/aarch64/arm_neon.h @@ -193,147 +193,6 @@ __vec; \ }) -/* vadd */ -__extension__ extern __inline int8x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vadd_s8 (int8x8_t __a, int8x8_t __b) -{ - return __a + __b; -} - -__extension__ extern __inline int16x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vadd_s16 (int16x4_t __a, int16x4_t __b) -{ - return __a + __b; -} - -__extension__ extern __inline int32x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vadd_s32 (int32x2_t __a, int32x2_t __b) -{ - return __a + __b; -} - -__extension__ extern __inline float32x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vadd_f32 (float32x2_t __a, float32x2_t __b) -{ - return __a + __b; -} - -__extension__ extern __inline float64x1_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vadd_f64 (float64x1_t __a, float64x1_t __b) -{ - return __a + __b; -} - -__extension__ extern __inline uint8x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vadd_u8 (uint8x8_t __a, uint8x8_t __b) -{ - return __a + __b; -} - -__extension__ extern __inline uint16x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vadd_u16 (uint16x4_t __a, uint16x4_t __b) -{ - return __a + __b; -} - -__extension__ extern __inline uint32x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vadd_u32 (uint32x2_t __a, uint32x2_t __b) -{ - return __a + __b; -} - -__extension__ extern __inline int64x1_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vadd_s64 (int64x1_t __a, int64x1_t __b) -{ - return __a + __b; -} - -__extension__ extern __inline uint64x1_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vadd_u64 (uint64x1_t __a, uint64x1_t __b) -{ - return __a + __b; -} - -__extension__ extern __inline int8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vaddq_s8 (int8x16_t __a, int8x16_t __b) -{ - return __a + __b; -} - -__extension__ extern __inline int16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vaddq_s16 (int16x8_t __a, int16x8_t __b) -{ - return __a + __b; -} - -__extension__ extern __inline int32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vaddq_s32 (int32x4_t __a, int32x4_t __b) -{ - return __a + __b; -} - -__extension__ extern __inline int64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vaddq_s64 (int64x2_t __a, int64x2_t __b) -{ - return __a + __b; -} - -__extension__ extern __inline float32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vaddq_f32 (float32x4_t __a, float32x4_t __b) -{ - return __a + __b; -} - -__extension__ extern __inline float64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vaddq_f64 (float64x2_t __a, float64x2_t __b) -{ - return __a + __b; -} - -__extension__ extern __inline uint8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vaddq_u8 (uint8x16_t __a, uint8x16_t __b) -{ - return __a + __b; -} - -__extension__ extern __inline uint16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vaddq_u16 (uint16x8_t __a, uint16x8_t __b) -{ - return __a + __b; -} - -__extension__ extern __inline uint32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vaddq_u32 (uint32x4_t __a, uint32x4_t __b) -{ - return __a + __b; -} - -__extension__ extern __inline uint64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vaddq_u64 (uint64x2_t __a, uint64x2_t __b) -{ - return __a + __b; -} - __extension__ extern __inline int16x8_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vaddl_s8 (int8x8_t __a, int8x8_t __b) @@ -26043,20 +25902,6 @@ vsqrtq_f16 (float16x8_t __a) /* ARMv8.2-A FP16 two operands vector intrinsics. */ -__extension__ extern __inline float16x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vadd_f16 (float16x4_t __a, float16x4_t __b) -{ - return __a + __b; -} - -__extension__ extern __inline float16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vaddq_f16 (float16x8_t __a, float16x8_t __b) -{ - return __a + __b; -} - __extension__ extern __inline float16x4_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vabd_f16 (float16x4_t __a, float16x4_t __b) @@ -28665,55 +28510,6 @@ vusmmlaq_s32 (int32x4_t __r, uint8x16_t __a, int8x16_t __b) #pragma GCC pop_options -__extension__ extern __inline poly8x8_t -__attribute ((__always_inline__, __gnu_inline__, __artificial__)) -vadd_p8 (poly8x8_t __a, poly8x8_t __b) -{ - return __a ^ __b; -} - -__extension__ extern __inline poly16x4_t -__attribute ((__always_inline__, __gnu_inline__, __artificial__)) -vadd_p16 (poly16x4_t __a, poly16x4_t __b) -{ - return __a ^ __b; -} - -__extension__ extern __inline poly64x1_t -__attribute ((__always_inline__, __gnu_inline__, __artificial__)) -vadd_p64 (poly64x1_t __a, poly64x1_t __b) -{ - return __a ^ __b; -} - -__extension__ extern __inline poly8x16_t -__attribute ((__always_inline__, __gnu_inline__, __artificial__)) -vaddq_p8 (poly8x16_t __a, poly8x16_t __b) -{ - return __a ^ __b; -} - -__extension__ extern __inline poly16x8_t -__attribute ((__always_inline__, __gnu_inline__, __artificial__)) -vaddq_p16 (poly16x8_t __a, poly16x8_t __b) -{ - return __a ^__b; -} - -__extension__ extern __inline poly64x2_t -__attribute ((__always_inline__, __gnu_inline__, __artificial__)) -vaddq_p64 (poly64x2_t __a, poly64x2_t __b) -{ - return __a ^ __b; -} - -__extension__ extern __inline poly128_t -__attribute ((__always_inline__, __gnu_inline__, __artificial__)) -vaddq_p128 (poly128_t __a, poly128_t __b) -{ - return __a ^ __b; -} - #undef __aarch64_vget_lane_any #undef __aarch64_vdup_lane_any diff --git a/gcc/config/aarch64/t-aarch64 b/gcc/config/aarch64/t-aarch64 index 7c25ea16dc50..3942a1049b9c 100644 --- a/gcc/config/aarch64/t-aarch64 +++ b/gcc/config/aarch64/t-aarch64 @@ -67,11 +67,40 @@ aarch64-builtins.o: $(srcdir)/config/aarch64/aarch64-builtins.cc $(CONFIG_H) \ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ $(srcdir)/config/aarch64/aarch64-builtins.cc +aarch64-neon-builtins-shapes.o: \ + $(srcdir)/config/aarch64/aarch64-neon-builtins-shapes.cc \ + $(srcdir)/config/aarch64/aarch64-neon-builtins.def \ + $(srcdir)/config/aarch64/aarch64-neon-builtins-base.def \ + $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) \ + $(TM_P_H) memmodel.h insn-codes.h $(OPTABS_H) \ + $(srcdir)/config/aarch64/aarch64-acle-builtins.h \ + $(srcdir)/config/aarch64/aarch64-neon-builtins-shapes.h + $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ + $(srcdir)/config/aarch64/aarch64-neon-builtins-shapes.cc + +aarch64-neon-builtins-base.o: \ + $(srcdir)/config/aarch64/aarch64-neon-builtins-base.cc \ + $(srcdir)/config/aarch64/aarch64-neon-builtins.def \ + $(srcdir)/config/aarch64/aarch64-neon-builtins-base.def \ + $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) \ + $(TM_P_H) memmodel.h insn-codes.h $(OPTABS_H) $(RECOG_H) \ + $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) fold-const.h $(GIMPLE_H) \ + gimple-iterator.h gimplify.h explow.h $(EMIT_RTL_H) tree-vector-builder.h \ + rtx-vector-builder.h vec-perm-indices.h \ + $(srcdir)/config/aarch64/aarch64-acle-builtins.h \ + $(srcdir)/config/aarch64/aarch64-neon-builtins-shapes.h \ + $(srcdir)/config/aarch64/aarch64-neon-builtins-base.h \ + $(srcdir)/config/aarch64/aarch64-neon-builtins-functions.h + $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ + $(srcdir)/config/aarch64/aarch64-neon-builtins-base.cc + aarch64-acle-builtins.o: $(srcdir)/config/aarch64/aarch64-acle-builtins.cc \ $(srcdir)/config/aarch64/aarch64-sve-builtins.def \ $(srcdir)/config/aarch64/aarch64-sve-builtins-base.def \ $(srcdir)/config/aarch64/aarch64-sve-builtins-sve2.def \ $(srcdir)/config/aarch64/aarch64-sve-builtins-sme.def \ + $(srcdir)/config/aarch64/aarch64-neon-builtins.def \ + $(srcdir)/config/aarch64/aarch64-neon-builtins-base.def \ $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TARGET_H) $(TREE_H) $(RTL_H) \ $(TM_P_H) memmodel.h insn-codes.h $(OPTABS_H) $(RECOG_H) $(DIAGNOSTIC_H) \ $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) fold-const.h $(GIMPLE_H) \ diff --git a/gcc/testsuite/g++.target/aarch64/pr103147-6.C b/gcc/testsuite/g++.target/aarch64/pr103147-6.C index 15a606f976c8..bbea67b9b7db 100644 --- a/gcc/testsuite/g++.target/aarch64/pr103147-6.C +++ b/gcc/testsuite/g++.target/aarch64/pr103147-6.C @@ -1,3 +1,4 @@ /* { dg-options "-mgeneral-regs-only" } */ +/* { dg-excess-errors "arm_neon.h" } */ #include <arm_neon.h> diff --git a/gcc/testsuite/g++.target/aarch64/pr117048.C b/gcc/testsuite/g++.target/aarch64/pr117048.C index ae46e5875e4c..a9775700c5bf 100644 --- a/gcc/testsuite/g++.target/aarch64/pr117048.C +++ b/gcc/testsuite/g++.target/aarch64/pr117048.C @@ -30,5 +30,5 @@ void G( v[12] = vgetq_lane_s64(vd01, 0); } -/* { dg-final { scan-assembler {\txar\tv[0-9]+\.2d, v[0-9]+\.2d, v[0-9]+\.2d, 32\n} } } */ +/* { dg-final { scan-assembler {\txar\tv[0-9]+\.2d, v[0-9]+\.2d, v[0-9]+\.2d, #?32\n} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/neon/aarch64-neon.exp b/gcc/testsuite/gcc.target/aarch64/neon/aarch64-neon.exp new file mode 100644 index 000000000000..e3a48b306a50 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/neon/aarch64-neon.exp @@ -0,0 +1,43 @@ +# Specific regression driver for AArch64 NEON. +# Copyright (C) 2026-2026 Free Software Foundation, Inc. +# Contributed by ARM Ltd. +# +# This file is part of GCC. +# +# GCC is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GCC is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. */ + +# GCC testsuite that uses the `dg.exp' driver. + +# Exit immediately if this isn't an AArch64 target. +if {![istarget aarch64*-*-*] } then { + return +} + +# Load support procs. +load_lib gcc-dg.exp + +# Initialize `dg'. +dg-init + +# Main loop. +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*\[cCs\]]] \ + " -ansi -pedantic-errors -std=c23 -O2 -march=armv8-a+simd" "" + +# Again, for big-endian targets. +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*\[cCs\]]] \ + " -ansi -pedantic-errors -std=c23 -O2 -march=armv8-a+simd -mbig-endian" "" + +# All done. +dg-finish diff --git a/gcc/testsuite/gcc.target/aarch64/neon/arm_neon_test.h b/gcc/testsuite/gcc.target/aarch64/neon/arm_neon_test.h new file mode 100644 index 000000000000..7d9371e01047 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/neon/arm_neon_test.h @@ -0,0 +1,22 @@ +#include "arm_neon.h" + +#pragma GCC target "+simd+fp16+bf16+sha3" + +#define TEST_UNARY(NAME, RET_TYPE, ARG_1_TYPE) \ + RET_TYPE test_##NAME (ARG_1_TYPE a) { return NAME (a); } + +#define TEST_UNIFORM_UNARY(NAME, TYPE) TEST_UNARY (NAME, TYPE, TYPE) + +#define TEST_BINARY(NAME, RET_TYPE, ARG_1_TYPE, ARG_2_TYPE) \ + RET_TYPE test_##NAME (ARG_1_TYPE a, ARG_2_TYPE b) { return NAME (a, b); } + +#define TEST_UNIFORM_BINARY(NAME, TYPE) TEST_BINARY (NAME, TYPE, TYPE, TYPE) + +#define TEST_TERNARY(NAME, RET_TYPE, ARG_1_TYPE, ARG_2_TYPE, ARG_3_TYPE) \ + RET_TYPE test_##NAME (ARG_1_TYPE a, ARG_2_TYPE b, ARG_3_TYPE c) \ + { \ + return NAME (a, b, c); \ + } + +#define TEST_UNIFORM_TERNARY(NAME, TYPE) \ + TEST_TERNARY (NAME, TYPE, TYPE, TYPE, TYPE) diff --git a/gcc/testsuite/gcc.target/aarch64/neon/vadd.c b/gcc/testsuite/gcc.target/aarch64/neon/vadd.c new file mode 100644 index 000000000000..e622718685db --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/neon/vadd.c @@ -0,0 +1,203 @@ +/* { dg-do compile } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include "arm_neon_test.h" + +/* +** test_vadd_u8: +** add v0\.8b, (v0\.8b, v1\.8b|v1\.8b, v0\.8b) +** ret +*/ +TEST_UNIFORM_BINARY (vadd_u8, uint8x8_t) + +/* +** test_vadd_s8: +** add v0\.8b, (v0\.8b, v1\.8b|v1\.8b, v0\.8b) +** ret +*/ +TEST_UNIFORM_BINARY (vadd_s8, int8x8_t) + +/* +** test_vadd_p8: +** eor v0\.8b, (v0\.8b, v1\.8b|v1\.8b, v0\.8b) +** ret +*/ +TEST_UNIFORM_BINARY (vadd_p8, poly8x8_t) + +/* +** test_vadd_u16: +** add v0\.4h, (v0\.4h, v1\.4h|v1\.4h, v0\.4h) +** ret +*/ +TEST_UNIFORM_BINARY (vadd_u16, uint16x4_t) + +/* +** test_vadd_s16: +** add v0\.4h, (v0\.4h, v1\.4h|v1\.4h, v0\.4h) +** ret +*/ +TEST_UNIFORM_BINARY (vadd_s16, int16x4_t) + +/* +** test_vadd_p16: +** eor v0\.8b, (v0\.8b, v1\.8b|v1\.8b, v0\.8b) +** ret +*/ +TEST_UNIFORM_BINARY (vadd_p16, poly16x4_t) + +/* +** test_vadd_u32: +** add v0\.2s, (v0\.2s, v1\.2s|v1\.2s, v0\.2s) +** ret +*/ +TEST_UNIFORM_BINARY (vadd_u32, uint32x2_t) + +/* +** test_vadd_s32: +** add v0\.2s, (v0\.2s, v1\.2s|v1\.2s, v0\.2s) +** ret +*/ +TEST_UNIFORM_BINARY (vadd_s32, int32x2_t) + +/* +** test_vadd_u64: +** add d0, (d0, d1|d1, d0) +** ret +*/ +TEST_UNIFORM_BINARY (vadd_u64, uint64x1_t) + +/* +** test_vadd_s64: +** add d0, (d0, d1|d1, d0) +** ret +*/ +TEST_UNIFORM_BINARY (vadd_s64, int64x1_t) + +/* +** test_vadd_p64: +** eor v0\.8b, (v0\.8b, v1\.8b|v1\.8b, v0\.8b) +** ret +*/ +TEST_UNIFORM_BINARY (vadd_p64, poly64x1_t) + +/* +** test_vaddq_u8: +** add v0\.16b, (v0\.16b, v1\.16b|v1\.16b, v0\.16b) +** ret +*/ +TEST_UNIFORM_BINARY (vaddq_u8, uint8x16_t) + +/* +** test_vaddq_s8: +** add v0\.16b, (v0\.16b, v1\.16b|v1\.16b, v0\.16b) +** ret +*/ +TEST_UNIFORM_BINARY (vaddq_s8, int8x16_t) + +/* +** test_vaddq_p8: +** eor v0\.16b, (v0\.16b, v1\.16b|v1\.16b, v0\.16b) +** ret +*/ +TEST_UNIFORM_BINARY (vaddq_p8, poly8x16_t) + +/* +** test_vaddq_u16: +** add v0\.8h, (v0\.8h, v1\.8h|v1\.8h, v0\.8h) +** ret +*/ +TEST_UNIFORM_BINARY (vaddq_u16, uint16x8_t) + +/* +** test_vaddq_s16: +** add v0\.8h, (v0\.8h, v1\.8h|v1\.8h, v0\.8h) +** ret +*/ +TEST_UNIFORM_BINARY (vaddq_s16, int16x8_t) + +/* +** test_vaddq_f16: +** fadd v0\.8h, (v0\.8h, v1\.8h|v1\.8h, v0\.8h) +** ret +*/ +TEST_UNIFORM_BINARY (vaddq_f16, float16x8_t) + +/* +** test_vaddq_p16: +** eor v0\.16b, (v0\.16b, v1\.16b|v1\.16b, v0\.16b) +** ret +*/ +TEST_UNIFORM_BINARY (vaddq_p16, poly16x8_t) + +/* +** test_vaddq_u32: +** add v0\.4s, (v0\.4s, v1\.4s|v1\.4s, v0\.4s) +** ret +*/ +TEST_UNIFORM_BINARY (vaddq_u32, uint32x4_t) + +/* +** test_vaddq_s32: +** add v0\.4s, (v0\.4s, v1\.4s|v1\.4s, v0\.4s) +** ret +*/ +TEST_UNIFORM_BINARY (vaddq_s32, int32x4_t) + +/* +** test_vaddq_f32: +** fadd v0\.4s, (v0\.4s, v1\.4s|v1\.4s, v0\.4s) +** ret +*/ +TEST_UNIFORM_BINARY (vaddq_f32, float32x4_t) + +/* +** test_vaddq_u64: +** add v0\.2d, (v0\.2d, v1\.2d|v1\.2d, v0\.2d) +** ret +*/ +TEST_UNIFORM_BINARY (vaddq_u64, uint64x2_t) + +/* +** test_vaddq_s64: +** add v0\.2d, (v0\.2d, v1\.2d|v1\.2d, v0\.2d) +** ret +*/ +TEST_UNIFORM_BINARY (vaddq_s64, int64x2_t) + +/* +** test_vaddq_f64: +** fadd v0\.2d, (v0\.2d, v1\.2d|v1\.2d, v0\.2d) +** ret +*/ +TEST_UNIFORM_BINARY (vaddq_f64, float64x2_t) + +/* +** test_vaddq_p64: +** eor v0\.16b, (v0\.16b, v1\.16b|v1\.16b, v0\.16b) +** ret +*/ +TEST_UNIFORM_BINARY (vaddq_p64, poly64x2_t) + +/* `poly128_t` is a scalar type, like `__uint128_t`, so it is passed in two GPR + registers. * +/* +** test_vaddq_p128: +** eor x[0-9], x[0-9]+, x[0-9]+ +** eor x[0-9], x[0-9]+, x[0-9]+ +** ret +*/ +TEST_UNIFORM_BINARY (vaddq_p128, poly128_t) + +/* +** test_vaddd_u64: +** add x0, (x0, x1|x1, x0) +** ret +*/ +TEST_UNIFORM_BINARY (vaddd_u64, uint64_t) + +/* +** test_vaddd_s64: +** add x0, (x0, x1|x1, x0) +** ret +*/ +TEST_UNIFORM_BINARY (vaddd_s64, int64_t) diff --git a/gcc/testsuite/gcc.target/aarch64/pr103147-6.c b/gcc/testsuite/gcc.target/aarch64/pr103147-6.c index 15a606f976c8..bbea67b9b7db 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr103147-6.c +++ b/gcc/testsuite/gcc.target/aarch64/pr103147-6.c @@ -1,3 +1,4 @@ /* { dg-options "-mgeneral-regs-only" } */ +/* { dg-excess-errors "arm_neon.h" } */ #include <arm_neon.h>
