From 2a380e2ed0522b30070cf0b3f730f47eb1375976 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Fri, 17 May 2019 16:02:20 +0000 Subject: [PATCH] x86-64: Add vector vararg ABI tests We can scan stack for return address to get vector arguments passed on stack. Tested on Linux/x86-64 and Linux/x32. * gcc.target/x86_64/abi/test_varargs-m128.c: New file. * gcc.target/x86_64/abi/avx/test_varargs-m256.c: Likewise. * gcc.target/x86_64/abi/avx512f/test_varargs-m512.c: Likewise. From-SVN: r271329 --- gcc/testsuite/ChangeLog | 6 + .../x86_64/abi/avx/test_varargs-m256.c | 104 +++++++++++++++++ .../x86_64/abi/avx512f/test_varargs-m512.c | 104 +++++++++++++++++ .../gcc.target/x86_64/abi/test_varargs-m128.c | 110 ++++++++++++++++++ 4 files changed, 324 insertions(+) create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/avx/test_varargs-m256.c create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/avx512f/test_varargs-m512.c create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/test_varargs-m128.c diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d60a7f4a5d0..af5de86ae15 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-05-17 H.J. Lu + + * gcc.target/x86_64/abi/test_varargs-m128.c: New file. + * gcc.target/x86_64/abi/avx/test_varargs-m256.c: Likewise. + * gcc.target/x86_64/abi/avx512f/test_varargs-m512.c: Likewise. + 2019-05-17 H.J. Lu PR target/90497 diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx/test_varargs-m256.c b/gcc/testsuite/gcc.target/x86_64/abi/avx/test_varargs-m256.c new file mode 100644 index 00000000000..0c6d61f072f --- /dev/null +++ b/gcc/testsuite/gcc.target/x86_64/abi/avx/test_varargs-m256.c @@ -0,0 +1,104 @@ +/* Test variable number of 256-bit vector arguments passed to functions. */ + +#include +#include "avx-check.h" +#include "args.h" + +struct IntegerRegisters iregs; +struct FloatRegisters fregs; + +/* This struct holds values for argument checking. */ +struct +{ + YMM_T i0, i1, i2, i3, i4, i5, i6, i7, i8, i9; +} values; + +char *pass; +int failed = 0; + +#undef assert +#define assert(c) do { \ + if (!(c)) {failed++; printf ("failed %s\n", pass); } \ +} while (0) + +#define compare(X1,X2,T) do { \ + assert (memcmp (&X1, &X2, sizeof (T)) == 0); \ +} while (0) + +void +fun_check_passing_m256_varargs (__m256 i0, __m256 i1, __m256 i2, + __m256 i3, ...) +{ + /* Check argument values. */ + void **fp = __builtin_frame_address (0); + void *ra = __builtin_return_address (0); + __m256 *argp; + + compare (values.i0, i0, __m256); + compare (values.i1, i1, __m256); + compare (values.i2, i2, __m256); + compare (values.i3, i3, __m256); + + /* Get the pointer to the return address on stack. */ + while (*fp != ra) + fp++; + + /* Skip the return address stack slot. */ + argp = (__m256 *) (((char *) fp) + 8); + + /* Check __m256 arguments passed on stack. */ + compare (values.i4, argp[0], __m256); + compare (values.i5, argp[1], __m256); + compare (values.i6, argp[2], __m256); + compare (values.i7, argp[3], __m256); + compare (values.i8, argp[4], __m256); + compare (values.i9, argp[5], __m256); + + /* Check register contents. */ + compare (fregs.ymm0, ymm_regs[0], __m256); + compare (fregs.ymm1, ymm_regs[1], __m256); + compare (fregs.ymm2, ymm_regs[2], __m256); + compare (fregs.ymm3, ymm_regs[3], __m256); +} + +#define def_check_int_passing_varargs(_i0, _i1, _i2, _i3, _i4, _i5, \ + _i6, _i7, _i8, _i9, \ + _func, TYPE) \ + values.i0.TYPE[0] = _i0; \ + values.i1.TYPE[0] = _i1; \ + values.i2.TYPE[0] = _i2; \ + values.i3.TYPE[0] = _i3; \ + values.i4.TYPE[0] = _i4; \ + values.i5.TYPE[0] = _i5; \ + values.i6.TYPE[0] = _i6; \ + values.i7.TYPE[0] = _i7; \ + values.i8.TYPE[0] = _i8; \ + values.i9.TYPE[0] = _i9; \ + clear_struct_registers; \ + fregs.F0.TYPE[0] = _i0; \ + fregs.F1.TYPE[0] = _i1; \ + fregs.F2.TYPE[0] = _i2; \ + fregs.F3.TYPE[0] = _i3; \ + WRAP_CALL(_func) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9); + +void +test_m256_varargs (void) +{ + __m256 x[10]; + int i; + for (i = 0; i < 10; i++) + x[i] = (__m256){32+i, 0, 0, 0, 0, 0, 0, 0}; + pass = "m256-varargs"; + def_check_int_passing_varargs (x[0], x[1], x[2], x[3], x[4], x[5], + x[6], x[7], x[8], x[9], + fun_check_passing_m256_varargs, + _m256); +} + +void +avx_test (void) +{ + test_m256_varargs (); + if (failed) + abort (); +} diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512f/test_varargs-m512.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512f/test_varargs-m512.c new file mode 100644 index 00000000000..b2ba0e5ab22 --- /dev/null +++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512f/test_varargs-m512.c @@ -0,0 +1,104 @@ +/* Test variable number of 512-bit vector arguments passed to functions. */ + +#include +#include "avx512f-check.h" +#include "args.h" + +struct IntegerRegisters iregs; +struct FloatRegisters fregs; + +/* This struct holds values for argument checking. */ +struct +{ + ZMM_T i0, i1, i2, i3, i4, i5, i6, i7, i8, i9; +} values; + +char *pass; +int failed = 0; + +#undef assert +#define assert(c) do { \ + if (!(c)) {failed++; printf ("failed %s\n", pass); } \ +} while (0) + +#define compare(X1,X2,T) do { \ + assert (memcmp (&X1, &X2, sizeof (T)) == 0); \ +} while (0) + +void +fun_check_passing_m512_varargs (__m512 i0, __m512 i1, __m512 i2, + __m512 i3, ...) +{ + /* Check argument values. */ + void **fp = __builtin_frame_address (0); + void *ra = __builtin_return_address (0); + __m512 *argp; + + compare (values.i0, i0, __m512); + compare (values.i1, i1, __m512); + compare (values.i2, i2, __m512); + compare (values.i3, i3, __m512); + + /* Get the pointer to the return address on stack. */ + while (*fp != ra) + fp++; + + /* Skip the return address stack slot. */ + argp = (__m512 *)(((char *) fp) + 8); + + /* Check __m512 arguments passed on stack. */ + compare (values.i4, argp[0], __m512); + compare (values.i5, argp[1], __m512); + compare (values.i6, argp[2], __m512); + compare (values.i7, argp[3], __m512); + compare (values.i8, argp[4], __m512); + compare (values.i9, argp[5], __m512); + + /* Check register contents. */ + compare (fregs.zmm0, zmm_regs[0], __m512); + compare (fregs.zmm1, zmm_regs[1], __m512); + compare (fregs.zmm2, zmm_regs[2], __m512); + compare (fregs.zmm3, zmm_regs[3], __m512); +} + +#define def_check_int_passing_varargs(_i0, _i1, _i2, _i3, _i4, _i5, \ + _i6, _i7, _i8, _i9, \ + _func, TYPE) \ + values.i0.TYPE[0] = _i0; \ + values.i1.TYPE[0] = _i1; \ + values.i2.TYPE[0] = _i2; \ + values.i3.TYPE[0] = _i3; \ + values.i4.TYPE[0] = _i4; \ + values.i5.TYPE[0] = _i5; \ + values.i6.TYPE[0] = _i6; \ + values.i7.TYPE[0] = _i7; \ + values.i8.TYPE[0] = _i8; \ + values.i9.TYPE[0] = _i9; \ + clear_struct_registers; \ + fregs.F0.TYPE[0] = _i0; \ + fregs.F1.TYPE[0] = _i1; \ + fregs.F2.TYPE[0] = _i2; \ + fregs.F3.TYPE[0] = _i3; \ + WRAP_CALL(_func) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9); + +void +test_m512_varargs (void) +{ + __m512 x[10]; + int i; + for (i = 0; i < 10; i++) + x[i] = (__m512){32+i, 0, 0, 0, 0, 0, 0, 0}; + pass = "m512-varargs"; + def_check_int_passing_varargs (x[0], x[1], x[2], x[3], x[4], x[5], + x[6], x[7], x[8], x[9], + fun_check_passing_m512_varargs, + _m512); +} + +void +avx512f_test (void) +{ + test_m512_varargs (); + if (failed) + abort (); +} diff --git a/gcc/testsuite/gcc.target/x86_64/abi/test_varargs-m128.c b/gcc/testsuite/gcc.target/x86_64/abi/test_varargs-m128.c new file mode 100644 index 00000000000..30757687439 --- /dev/null +++ b/gcc/testsuite/gcc.target/x86_64/abi/test_varargs-m128.c @@ -0,0 +1,110 @@ +/* Test variable number of 128-bit vector arguments passed to functions. */ + +#include +#include "defines.h" +#include "macros.h" +#include "args.h" + +struct IntegerRegisters iregs; +struct FloatRegisters fregs; + +/* This struct holds values for argument checking. */ +struct +{ + XMM_T i0, i1, i2, i3, i4, i5, i6, i7, i8, i9; +} values; + +char *pass; +int failed = 0; + +#undef assert +#define assert(c) do { \ + if (!(c)) {failed++; printf ("failed %s\n", pass); } \ +} while (0) + +#define compare(X1,X2,T) do { \ + assert (memcmp (&X1, &X2, sizeof (T)) == 0); \ +} while (0) + +void +fun_check_passing_m128_varargs (__m128 i0, __m128 i1, __m128 i2, + __m128 i3, ...) +{ + /* Check argument values. */ + void **fp = __builtin_frame_address (0); + void *ra = __builtin_return_address (0); + __m128 *argp; + + compare (values.i0, i0, __m128); + compare (values.i1, i1, __m128); + compare (values.i2, i2, __m128); + compare (values.i3, i3, __m128); + + /* Get the pointer to the return address on stack. */ + while (*fp != ra) + fp++; + + /* Skip the return address stack slot. */ + argp = (__m128 *) (((char *) fp) + 8); + + /* Check __m128 arguments passed on stack. */ + compare (values.i8, argp[0], __m128); + compare (values.i9, argp[1], __m128); + + /* Check register contents. */ + compare (fregs.xmm0, xmm_regs[0], __m128); + compare (fregs.xmm1, xmm_regs[1], __m128); + compare (fregs.xmm2, xmm_regs[2], __m128); + compare (fregs.xmm3, xmm_regs[3], __m128); + compare (fregs.xmm4, xmm_regs[4], __m128); + compare (fregs.xmm5, xmm_regs[5], __m128); + compare (fregs.xmm6, xmm_regs[6], __m128); + compare (fregs.xmm7, xmm_regs[7], __m128); +} + +#define def_check_int_passing_varargs(_i0, _i1, _i2, _i3, _i4, _i5, \ + _i6, _i7, _i8, _i9, \ + _func, TYPE) \ + values.i0.TYPE[0] = _i0; \ + values.i1.TYPE[0] = _i1; \ + values.i2.TYPE[0] = _i2; \ + values.i3.TYPE[0] = _i3; \ + values.i4.TYPE[0] = _i4; \ + values.i5.TYPE[0] = _i5; \ + values.i6.TYPE[0] = _i6; \ + values.i7.TYPE[0] = _i7; \ + values.i8.TYPE[0] = _i8; \ + values.i9.TYPE[0] = _i9; \ + clear_float_registers; \ + fregs.F0.TYPE[0] = _i0; \ + fregs.F1.TYPE[0] = _i1; \ + fregs.F2.TYPE[0] = _i2; \ + fregs.F3.TYPE[0] = _i3; \ + fregs.F4.TYPE[0] = _i4; \ + fregs.F5.TYPE[0] = _i5; \ + fregs.F6.TYPE[0] = _i6; \ + fregs.F7.TYPE[0] = _i7; \ + WRAP_CALL(_func) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9); + +void +test_m128_varargs (void) +{ + __m128 x[10]; + int i; + for (i = 0; i < 10; i++) + x[i] = (__m128){32+i, 0, 0, 0}; + pass = "m128-varargs"; + def_check_int_passing_varargs (x[0], x[1], x[2], x[3], x[4], x[5], + x[6], x[7], x[8], x[9], + fun_check_passing_m128_varargs, + _m128); +} + +int +main (void) +{ + test_m128_varargs (); + if (failed) + abort (); + return 0; +} -- 2.30.2