From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2078) id DB93C3861038; Wed, 8 Sep 2021 04:46:05 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org DB93C3861038 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: hongtao Liu To: gcc-cvs@gcc.gnu.org Subject: [gcc r12-3412] AVX512FP16: Add abi test for zmm X-Act-Checkin: gcc X-Git-Author: liuhongt X-Git-Refname: refs/heads/master X-Git-Oldrev: 07308cdb0c865b846396af4ebe07ccc9f3a6f3f3 X-Git-Newrev: 4a61bcaca074e967f694b30b484671aaeec190ff Message-Id: <20210908044605.DB93C3861038@sourceware.org> Date: Wed, 8 Sep 2021 04:46:05 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 08 Sep 2021 04:46:06 -0000 https://gcc.gnu.org/g:4a61bcaca074e967f694b30b484671aaeec190ff commit r12-3412-g4a61bcaca074e967f694b30b484671aaeec190ff Author: liuhongt Date: Thu Mar 5 09:57:25 2020 +0800 AVX512FP16: Add abi test for zmm gcc/testsuite/ChangeLog: * gcc.target/x86_64/abi/avx512fp16/m512h/abi-avx512fp16-zmm.exp: New file. * gcc.target/x86_64/abi/avx512fp16/m512h/args.h: Likewise. * gcc.target/x86_64/abi/avx512fp16/m512h/asm-support.S: Likewise. * gcc.target/x86_64/abi/avx512fp16/m512h/avx512fp16-zmm-check.h: Likewise. * gcc.target/x86_64/abi/avx512fp16/m512h/test_m512_returning.c: Likewise. * gcc.target/x86_64/abi/avx512fp16/m512h/test_passing_m512.c: Likewise. * gcc.target/x86_64/abi/avx512fp16/m512h/test_passing_structs.c: Likewise. * gcc.target/x86_64/abi/avx512fp16/m512h/test_passing_unions.c: Likewise. * gcc.target/x86_64/abi/avx512fp16/m512h/test_varargs-m512.c: Likewise. Diff: --- .../abi/avx512fp16/m512h/abi-avx512fp16-zmm.exp | 48 +++ .../gcc.target/x86_64/abi/avx512fp16/m512h/args.h | 186 +++++++++ .../x86_64/abi/avx512fp16/m512h/asm-support.S | 97 +++++ .../abi/avx512fp16/m512h/avx512fp16-zmm-check.h | 4 + .../abi/avx512fp16/m512h/test_m512_returning.c | 62 +++ .../abi/avx512fp16/m512h/test_passing_m512.c | 380 +++++++++++++++++++ .../abi/avx512fp16/m512h/test_passing_structs.c | 123 ++++++ .../abi/avx512fp16/m512h/test_passing_unions.c | 415 +++++++++++++++++++++ .../abi/avx512fp16/m512h/test_varargs-m512.c | 164 ++++++++ 9 files changed, 1479 insertions(+) diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/abi-avx512fp16-zmm.exp b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/abi-avx512fp16-zmm.exp new file mode 100644 index 00000000000..33d24762788 --- /dev/null +++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/abi-avx512fp16-zmm.exp @@ -0,0 +1,48 @@ +# Copyright (C) 2019 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# . + +# The x86-64 ABI testsuite needs one additional assembler file for most +# testcases. For simplicity we will just link it into each test. + +load_lib c-torture.exp +load_lib target-supports.exp +load_lib torture-options.exp +load_lib clearcap.exp +load_lib file-format.exp + +if { (![istarget x86_64-*-*] && ![istarget i?86-*-*]) + || [is-effective-target ia32] + || [gcc_target_object_format] != "elf" + || ![is-effective-target avx512fp16] } then { + return +} + + +torture-init +clearcap-init +set-torture-options $C_TORTURE_OPTIONS +set additional_flags "-W -Wall -Wno-abi -mavx512fp16" + +foreach src [lsort [glob -nocomplain $srcdir/$subdir/test_*.c]] { + if {[runtest_file_p $runtests $src]} { + c-torture-execute [list $src \ + $srcdir/$subdir/asm-support.S] \ + $additional_flags + } +} + +clearcap-finish +torture-finish diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/args.h b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/args.h new file mode 100644 index 00000000000..ec89fae4597 --- /dev/null +++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/args.h @@ -0,0 +1,186 @@ +#ifndef INCLUDED_ARGS_H +#define INCLUDED_ARGS_H + +#include +#include + +/* Assertion macro. */ +#define assert(test) if (!(test)) abort() + +#ifdef __GNUC__ +#define ATTRIBUTE_UNUSED __attribute__((__unused__)) +#else +#define ATTRIBUTE_UNUSED +#endif + +/* This defines the calling sequences for integers and floats. */ +#define I0 rdi +#define I1 rsi +#define I2 rdx +#define I3 rcx +#define I4 r8 +#define I5 r9 +#define F0 zmm0 +#define F1 zmm1 +#define F2 zmm2 +#define F3 zmm3 +#define F4 zmm4 +#define F5 zmm5 +#define F6 zmm6 +#define F7 zmm7 + +typedef union { + _Float16 __Float16[32]; + float _float[16]; + double _double[8]; + long _long[8]; + int _int[16]; + unsigned long _ulong[8]; + __m64 _m64[8]; + __m128 _m128[4]; + __m256 _m256[2]; + __m512 _m512[1]; + __m512h _m512h[1]; +} ZMM_T; + +typedef union { + float _float; + double _double; + long double _ldouble; + unsigned long _ulong[2]; +} X87_T; +extern void (*callthis)(void); +extern unsigned long rax,rbx,rcx,rdx,rsi,rdi,rsp,rbp,r8,r9,r10,r11,r12,r13,r14,r15; +ZMM_T zmm_regs[32]; +X87_T x87_regs[8]; +extern volatile unsigned long volatile_var; +extern void snapshot (void); +extern void snapshot_ret (void); +#define WRAP_CALL(N) \ + (callthis = (void (*)()) (N), (typeof (&N)) snapshot) +#define WRAP_RET(N) \ + (callthis = (void (*)()) (N), (typeof (&N)) snapshot_ret) + +/* Clear all integer registers. */ +#define clear_int_hardware_registers \ + asm __volatile__ ("xor %%rax, %%rax\n\t" \ + "xor %%rbx, %%rbx\n\t" \ + "xor %%rcx, %%rcx\n\t" \ + "xor %%rdx, %%rdx\n\t" \ + "xor %%rsi, %%rsi\n\t" \ + "xor %%rdi, %%rdi\n\t" \ + "xor %%r8, %%r8\n\t" \ + "xor %%r9, %%r9\n\t" \ + "xor %%r10, %%r10\n\t" \ + "xor %%r11, %%r11\n\t" \ + "xor %%r12, %%r12\n\t" \ + "xor %%r13, %%r13\n\t" \ + "xor %%r14, %%r14\n\t" \ + "xor %%r15, %%r15\n\t" \ + ::: "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", \ + "r9", "r10", "r11", "r12", "r13", "r14", "r15"); + +/* This is the list of registers available for passing arguments. Not all of + these are used or even really available. */ +struct IntegerRegisters +{ + unsigned long rax, rbx, rcx, rdx, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15; +}; +struct FloatRegisters +{ + double mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7; + long double st0, st1, st2, st3, st4, st5, st6, st7; + ZMM_T zmm0, zmm1, zmm2, zmm3, zmm4, zmm5, zmm6, zmm7, zmm8, zmm9, + zmm10, zmm11, zmm12, zmm13, zmm14, zmm15, zmm16, zmm17, zmm18, + zmm19, zmm20, zmm21, zmm22, zmm23, zmm24, zmm25, zmm26, zmm27, + zmm28, zmm29, zmm30, zmm31; +}; + +/* Implemented in scalarargs.c */ +extern struct IntegerRegisters iregs; +extern struct FloatRegisters fregs; +extern unsigned int num_iregs, num_fregs; + +#define check_int_arguments do { \ + assert (num_iregs <= 0 || iregs.I0 == I0); \ + assert (num_iregs <= 1 || iregs.I1 == I1); \ + assert (num_iregs <= 2 || iregs.I2 == I2); \ + assert (num_iregs <= 3 || iregs.I3 == I3); \ + assert (num_iregs <= 4 || iregs.I4 == I4); \ + assert (num_iregs <= 5 || iregs.I5 == I5); \ + } while (0) + +#define check_char_arguments check_int_arguments +#define check_short_arguments check_int_arguments +#define check_long_arguments check_int_arguments + +/* Clear register struct. */ +#define clear_struct_registers \ + rax = rbx = rcx = rdx = rdi = rsi = rbp = rsp \ + = r8 = r9 = r10 = r11 = r12 = r13 = r14 = r15 = 0; \ + memset (&iregs, 0, sizeof (iregs)); \ + memset (&fregs, 0, sizeof (fregs)); \ + memset (zmm_regs, 0, sizeof (zmm_regs)); \ + memset (x87_regs, 0, sizeof (x87_regs)); + +/* Clear both hardware and register structs for integers. */ +#define clear_int_registers \ + clear_struct_registers \ + clear_int_hardware_registers + +/* TODO: Do the checking. */ +#define check_f_arguments(T) do { \ + assert (num_fregs <= 0 || fregs.zmm0._ ## T [0] == zmm_regs[0]._ ## T [0]); \ + assert (num_fregs <= 1 || fregs.zmm1._ ## T [0] == zmm_regs[1]._ ## T [0]); \ + assert (num_fregs <= 2 || fregs.zmm2._ ## T [0] == zmm_regs[2]._ ## T [0]); \ + assert (num_fregs <= 3 || fregs.zmm3._ ## T [0] == zmm_regs[3]._ ## T [0]); \ + assert (num_fregs <= 4 || fregs.zmm4._ ## T [0] == zmm_regs[4]._ ## T [0]); \ + assert (num_fregs <= 5 || fregs.zmm5._ ## T [0] == zmm_regs[5]._ ## T [0]); \ + assert (num_fregs <= 6 || fregs.zmm6._ ## T [0] == zmm_regs[6]._ ## T [0]); \ + assert (num_fregs <= 7 || fregs.zmm7._ ## T [0] == zmm_regs[7]._ ## T [0]); \ + } while (0) + +#define check_float_arguments check_f_arguments(float) +#define check_double_arguments check_f_arguments(double) + +#define check_vector_arguments(T,O) do { \ + assert (num_fregs <= 0 \ + || memcmp (((char *) &fregs.zmm0) + (O), \ + &zmm_regs[0], \ + sizeof (__ ## T) - (O)) == 0); \ + assert (num_fregs <= 1 \ + || memcmp (((char *) &fregs.zmm1) + (O), \ + &zmm_regs[1], \ + sizeof (__ ## T) - (O)) == 0); \ + assert (num_fregs <= 2 \ + || memcmp (((char *) &fregs.zmm2) + (O), \ + &zmm_regs[2], \ + sizeof (__ ## T) - (O)) == 0); \ + assert (num_fregs <= 3 \ + || memcmp (((char *) &fregs.zmm3) + (O), \ + &zmm_regs[3], \ + sizeof (__ ## T) - (O)) == 0); \ + assert (num_fregs <= 4 \ + || memcmp (((char *) &fregs.zmm4) + (O), \ + &zmm_regs[4], \ + sizeof (__ ## T) - (O)) == 0); \ + assert (num_fregs <= 5 \ + || memcmp (((char *) &fregs.zmm5) + (O), \ + &zmm_regs[5], \ + sizeof (__ ## T) - (O)) == 0); \ + assert (num_fregs <= 6 \ + || memcmp (((char *) &fregs.zmm6) + (O), \ + &zmm_regs[6], \ + sizeof (__ ## T) - (O)) == 0); \ + assert (num_fregs <= 7 \ + || memcmp (((char *) &fregs.zmm7) + (O), \ + &zmm_regs[7], \ + sizeof (__ ## T) - (O)) == 0); \ + } while (0) + +#define check_m64_arguments check_vector_arguments(m64, 0) +#define check_m128_arguments check_vector_arguments(m128, 0) +#define check_m256_arguments check_vector_arguments(m256, 0) +#define check_m512_arguments check_vector_arguments(m512, 0) + +#endif /* INCLUDED_ARGS_H */ diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/asm-support.S b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/asm-support.S new file mode 100644 index 00000000000..0ef82876dd9 --- /dev/null +++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/asm-support.S @@ -0,0 +1,97 @@ + .text + .p2align 4,,15 +.globl snapshot + .type snapshot, @function +snapshot: +.LFB3: + movq %rax, rax(%rip) + movq %rbx, rbx(%rip) + movq %rcx, rcx(%rip) + movq %rdx, rdx(%rip) + movq %rdi, rdi(%rip) + movq %rsi, rsi(%rip) + movq %rbp, rbp(%rip) + movq %rsp, rsp(%rip) + movq %r8, r8(%rip) + movq %r9, r9(%rip) + movq %r10, r10(%rip) + movq %r11, r11(%rip) + movq %r12, r12(%rip) + movq %r13, r13(%rip) + movq %r14, r14(%rip) + movq %r15, r15(%rip) + vmovdqu32 %zmm0, zmm_regs+0(%rip) + vmovdqu32 %zmm1, zmm_regs+64(%rip) + vmovdqu32 %zmm2, zmm_regs+128(%rip) + vmovdqu32 %zmm3, zmm_regs+192(%rip) + vmovdqu32 %zmm4, zmm_regs+256(%rip) + vmovdqu32 %zmm5, zmm_regs+320(%rip) + vmovdqu32 %zmm6, zmm_regs+384(%rip) + vmovdqu32 %zmm7, zmm_regs+448(%rip) + vmovdqu32 %zmm8, zmm_regs+512(%rip) + vmovdqu32 %zmm9, zmm_regs+576(%rip) + vmovdqu32 %zmm10, zmm_regs+640(%rip) + vmovdqu32 %zmm11, zmm_regs+704(%rip) + vmovdqu32 %zmm12, zmm_regs+768(%rip) + vmovdqu32 %zmm13, zmm_regs+832(%rip) + vmovdqu32 %zmm14, zmm_regs+896(%rip) + vmovdqu32 %zmm15, zmm_regs+960(%rip) + vmovdqu32 %zmm16, zmm_regs+1024(%rip) + vmovdqu32 %zmm17, zmm_regs+1088(%rip) + vmovdqu32 %zmm18, zmm_regs+1152(%rip) + vmovdqu32 %zmm19, zmm_regs+1216(%rip) + vmovdqu32 %zmm20, zmm_regs+1280(%rip) + vmovdqu32 %zmm21, zmm_regs+1344(%rip) + vmovdqu32 %zmm22, zmm_regs+1408(%rip) + vmovdqu32 %zmm23, zmm_regs+1472(%rip) + vmovdqu32 %zmm24, zmm_regs+1536(%rip) + vmovdqu32 %zmm25, zmm_regs+1600(%rip) + vmovdqu32 %zmm26, zmm_regs+1664(%rip) + vmovdqu32 %zmm27, zmm_regs+1728(%rip) + vmovdqu32 %zmm28, zmm_regs+1792(%rip) + vmovdqu32 %zmm29, zmm_regs+1856(%rip) + vmovdqu32 %zmm30, zmm_regs+1920(%rip) + vmovdqu32 %zmm31, zmm_regs+1984(%rip) + jmp *callthis(%rip) +.LFE3: + .size snapshot, .-snapshot + + .p2align 4,,15 +.globl snapshot_ret + .type snapshot_ret, @function +snapshot_ret: + movq %rdi, rdi(%rip) + subq $8, %rsp + call *callthis(%rip) + addq $8, %rsp + movq %rax, rax(%rip) + movq %rdx, rdx(%rip) + vmovdqu32 %zmm0, zmm_regs+0(%rip) + vmovdqu32 %zmm1, zmm_regs+64(%rip) + fstpt x87_regs(%rip) + fstpt x87_regs+16(%rip) + fldt x87_regs+16(%rip) + fldt x87_regs(%rip) + ret + .size snapshot_ret, .-snapshot_ret + + .comm callthis,8,8 + .comm rax,8,8 + .comm rbx,8,8 + .comm rcx,8,8 + .comm rdx,8,8 + .comm rsi,8,8 + .comm rdi,8,8 + .comm rsp,8,8 + .comm rbp,8,8 + .comm r8,8,8 + .comm r9,8,8 + .comm r10,8,8 + .comm r11,8,8 + .comm r12,8,8 + .comm r13,8,8 + .comm r14,8,8 + .comm r15,8,8 + .comm zmm_regs,2048,64 + .comm x87_regs,128,32 + .comm volatile_var,8,8 diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/avx512fp16-zmm-check.h b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/avx512fp16-zmm-check.h new file mode 100644 index 00000000000..4b882cc11fc --- /dev/null +++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/avx512fp16-zmm-check.h @@ -0,0 +1,4 @@ +#define AVX512VL(ebx) 1 +#define XSTATE_MASK (XSTATE_SSE | XSTATE_YMM | XSTATE_ZMM \ + | XSTATE_HI_ZMM | XSTATE_OPMASK) +#include "../avx512fp16-check.h" diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_m512_returning.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_m512_returning.c new file mode 100644 index 00000000000..5cb59436cfd --- /dev/null +++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_m512_returning.c @@ -0,0 +1,62 @@ +#include +#include "avx512fp16-zmm-check.h" +#include "args.h" + +struct IntegerRegisters iregs; +struct FloatRegisters fregs; +unsigned int num_iregs, num_fregs; + +__m512 +fun_test_returning___m512 (void) +{ + volatile_var++; + return (__m512){73,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +} + +__m512h +fun_test_returning___m512h (void) +{ + volatile_var++; + return (__m512h){ 1.1f16, 2.2f16, 3.3f16, 4.4f16, + 5.5f16, 6.6f16, 7.7f16, 8.8f16, + 9.9f16, 10.10f16, 11.11f16, 12.12f16, + 13.13f16, 14.14f16, 15.15f16, 16.16f16, + 17.17f16, 18.18f16, 19.19f16, 20.20f16, + 21.21f16, 22.22f16, 23.23f16, 24.24f16, + 25.25f16, 26.26f16, 27.27f16, 28.28f16, + 29.29f16, 30.30f16, 31.31f16, 32.32f16}; +} + +__m512 test_512; +__m512h test_512h; + +static void +do_test (void) +{ + unsigned failed = 0; + ZMM_T zmmt1, zmmt2; + + clear_struct_registers; + test_512 = (__m512){73,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + zmmt1._m512[0] = test_512; + zmmt2._m512[0] = WRAP_RET (fun_test_returning___m512)(); + if (memcmp (&zmmt1, &zmmt2, sizeof (zmmt2)) != 0) + printf ("fail m512\n"), failed++; + + clear_struct_registers; + test_512h = (__m512h){ 1.1f16, 2.2f16, 3.3f16, 4.4f16, + 5.5f16, 6.6f16, 7.7f16, 8.8f16, + 9.9f16, 10.10f16, 11.11f16, 12.12f16, + 13.13f16, 14.14f16, 15.15f16, 16.16f16, + 17.17f16, 18.18f16, 19.19f16, 20.20f16, + 21.21f16, 22.22f16, 23.23f16, 24.24f16, + 25.25f16, 26.26f16, 27.27f16, 28.28f16, + 29.29f16, 30.30f16, 31.31f16, 32.32f16}; + zmmt1._m512h[0] = test_512h; + zmmt2._m512h[0] = WRAP_RET (fun_test_returning___m512h)(); + if (memcmp (&zmmt1, &zmmt2, sizeof (zmmt2)) != 0) + printf ("fail m512h\n"), failed++; + + if (failed) + abort (); +} diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_passing_m512.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_passing_m512.c new file mode 100644 index 00000000000..ad5ba2e7f92 --- /dev/null +++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_passing_m512.c @@ -0,0 +1,380 @@ +#include +#include "avx512fp16-zmm-check.h" +#include "args.h" + +struct IntegerRegisters iregs; +struct FloatRegisters fregs; +unsigned int num_iregs, num_fregs; + +/* This struct holds values for argument checking. */ +struct +{ + ZMM_T i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15, + i16, i17, i18, i19, i20, i21, i22, i23; +} 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) + +fun_check_passing_m512_8_values (__m512 i0 ATTRIBUTE_UNUSED, + __m512 i1 ATTRIBUTE_UNUSED, + __m512 i2 ATTRIBUTE_UNUSED, + __m512 i3 ATTRIBUTE_UNUSED, + __m512 i4 ATTRIBUTE_UNUSED, + __m512 i5 ATTRIBUTE_UNUSED, + __m512 i6 ATTRIBUTE_UNUSED, + __m512 i7 ATTRIBUTE_UNUSED) +{ + /* Check argument values. */ + compare (values.i0, i0, __m512); + compare (values.i1, i1, __m512); + compare (values.i2, i2, __m512); + compare (values.i3, i3, __m512); + compare (values.i4, i4, __m512); + compare (values.i5, i5, __m512); + compare (values.i6, i6, __m512); + compare (values.i7, i7, __m512); +} + +fun_check_passing_m512h_8_values (__m512h i0 ATTRIBUTE_UNUSED, + __m512h i1 ATTRIBUTE_UNUSED, + __m512h i2 ATTRIBUTE_UNUSED, + __m512h i3 ATTRIBUTE_UNUSED, + __m512h i4 ATTRIBUTE_UNUSED, + __m512h i5 ATTRIBUTE_UNUSED, + __m512h i6 ATTRIBUTE_UNUSED, + __m512h i7 ATTRIBUTE_UNUSED) +{ + /* Check argument values. */ + compare (values.i0, i0, __m512h); + compare (values.i1, i1, __m512h); + compare (values.i2, i2, __m512h); + compare (values.i3, i3, __m512h); + compare (values.i4, i4, __m512h); + compare (values.i5, i5, __m512h); + compare (values.i6, i6, __m512h); + compare (values.i7, i7, __m512h); +} + +void +fun_check_passing_m512_8_regs (__m512 i0 ATTRIBUTE_UNUSED, + __m512 i1 ATTRIBUTE_UNUSED, + __m512 i2 ATTRIBUTE_UNUSED, + __m512 i3 ATTRIBUTE_UNUSED, + __m512 i4 ATTRIBUTE_UNUSED, + __m512 i5 ATTRIBUTE_UNUSED, + __m512 i6 ATTRIBUTE_UNUSED, + __m512 i7 ATTRIBUTE_UNUSED) +{ + /* Check register contents. */ + check_m512_arguments; +} + +void +fun_check_passing_m512h_8_regs (__m512h i0 ATTRIBUTE_UNUSED, + __m512h i1 ATTRIBUTE_UNUSED, + __m512h i2 ATTRIBUTE_UNUSED, + __m512h i3 ATTRIBUTE_UNUSED, + __m512h i4 ATTRIBUTE_UNUSED, + __m512h i5 ATTRIBUTE_UNUSED, + __m512h i6 ATTRIBUTE_UNUSED, + __m512h i7 ATTRIBUTE_UNUSED) +{ + /* Check register contents. */ + check_m512_arguments; +} + +void +fun_check_passing_m512_20_values (__m512 i0 ATTRIBUTE_UNUSED, + __m512 i1 ATTRIBUTE_UNUSED, + __m512 i2 ATTRIBUTE_UNUSED, + __m512 i3 ATTRIBUTE_UNUSED, + __m512 i4 ATTRIBUTE_UNUSED, + __m512 i5 ATTRIBUTE_UNUSED, + __m512 i6 ATTRIBUTE_UNUSED, + __m512 i7 ATTRIBUTE_UNUSED, + __m512 i8 ATTRIBUTE_UNUSED, + __m512 i9 ATTRIBUTE_UNUSED, + __m512 i10 ATTRIBUTE_UNUSED, + __m512 i11 ATTRIBUTE_UNUSED, + __m512 i12 ATTRIBUTE_UNUSED, + __m512 i13 ATTRIBUTE_UNUSED, + __m512 i14 ATTRIBUTE_UNUSED, + __m512 i15 ATTRIBUTE_UNUSED, + __m512 i16 ATTRIBUTE_UNUSED, + __m512 i17 ATTRIBUTE_UNUSED, + __m512 i18 ATTRIBUTE_UNUSED, + __m512 i19 ATTRIBUTE_UNUSED) +{ + /* Check argument values. */ + compare (values.i0, i0, __m512); + compare (values.i1, i1, __m512); + compare (values.i2, i2, __m512); + compare (values.i3, i3, __m512); + compare (values.i4, i4, __m512); + compare (values.i5, i5, __m512); + compare (values.i6, i6, __m512); + compare (values.i7, i7, __m512); + compare (values.i8, i8, __m512); + compare (values.i9, i9, __m512); + compare (values.i10, i10, __m512); + compare (values.i11, i11, __m512); + compare (values.i12, i12, __m512); + compare (values.i13, i13, __m512); + compare (values.i14, i14, __m512); + compare (values.i15, i15, __m512); + compare (values.i16, i16, __m512); + compare (values.i17, i17, __m512); + compare (values.i18, i18, __m512); + compare (values.i19, i19, __m512); +} + +void +fun_check_passing_m512h_20_values (__m512h i0 ATTRIBUTE_UNUSED, + __m512h i1 ATTRIBUTE_UNUSED, + __m512h i2 ATTRIBUTE_UNUSED, + __m512h i3 ATTRIBUTE_UNUSED, + __m512h i4 ATTRIBUTE_UNUSED, + __m512h i5 ATTRIBUTE_UNUSED, + __m512h i6 ATTRIBUTE_UNUSED, + __m512h i7 ATTRIBUTE_UNUSED, + __m512h i8 ATTRIBUTE_UNUSED, + __m512h i9 ATTRIBUTE_UNUSED, + __m512h i10 ATTRIBUTE_UNUSED, + __m512h i11 ATTRIBUTE_UNUSED, + __m512h i12 ATTRIBUTE_UNUSED, + __m512h i13 ATTRIBUTE_UNUSED, + __m512h i14 ATTRIBUTE_UNUSED, + __m512h i15 ATTRIBUTE_UNUSED, + __m512h i16 ATTRIBUTE_UNUSED, + __m512h i17 ATTRIBUTE_UNUSED, + __m512h i18 ATTRIBUTE_UNUSED, + __m512h i19 ATTRIBUTE_UNUSED) +{ + /* Check argument values. */ + compare (values.i0, i0, __m512h); + compare (values.i1, i1, __m512h); + compare (values.i2, i2, __m512h); + compare (values.i3, i3, __m512h); + compare (values.i4, i4, __m512h); + compare (values.i5, i5, __m512h); + compare (values.i6, i6, __m512h); + compare (values.i7, i7, __m512h); + compare (values.i8, i8, __m512h); + compare (values.i9, i9, __m512h); + compare (values.i10, i10, __m512h); + compare (values.i11, i11, __m512h); + compare (values.i12, i12, __m512h); + compare (values.i13, i13, __m512h); + compare (values.i14, i14, __m512h); + compare (values.i15, i15, __m512h); + compare (values.i16, i16, __m512h); + compare (values.i17, i17, __m512h); + compare (values.i18, i18, __m512h); + compare (values.i19, i19, __m512h); +} + +void +fun_check_passing_m512_20_regs (__m512 i0 ATTRIBUTE_UNUSED, + __m512 i1 ATTRIBUTE_UNUSED, + __m512 i2 ATTRIBUTE_UNUSED, + __m512 i3 ATTRIBUTE_UNUSED, + __m512 i4 ATTRIBUTE_UNUSED, + __m512 i5 ATTRIBUTE_UNUSED, + __m512 i6 ATTRIBUTE_UNUSED, + __m512 i7 ATTRIBUTE_UNUSED, + __m512 i8 ATTRIBUTE_UNUSED, + __m512 i9 ATTRIBUTE_UNUSED, + __m512 i10 ATTRIBUTE_UNUSED, + __m512 i11 ATTRIBUTE_UNUSED, + __m512 i12 ATTRIBUTE_UNUSED, + __m512 i13 ATTRIBUTE_UNUSED, + __m512 i14 ATTRIBUTE_UNUSED, + __m512 i15 ATTRIBUTE_UNUSED, + __m512 i16 ATTRIBUTE_UNUSED, + __m512 i17 ATTRIBUTE_UNUSED, + __m512 i18 ATTRIBUTE_UNUSED, + __m512 i19 ATTRIBUTE_UNUSED) +{ + /* Check register contents. */ + check_m512_arguments; +} + +void +fun_check_passing_m512h_20_regs (__m512h i0 ATTRIBUTE_UNUSED, + __m512h i1 ATTRIBUTE_UNUSED, + __m512h i2 ATTRIBUTE_UNUSED, + __m512h i3 ATTRIBUTE_UNUSED, + __m512h i4 ATTRIBUTE_UNUSED, + __m512h i5 ATTRIBUTE_UNUSED, + __m512h i6 ATTRIBUTE_UNUSED, + __m512h i7 ATTRIBUTE_UNUSED, + __m512h i8 ATTRIBUTE_UNUSED, + __m512h i9 ATTRIBUTE_UNUSED, + __m512h i10 ATTRIBUTE_UNUSED, + __m512h i11 ATTRIBUTE_UNUSED, + __m512h i12 ATTRIBUTE_UNUSED, + __m512h i13 ATTRIBUTE_UNUSED, + __m512h i14 ATTRIBUTE_UNUSED, + __m512h i15 ATTRIBUTE_UNUSED, + __m512h i16 ATTRIBUTE_UNUSED, + __m512h i17 ATTRIBUTE_UNUSED, + __m512h i18 ATTRIBUTE_UNUSED, + __m512h i19 ATTRIBUTE_UNUSED) +{ + /* Check register contents. */ + check_m512_arguments; +} + +#define def_check_passing8(_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _func1, _func2, 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; \ + WRAP_CALL(_func1) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7); \ + \ + clear_struct_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; \ + num_fregs = 8; \ + WRAP_CALL(_func2) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7); + +#define def_check_passing20(_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9, \ + _i10, _i11, _i12, _i13, _i14, _i15, _i16, _i17, \ + _i18, _i19, _func1, _func2, 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; \ + values.i10.TYPE[0] = _i10; \ + values.i11.TYPE[0] = _i11; \ + values.i12.TYPE[0] = _i12; \ + values.i13.TYPE[0] = _i13; \ + values.i14.TYPE[0] = _i14; \ + values.i15.TYPE[0] = _i15; \ + values.i16.TYPE[0] = _i16; \ + values.i17.TYPE[0] = _i17; \ + values.i18.TYPE[0] = _i18; \ + values.i19.TYPE[0] = _i19; \ + WRAP_CALL(_func1) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9, \ + _i10, _i11, _i12, _i13, _i14, _i15, _i16, _i17, \ + _i18, _i19); \ + \ + clear_struct_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; \ + num_fregs = 8; \ + WRAP_CALL(_func2) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9, \ + _i10, _i11, _i12, _i13, _i14, _i15, _i16, _i17, \ + _i18, _i19); + +void +test_m512_on_stack () +{ + __m512 x[8]; + int i; + for (i = 0; i < 8; i++) + x[i] = (__m512){32 + i, 0, 0, 0, 0, 0, 0, 0}; + pass = "m512-8"; + def_check_passing8 (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], + fun_check_passing_m512_8_values, + fun_check_passing_m512_8_regs, _m512); +} + +void +test_m512h_on_stack () +{ + __m512h x[8]; + int i; + for (i = 0; i < 8; i++) + x[i] = (__m512h){1.1f16 + i, 2.2f16 + i, 3.3f16 + i, 4.4f16 + i, + 5.5f16 + i, 6.6f16 + i, 7.7f16 + i, 8.8f16 + i, + 9.9f16 + i, 10.10f16 + i, 11.11f16 + i, 12.12f16 + i, + 13.13f16 + i, 14.14f16 + i, 15.15f16 + i, 16.16f16 + i, + 17.17f16 + i, 18.18f16 + i, 19.19f16 + i, 20.20f16 + i, + 21.21f16 + i, 22.22f16 + i, 23.23f16 + i, 24.24f16 + i, + 25.25f16 + i, 26.26f16 + i, 27.27f16 + i, 28.28f16 + i, + 29.29f16 + i, 30.30f16 + i, 31.31f16 + i, 32.32f16 + i}; + + pass = "m512h-8"; + def_check_passing8 (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], + fun_check_passing_m512h_8_values, + fun_check_passing_m512h_8_regs, _m512h); +} + +void +test_too_many_m512 () +{ + __m512 x[20]; + int i; + for (i = 0; i < 20; i++) + x[i] = (__m512){32 + i, 0, 0, 0, 0, 0, 0, 0}; + pass = "m512-20"; + def_check_passing20 (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], + x[9], x[10], x[11], x[12], x[13], x[14], x[15], x[16], + x[17], x[18], x[19], fun_check_passing_m512_20_values, + fun_check_passing_m512_20_regs, _m512); +} + +void +test_too_many_m512h () +{ + __m512h x[20]; + int i; + for (i = 0; i < 20; i++) + x[i] = (__m512h){ 1.1f16 + i, 2.2f16 + i, 3.3f16 + i, 4.4f16 + i, + 5.5f16 + i, 6.6f16 + i, 7.7f16 + i, 8.8f16 + i, + 9.9f16 + i, 10.10f16 + i, 11.11f16 + i, 12.12f16 + i, + 13.13f16 + i, 14.14f16 + i, 15.15f16 + i, 16.16f16 + i, + 17.17f16 + i, 18.18f16 + i, 19.19f16 + i, 20.20f16 + i, + 21.21f16 + i, 22.22f16 + i, 23.23f16 + i, 24.24f16 + i, + 25.25f16 + i, 26.26f16 + i, 27.27f16 + i, 28.28f16 + i, + 29.29f16 + i, 30.30f16 + i, 31.31f16 + i, 32.32f16 + i}; + pass = "m512h-20"; + def_check_passing20 (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], + x[9], x[10], x[11], x[12], x[13], x[14], x[15], x[16], + x[17], x[18], x[19], fun_check_passing_m512h_20_values, + fun_check_passing_m512h_20_regs, _m512h); +} + +static void +do_test (void) +{ + test_m512_on_stack (); + test_too_many_m512 (); + test_m512h_on_stack (); + test_too_many_m512h (); + if (failed) + abort (); +} diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_passing_structs.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_passing_structs.c new file mode 100644 index 00000000000..734e0f8e9e9 --- /dev/null +++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_passing_structs.c @@ -0,0 +1,123 @@ +#include "avx512fp16-zmm-check.h" +#include "args.h" + +struct IntegerRegisters iregs; +struct FloatRegisters fregs; +unsigned int num_iregs, num_fregs; + +struct m512_struct +{ + __m512 x; +}; + +struct m512h_struct +{ + __m512h x; +}; + +struct m512_2_struct +{ + __m512 x1, x2; +}; + +struct m512h_2_struct +{ + __m512h x1, x2; +}; + +/* Check that the struct is passed as the individual members in fregs. */ +void +check_struct_passing1 (struct m512_struct ms1 ATTRIBUTE_UNUSED, + struct m512_struct ms2 ATTRIBUTE_UNUSED, + struct m512_struct ms3 ATTRIBUTE_UNUSED, + struct m512_struct ms4 ATTRIBUTE_UNUSED, + struct m512_struct ms5 ATTRIBUTE_UNUSED, + struct m512_struct ms6 ATTRIBUTE_UNUSED, + struct m512_struct ms7 ATTRIBUTE_UNUSED, + struct m512_struct ms8 ATTRIBUTE_UNUSED) +{ + /* Check register contents. */ + check_m512_arguments; +} + +void +check_struct_passing1h (struct m512h_struct ms1 ATTRIBUTE_UNUSED, + struct m512h_struct ms2 ATTRIBUTE_UNUSED, + struct m512h_struct ms3 ATTRIBUTE_UNUSED, + struct m512h_struct ms4 ATTRIBUTE_UNUSED, + struct m512h_struct ms5 ATTRIBUTE_UNUSED, + struct m512h_struct ms6 ATTRIBUTE_UNUSED, + struct m512h_struct ms7 ATTRIBUTE_UNUSED, + struct m512h_struct ms8 ATTRIBUTE_UNUSED) +{ + /* Check register contents. */ + check_m512_arguments; +} + +void +check_struct_passing2 (struct m512_2_struct ms ATTRIBUTE_UNUSED) +{ + /* Check the passing on the stack by comparing the address of the + stack elements to the expected place on the stack. */ + assert ((unsigned long)&ms.x1 == rsp+8); + assert ((unsigned long)&ms.x2 == rsp+72); +} + +void +check_struct_passing2h (struct m512h_2_struct ms ATTRIBUTE_UNUSED) +{ + /* Check the passing on the stack by comparing the address of the + stack elements to the expected place on the stack. */ + assert ((unsigned long)&ms.x1 == rsp+8); + assert ((unsigned long)&ms.x2 == rsp+72); +} + +static void +do_test (void) +{ + struct m512_struct m512s [8]; + struct m512h_struct m512hs [8]; + struct m512_2_struct m512_2s = { + { 48.394, 39.3, -397.9, 3484.9, -8.394, -93.3, 7.9, 84.94, + 48.3941, 39.31, -397.91, 3484.91, -8.3941, -93.31, 7.91, 84.941 }, + { -8.394, -3.3, -39.9, 34.9, 7.9, 84.94, -48.394, 39.3, + -8.3942, -3.32, -39.92, 34.92, 7.92, 84.942, -48.3942, 39.32 } + }; + struct m512h_2_struct m512h_2s = { + { 58.395f16, 39.3f16, -397.9f16, 3585.9f16, -8.395f16, -93.3f16, 7.9f16, 85.95f16, + 58.395f16, 39.3f16, -397.9f16, 3585.9f16, -8.395f16, -93.3f16, 7.9f16, 85.95f16, + 58.395f16, 39.3f16, -397.9f16, 3585.9f16, -8.395f16, -93.3f16, 7.9f16, 85.95f16, + 58.3951f16, 39.31f16, -397.91f16, 3585.91f16, -8.3951f16, -93.31f16, 7.91f16, 85.951f16}, + { 67.396f16, 39.3f16, -397.9f16, 3676.9f16, -7.396f16, -93.3f16, 7.9f16, 76.96f16, + 67.396f16, 39.3f16, -397.9f16, 3676.9f16, -7.396f16, -93.3f16, 7.9f16, 76.96f16, + 67.396f16, 39.3f16, -397.9f16, 3676.9f16, -7.396f16, -93.3f16, 7.9f16, 76.96f16, + 67.3961f16, 39.31f16, -397.91f16, 3676.91f16, -7.3961f16, -93.31f16, 7.91f16, 76.961f16}, + }; + int i; + + for (i = 0; i < 8; i++) + { + m512s[i].x = (__m512){32+i, 0, i, 0, -i, 0, i - 12, i + 8, + 32+i, 0, i, 0, -i, 0, i - 12, i + 8}; + m512hs[i].x = (__m512h){33+i, 1, i, 2, -i, 0, i - 15, i + 9, + 34+i, 1, i, 2, -i, 0, i - 15, i + 9, + 35+i, 1, i, 2, -i, 0, i - 15, i + 9, + 36+i, 1, i, 2, -i, 0, i - 15, i + 9}; + } + + clear_struct_registers; + for (i = 0; i < 8; i++) + (&fregs.zmm0)[i]._m512[0] = m512s[i].x; + num_fregs = 8; + WRAP_CALL (check_struct_passing1)(m512s[0], m512s[1], m512s[2], m512s[3], + m512s[4], m512s[5], m512s[6], m512s[7]); + WRAP_CALL (check_struct_passing2)(m512_2s); + + clear_struct_registers; + for (i = 0; i < 8; i++) + (&fregs.zmm0)[i]._m512h[0] = m512hs[i].x; + num_fregs = 8; + WRAP_CALL (check_struct_passing1h)(m512hs[0], m512hs[1], m512hs[2], m512hs[3], + m512hs[4], m512hs[5], m512hs[6], m512hs[7]); + WRAP_CALL (check_struct_passing2h)(m512h_2s); +} diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_passing_unions.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_passing_unions.c new file mode 100644 index 00000000000..fa801fbf7ce --- /dev/null +++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_passing_unions.c @@ -0,0 +1,415 @@ +#include "avx512fp16-zmm-check.h" +#include "args.h" + +struct IntegerRegisters iregs; +struct FloatRegisters fregs; +unsigned int num_iregs, num_fregs; + +union un1 +{ + __m512 x; + float f; +}; + +union un2 +{ + __m512 x; + double d; +}; + +union un3 +{ + __m512 x; + __m128 v; +}; + +union un4 +{ + __m512 x; + long double ld; +}; + +union un5 +{ + __m512 x; + int i; +}; + +union un6 +{ + __m512 x; + __m256 v; +}; + +union un1h +{ + __m512 x; + _Float16 f; +}; + +union un1hf +{ + __m512h x; + float f; +}; + +union un1hh +{ + __m512h x; + _Float16 f; +}; + +union un2h +{ + __m512h x; + double d; +}; + +union un3h +{ + __m512h x; + __m128 v; +}; + +union un4h +{ + __m512h x; + long double ld; +}; + +union un5h +{ + __m512h x; + int i; +}; + +union un6h +{ + __m512h x; + __m256 v; +}; + +void +check_union_passing1(union un1 u1 ATTRIBUTE_UNUSED, + union un1 u2 ATTRIBUTE_UNUSED, + union un1 u3 ATTRIBUTE_UNUSED, + union un1 u4 ATTRIBUTE_UNUSED, + union un1 u5 ATTRIBUTE_UNUSED, + union un1 u6 ATTRIBUTE_UNUSED, + union un1 u7 ATTRIBUTE_UNUSED, + union un1 u8 ATTRIBUTE_UNUSED) +{ + /* Check register contents. */ + check_m512_arguments; +} + +void +check_union_passing1h(union un1h u1 ATTRIBUTE_UNUSED, + union un1h u2 ATTRIBUTE_UNUSED, + union un1h u3 ATTRIBUTE_UNUSED, + union un1h u4 ATTRIBUTE_UNUSED, + union un1h u5 ATTRIBUTE_UNUSED, + union un1h u6 ATTRIBUTE_UNUSED, + union un1h u7 ATTRIBUTE_UNUSED, + union un1h u8 ATTRIBUTE_UNUSED) +{ + /* Check register contents. */ + check_m512_arguments; +} + +void +check_union_passing1hf(union un1hf u1 ATTRIBUTE_UNUSED, + union un1hf u2 ATTRIBUTE_UNUSED, + union un1hf u3 ATTRIBUTE_UNUSED, + union un1hf u4 ATTRIBUTE_UNUSED, + union un1hf u5 ATTRIBUTE_UNUSED, + union un1hf u6 ATTRIBUTE_UNUSED, + union un1hf u7 ATTRIBUTE_UNUSED, + union un1hf u8 ATTRIBUTE_UNUSED) +{ + /* Check register contents. */ + check_m512_arguments; +} + +void +check_union_passing1hh(union un1hh u1 ATTRIBUTE_UNUSED, + union un1hh u2 ATTRIBUTE_UNUSED, + union un1hh u3 ATTRIBUTE_UNUSED, + union un1hh u4 ATTRIBUTE_UNUSED, + union un1hh u5 ATTRIBUTE_UNUSED, + union un1hh u6 ATTRIBUTE_UNUSED, + union un1hh u7 ATTRIBUTE_UNUSED, + union un1hh u8 ATTRIBUTE_UNUSED) +{ + /* Check register contents. */ + check_m512_arguments; +} + + +void +check_union_passing2(union un2 u1 ATTRIBUTE_UNUSED, + union un2 u2 ATTRIBUTE_UNUSED, + union un2 u3 ATTRIBUTE_UNUSED, + union un2 u4 ATTRIBUTE_UNUSED, + union un2 u5 ATTRIBUTE_UNUSED, + union un2 u6 ATTRIBUTE_UNUSED, + union un2 u7 ATTRIBUTE_UNUSED, + union un2 u8 ATTRIBUTE_UNUSED) +{ + /* Check register contents. */ + check_m512_arguments; +} + +void +check_union_passing2h(union un2h u1 ATTRIBUTE_UNUSED, + union un2h u2 ATTRIBUTE_UNUSED, + union un2h u3 ATTRIBUTE_UNUSED, + union un2h u4 ATTRIBUTE_UNUSED, + union un2h u5 ATTRIBUTE_UNUSED, + union un2h u6 ATTRIBUTE_UNUSED, + union un2h u7 ATTRIBUTE_UNUSED, + union un2h u8 ATTRIBUTE_UNUSED) +{ + /* Check register contents. */ + check_m512_arguments; +} + +void +check_union_passing3(union un3 u1 ATTRIBUTE_UNUSED, + union un3 u2 ATTRIBUTE_UNUSED, + union un3 u3 ATTRIBUTE_UNUSED, + union un3 u4 ATTRIBUTE_UNUSED, + union un3 u5 ATTRIBUTE_UNUSED, + union un3 u6 ATTRIBUTE_UNUSED, + union un3 u7 ATTRIBUTE_UNUSED, + union un3 u8 ATTRIBUTE_UNUSED) +{ + /* Check register contents. */ + check_m512_arguments; +} + +void +check_union_passing3h(union un3h u1 ATTRIBUTE_UNUSED, + union un3h u2 ATTRIBUTE_UNUSED, + union un3h u3 ATTRIBUTE_UNUSED, + union un3h u4 ATTRIBUTE_UNUSED, + union un3h u5 ATTRIBUTE_UNUSED, + union un3h u6 ATTRIBUTE_UNUSED, + union un3h u7 ATTRIBUTE_UNUSED, + union un3h u8 ATTRIBUTE_UNUSED) +{ + /* Check register contents. */ + check_m512_arguments; +} + +void +check_union_passing4(union un4 u ATTRIBUTE_UNUSED) +{ + /* Check the passing on the stack by comparing the address of the + stack elements to the expected place on the stack. */ + assert ((unsigned long)&u.x == rsp+8); + assert ((unsigned long)&u.ld == rsp+8); +} + +void +check_union_passing4h(union un4h u ATTRIBUTE_UNUSED) +{ + /* Check the passing on the stack by comparing the address of the + stack elements to the expected place on the stack. */ + assert ((unsigned long)&u.x == rsp+8); + assert ((unsigned long)&u.ld == rsp+8); +} + +void +check_union_passing5(union un5 u ATTRIBUTE_UNUSED) +{ + /* Check the passing on the stack by comparing the address of the + stack elements to the expected place on the stack. */ + assert ((unsigned long)&u.x == rsp+8); + assert ((unsigned long)&u.i == rsp+8); +} + +void +check_union_passing5h(union un5h u ATTRIBUTE_UNUSED) +{ + /* Check the passing on the stack by comparing the address of the + stack elements to the expected place on the stack. */ + assert ((unsigned long)&u.x == rsp+8); + assert ((unsigned long)&u.i == rsp+8); +} + +void +check_union_passing6(union un6 u1 ATTRIBUTE_UNUSED, + union un6 u2 ATTRIBUTE_UNUSED, + union un6 u3 ATTRIBUTE_UNUSED, + union un6 u4 ATTRIBUTE_UNUSED, + union un6 u5 ATTRIBUTE_UNUSED, + union un6 u6 ATTRIBUTE_UNUSED, + union un6 u7 ATTRIBUTE_UNUSED, + union un6 u8 ATTRIBUTE_UNUSED) +{ + /* Check register contents. */ + check_m512_arguments; +} + +void +check_union_passing6h(union un6h u1 ATTRIBUTE_UNUSED, + union un6h u2 ATTRIBUTE_UNUSED, + union un6h u3 ATTRIBUTE_UNUSED, + union un6h u4 ATTRIBUTE_UNUSED, + union un6h u5 ATTRIBUTE_UNUSED, + union un6h u6 ATTRIBUTE_UNUSED, + union un6h u7 ATTRIBUTE_UNUSED, + union un6h u8 ATTRIBUTE_UNUSED) +{ + /* Check register contents. */ + check_m512_arguments; +} + +#define check_union_passing1 WRAP_CALL(check_union_passing1) +#define check_union_passing2 WRAP_CALL(check_union_passing2) +#define check_union_passing3 WRAP_CALL(check_union_passing3) +#define check_union_passing4 WRAP_CALL(check_union_passing4) +#define check_union_passing5 WRAP_CALL(check_union_passing5) +#define check_union_passing6 WRAP_CALL(check_union_passing6) + +#define check_union_passing1h WRAP_CALL(check_union_passing1h) +#define check_union_passing1hf WRAP_CALL(check_union_passing1hf) +#define check_union_passing1hh WRAP_CALL(check_union_passing1hh) +#define check_union_passing2h WRAP_CALL(check_union_passing2h) +#define check_union_passing3h WRAP_CALL(check_union_passing3h) +#define check_union_passing4h WRAP_CALL(check_union_passing4h) +#define check_union_passing5h WRAP_CALL(check_union_passing5h) +#define check_union_passing6h WRAP_CALL(check_union_passing6h) + + +static void +do_test (void) +{ + union un1 u1[8]; + union un2 u2[8]; + union un3 u3[8]; + union un4 u4; + union un5 u5; + union un6 u6[8]; + union un1h u1h[8]; + union un1hf u1hf[8]; + union un1hh u1hh[8]; + union un2h u2h[8]; + union un3h u3h[8]; + union un4h u4h; + union un5h u5h; + union un6h u6h[8]; + int i; + + for (i = 0; i < 8; i++) + { + u1[i].x = (__m512){32+i, 0, i, 0, -i, 0, i - 12, i + 8, + 32+i, 0, i, 0, -i, 0, i - 12, i + 8}; + + u1hf[i].x = (__m512h){ 33+i, 1, i, 2, -i, 0, i - 15, i + 9, + 34+i, 1, i, 2, -i, 0, i - 15, i + 9, + 35+i, 1, i, 2, -i, 0, i - 15, i + 9, + 36+i, 1, i, 2, -i, 0, i - 15, i + 9}; + } + + clear_struct_registers; + for (i = 0; i < 8; i++) + (&fregs.zmm0)[i]._m512[0] = u1[i].x; + num_fregs = 8; + check_union_passing1(u1[0], u1[1], u1[2], u1[3], + u1[4], u1[5], u1[6], u1[7]); + + clear_struct_registers; + for (i = 0; i < 8; i++) + { + u1h[i].x = u1[i].x; + (&fregs.zmm0)[i]._m512[0] = u1h[i].x; + } + num_fregs = 8; + check_union_passing1h(u1h[0], u1h[1], u1h[2], u1h[3], + u1h[4], u1h[5], u1h[6], u1h[7]); + + clear_struct_registers; + for (i = 0; i < 8; i++) + (&fregs.zmm0)[i]._m512h[0] = u1hf[i].x; + num_fregs = 8; + check_union_passing1hf(u1hf[0], u1hf[1], u1hf[2], u1hf[3], + u1hf[4], u1hf[5], u1hf[6], u1hf[7]); + + clear_struct_registers; + for (i = 0; i < 8; i++) + { + u1hh[i].x = u1hf[i].x; + (&fregs.zmm0)[i]._m512h[0] = u1hh[i].x; + } + num_fregs = 8; + check_union_passing1hh(u1hh[0], u1hh[1], u1hh[2], u1hh[3], + u1hh[4], u1hh[5], u1hh[6], u1hh[7]); + + clear_struct_registers; + for (i = 0; i < 8; i++) + { + u2[i].x = u1[i].x; + (&fregs.zmm0)[i]._m512[0] = u2[i].x; + } + num_fregs = 8; + check_union_passing2(u2[0], u2[1], u2[2], u2[3], + u2[4], u2[5], u2[6], u2[7]); + + clear_struct_registers; + for (i = 0; i < 8; i++) + { + u2h[i].x = u1hf[i].x; + (&fregs.zmm0)[i]._m512h[0] = u2h[i].x; + } + num_fregs = 8; + check_union_passing2h(u2h[0], u2h[1], u2h[2], u2h[3], + u2h[4], u2h[5], u2h[6], u2h[7]); + + clear_struct_registers; + for (i = 0; i < 8; i++) + { + u3[i].x = u1[i].x; + (&fregs.zmm0)[i]._m512[0] = u3[i].x; + } + num_fregs = 8; + check_union_passing3(u3[0], u3[1], u3[2], u3[3], + u3[4], u3[5], u3[6], u3[7]); + + clear_struct_registers; + for (i = 0; i < 8; i++) + { + u3h[i].x = u1hf[i].x; + (&fregs.zmm0)[i]._m512h[0] = u3h[i].x; + } + num_fregs = 8; + check_union_passing3h(u3h[0], u3h[1], u3h[2], u3h[3], + u3h[4], u3h[5], u3h[6], u3h[7]); + + check_union_passing4(u4); + check_union_passing5(u5); + + check_union_passing4h(u4h); + check_union_passing5h(u5h); + + clear_struct_registers; + for (i = 0; i < 8; i++) + { + u6[i].x = u1[i].x; + (&fregs.zmm0)[i]._m512[0] = u6[i].x; + } + num_fregs = 8; + check_union_passing6(u6[0], u6[1], u6[2], u6[3], + u6[4], u6[5], u6[6], u6[7]); + + clear_struct_registers; + for (i = 0; i < 8; i++) + { + u6h[i].x = u1hf[i].x; + (&fregs.zmm0)[i]._m512h[0] = u6h[i].x; + } + num_fregs = 8; + check_union_passing6h(u6h[0], u6h[1], u6h[2], u6h[3], + u6h[4], u6h[5], u6h[6], u6h[7]); +} diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_varargs-m512.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_varargs-m512.c new file mode 100644 index 00000000000..e6d165a8247 --- /dev/null +++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_varargs-m512.c @@ -0,0 +1,164 @@ +/* Test variable number of 512-bit vector arguments passed to functions. */ + +#include +#include "avx512fp16-zmm-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); +} + +void +fun_check_passing_m512h_varargs (__m512h i0, __m512h i1, __m512h i2, + __m512h i3, ...) +{ + /* Check argument values. */ + void **fp = __builtin_frame_address (0); + void *ra = __builtin_return_address (0); + __m512h *argp; + + compare (values.i0, i0, __m512h); + compare (values.i1, i1, __m512h); + compare (values.i2, i2, __m512h); + compare (values.i3, i3, __m512h); + + /* Get the pointer to the return address on stack. */ + while (*fp != ra) + fp++; + + /* Skip the return address stack slot. */ + argp = (__m512h *)(((char *) fp) + 8); + + /* Check __m512h arguments passed on stack. */ + compare (values.i4, argp[0], __m512h); + compare (values.i5, argp[1], __m512h); + compare (values.i6, argp[2], __m512h); + compare (values.i7, argp[3], __m512h); + compare (values.i8, argp[4], __m512h); + compare (values.i9, argp[5], __m512h); + + /* Check register contents. */ + compare (fregs.zmm0, zmm_regs[0], __m512h); + compare (fregs.zmm1, zmm_regs[1], __m512h); + compare (fregs.zmm2, zmm_regs[2], __m512h); + compare (fregs.zmm3, zmm_regs[3], __m512h); +} + +#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 +test_m512h_varargs (void) +{ + __m512h x[10]; + int i; + for (i = 0; i < 10; i++) + x[i] = (__m512h) { + 1.1f16 + i, 2.2f16 + i, 3.3f16 + i, 4.4f16 + i, + 5.5f16 + i, 6.6f16 + i, 7.7f16 + i, 8.8f16 + i, + 9.9f16 + i, 10.10f16 + i, 11.11f16 + i, 12.12f16 + i, + 13.13f16 + i, 14.14f16 + i, 15.15f16 + i, 16.16f16 + i, + 17.17f16 + i, 18.18f16 + i, 19.19f16 + i, 20.20f16 + i, + 21.21f16 + i, 22.22f16 + i, 23.23f16 + i, 24.24f16 + i, + 25.25f16 + i, 26.26f16 + i, 27.27f16 + i, 28.28f16 + i, + 29.29f16 + i, 30.30f16 + i, 31.31f16 + i, 32.32f16 + i + }; + pass = "m512h-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_m512h_varargs, + _m512h); +} + +void +do_test (void) +{ + test_m512_varargs (); + test_m512h_varargs (); + if (failed) + abort (); +}