https://gcc.gnu.org/g:f855bc3006f43a623bd6197a795f238e70a3f007
commit r15-5883-gf855bc3006f43a623bd6197a795f238e70a3f007 Author: Saurabh Jha <saurabh....@arm.com> Date: Tue Dec 3 09:54:00 2024 +0000 aarch64: Refactor AdvSIMD intrinsics Refactor AdvSIMD intrinsics defined using the new pragma-based approach so that it is more extensible. Introduce a new struct, simd_type, which defines types using a mode and qualifiers, and use objects of this struct in the declaration of intrinsics in the aarch64-simd-pragma-builtins.def file. Change aarch64_pragma_builtins_data struct to support return type and argument types. Refactor aarch64_fntype and aarch64_expand_pragma_builtin so that it initialises corresponding vectors in a loop. As we add intrinsics with more arguments, these functions won't need to change to support those. gcc/ChangeLog: * config/aarch64/aarch64-builtins.cc (ENTRY): Modify to add support of return and argument types. (struct simd_type): New struct to declare types using mode and qualifiers. (struct aarch64_pragma_builtins_data): Replace mode with the array of types to support return and argument types. (aarch64_fntype): Modify to handle different signatures. (aarch64_expand_pragma_builtin): Modify to handle different signatures. * config/aarch64/aarch64-simd-pragma-builtins.def (ENTRY_VHSDF): Rename to ENTRY_BINARY_VHSDF. (ENTRY_BINARY): New macro to declare binary intrinsics. (ENTRY_BINARY_VHSDF): Remove signature argument and use ENTRY_BINARY. Co-authored-by: Vladimir Miloserdov <vladimir.miloser...@arm.com> Co-authored-by: Richard Sandiford <richard.sandif...@arm.com> Diff: --- gcc/config/aarch64/aarch64-builtins.cc | 108 ++++++++++++++++----- .../aarch64/aarch64-simd-pragma-builtins.def | 22 +++-- 2 files changed, 98 insertions(+), 32 deletions(-) diff --git a/gcc/config/aarch64/aarch64-builtins.cc b/gcc/config/aarch64/aarch64-builtins.cc index bc1719adbaa4..8984f0c59b97 100644 --- a/gcc/config/aarch64/aarch64-builtins.cc +++ b/gcc/config/aarch64/aarch64-builtins.cc @@ -780,7 +780,7 @@ typedef struct AARCH64_SIMD_BUILTIN_##T##_##N##A, #undef ENTRY -#define ENTRY(N, S, M, U) \ +#define ENTRY(N, S, T0, T1, T2, U) \ AARCH64_##N, enum aarch64_builtins @@ -1602,10 +1602,50 @@ enum class aarch64_builtin_signatures binary, }; +namespace { + +/* Pairs a machine mode with the information needed to turn it into a + function argument type or return type. */ +struct simd_type { + tree type () const { return aarch64_simd_builtin_type (mode, qualifiers); } + + machine_mode mode; + aarch64_type_qualifiers qualifiers; +}; + +namespace simd_types { + constexpr simd_type p8 { V8QImode, qualifier_poly }; + constexpr simd_type p8q { V16QImode, qualifier_poly }; + constexpr simd_type s8 { V8QImode, qualifier_none }; + constexpr simd_type s8q { V16QImode, qualifier_none }; + constexpr simd_type u8 { V8QImode, qualifier_unsigned }; + constexpr simd_type u8q { V16QImode, qualifier_unsigned }; + + constexpr simd_type f16 { V4HFmode, qualifier_none }; + constexpr simd_type f16q { V8HFmode, qualifier_none }; + constexpr simd_type p16 { V4HImode, qualifier_poly }; + constexpr simd_type p16q { V8HImode, qualifier_poly }; + constexpr simd_type s16 { V4HImode, qualifier_none }; + constexpr simd_type s16q { V8HImode, qualifier_none }; + constexpr simd_type u16 { V4HImode, qualifier_unsigned }; + constexpr simd_type u16q { V8HImode, qualifier_unsigned }; + + constexpr simd_type bf16 { V4BFmode, qualifier_none }; + constexpr simd_type bf16q { V8BFmode, qualifier_none }; + + constexpr simd_type f32 { V2SFmode, qualifier_none }; + constexpr simd_type f32q { V4SFmode, qualifier_none }; + constexpr simd_type f64q { V2DFmode, qualifier_none }; + + constexpr simd_type none { VOIDmode, qualifier_none }; +} + +} + #undef ENTRY -#define ENTRY(N, S, M, U) \ - {#N, aarch64_builtin_signatures::S, E_##M##mode, U, \ - aarch64_required_extensions::REQUIRED_EXTENSIONS}, +#define ENTRY(N, S, T0, T1, T2, U) \ + {#N, aarch64_builtin_signatures::S, simd_types::T0, simd_types::T1, \ + simd_types::T2, U, aarch64_required_extensions::REQUIRED_EXTENSIONS}, /* Initialize pragma builtins. */ @@ -1613,7 +1653,7 @@ struct aarch64_pragma_builtins_data { const char *name; aarch64_builtin_signatures signature; - machine_mode mode; + simd_type types[3]; int unspec; aarch64_required_extensions required_extensions; }; @@ -1622,19 +1662,26 @@ static aarch64_pragma_builtins_data aarch64_pragma_builtins[] = { #include "aarch64-simd-pragma-builtins.def" }; +/* Return the function type for BUILTIN_DATA. */ static tree aarch64_fntype (const aarch64_pragma_builtins_data &builtin_data) { - auto type = aarch64_simd_builtin_type (builtin_data.mode, qualifier_none); + tree return_type = NULL_TREE; + auto_vec<tree, 8> arg_types; switch (builtin_data.signature) { case aarch64_builtin_signatures::binary: - return build_function_type_list (type, type, type, NULL_TREE); - default: - gcc_unreachable (); + return_type = builtin_data.types[0].type (); + for (int i = 1; i <= 2; ++i) + arg_types.quick_push (builtin_data.types[i].type ()); + break; } + return build_function_type_array (return_type, arg_types.length (), + arg_types.address ()); } +/* Simulate function definitions for all of the builtins in + aarch64_pragma_builtins. */ static void aarch64_init_pragma_builtins () { @@ -3376,23 +3423,39 @@ aarch64_expand_builtin_data_intrinsic (unsigned int fcode, tree exp, rtx target) return ops[0].value; } +/* Expand CALL_EXPR EXP, given that it is a call to the function described + by BUILTIN_DATA, and return the function's return value. Put the result + in TARGET if convenient. */ static rtx aarch64_expand_pragma_builtin (tree exp, rtx target, - const aarch64_pragma_builtins_data *builtin_data) + const aarch64_pragma_builtins_data &builtin_data) { - expand_operand ops[3]; - auto mode = builtin_data->mode; - auto op1 = expand_normal (CALL_EXPR_ARG (exp, 0)); - auto op2 = expand_normal (CALL_EXPR_ARG (exp, 1)); - create_output_operand (&ops[0], target, mode); - create_input_operand (&ops[1], op1, mode); - create_input_operand (&ops[2], op2, mode); + unsigned int nargs = call_expr_nargs (exp); - auto unspec = builtin_data->unspec; - auto icode = code_for_aarch64 (unspec, mode); - expand_insn (icode, 3, ops); + auto_vec<expand_operand, 8> ops; + ops.safe_grow (nargs + 1); + create_output_operand (&ops[0], target, TYPE_MODE (TREE_TYPE (exp))); + for (unsigned int i = 1; i <= nargs; ++i) + { + tree arg = CALL_EXPR_ARG (exp, i - 1); + create_input_operand (&ops[i], expand_normal (arg), + TYPE_MODE (TREE_TYPE (arg))); + } - return target; + insn_code icode; + switch (builtin_data.unspec) + { + case UNSPEC_FAMAX: + case UNSPEC_FAMIN: + icode = code_for_aarch64 (builtin_data.unspec, + builtin_data.types[0].mode); + break; + default: + gcc_unreachable (); + } + + expand_insn (icode, ops.length (), ops.address ()); + return ops[0].value; } /* Expand an expression EXP as fpsr or fpcr setter (depending on @@ -3632,7 +3695,7 @@ aarch64_general_expand_builtin (unsigned int fcode, tree exp, rtx target, return aarch64_expand_builtin_data_intrinsic (fcode, exp, target); if (auto builtin_data = aarch64_get_pragma_builtin (fcode)) - return aarch64_expand_pragma_builtin (exp, target, builtin_data); + return aarch64_expand_pragma_builtin (exp, target, *builtin_data); gcc_unreachable (); } @@ -4286,7 +4349,6 @@ aarch64_resolve_overloaded_builtin_general (location_t loc, tree function, #undef CF3 #undef CF4 #undef CF10 -#undef ENTRY_VHSDF #undef VAR1 #undef VAR2 #undef VAR3 diff --git a/gcc/config/aarch64/aarch64-simd-pragma-builtins.def b/gcc/config/aarch64/aarch64-simd-pragma-builtins.def index d66642eaa0af..e49db23cbd18 100644 --- a/gcc/config/aarch64/aarch64-simd-pragma-builtins.def +++ b/gcc/config/aarch64/aarch64-simd-pragma-builtins.def @@ -18,16 +18,20 @@ along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ -#undef ENTRY_VHSDF -#define ENTRY_VHSDF(NAME, SIGNATURE, UNSPEC) \ - ENTRY (NAME##_f16, SIGNATURE, V4HF, UNSPEC) \ - ENTRY (NAME##q_f16, SIGNATURE, V8HF, UNSPEC) \ - ENTRY (NAME##_f32, SIGNATURE, V2SF, UNSPEC) \ - ENTRY (NAME##q_f32, SIGNATURE, V4SF, UNSPEC) \ - ENTRY (NAME##q_f64, SIGNATURE, V2DF, UNSPEC) +#undef ENTRY_BINARY +#define ENTRY_BINARY(N, T0, T1, T2, U) \ + ENTRY (N, binary, T0, T1, T2, U) + +#undef ENTRY_BINARY_VHSDF +#define ENTRY_BINARY_VHSDF(NAME, UNSPEC) \ + ENTRY_BINARY (NAME##_f16, f16, f16, f16, UNSPEC) \ + ENTRY_BINARY (NAME##q_f16, f16q, f16q, f16q, UNSPEC) \ + ENTRY_BINARY (NAME##_f32, f32, f32, f32, UNSPEC) \ + ENTRY_BINARY (NAME##q_f32, f32q, f32q, f32q, UNSPEC) \ + ENTRY_BINARY (NAME##q_f64, f64q, f64q, f64q, UNSPEC) // faminmax #define REQUIRED_EXTENSIONS nonstreaming_only (AARCH64_FL_FAMINMAX) -ENTRY_VHSDF (vamax, binary, UNSPEC_FAMAX) -ENTRY_VHSDF (vamin, binary, UNSPEC_FAMIN) +ENTRY_BINARY_VHSDF (vamax, UNSPEC_FAMAX) +ENTRY_BINARY_VHSDF (vamin, UNSPEC_FAMIN) #undef REQUIRED_EXTENSIONS