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

Reply via email to