From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by sourceware.org (Postfix) with ESMTP id D529F3858C2A for ; Tue, 5 Dec 2023 10:25:13 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org D529F3858C2A Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=arm.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org D529F3858C2A Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701771917; cv=none; b=IFBBa2PkhscBPsIUgrnjAXoxMlmc7jrrGQc4XrrpeskI5HVnrF38yLSbOIOkoLoCwysuiBcVNK97HUYCUCbvjvIBK48/peHA05kX+NnuABqyA5Euobiu+7JQ6lWluc+Zwcw8X+Oelzv47qXdETRVC4Fq4SRDKA6mBZINOyHso+I= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701771917; c=relaxed/simple; bh=cgNkNKgPWCUi/TcPFiCPuISGt8AXsEO2j4UvktxWaoc=; h=From:To:Subject:Date:Message-Id:MIME-Version; b=sUns2NQJ+OHjAzEmgQclPWCW7LO3w20XHtFulw19/Bjy2GJDDK/wnsW9wzn0WJFwGCitcu0Z75rKIBbS4rkgdYsm+JZPWDJr9M3UoEDq18k1Ou4DKyTwBUwHK164qDeEE3uMEZhhvdNTadtLzqHE3RZ3Ss0hCcb3YIeloUZzNBI= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 446241476; Tue, 5 Dec 2023 02:26:00 -0800 (PST) Received: from e121540-lin.manchester.arm.com (e121540-lin.manchester.arm.com [10.32.110.72]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 365113F5A1; Tue, 5 Dec 2023 02:25:13 -0800 (PST) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Cc: Richard Sandiford Subject: [pushed v2 2/5] aarch64: Add svcount_t Date: Tue, 5 Dec 2023 10:25:00 +0000 Message-Id: <20231205102503.1923331-3-richard.sandiford@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231205102503.1923331-1-richard.sandiford@arm.com> References: <20231205102503.1923331-1-richard.sandiford@arm.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-22.3 required=5.0 tests=BAYES_00,GIT_PATCH_0,KAM_DMARC_NONE,KAM_DMARC_STATUS,KAM_LAZY_DOMAIN_SECURITY,KAM_SHORT,SPF_HELO_NONE,SPF_NONE,TXREP,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: Some SME2 instructions interpret predicates as counters, rather than as bit-per-byte masks. The SME2 ACLE defines an svcount_t type for this interpretation. I don't think we have a better way of representing counters than the VNx16BI that we use for masks. The patch therefore doesn't add a new mode for this representation. It's just something that is interpreted in context, a bit like signed vs. unsigned integers. gcc/ * config/aarch64/aarch64-sve-builtins-base.cc (svreinterpret_impl::fold): Handle reinterprets between svbool_t and svcount_t. (svreinterpret_impl::expand): Likewise. * config/aarch64/aarch64-sve-builtins-base.def (svreinterpret): Add b<->c forms. * config/aarch64/aarch64-sve-builtins.cc (TYPES_reinterpret_b): New type suffix list. (wrap_type_in_struct, register_type_decl): New functions, split out from... (register_tuple_type): ...here. (register_builtin_types): Handle svcount_t. (handle_arm_sve_h): Don't create tuples of svcount_t. * config/aarch64/aarch64-sve-builtins.def (svcount_t): New type. (c): New type suffix. * config/aarch64/aarch64-sve-builtins.h (TYPE_count): New type class. gcc/testsuite/ * g++.target/aarch64/sve/acle/general-c++/mangle_1.C: Add test for svcount_t. * g++.target/aarch64/sve/acle/general-c++/mangle_2.C: Likewise. * g++.target/aarch64/sve/acle/general-c++/svcount_1.C: New test. * gcc.target/aarch64/sve/acle/asm/test_sve_acle.h (TEST_DUAL_P) (TEST_DUAL_P_REV): New macros. * gcc.target/aarch64/sve/acle/asm/reinterpret_b.c: New test. * gcc.target/aarch64/sve/acle/general-c/load_1.c: Test passing an svcount_t. * gcc.target/aarch64/sve/acle/general-c/svcount_1.c: New test. * gcc.target/aarch64/sve/acle/general-c/unary_convert_1.c: Test reinterprets involving svcount_t. * gcc.target/aarch64/sve/acle/general/attributes_7.c: Test svcount_t. * gcc.target/aarch64/sve/pcs/annotate_1.c: Likewise. * gcc.target/aarch64/sve/pcs/annotate_2.c: Likewise. * gcc.target/aarch64/sve/pcs/args_12.c: New test. --- .../aarch64/aarch64-sve-builtins-base.cc | 8 +- .../aarch64/aarch64-sve-builtins-base.def | 1 + gcc/config/aarch64/aarch64-sve-builtins.cc | 157 ++++++++----- gcc/config/aarch64/aarch64-sve-builtins.def | 2 + gcc/config/aarch64/aarch64-sve-builtins.h | 4 +- .../aarch64/sve/acle/general-c++/mangle_1.C | 2 + .../aarch64/sve/acle/general-c++/mangle_2.C | 2 + .../aarch64/sve/acle/general-c++/svcount_1.C | 10 + .../aarch64/sve/acle/asm/reinterpret_b.c | 20 ++ .../aarch64/sve/acle/asm/test_sve_acle.h | 15 ++ .../aarch64/sve/acle/general-c/load_1.c | 4 +- .../aarch64/sve/acle/general-c/svcount_1.c | 10 + .../sve/acle/general-c/unary_convert_1.c | 8 +- .../aarch64/sve/acle/general/attributes_7.c | 1 + .../gcc.target/aarch64/sve/pcs/annotate_1.c | 4 + .../gcc.target/aarch64/sve/pcs/annotate_2.c | 4 + .../gcc.target/aarch64/sve/pcs/args_12.c | 214 ++++++++++++++++++ 17 files changed, 402 insertions(+), 64 deletions(-) create mode 100644 gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/svcount_1.C create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_b.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/svcount_1.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/pcs/args_12.c diff --git a/gcc/config/aarch64/aarch64-sve-builtins-base.cc b/gcc/config/aarch64/aarch64-sve-builtins-base.cc index a219c88085a..89035135a38 100644 --- a/gcc/config/aarch64/aarch64-sve-builtins-base.cc +++ b/gcc/config/aarch64/aarch64-sve-builtins-base.cc @@ -2153,8 +2153,9 @@ public: /* Punt to rtl if the effect of the reinterpret on registers does not conform to GCC's endianness model. */ - if (!targetm.can_change_mode_class (f.vector_mode (0), - f.vector_mode (1), FP_REGS)) + if (GET_MODE_CLASS (f.vector_mode (0)) != MODE_VECTOR_BOOL + && !targetm.can_change_mode_class (f.vector_mode (0), + f.vector_mode (1), FP_REGS)) return NULL; /* Otherwise svreinterpret corresponds directly to a VIEW_CONVERT_EXPR @@ -2168,6 +2169,9 @@ public: expand (function_expander &e) const override { machine_mode mode = e.tuple_mode (0); + /* Handle svbool_t <-> svcount_t. */ + if (mode == e.tuple_mode (1)) + return e.args[0]; return e.use_exact_insn (code_for_aarch64_sve_reinterpret (mode)); } }; diff --git a/gcc/config/aarch64/aarch64-sve-builtins-base.def b/gcc/config/aarch64/aarch64-sve-builtins-base.def index ac53f35220d..a742c7bbc56 100644 --- a/gcc/config/aarch64/aarch64-sve-builtins-base.def +++ b/gcc/config/aarch64/aarch64-sve-builtins-base.def @@ -198,6 +198,7 @@ DEF_SVE_FUNCTION (svrecpe, unary, all_float, none) DEF_SVE_FUNCTION (svrecps, binary, all_float, none) DEF_SVE_FUNCTION (svrecpx, unary, all_float, mxz) DEF_SVE_FUNCTION_GS (svreinterpret, reinterpret, reinterpret, x1234, none) +DEF_SVE_FUNCTION (svreinterpret, reinterpret, reinterpret_b, none) DEF_SVE_FUNCTION (svrev, unary, all_data, none) DEF_SVE_FUNCTION (svrev, unary_pred, all_pred, none) DEF_SVE_FUNCTION (svrevb, unary, hsd_integer, mxz) diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc index a40d448685d..e32f0f8f903 100644 --- a/gcc/config/aarch64/aarch64-sve-builtins.cc +++ b/gcc/config/aarch64/aarch64-sve-builtins.cc @@ -430,6 +430,12 @@ CONSTEXPR const group_suffix_info group_suffixes[] = { TYPES_reinterpret1 (D, u32), \ TYPES_reinterpret1 (D, u64) +/* _b_c + _c_b. */ +#define TYPES_reinterpret_b(S, D) \ + D (b, c), \ + D (c, b) + /* { _b8 _b16 _b32 _b64 } x { _s32 _s64 } { _u32 _u64 } */ #define TYPES_while1(D, bn) \ @@ -579,6 +585,7 @@ DEF_SVE_TYPES_ARRAY (cvt_narrow_s); DEF_SVE_TYPES_ARRAY (cvt_narrow); DEF_SVE_TYPES_ARRAY (inc_dec_n); DEF_SVE_TYPES_ARRAY (reinterpret); +DEF_SVE_TYPES_ARRAY (reinterpret_b); DEF_SVE_TYPES_ARRAY (while); DEF_SVE_TYPES_ARRAY (all_za); DEF_SVE_TYPES_ARRAY (d_za); @@ -3789,6 +3796,49 @@ function_expander::expand () return base->expand (*this); } +/* Return a structure type that contains a single field of type FIELD_TYPE. + The field is called __val, but that's an internal detail rather than + an exposed part of the API. */ +static tree +wrap_type_in_struct (tree field_type) +{ + tree field = build_decl (input_location, FIELD_DECL, + get_identifier ("__val"), field_type); + tree struct_type = lang_hooks.types.make_type (RECORD_TYPE); + DECL_FIELD_CONTEXT (field) = struct_type; + TYPE_FIELDS (struct_type) = field; + make_type_sizeless (struct_type); + layout_type (struct_type); + return struct_type; +} + +/* Register a built-in TYPE_DECL called NAME for TYPE. This is used/needed + when TYPE is a structure type. */ +static void +register_type_decl (tree type, const char *name) +{ + tree decl = build_decl (input_location, TYPE_DECL, + get_identifier (name), type); + TYPE_NAME (type) = decl; + TYPE_STUB_DECL (type) = decl; + lang_hooks.decls.pushdecl (decl); + /* ??? Undo the effect of set_underlying_type for C. The C frontend + doesn't recognize DECL as a built-in because (as intended) the decl has + a real location instead of BUILTINS_LOCATION. The frontend therefore + treats the decl like a normal C "typedef struct foo foo;", expecting + the type for tag "struct foo" to have a dummy unnamed TYPE_DECL instead + of the named one we attached above. It then sets DECL_ORIGINAL_TYPE + on the supposedly unnamed decl, creating a circularity that upsets + dwarf2out. + + We don't want to follow the normal C model and create "struct foo" + tags for tuple types since (a) the types are supposed to be opaque + and (b) they couldn't be defined as a real struct anyway. Treating + the TYPE_DECLs as "typedef struct foo foo;" without creating + "struct foo" would lead to confusing error messages. */ + DECL_ORIGINAL_TYPE (decl) = NULL_TREE; +} + /* Register the built-in SVE ABI types, such as __SVBool_t. */ static void register_builtin_types () @@ -3799,48 +3849,63 @@ register_builtin_types () for (unsigned int i = 0; i < NUM_VECTOR_TYPES; ++i) { - tree eltype = scalar_types[i]; tree vectype; unsigned int num_zr = 0, num_pr = 0; - if (eltype == boolean_type_node) + if (vector_type_index (i) == VECTOR_TYPE_svcount_t) { - vectype = build_truth_vector_type_for_mode (BYTES_PER_SVE_VECTOR, - VNx16BImode); - gcc_assert (TYPE_MODE (vectype) == VNx16BImode - && TYPE_MODE (vectype) == TYPE_MODE_RAW (vectype) - && TYPE_ALIGN (vectype) == 16 - && known_eq (wi::to_poly_offset (TYPE_SIZE (vectype)), - BYTES_PER_SVE_VECTOR)); + vectype = abi_vector_types[VECTOR_TYPE_svbool_t]; + vectype = wrap_type_in_struct (vectype); num_pr = 1; } else { - scalar_mode elmode = SCALAR_TYPE_MODE (eltype); - unsigned int elbytes = GET_MODE_SIZE (elmode); - poly_uint64 nunits = exact_div (BYTES_PER_SVE_VECTOR, elbytes); - machine_mode mode - = aarch64_sve_data_mode (elmode, nunits).require (); - vectype = build_vector_type_for_mode (eltype, mode); - gcc_assert (VECTOR_MODE_P (TYPE_MODE (vectype)) - && TYPE_MODE (vectype) == mode - && TYPE_MODE_RAW (vectype) == mode - && TYPE_ALIGN (vectype) == 128 - && known_eq (wi::to_poly_offset (TYPE_SIZE (vectype)), - BITS_PER_SVE_VECTOR)); - num_zr = 1; + tree eltype = scalar_types[i]; + if (eltype == boolean_type_node) + { + vectype = build_truth_vector_type_for_mode (BYTES_PER_SVE_VECTOR, + VNx16BImode); + num_pr = 1; + } + else + { + scalar_mode elmode = SCALAR_TYPE_MODE (eltype); + unsigned int elbytes = GET_MODE_SIZE (elmode); + poly_uint64 nunits = exact_div (BYTES_PER_SVE_VECTOR, elbytes); + machine_mode mode + = aarch64_sve_data_mode (elmode, nunits).require (); + vectype = build_vector_type_for_mode (eltype, mode); + auto size = wi::to_poly_offset (TYPE_SIZE (vectype)); + gcc_assert (VECTOR_MODE_P (TYPE_MODE (vectype)) + && TYPE_MODE (vectype) == mode + && TYPE_MODE_RAW (vectype) == mode + && TYPE_ALIGN (vectype) == 128 + && known_eq (size, BITS_PER_SVE_VECTOR)); + num_zr = 1; + } + vectype = build_distinct_type_copy (vectype); + gcc_assert (vectype == TYPE_MAIN_VARIANT (vectype)); + SET_TYPE_STRUCTURAL_EQUALITY (vectype); + TYPE_ARTIFICIAL (vectype) = 1; + TYPE_INDIVISIBLE_P (vectype) = 1; + make_type_sizeless (vectype); + } + if (num_pr) + { + auto size = wi::to_poly_offset (TYPE_SIZE (vectype)); + gcc_assert (TYPE_MODE (vectype) == VNx16BImode + && TYPE_MODE (vectype) == TYPE_MODE_RAW (vectype) + && TYPE_ALIGN (vectype) == 16 + && known_eq (size, BYTES_PER_SVE_VECTOR)); } - vectype = build_distinct_type_copy (vectype); - gcc_assert (vectype == TYPE_MAIN_VARIANT (vectype)); - SET_TYPE_STRUCTURAL_EQUALITY (vectype); - TYPE_ARTIFICIAL (vectype) = 1; - TYPE_INDIVISIBLE_P (vectype) = 1; add_sve_type_attribute (vectype, num_zr, num_pr, vector_types[i].mangled_name, vector_types[i].acle_name); - make_type_sizeless (vectype); abi_vector_types[i] = vectype; - lang_hooks.types.register_builtin_type (vectype, - vector_types[i].abi_name); + if (TREE_CODE (vectype) == RECORD_TYPE) + register_type_decl (vectype, vector_types[i].abi_name); + else + lang_hooks.types.register_builtin_type (vectype, + vector_types[i].abi_name); } } @@ -3884,8 +3949,6 @@ register_vector_type (vector_type_index type) static void register_tuple_type (unsigned int num_vectors, vector_type_index type) { - tree tuple_type = lang_hooks.types.make_type (RECORD_TYPE); - /* Work out the structure name. */ char buffer[sizeof ("svbfloat16x4_t")]; const char *vector_type_name = vector_types[type].acle_name; @@ -3912,37 +3975,13 @@ register_tuple_type (unsigned int num_vectors, vector_type_index type) && TYPE_MODE_RAW (array_type) == TYPE_MODE (array_type) && TYPE_ALIGN (array_type) == 128); - tree field = build_decl (input_location, FIELD_DECL, - get_identifier ("__val"), array_type); - DECL_FIELD_CONTEXT (field) = tuple_type; - TYPE_FIELDS (tuple_type) = field; + tree tuple_type = wrap_type_in_struct (array_type); add_sve_type_attribute (tuple_type, num_vectors, 0, NULL, buffer); - make_type_sizeless (tuple_type); - layout_type (tuple_type); gcc_assert (VECTOR_MODE_P (TYPE_MODE (tuple_type)) && TYPE_MODE_RAW (tuple_type) == TYPE_MODE (tuple_type) && TYPE_ALIGN (tuple_type) == 128); - tree decl = build_decl (input_location, TYPE_DECL, - get_identifier (buffer), tuple_type); - TYPE_NAME (tuple_type) = decl; - TYPE_STUB_DECL (tuple_type) = decl; - lang_hooks.decls.pushdecl (decl); - /* ??? Undo the effect of set_underlying_type for C. The C frontend - doesn't recognize DECL as a built-in because (as intended) the decl has - a real location instead of BUILTINS_LOCATION. The frontend therefore - treats the decl like a normal C "typedef struct foo foo;", expecting - the type for tag "struct foo" to have a dummy unnamed TYPE_DECL instead - of the named one we attached above. It then sets DECL_ORIGINAL_TYPE - on the supposedly unnamed decl, creating a circularity that upsets - dwarf2out. - - We don't want to follow the normal C model and create "struct foo" - tags for tuple types since (a) the types are supposed to be opaque - and (b) they couldn't be defined as a real struct anyway. Treating - the TYPE_DECLs as "typedef struct foo foo;" without creating - "struct foo" would lead to confusing error messages. */ - DECL_ORIGINAL_TYPE (decl) = NULL_TREE; + register_type_decl (tuple_type, buffer); acle_vector_types[num_vectors - 1][type] = tuple_type; } @@ -3992,7 +4031,7 @@ handle_arm_sve_h () { vector_type_index type = vector_type_index (type_i); register_vector_type (type); - if (type != VECTOR_TYPE_svbool_t) + if (scalar_types[type_i] != boolean_type_node) for (unsigned int count = 2; count <= MAX_TUPLE_SIZE; ++count) register_tuple_type (count, type); } diff --git a/gcc/config/aarch64/aarch64-sve-builtins.def b/gcc/config/aarch64/aarch64-sve-builtins.def index 5824dc797f9..297904f3e47 100644 --- a/gcc/config/aarch64/aarch64-sve-builtins.def +++ b/gcc/config/aarch64/aarch64-sve-builtins.def @@ -84,6 +84,7 @@ DEF_SVE_MODE (u64offset, none, svuint64_t, bytes) DEF_SVE_MODE (vnum, none, none, vectors) DEF_SVE_TYPE (svbool_t, 10, __SVBool_t, boolean_type_node) +DEF_SVE_TYPE (svcount_t, 11, __SVCount_t, boolean_type_node) DEF_SVE_TYPE (svbfloat16_t, 14, __SVBfloat16_t, bfloat16_type_node) DEF_SVE_TYPE (svfloat16_t, 13, __SVFloat16_t, aarch64_fp16_type_node) DEF_SVE_TYPE (svfloat32_t, 13, __SVFloat32_t, float_type_node) @@ -106,6 +107,7 @@ DEF_SVE_TYPE_SUFFIX (b16, svbool_t, bool, 16, VNx8BImode) DEF_SVE_TYPE_SUFFIX (b32, svbool_t, bool, 32, VNx4BImode) DEF_SVE_TYPE_SUFFIX (b64, svbool_t, bool, 64, VNx2BImode) DEF_SVE_TYPE_SUFFIX (bf16, svbfloat16_t, bfloat, 16, VNx8BFmode) +DEF_SVE_TYPE_SUFFIX (c, svcount_t, count, 8, VNx16BImode) DEF_SVE_TYPE_SUFFIX (f16, svfloat16_t, float, 16, VNx8HFmode) DEF_SVE_TYPE_SUFFIX (f32, svfloat32_t, float, 32, VNx4SFmode) DEF_SVE_TYPE_SUFFIX (f64, svfloat64_t, float, 64, VNx2DFmode) diff --git a/gcc/config/aarch64/aarch64-sve-builtins.h b/gcc/config/aarch64/aarch64-sve-builtins.h index 1cd31d2d733..51774825c23 100644 --- a/gcc/config/aarch64/aarch64-sve-builtins.h +++ b/gcc/config/aarch64/aarch64-sve-builtins.h @@ -152,11 +152,13 @@ enum predication_index }; /* Classifies element types, based on type suffixes with the bit count - removed. */ + removed. "count" isn't really an element type, but we pretend it is + for consistency. */ enum type_class_index { TYPE_bool, TYPE_bfloat, + TYPE_count, TYPE_float, TYPE_signed, TYPE_unsigned, diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/mangle_1.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/mangle_1.C index 36dab3c9b71..2ad0c7f9838 100644 --- a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/mangle_1.C +++ b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/mangle_1.C @@ -15,6 +15,7 @@ void f10(svfloat16_t) {} void f11(svfloat32_t) {} void f12(svfloat64_t) {} void f13(svbfloat16_t) {} +void f14(svcount_t) {} /* { dg-final { scan-assembler "_Z2f1u10__SVBool_t:" } } */ /* { dg-final { scan-assembler "_Z2f2u10__SVInt8_t:" } } */ @@ -29,3 +30,4 @@ void f13(svbfloat16_t) {} /* { dg-final { scan-assembler "_Z3f11u13__SVFloat32_t:" } } */ /* { dg-final { scan-assembler "_Z3f12u13__SVFloat64_t:" } } */ /* { dg-final { scan-assembler "_Z3f13u14__SVBfloat16_t:" } } */ +/* { dg-final { scan-assembler "_Z3f14u11__SVCount_t:" } } */ diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/mangle_2.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/mangle_2.C index ad4aaee291f..c8bfcc5a9c2 100644 --- a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/mangle_2.C +++ b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/mangle_2.C @@ -13,6 +13,7 @@ void f10(__SVFloat16_t) {} void f11(__SVFloat32_t) {} void f12(__SVFloat64_t) {} void f13(__SVBfloat16_t) {} +void f14(__SVCount_t) {} /* { dg-final { scan-assembler "_Z2f1u10__SVBool_t:" } } */ /* { dg-final { scan-assembler "_Z2f2u10__SVInt8_t:" } } */ @@ -27,3 +28,4 @@ void f13(__SVBfloat16_t) {} /* { dg-final { scan-assembler "_Z3f11u13__SVFloat32_t:" } } */ /* { dg-final { scan-assembler "_Z3f12u13__SVFloat64_t:" } } */ /* { dg-final { scan-assembler "_Z3f13u14__SVBfloat16_t:" } } */ +/* { dg-final { scan-assembler "_Z3f14u11__SVCount_t:" } } */ diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/svcount_1.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/svcount_1.C new file mode 100644 index 00000000000..9eac65aafff --- /dev/null +++ b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/svcount_1.C @@ -0,0 +1,10 @@ +#include + +svbool_t f1 (svcount_t x) { return x; } // { dg-error {cannot convert 'svcount_t' to 'svbool_t' in return} } +svcount_t f2 (svbool_t x) { return x; } // { dg-error {cannot convert 'svbool_t' to 'svcount_t' in return} } +void f3 (svbool_t *p, svcount_t x) { *p = x; } // { dg-error {cannot convert 'svcount_t' to 'svbool_t' in assignment} } +void f4 (svcount_t *p, svbool_t x) { *p = x; } // { dg-error {cannot convert 'svbool_t' to 'svcount_t' in assignment} } +svbool_t *f5 (svcount_t *p) { return p; } // { dg-error {cannot convert} } +svcount_t *f6 (svbool_t *p) { return p; } // { dg-error {cannot convert} } +svbool_t f7 (svcount_t x) { return (svbool_t) x; } // { dg-error {invalid cast from type 'svcount_t' to type 'svbool_t'} } +svcount_t f8 (svbool_t x) { return (svcount_t) x; } // { dg-error {invalid cast from type 'svbool_t' to type 'svcount_t'} } diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_b.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_b.c new file mode 100644 index 00000000000..57736ecb6c2 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_b.c @@ -0,0 +1,20 @@ +/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */ + +#include "test_sve_acle.h" + +/* +** reinterpret_b_c_tied1: +** ret +*/ +TEST_DUAL_P_REV (reinterpret_b_c_tied1, svbool_t, svcount_t, + p0_res = svreinterpret_b_c (p0), + p0_res = svreinterpret_b (p0)) + +/* +** reinterpret_b_c_untied: +** mov p0\.b, p2\.b +** ret +*/ +TEST_DUAL_P (reinterpret_b_c_untied, svbool_t, svcount_t, + p0 = svreinterpret_b_c (p2), + p0 = svreinterpret_b (p2)) diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/test_sve_acle.h b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/test_sve_acle.h index 84925b9bd48..5ce0be5947b 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/test_sve_acle.h +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/test_sve_acle.h @@ -85,6 +85,21 @@ return z0_res; \ } +#define TEST_DUAL_P(NAME, TYPE1, TYPE2, CODE1, CODE2) \ + PROTO (NAME, TYPE1, (TYPE1 p0, TYPE1 p1, TYPE2 p2, TYPE2 p3)) \ + { \ + INVOKE (CODE1, CODE2); \ + return p0; \ + } + +#define TEST_DUAL_P_REV(NAME, TYPE1, TYPE2, CODE1, CODE2) \ + PROTO (NAME, TYPE1, (TYPE2 p0, TYPE2 p1, TYPE1 p2, TYPE1 p3)) \ + { \ + TYPE1 p0_res; \ + INVOKE (CODE1, CODE2); \ + return p0_res; \ + } + #define TEST_TRIPLE_Z(NAME, TYPE1, TYPE2, TYPE3, CODE1, CODE2) \ PROTO (NAME, TYPE1, (TYPE1 z0, TYPE1 z1, TYPE2 z2, TYPE2 z3, \ TYPE3 z4, TYPE3 z5, \ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_1.c index 784fdc317e6..564295a87f3 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_1.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_1.c @@ -6,12 +6,14 @@ struct s { signed char x; }; svuint8_t -f1 (svbool_t pg, signed char *s8_ptr, void *void_ptr, struct s *s_ptr, +f1 (svbool_t pg, svcount_t pn, + signed char *s8_ptr, void *void_ptr, struct s *s_ptr, float *f32_ptr, _Complex float *cf32_ptr, int **ptr_ptr) { svld1 (pg); /* { dg-error {too few arguments to function 'svld1'} } */ svld1 (pg, s8_ptr, 0); /* { dg-error {too many arguments to function 'svld1'} } */ svld1 (0, s8_ptr); /* { dg-error {passing 'int' to argument 1 of 'svld1', which expects 'svbool_t'} } */ + svld1 (pn, s8_ptr); /* { dg-error {passing 'svcount_t' to argument 1 of 'svld1', which expects 'svbool_t'} } */ svld1 (pg, 0); /* { dg-error {passing 'int' to argument 2 of 'svld1', which expects a pointer type} } */ svld1 (pg, (int32_t *) 0); svld1 (pg, void_ptr); /* { dg-error {passing 'void \*' to argument 2 of 'svld1', but 'void' is not a valid SVE element type} } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/svcount_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/svcount_1.c new file mode 100644 index 00000000000..920d37e4ce7 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/svcount_1.c @@ -0,0 +1,10 @@ +#include + +svbool_t f1 (svcount_t x) { return x; } /* { dg-error {incompatible types} } */ +svcount_t f2 (svbool_t x) { return x; } /* { dg-error {incompatible types} } */ +void f3 (svbool_t *p, svcount_t x) { *p = x; } /* { dg-error {incompatible types} } */ +void f4 (svcount_t *p, svbool_t x) { *p = x; } /* { dg-error {incompatible types} } */ +svbool_t *f5 (svcount_t *p) { return p; } /* { dg-error {incompatible return type} } */ +svcount_t *f6 (svbool_t *p) { return p; } /* { dg-error {incompatible return type} } */ +svbool_t f7 (svcount_t x) { return (svbool_t) x; } /* { dg-error {conversion to non-scalar} } */ +svcount_t f8 (svbool_t x) { return (svcount_t) x; } /* { dg-error {conversion to non-scalar} } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_convert_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_convert_1.c index f59ad590ba4..b7258e434db 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_convert_1.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_convert_1.c @@ -4,7 +4,7 @@ void test (svbool_t pg, svint8_t s8, svuint8_t u8, svint16_t s16, svuint16_t u16, svint32_t s32, svuint32_t u32, svint64_t s64, svuint64_t u64, svfloat16_t f16, svfloat32_t f32, - svfloat64_t f64) + svfloat64_t f64, svcount_t pn) { svcvt_f64_x (pg); /* { dg-error {too few arguments to function 'svcvt_f64_x'} } */ svcvt_f64_x (pg, s32, 0); /* { dg-error {too many arguments to function 'svcvt_f64_x'} } */ @@ -70,4 +70,10 @@ test (svbool_t pg, svint8_t s8, svuint8_t u8, svcvt_u16_x (pg, f16); svcvt_u16_x (pg, f32); /* { dg-error {'svcvt_u16_x' has no form that takes 'svfloat32_t' arguments} } */ svcvt_u16_x (pg, f64); /* { dg-error {'svcvt_u16_x' has no form that takes 'svfloat64_t' arguments} } */ + + svreinterpret_b (pg); /* { dg-error {'svreinterpret_b' has no form that takes 'svbool_t' arguments} } */ + svreinterpret_b (pn); + + svreinterpret_c (pg); + svreinterpret_c (pn); /* { dg-error {'svreinterpret_c' has no form that takes 'svcount_t' arguments} } */ } diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_7.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_7.c index 5658a206fa3..edfadb8da38 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_7.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_7.c @@ -27,6 +27,7 @@ typedef svint32x2_t bad_type_6 __attribute__ ((arm_sve_vector_bits (N))); // { d typedef svint8_t bad_type_7 __attribute__ ((arm_sve_vector_bits (N))) __attribute__ ((arm_sve_vector_bits (N))); // { dg-error {'arm_sve_vector_bits' applied to type 'svint8_t __attribute__\(\(arm_sve_vector_bits\([0-9]+\)\)\)', which already has a size} } typedef fixed_bool_t bad_type_8 __attribute__ ((arm_sve_vector_bits (N))) __attribute__ ((arm_sve_vector_bits (N))); // { dg-error {'arm_sve_vector_bits' applied to type 'fixed_bool_t' {aka 'svbool_t __attribute__\(\(arm_sve_vector_bits\([0-9]+\)\)\)'}, which already has a size} } typedef gnu_int8_t bad_type_9 __attribute__ ((arm_sve_vector_bits (N))) __attribute__ ((arm_sve_vector_bits (N))); // { dg-error {'arm_sve_vector_bits' applied to non-SVE type 'gnu_int8_t'} } +typedef svcount_t bad_type_10 __attribute__ ((arm_sve_vector_bits (N))); // { dg-error {'arm_sve_vector_bits' applied to non-vector type 'svcount_t'} } void f (int c) diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/annotate_1.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/annotate_1.c index 12ae7678948..c3ac692d7ff 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/annotate_1.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/annotate_1.c @@ -4,6 +4,8 @@ svbool_t ret_b (void) { return svptrue_b8 (); } +svcount_t ret_c (svcount_t *ptr) { return *ptr; } + svint8_t ret_s8 (void) { return svdup_s8 (0); } svint16_t ret_s16 (void) { return svdup_s16 (0); } svint32_t ret_s32 (void) { return svdup_s32 (0); } @@ -58,6 +60,8 @@ svfloat64x4_t ret_f64x4 (void) { return svundef4_f64 (); } /* { dg-final { scan-assembler {\t\.variant_pcs\tret_b\n} } } */ +/* { dg-final { scan-assembler {\t\.variant_pcs\tret_c\n} } } */ + /* { dg-final { scan-assembler {\t\.variant_pcs\tret_s8\n} } } */ /* { dg-final { scan-assembler {\t\.variant_pcs\tret_s16\n} } } */ /* { dg-final { scan-assembler {\t\.variant_pcs\tret_s32\n} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/annotate_2.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/annotate_2.c index 9f0741e3c26..c3508735fc4 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/annotate_2.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/annotate_2.c @@ -4,6 +4,8 @@ void fn_b (svbool_t x) {} +void fn_c (svcount_t x) {} + void fn_s8 (svint8_t x) {} void fn_s16 (svint16_t x) {} void fn_s32 (svint32_t x) {} @@ -58,6 +60,8 @@ void fn_f64x4 (svfloat64x4_t x) {} /* { dg-final { scan-assembler {\t\.variant_pcs\tfn_b\n} } } */ +/* { dg-final { scan-assembler {\t\.variant_pcs\tfn_c\n} } } */ + /* { dg-final { scan-assembler {\t\.variant_pcs\tfn_s8\n} } } */ /* { dg-final { scan-assembler {\t\.variant_pcs\tfn_s16\n} } } */ /* { dg-final { scan-assembler {\t\.variant_pcs\tfn_s32\n} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/args_12.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/args_12.c new file mode 100644 index 00000000000..a589484b394 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/args_12.c @@ -0,0 +1,214 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fno-stack-clash-protection -g" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include + +/* +** callee_1: +** mov p0\.b, p3\.b +** ret +*/ +svcount_t __attribute__ ((noipa)) +callee_1 (svcount_t p0, svcount_t p1, svcount_t p2, svcount_t p3) +{ + return p3; +} + +/* +** callee_2: +** str p0, \[x0\] +** str p1, \[x1\] +** str p2, \[x2\] +** str p3, \[x3\] +** ret +*/ +void __attribute__ ((noipa)) +callee_2 (svcount_t p0, svcount_t p1, svcount_t p2, svcount_t p3, + svcount_t *ptr0, svcount_t *ptr1, svcount_t *ptr2, svcount_t *ptr3) +{ + *ptr0 = p0; + *ptr1 = p1; + *ptr2 = p2; + *ptr3 = p3; +} + +/* +** callee_3: +** str p3, \[x0\] +** ret +*/ +void __attribute__ ((noipa)) +callee_3 (svbool_t p0, svbool_t p1, svbool_t p2, svcount_t p3, svcount_t *ptr) +{ + *ptr = p3; +} + +/* +** callee_4: +** str p3, \[x0\] +** ret +*/ +void __attribute__ ((noipa)) +callee_4 (svcount_t p0, svcount_t p1, svcount_t p2, svbool_t p3, svbool_t *ptr) +{ + *ptr = p3; +} + +/* +** callee_5: +** ldr p0, \[x0\] +** ret +*/ +svcount_t __attribute__ ((noipa)) +callee_5 (svcount_t p0, svcount_t p1, svcount_t p2, svcount_t p3, + svcount_t p4) +{ + return p4; +} + +/* +** callee_6: +** ldr p0, \[x0\] +** ret +*/ +svcount_t __attribute__ ((noipa)) +callee_6 (svcount_t p0, svcount_t p1, svcount_t p2, svcount_t p3, + svcount_t p4, int x1, int x2, int x3, int x4, int x5, int x6, int x7, + int x8) +{ + return p4; +} + +/* +** callee_7: +** ldr (x[0-9]+), \[sp\] +** ldr p0, \[\1\] +** ret +*/ +svcount_t __attribute__ ((noipa)) +callee_7 (svcount_t p0, svcount_t p1, svcount_t p2, svcount_t p3, + int x0, int x1, int x2, int x3, int x4, int x5, int x6, int x7, + svcount_t p4) +{ + return p4; +} + +/* +** caller_1: +** ... +** ldr p0, \[x0\] +** ldr p1, \[x1\] +** ldr p2, \[x2\] +** ldr p3, \[x3\] +** bl callee_1 +** ... +** str p0, .* +** ... +*/ +void __attribute__ ((noipa)) +caller_1 (volatile svcount_t *ptr0, volatile svcount_t *ptr1, + volatile svcount_t *ptr2, volatile svcount_t *ptr3, + svcount_t *ptr4) +{ + svcount_t p0 = *ptr0; + svcount_t p1 = *ptr1; + svcount_t p2 = *ptr2; + svcount_t p3 = *ptr3; + *ptr4 = callee_1 (p0, p1, p2, p3); +} + +/* +** caller_3: +** ... +** ldr p0, \[x1\] +** ldr p1, \[x2\] +** ldr p2, \[x3\] +** ldr p3, \[x4\] +** bl callee_3 +** ... +*/ +void __attribute__ ((noipa)) +caller_3 (svcount_t *ptr, + volatile svbool_t *ptr0, volatile svbool_t *ptr1, + volatile svbool_t *ptr2, volatile svcount_t *ptr3) +{ + svbool_t p0 = *ptr0; + svbool_t p1 = *ptr1; + svbool_t p2 = *ptr2; + svcount_t p3 = *ptr3; + callee_3 (p0, p1, p2, p3, ptr); +} + +/* +** caller_4: +** ... +** ldr p0, \[x1\] +** ldr p1, \[x2\] +** ldr p2, \[x3\] +** ldr p3, \[x4\] +** bl callee_4 +** ... +*/ +void __attribute__ ((noipa)) +caller_4 (svbool_t *ptr, + volatile svcount_t *ptr0, volatile svcount_t *ptr1, + volatile svcount_t *ptr2, volatile svbool_t *ptr3) +{ + svcount_t p0 = *ptr0; + svcount_t p1 = *ptr1; + svcount_t p2 = *ptr2; + svbool_t p3 = *ptr3; + callee_4 (p0, p1, p2, p3, ptr); +} + +/* +** caller_5: +** ... +** ldr p0, \[x1\] +** ldr p1, \[x2\] +** ldr p2, \[x3\] +** ldr p3, \[x4\] +** ... +** mov x0, sp +** ... +** str p[0-9]+, \[(?:x0|sp)\] +** ... +** bl callee_5 +** ... +** str p0, .* +** ... +*/ +void __attribute__ ((noipa)) +caller_5 (svcount_t *ptr, + volatile svcount_t *ptr0, volatile svcount_t *ptr1, + volatile svcount_t *ptr2, volatile svcount_t *ptr3, + volatile svcount_t *ptr4) +{ + svcount_t p0 = *ptr0; + svcount_t p1 = *ptr1; + svcount_t p2 = *ptr2; + svcount_t p3 = *ptr3; + svcount_t p4 = *ptr4; + *ptr = callee_5 (p0, p1, p2, p3, p4); +} + +/* +** caller_7: +** ... +** ldr (p[0-9]+), \[x2\] +** ... +** str \1, \[(x[0-9]+)\] +** ... +** str \2, \[sp\] +** ... +** bl callee_7 +** ... +*/ +void __attribute__ ((noipa)) +caller_7 (svcount_t *ptr, volatile svcount_t *ptr0, volatile svcount_t *ptr1) +{ + svcount_t p0 = *ptr0; + svcount_t p1 = *ptr1; + *ptr = callee_7 (p0, p0, p0, p0, 0, 0, 0, 0, 0, 0, 0, 0, p1); +} -- 2.25.1