Tejas Belagod <tejas.bela...@arm.com> writes: > On 11/7/24 4:52 PM, Richard Sandiford wrote: >> Tejas Belagod <tejas.bela...@arm.com> writes: >>> This patch adds a test case to cover C/C++ operators on SVE ACLE types. >>> This >>> does not cover all types, but covers most representative types. >>> >>> gcc/testsuite: >>> >>> * gcc.target/aarch64/sve/acle/general/cops.c: New test. >>> --- >>> .../aarch64/sve/acle/general/cops.c | 570 ++++++++++++++++++ >>> 1 file changed, 570 insertions(+) >>> create mode 100644 >>> gcc/testsuite/gcc.target/aarch64/sve/acle/general/cops.c >>> >>> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cops.c >>> b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cops.c >>> new file mode 100644 >>> index 00000000000..28da602301e >>> --- /dev/null >>> +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cops.c >>> @@ -0,0 +1,570 @@ >>> +/* { dg-do run { target aarch64_sve_hw } } */ >>> +/* { dg-options "-O2" } */ >>> + >>> +#include <arm_sve.h> >>> +#include <stdio.h> >>> + >>> +#define DECL_FUNC_UNARY(type, name, op, intr, su, sz, id) \ >>> + __attribute__ ((noipa)) \ >>> + type func_ ## name ## type ## _unary (type a) { \ >>> + return op (a); \ >>> + } \ >>> + void checkfunc_ ## name ## type ## _unary () { \ >>> + type data = svindex_ ## su ## sz (0, 1); \ >>> + type zr = svindex_ ## su ## sz (0, 0); \ >>> + type one = svindex_ ## su ## sz (1, 0); \ >>> + type mone = svindex_ ## su ## sz (-1, 0); \ >>> + svbool_t pg = svptrue_b ## sz (); \ >>> + type exp = intr ## su ## sz ## _z (pg, id, data); \ >>> + type actual = func_ ## name ## type ## _unary (data); \ >>> + svbool_t res = svcmpeq_ ## su ## sz (pg, exp, actual); \ >>> + if (svptest_any (pg, svnot_b_z (pg, res))) \ >>> + __builtin_abort (); \ >>> + } >>> + >>> +#define DECL_FUNC_UNARY_FLOAT(type, name, op, intr, su, sz, id) \ >>> + __attribute__ ((noipa)) \ >>> + type func_ ## name ## type ## _unary (type a) { \ >>> + return op (a); \ >>> + } \ >>> + void checkfunc_ ## name ## type ## _unary () { \ >>> + type data = svdup_n_ ## su ## sz (2.0); \ >>> + type zr = svdup_n_ ## su ## sz (0.0); \ >>> + type one = svdup_n_ ## su ## sz (1.0); \ >>> + type mone = svdup_n_ ## su ## sz (-1.0); \ >>> + svbool_t pg = svptrue_b ## sz (); \ >>> + type exp = intr ## su ## sz ## _z (pg, id, data); \ >>> + type actual = func_ ## name ## type ## _unary (data); \ >>> + svbool_t res = svcmpeq_ ## su ## sz (pg, exp, actual); \ >>> + if (svptest_any (pg, svnot_b_z (pg, res))) \ >>> + __builtin_abort (); \ >>> + } >>> + >>> +#define DECL_FUNC_INDEX(rtype, type, intr, su, sz) \ >>> + __attribute__ ((noipa)) \ >>> + rtype func_ ## rtype ## type ## _vindex (type a, int n) { \ >>> + return (a[n]); \ >>> + } \ >>> + __attribute__ ((noipa)) \ >>> + rtype func_ ## rtype ## type ## _cindex (type a) { \ >>> + return (a[0]); \ >>> + } \ >>> + void checkfunc_ ## rtype ## type ## _vindex () { \ >>> + type a = svindex_ ## su ## sz (0, 1); \ >>> + int n = 2; \ >>> + if (2 != func_ ## rtype ## type ## _vindex (a, n)) \ >>> + __builtin_abort (); \ >>> + } \ >>> + void checkfunc_ ## rtype ## type ## _cindex () { \ >>> + type a = svindex_ ## su ## sz (1, 0); \ >>> + if (1 != func_ ## rtype ## type ## _cindex (a)) \ >>> + __builtin_abort (); \ >>> + } >>> + >>> +#define DECL_FUNC_INDEX_FLOAT(rtype, type, intr, su, sz) \ >>> + __attribute__ ((noipa)) \ >>> + rtype func_ ## rtype ## type ## _vindex (type a, int n) { \ >>> + return (a[n]); \ >>> + } \ >>> + __attribute__ ((noipa)) \ >>> + rtype func_ ## rtype ## type ## _cindex (type a) { \ >>> + return (a[0]); \ >>> + } \ >>> + void checkfunc_ ## rtype ## type ## _vindex () { \ >>> + type a = svdup_n_ ## su ## sz (2.0); \ >>> + int n = 2; \ >>> + if (2.0 != func_ ## rtype ## type ## _vindex (a, n)) \ >>> + __builtin_abort (); \ >>> + } \ >>> + void checkfunc_ ## rtype ## type ## _cindex () { \ >>> + type a = svdup_n_ ## su ## sz (4.0); \ >>> + if (4.0 != func_ ## rtype ## type ## _cindex (a)) \ >>> + __builtin_abort (); \ >>> + } >>> + >>> +#define DECL_FUNC_BINARY(type, name, op, intr, su, sz) \ >>> + __attribute__ ((noipa)) \ >>> + type func_ ## name ## type ## _binary(type a, type b) { \ >>> + return (a) op (b); \ >>> + } \ >>> + void checkfunc_ ## name ## type ## _binary () { \ >>> + type a = svindex_ ## su ## sz (0, 1); \ >>> + type b = svindex_ ## su ## sz (0, 2); \ >>> + svbool_t all_true = svptrue_b ## sz (); \ >>> + type exp = intr ## su ## sz ## _z (all_true, a, b); \ >>> + type actual = func_ ## name ## type ## _binary (a, b); \ >>> + svbool_t res = svcmpeq_ ## su ## sz (all_true, exp, actual); \ >>> + if (svptest_any (all_true, svnot_b_z (all_true, res))) \ >>> + __builtin_abort (); \ >>> + } >>> + >>> +#define DECL_FUNC_BINARY_SHIFT(type, name, op, intr, su, sz) \ >>> + __attribute__ ((noipa)) \ >>> + type func_ ## name ## type ## _binary(type a, type b) { \ >>> + return (a) op (b); \ >>> + } \ >>> + void checkfunc_ ## name ## type ## _binary () { \ >>> + type a = svindex_ ## su ## sz (0, 1); \ >>> + svuint ## sz ## _t b = svindex_u ## sz (0, 2); \ >>> + type c = svindex_ ## su ## sz (0, 2); \ >>> + svbool_t all_true = svptrue_b ## sz (); \ >>> + type exp = intr ## su ## sz ## _z (all_true, a, b); \ >>> + type actual = func_ ## name ## type ## _binary (a, c); \ >>> + svbool_t res = svcmpeq_ ## su ## sz (all_true, exp, actual); \ >>> + if (svptest_any (all_true, svnot_b_z (all_true, res))) \ >>> + __builtin_abort (); \ >>> + } >>> + >>> +#define DECL_FUNC_BINARY_FLOAT(type, name, op, intr, su, sz) \ >>> + __attribute__ ((noipa)) \ >>> + type func_ ## name ## type ## _binary(type a, type b) { \ >>> + return (a) op (b); \ >>> + } \ >>> + void checkfunc_ ## name ## type ## _binary () { \ >>> + type a = svdup_n_ ## su ## sz (1.0); \ >>> + type b = svdup_n_ ## su ## sz (2.0); \ >>> + svbool_t all_true = svptrue_b ## sz (); \ >>> + type exp = intr ## su ## sz ## _z (all_true, a, b); \ >>> + type actual = func_ ## name ## type ## _binary (a, b); \ >>> + svbool_t res = svcmpeq_ ## su ## sz (all_true, exp, actual); \ >>> + if (svptest_any (all_true, svnot_b_z (all_true, res))) \ >>> + __builtin_abort (); \ >>> + } >>> + >>> +#define DECL_FUNC_BINARY_CMP(type, name, op, intr, su, sz) \ >>> + __attribute__ ((noipa)) \ >>> + type func_ ## name ## type ## _binary_cmp(type a, type b) { \ >>> + return (a) op (b); \ >>> + } \ >>> + void checkfunc_ ## name ## type ## _binary_cmp () { \ >>> + type a = svindex_ ## su ## sz (0, 1); \ >>> + type b = svindex_ ## su ## sz (0, 2); \ >>> + type c = func_ ## name ## type ## _binary_cmp (a, b); \ >>> + svbool_t all_true = svptrue_b ## sz (); \ >>> + svbool_t pgc = svcmpne_n_ ## su ## sz (all_true, c, 0); \ >>> + svbool_t pg = intr ## su ## sz (all_true, a, b); \ >>> + svbool_t res = sveor_b_z (all_true, pgc, pg); \ >>> + if (svptest_any (all_true, res)) \ >>> + __builtin_abort (); \ >>> + } >>> + >>> +#define DECL_FUNC_TERNARY(type, su, sz) \ >>> + __attribute__ ((noipa)) \ >>> + type func_ ## type ## _ternary(type p, type q, type a, type b) { \ >>> + return (p >= q) ? a : b; \ >>> + } \ >>> + void checkfunc_ ## type ## _ternary() { \ >>> + type p = svindex_ ## su ## sz (0, 1); \ >>> + type q = svindex_ ## su ## sz (1, 1); \ >>> + type a = svindex_ ## su ## sz (2, 1); \ >>> + type b = svindex_ ## su ## sz (3, 1); \ >>> + svbool_t all_true = svptrue_b ## sz (); \ >>> + svbool_t cmp = svcmpge_ ## su ## sz (all_true, p, q); \ >>> + type res = svsel_ ## su ## sz (cmp, a, b); \ >>> + type actual = func_ ## type ## _ternary(p, q, a, b); \ >>> + svbool_t pgc = svcmpeq_ ## su ## sz (all_true, res, actual); \ >>> + if (svptest_any (all_true, svnot_b_z (all_true, pgc))) \ >>> + __builtin_abort (); \ >>> + } >>> + >>> +#define VECT_CST_s8 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, >>> 15 } >>> +#define VECT_CST_s16 { 0, 1, 2, 3, 4, 5, 6, 7 } >>> +#define VECT_CST_s32 { 0, 1, 2, 3 } >>> +#define VECT_CST_s64 { 0, 1 } >>> + >>> +#define DECL_FUNC_INIT(type, su, sz, nelem) \ >>> + __attribute__ ((noipa)) \ >>> + type func_ ## type ## _init1() { \ >>> + type temp = VECT_CST_ ## su ## sz; \ >>> + return temp; \ >>> + } \ >>> + __attribute__ ((noipa)) \ >>> + type func_ ## type ## _init2() { \ >>> + type temp = { 0 }; \ >>> + return temp; \ >>> + } \ >>> + __attribute__ ((noipa)) \ >>> + type func_ ## type ## _init3() { \ >>> + type temp = { }; \ >>> + return temp; \ >>> + } \ >>> + __attribute__ ((noipa)) \ >>> + type func_ ## type ## _init4() { \ >>> + type temp = VECT_CST_ ## su ## sz; \ >>> + return temp; \ >>> + } \ >> >> It looks like init4 repeats init1. Is that intentional? > > No, this is an oversight - init1 and init4 started out as something > else, but ended up becoming the same. I'll fix it. Thanks for spotting it. > > >> >> Otherwise it looks good, although the macros are a challenge :) > > Thanks. I could expand it if that makes it easier for reviewing the code?
No, I think we should keep it as-is. (I cpp:ed it locally as a double check.) Thanks, Richard