@@ -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));
}
};
@@ -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)
@@ -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);
}
@@ -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)
@@ -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,
@@ -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:" } } */
@@ -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:" } } */
new file mode 100644
@@ -0,0 +1,10 @@
+#include <arm_sve.h>
+
+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'} }
new file mode 100644
@@ -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))
@@ -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, \
@@ -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} } */
new file mode 100644
@@ -0,0 +1,10 @@
+#include <arm_sve.h>
+
+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} } */
@@ -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} } */
}
@@ -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)
@@ -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} } } */
@@ -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} } } */
new file mode 100644
@@ -0,0 +1,214 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fno-stack-clash-protection -g" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+/*
+** 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);
+}