On Thu, May 16, 2019 at 10:10 PM H.J. Lu <hjl.to...@gmail.com> wrote: > > We can scan stack for return address to get vector arguments passed on > stack. > > * 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.
Bootstrapped and regression tested on which target? Does x32 passes the test? > + /* Check __m256 arguments passed on stack. */ > + argp = (__m256 *) (((char *) fp) + 8); It took me a while to figure out that RA slot is skipped here. Please add some comment, maybe: /* Skip return address stack slot. */ argp = (__m256 *) (((char *) fp) + 8); /* Check __m256 arguments passed on stack. */ compare (values.i4, argp[0], __m256); Uros. > --- > .../x86_64/abi/avx/test_varargs-m256.c | 102 +++++++++++++++++ > .../x86_64/abi/avx512f/test_varargs-m512.c | 102 +++++++++++++++++ > .../gcc.target/x86_64/abi/test_varargs-m128.c | 108 ++++++++++++++++++ > 3 files changed, 312 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/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..d1bcf865487 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/x86_64/abi/avx/test_varargs-m256.c > @@ -0,0 +1,102 @@ > +/* Test variable number of 256-bit vector arguments passed to functions. */ > + > +#include <stdio.h> > +#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++; > + > + /* Check __m256 arguments passed on stack. */ > + argp = (__m256 *) (((char *) fp) + 8); > + 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..328f76de3df > --- /dev/null > +++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512f/test_varargs-m512.c > @@ -0,0 +1,102 @@ > +/* Test variable number of 512-bit vector arguments passed to functions. */ > + > +#include <stdio.h> > +#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++; > + > + /* Check __m512 arguments passed on stack. */ > + argp = (__m512 *)(((char *) fp) + 8); > + 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..b6359b52597 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/x86_64/abi/test_varargs-m128.c > @@ -0,0 +1,108 @@ > +/* Test variable number of 128-bit vector arguments passed to functions. */ > + > +#include <stdio.h> > +#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++; > + > + /* Check __m128 arguments passed on stack. */ > + argp = (__m128 *) (((char *) fp) + 8); > + 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.20.1 >