[PATCH 05/62] AVX512FP16: Add ABI test for ymm.

liuhongt hongtao.liu@intel.com
Thu Jul 1 06:15:51 GMT 2021


gcc/testsuite/ChangeLog:

	* gcc.target/x86_64/abi/avx512fp16/m256h/abi-avx512fp16-ymm.exp:
	New exp file.
	* gcc.target/x86_64/abi/avx512fp16/m256h/args.h: New header.
	* gcc.target/x86_64/abi/avx512fp16/m256h/avx512fp16-ymm-check.h:
	Likewise.
	* gcc.target/x86_64/abi/avx512fp16/m256h/asm-support.S: New.
	* gcc.target/x86_64/abi/avx512fp16/m256h/test_m256_returning.c:
	New test.
	* gcc.target/x86_64/abi/avx512fp16/m256h/test_passing_m256.c: Likewise.
	* gcc.target/x86_64/abi/avx512fp16/m256h/test_passing_structs.c:
	Likewise.
	* gcc.target/x86_64/abi/avx512fp16/m256h/test_passing_unions.c:
	Likewise.
	* gcc.target/x86_64/abi/avx512fp16/m256h/test_varargs-m256.c: Likewise.
---
 .../avx512fp16/m256h/abi-avx512fp16-ymm.exp   |  45 +++
 .../x86_64/abi/avx512fp16/m256h/args.h        | 182 +++++++++
 .../x86_64/abi/avx512fp16/m256h/asm-support.S |  81 ++++
 .../avx512fp16/m256h/avx512fp16-ymm-check.h   |   3 +
 .../avx512fp16/m256h/test_m256_returning.c    |  54 +++
 .../abi/avx512fp16/m256h/test_passing_m256.c  | 370 ++++++++++++++++++
 .../avx512fp16/m256h/test_passing_structs.c   | 113 ++++++
 .../avx512fp16/m256h/test_passing_unions.c    | 337 ++++++++++++++++
 .../abi/avx512fp16/m256h/test_varargs-m256.c  | 160 ++++++++
 9 files changed, 1345 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/abi-avx512fp16-ymm.exp
 create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/args.h
 create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/asm-support.S
 create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/avx512fp16-ymm-check.h
 create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_m256_returning.c
 create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_passing_m256.c
 create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_passing_structs.c
 create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_passing_unions.c
 create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_varargs-m256.c

diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/abi-avx512fp16-ymm.exp b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/abi-avx512fp16-ymm.exp
new file mode 100644
index 00000000000..ecf673bf796
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/abi-avx512fp16-ymm.exp
@@ -0,0 +1,45 @@
+# 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
+# <http://www.gnu.org/licenses/>.
+
+# 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 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
+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
+    }
+}
+
+torture-finish
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/args.h b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/args.h
new file mode 100644
index 00000000000..136db48c144
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/args.h
@@ -0,0 +1,182 @@
+#ifndef INCLUDED_ARGS_H
+#define INCLUDED_ARGS_H
+
+#include <immintrin.h>
+#include <string.h>
+
+/* 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 ymm0
+#define F1 ymm1
+#define F2 ymm2
+#define F3 ymm3
+#define F4 ymm4
+#define F5 ymm5
+#define F6 ymm6
+#define F7 ymm7
+
+typedef union {
+  _Float16 __Float16[16];
+  float _float[8];
+  double _double[4];
+  long _long[4];
+  int _int[8];
+  unsigned long _ulong[4];
+  __m64 _m64[4];
+  __m128 _m128[2];
+  __m256 _m256[1];
+  __m256h _m256h[1];
+} YMM_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;
+YMM_T ymm_regs[16];
+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;
+  YMM_T ymm0, ymm1, ymm2, ymm3, ymm4, ymm5, ymm6, ymm7, ymm8, ymm9,
+        ymm10, ymm11, ymm12, ymm13, ymm14, ymm15;
+};
+
+/* 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 (ymm_regs, 0, sizeof (ymm_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.ymm0._ ## T [0] == ymm_regs[0]._ ## T [0]); \
+  assert (num_fregs <= 1 || fregs.ymm1._ ## T [0] == ymm_regs[1]._ ## T [0]); \
+  assert (num_fregs <= 2 || fregs.ymm2._ ## T [0] == ymm_regs[2]._ ## T [0]); \
+  assert (num_fregs <= 3 || fregs.ymm3._ ## T [0] == ymm_regs[3]._ ## T [0]); \
+  assert (num_fregs <= 4 || fregs.ymm4._ ## T [0] == ymm_regs[4]._ ## T [0]); \
+  assert (num_fregs <= 5 || fregs.ymm5._ ## T [0] == ymm_regs[5]._ ## T [0]); \
+  assert (num_fregs <= 6 || fregs.ymm6._ ## T [0] == ymm_regs[6]._ ## T [0]); \
+  assert (num_fregs <= 7 || fregs.ymm7._ ## T [0] == ymm_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.ymm0) + (O), \
+		     &ymm_regs[0], \
+		     sizeof (__ ## T) - (O)) == 0); \
+  assert (num_fregs <= 1 \
+	  || memcmp (((char *) &fregs.ymm1) + (O), \
+		     &ymm_regs[1], \
+		     sizeof (__ ## T) - (O)) == 0); \
+  assert (num_fregs <= 2 \
+	  || memcmp (((char *) &fregs.ymm2) + (O), \
+		     &ymm_regs[2], \
+		     sizeof (__ ## T) - (O)) == 0); \
+  assert (num_fregs <= 3 \
+	  || memcmp (((char *) &fregs.ymm3) + (O), \
+		     &ymm_regs[3], \
+		     sizeof (__ ## T) - (O)) == 0); \
+  assert (num_fregs <= 4 \
+	  || memcmp (((char *) &fregs.ymm4) + (O), \
+		     &ymm_regs[4], \
+		     sizeof (__ ## T) - (O)) == 0); \
+  assert (num_fregs <= 5 \
+	  || memcmp (((char *) &fregs.ymm5) + (O), \
+		     &ymm_regs[5], \
+		     sizeof (__ ## T) - (O)) == 0); \
+  assert (num_fregs <= 6 \
+	  || memcmp (((char *) &fregs.ymm6) + (O), \
+		     &ymm_regs[6], \
+		     sizeof (__ ## T) - (O)) == 0); \
+  assert (num_fregs <= 7 \
+	  || memcmp (((char *) &fregs.ymm7) + (O), \
+		     &ymm_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)
+
+#endif /* INCLUDED_ARGS_H  */
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/asm-support.S b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/asm-support.S
new file mode 100644
index 00000000000..73a59191d6d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/asm-support.S
@@ -0,0 +1,81 @@
+	.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)
+	vmovdqu	%ymm0, ymm_regs+0(%rip)
+	vmovdqu	%ymm1, ymm_regs+32(%rip)
+	vmovdqu	%ymm2, ymm_regs+64(%rip)
+	vmovdqu	%ymm3, ymm_regs+96(%rip)
+	vmovdqu	%ymm4, ymm_regs+128(%rip)
+	vmovdqu	%ymm5, ymm_regs+160(%rip)
+	vmovdqu	%ymm6, ymm_regs+192(%rip)
+	vmovdqu	%ymm7, ymm_regs+224(%rip)
+	vmovdqu	%ymm8, ymm_regs+256(%rip)
+	vmovdqu	%ymm9, ymm_regs+288(%rip)
+	vmovdqu	%ymm10, ymm_regs+320(%rip)
+	vmovdqu	%ymm11, ymm_regs+352(%rip)
+	vmovdqu	%ymm12, ymm_regs+384(%rip)
+	vmovdqu	%ymm13, ymm_regs+416(%rip)
+	vmovdqu	%ymm14, ymm_regs+448(%rip)
+	vmovdqu	%ymm15, ymm_regs+480(%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)
+	vmovdqu	%ymm0, ymm_regs+0(%rip)
+	vmovdqu	%ymm1, ymm_regs+32(%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	ymm_regs,512,32
+	.comm	x87_regs,128,32
+	.comm   volatile_var,8,8
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/avx512fp16-ymm-check.h b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/avx512fp16-ymm-check.h
new file mode 100644
index 00000000000..6a55030c0d4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/avx512fp16-ymm-check.h
@@ -0,0 +1,3 @@
+#define AVX512VL(ebx) (ebx & bit_AVX512VL)
+#define XSTATE_MASK (XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK)
+#include "../avx512fp16-check.h"
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_m256_returning.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_m256_returning.c
new file mode 100644
index 00000000000..48e0139f416
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_m256_returning.c
@@ -0,0 +1,54 @@
+#include <stdio.h>
+#include "avx512fp16-ymm-check.h"
+#include "args.h"
+
+struct IntegerRegisters iregs;
+struct FloatRegisters fregs;
+unsigned int num_iregs, num_fregs;
+
+__m256
+fun_test_returning___m256 (void)
+{
+  volatile_var++;
+  return (__m256){73,0,0,0,0,0,0,0};
+}
+
+__m256h
+fun_test_returning___m256h (void)
+{
+  volatile_var++;
+  return (__m256h){1.1f16,2.1f16,3.1f16,4.1f16,
+                   5.1f16,6.1f16,7.1f16,8.1f16,
+                   9.1f16,10.1f16,11.1f16,12.1f16,
+		   13.1f16,14.1f16,15.1f16,16.1f16};
+}
+
+__m256 test_256;
+__m256h test_256h;
+
+static void
+do_test (void)
+{
+  unsigned failed = 0;
+  YMM_T ymmt1, ymmt2;
+
+  clear_struct_registers;
+  test_256 = (__m256){73,0,0,0,0,0,0,0};
+  ymmt1._m256[0] = test_256;
+  ymmt2._m256[0] = WRAP_RET (fun_test_returning___m256)();
+  if (memcmp (&ymmt1, &ymmt2, sizeof (ymmt2)) != 0)
+    printf ("fail m256\n"), failed++;
+
+  clear_struct_registers;
+  test_256h = (__m256h){1.1f16,2.1f16,3.1f16,4.1f16,
+                        5.1f16,6.1f16,7.1f16,8.1f16,
+                        9.1f16,10.1f16,11.1f16,12.1f16,
+			13.1f16,14.1f16,15.1f16,16.1f16};
+  ymmt1._m256h[0] = test_256h;
+  ymmt2._m256h[0] = WRAP_RET (fun_test_returning___m256h)();
+  if (memcmp (&ymmt1, &ymmt2, sizeof (ymmt2)) != 0)
+    printf ("fail m256h\n"), failed++;
+
+  if (failed)
+    abort ();
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_passing_m256.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_passing_m256.c
new file mode 100644
index 00000000000..bfa80d616ee
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_passing_m256.c
@@ -0,0 +1,370 @@
+#include <stdio.h>
+#include "avx512fp16-ymm-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
+{
+  YMM_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_m256_8_values (__m256 i0 ATTRIBUTE_UNUSED,
+				 __m256 i1 ATTRIBUTE_UNUSED,
+				 __m256 i2 ATTRIBUTE_UNUSED,
+				 __m256 i3 ATTRIBUTE_UNUSED,
+				 __m256 i4 ATTRIBUTE_UNUSED,
+				 __m256 i5 ATTRIBUTE_UNUSED,
+				 __m256 i6 ATTRIBUTE_UNUSED,
+				 __m256 i7 ATTRIBUTE_UNUSED)
+{
+  /* Check argument values.  */
+  compare (values.i0, i0, __m256);
+  compare (values.i1, i1, __m256);
+  compare (values.i2, i2, __m256);
+  compare (values.i3, i3, __m256);
+  compare (values.i4, i4, __m256);
+  compare (values.i5, i5, __m256);
+  compare (values.i6, i6, __m256);
+  compare (values.i7, i7, __m256);
+}
+
+fun_check_passing_m256h_8_values (__m256h i0 ATTRIBUTE_UNUSED,
+				  __m256h i1 ATTRIBUTE_UNUSED,
+				  __m256h i2 ATTRIBUTE_UNUSED,
+				  __m256h i3 ATTRIBUTE_UNUSED,
+				  __m256h i4 ATTRIBUTE_UNUSED,
+				  __m256h i5 ATTRIBUTE_UNUSED,
+				  __m256h i6 ATTRIBUTE_UNUSED,
+				  __m256h i7 ATTRIBUTE_UNUSED)
+{
+  /* Check argument values.  */
+  compare (values.i0, i0, __m256h);
+  compare (values.i1, i1, __m256h);
+  compare (values.i2, i2, __m256h);
+  compare (values.i3, i3, __m256h);
+  compare (values.i4, i4, __m256h);
+  compare (values.i5, i5, __m256h);
+  compare (values.i6, i6, __m256h);
+  compare (values.i7, i7, __m256h);
+}
+
+void
+fun_check_passing_m256_8_regs (__m256 i0 ATTRIBUTE_UNUSED,
+			       __m256 i1 ATTRIBUTE_UNUSED,
+			       __m256 i2 ATTRIBUTE_UNUSED,
+			       __m256 i3 ATTRIBUTE_UNUSED,
+			       __m256 i4 ATTRIBUTE_UNUSED,
+			       __m256 i5 ATTRIBUTE_UNUSED,
+			       __m256 i6 ATTRIBUTE_UNUSED,
+			       __m256 i7 ATTRIBUTE_UNUSED)
+{
+  /* Check register contents.  */
+  check_m256_arguments;
+}
+
+void
+fun_check_passing_m256h_8_regs (__m256h i0 ATTRIBUTE_UNUSED,
+				__m256h i1 ATTRIBUTE_UNUSED,
+				__m256h i2 ATTRIBUTE_UNUSED,
+				__m256h i3 ATTRIBUTE_UNUSED,
+				__m256h i4 ATTRIBUTE_UNUSED,
+				__m256h i5 ATTRIBUTE_UNUSED,
+				__m256h i6 ATTRIBUTE_UNUSED,
+				__m256h i7 ATTRIBUTE_UNUSED)
+{
+  /* Check register contents.  */
+  check_m256_arguments;
+}
+
+void
+fun_check_passing_m256_20_values (__m256 i0 ATTRIBUTE_UNUSED,
+				  __m256 i1 ATTRIBUTE_UNUSED,
+				  __m256 i2 ATTRIBUTE_UNUSED,
+				  __m256 i3 ATTRIBUTE_UNUSED,
+				  __m256 i4 ATTRIBUTE_UNUSED,
+				  __m256 i5 ATTRIBUTE_UNUSED,
+				  __m256 i6 ATTRIBUTE_UNUSED,
+				  __m256 i7 ATTRIBUTE_UNUSED,
+				  __m256 i8 ATTRIBUTE_UNUSED,
+				  __m256 i9 ATTRIBUTE_UNUSED,
+				  __m256 i10 ATTRIBUTE_UNUSED,
+				  __m256 i11 ATTRIBUTE_UNUSED,
+				  __m256 i12 ATTRIBUTE_UNUSED,
+				  __m256 i13 ATTRIBUTE_UNUSED,
+				  __m256 i14 ATTRIBUTE_UNUSED,
+				  __m256 i15 ATTRIBUTE_UNUSED,
+				  __m256 i16 ATTRIBUTE_UNUSED,
+				  __m256 i17 ATTRIBUTE_UNUSED,
+				  __m256 i18 ATTRIBUTE_UNUSED,
+				  __m256 i19 ATTRIBUTE_UNUSED)
+{
+  /* Check argument values.  */
+  compare (values.i0, i0, __m256);
+  compare (values.i1, i1, __m256);
+  compare (values.i2, i2, __m256);
+  compare (values.i3, i3, __m256);
+  compare (values.i4, i4, __m256);
+  compare (values.i5, i5, __m256);
+  compare (values.i6, i6, __m256);
+  compare (values.i7, i7, __m256);
+  compare (values.i8, i8, __m256);
+  compare (values.i9, i9, __m256);
+  compare (values.i10, i10, __m256);
+  compare (values.i11, i11, __m256);
+  compare (values.i12, i12, __m256);
+  compare (values.i13, i13, __m256);
+  compare (values.i14, i14, __m256);
+  compare (values.i15, i15, __m256);
+  compare (values.i16, i16, __m256);
+  compare (values.i17, i17, __m256);
+  compare (values.i18, i18, __m256);
+  compare (values.i19, i19, __m256);
+}
+
+void
+fun_check_passing_m256h_20_values (__m256h i0 ATTRIBUTE_UNUSED,
+				   __m256h i1 ATTRIBUTE_UNUSED,
+				   __m256h i2 ATTRIBUTE_UNUSED,
+				   __m256h i3 ATTRIBUTE_UNUSED,
+				   __m256h i4 ATTRIBUTE_UNUSED,
+				   __m256h i5 ATTRIBUTE_UNUSED,
+				   __m256h i6 ATTRIBUTE_UNUSED,
+				   __m256h i7 ATTRIBUTE_UNUSED,
+				   __m256h i8 ATTRIBUTE_UNUSED,
+				   __m256h i9 ATTRIBUTE_UNUSED,
+				   __m256h i10 ATTRIBUTE_UNUSED,
+				   __m256h i11 ATTRIBUTE_UNUSED,
+				   __m256h i12 ATTRIBUTE_UNUSED,
+				   __m256h i13 ATTRIBUTE_UNUSED,
+				   __m256h i14 ATTRIBUTE_UNUSED,
+				   __m256h i15 ATTRIBUTE_UNUSED,
+				   __m256h i16 ATTRIBUTE_UNUSED,
+				   __m256h i17 ATTRIBUTE_UNUSED,
+				   __m256h i18 ATTRIBUTE_UNUSED,
+				   __m256h i19 ATTRIBUTE_UNUSED)
+{
+  /* Check argument values.  */
+  compare (values.i0, i0, __m256h);
+  compare (values.i1, i1, __m256h);
+  compare (values.i2, i2, __m256h);
+  compare (values.i3, i3, __m256h);
+  compare (values.i4, i4, __m256h);
+  compare (values.i5, i5, __m256h);
+  compare (values.i6, i6, __m256h);
+  compare (values.i7, i7, __m256h);
+  compare (values.i8, i8, __m256h);
+  compare (values.i9, i9, __m256h);
+  compare (values.i10, i10, __m256h);
+  compare (values.i11, i11, __m256h);
+  compare (values.i12, i12, __m256h);
+  compare (values.i13, i13, __m256h);
+  compare (values.i14, i14, __m256h);
+  compare (values.i15, i15, __m256h);
+  compare (values.i16, i16, __m256h);
+  compare (values.i17, i17, __m256h);
+  compare (values.i18, i18, __m256h);
+  compare (values.i19, i19, __m256h);
+}
+
+void
+fun_check_passing_m256_20_regs (__m256 i0 ATTRIBUTE_UNUSED,
+				__m256 i1 ATTRIBUTE_UNUSED,
+				__m256 i2 ATTRIBUTE_UNUSED,
+				__m256 i3 ATTRIBUTE_UNUSED,
+				__m256 i4 ATTRIBUTE_UNUSED,
+				__m256 i5 ATTRIBUTE_UNUSED,
+				__m256 i6 ATTRIBUTE_UNUSED,
+				__m256 i7 ATTRIBUTE_UNUSED,
+				__m256 i8 ATTRIBUTE_UNUSED,
+				__m256 i9 ATTRIBUTE_UNUSED,
+				__m256 i10 ATTRIBUTE_UNUSED,
+				__m256 i11 ATTRIBUTE_UNUSED,
+				__m256 i12 ATTRIBUTE_UNUSED,
+				__m256 i13 ATTRIBUTE_UNUSED,
+				__m256 i14 ATTRIBUTE_UNUSED,
+				__m256 i15 ATTRIBUTE_UNUSED,
+				__m256 i16 ATTRIBUTE_UNUSED,
+				__m256 i17 ATTRIBUTE_UNUSED,
+				__m256 i18 ATTRIBUTE_UNUSED,
+				__m256 i19 ATTRIBUTE_UNUSED)
+{
+  /* Check register contents.  */
+  check_m256_arguments;
+}
+
+void
+fun_check_passing_m256h_20_regs (__m256h i0 ATTRIBUTE_UNUSED,
+				 __m256h i1 ATTRIBUTE_UNUSED,
+				 __m256h i2 ATTRIBUTE_UNUSED,
+				 __m256h i3 ATTRIBUTE_UNUSED,
+				 __m256h i4 ATTRIBUTE_UNUSED,
+				 __m256h i5 ATTRIBUTE_UNUSED,
+				 __m256h i6 ATTRIBUTE_UNUSED,
+				 __m256h i7 ATTRIBUTE_UNUSED,
+				 __m256h i8 ATTRIBUTE_UNUSED,
+				 __m256h i9 ATTRIBUTE_UNUSED,
+				 __m256h i10 ATTRIBUTE_UNUSED,
+				 __m256h i11 ATTRIBUTE_UNUSED,
+				 __m256h i12 ATTRIBUTE_UNUSED,
+				 __m256h i13 ATTRIBUTE_UNUSED,
+				 __m256h i14 ATTRIBUTE_UNUSED,
+				 __m256h i15 ATTRIBUTE_UNUSED,
+				 __m256h i16 ATTRIBUTE_UNUSED,
+				 __m256h i17 ATTRIBUTE_UNUSED,
+				 __m256h i18 ATTRIBUTE_UNUSED,
+				 __m256h i19 ATTRIBUTE_UNUSED)
+{
+  /* Check register contents.  */
+  check_m256_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_m256_on_stack ()
+{
+  __m256 x[8];
+  int i;
+  for (i = 0; i < 8; i++)
+    x[i] = (__m256){32 + i, 0, 0, 0, 0, 0, 0, 0};
+  pass = "m256-8";
+  def_check_passing8 (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7],
+		      fun_check_passing_m256_8_values,
+		      fun_check_passing_m256_8_regs, _m256);
+}
+
+void
+test_m256h_on_stack ()
+{
+  __m256h x[8];
+  int i;
+  for (i = 0; i < 8; i++)
+    x[i] = (__m256h){1.1f16 + i, 2.1f16 + i, 3.1f16 + i, 4.1f16 + i,
+	             5.1f16 + i, 6.1f16 + i, 7.1f16 + i, 8.1f16 + i,
+	             9.1f16 + i, 10.1f16 + i, 11.1f16 + i, 12.1f16 + i,
+	             13.1f16 + i, 14.1f16 + i, 15.1f16 + i, 16.1f16 + i};
+  pass = "m256h-8";
+  def_check_passing8 (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7],
+		      fun_check_passing_m256h_8_values,
+		      fun_check_passing_m256h_8_regs, _m256h);
+}
+
+void
+test_too_many_m256 ()
+{
+  __m256 x[20];
+  int i;
+  for (i = 0; i < 20; i++)
+    x[i] = (__m256){32 + i, 0, 0, 0, 0, 0, 0, 0};
+  pass = "m256-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_m256_20_values,
+		       fun_check_passing_m256_20_regs, _m256);
+}
+
+void
+test_too_many_m256h ()
+{
+  __m256h x[20];
+  int i;
+  for (i = 0; i < 20; i++)
+    x[i] = (__m256h){1.1f16 + i, 2.1f16 + i, 3.1f16 + i, 4.1f16 + i,
+	             5.1f16 + i, 6.1f16 + i, 7.1f16 + i, 8.1f16 + i,
+	             9.1f16 + i, 10.1f16 + i, 11.1f16 + i, 12.1f16 + i,
+	             13.1f16 + i, 14.1f16 + i, 15.1f16 + i, 16.1f16 + i};
+  pass = "m256h-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_m256h_20_values,
+		       fun_check_passing_m256h_20_regs, _m256h);
+}
+
+static void
+do_test (void)
+{
+  test_m256_on_stack ();
+  test_too_many_m256 ();
+  test_m256h_on_stack ();
+  test_too_many_m256h ();
+  if (failed)
+    abort ();
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_passing_structs.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_passing_structs.c
new file mode 100644
index 00000000000..eff10badd6b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_passing_structs.c
@@ -0,0 +1,113 @@
+#include "avx512fp16-ymm-check.h"
+#include "args.h"
+
+struct IntegerRegisters iregs;
+struct FloatRegisters fregs;
+unsigned int num_iregs, num_fregs;
+
+struct m256_struct
+{
+  __m256 x;
+};
+
+struct m256_2_struct
+{
+  __m256 x1, x2;
+};
+
+struct m256h_struct
+{
+  __m256h x;
+};
+
+struct m256h_2_struct
+{
+  __m256h x1, x2;
+};
+
+/* Check that the struct is passed as the individual members in fregs.  */
+void
+check_struct_passing1 (struct m256_struct ms1 ATTRIBUTE_UNUSED,
+		       struct m256_struct ms2 ATTRIBUTE_UNUSED,
+		       struct m256_struct ms3 ATTRIBUTE_UNUSED,
+		       struct m256_struct ms4 ATTRIBUTE_UNUSED,
+		       struct m256_struct ms5 ATTRIBUTE_UNUSED,
+		       struct m256_struct ms6 ATTRIBUTE_UNUSED,
+		       struct m256_struct ms7 ATTRIBUTE_UNUSED,
+		       struct m256_struct ms8 ATTRIBUTE_UNUSED)
+{
+  check_m256_arguments;
+}
+
+void
+check_struct_passing2 (struct m256_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+40);
+}
+
+void
+check_struct_passing1h (struct m256h_struct ms1 ATTRIBUTE_UNUSED,
+		        struct m256h_struct ms2 ATTRIBUTE_UNUSED,
+		        struct m256h_struct ms3 ATTRIBUTE_UNUSED,
+		        struct m256h_struct ms4 ATTRIBUTE_UNUSED,
+		        struct m256h_struct ms5 ATTRIBUTE_UNUSED,
+		        struct m256h_struct ms6 ATTRIBUTE_UNUSED,
+		        struct m256h_struct ms7 ATTRIBUTE_UNUSED,
+		        struct m256h_struct ms8 ATTRIBUTE_UNUSED)
+{
+  check_m256_arguments;
+}
+
+void
+check_struct_passing2h (struct m256h_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+40);
+}
+
+static void
+do_test (void)
+{
+  struct m256_struct m256s [8];
+  struct m256h_struct m256hs [8];
+  struct m256_2_struct m256_2s = { 
+      { 48.394, 39.3, -397.9, 3484.9, -8.394, -93.3, 7.9, 84.94 },
+      { -8.394, -3.3, -39.9, 34.9, 7.9, 84.94, -48.394, 39.3 }
+  };
+  struct m256h_2_struct m256h_2s = { 
+      { 47.364f16, 36.3f16, -367.6f16, 3474.6f16, -7.364f16, -63.3f16, 7.6f16, 74.64f16,
+        57.865f16, 86.8f16, -867.6f16, 8575.6f16, -7.865f16, -68.8f16, 7.6f16, 75.65f16  },
+      { -7.364f16, -3.3f16, -36.6f16, 34.6f16, 7.6f16, 74.64f16, -47.364f16, 36.3f16,
+        -8.364f16, -3.3f16, -36.6f16, 34.6f16, 8.6f16, 84.64f16, -48.364f16, 36.3f16  }
+  };
+  int i;
+
+  for (i = 0; i < 8; i++)
+    {
+      m256s[i].x = (__m256){32+i, 0, i, 0, -i, 0, i - 12, i + 8};
+
+      m256hs[i].x = (__m256h){33+i, 0, i, 0, -i, 0, i - 11, i + 9,
+                              31+i, 2, i, 3, -i, 4, i - 10, i + 7};
+    }
+
+  clear_struct_registers;
+  for (i = 0; i < 8; i++)
+    (&fregs.ymm0)[i]._m256[0] = m256s[i].x;
+  num_fregs = 8;
+  WRAP_CALL (check_struct_passing1)(m256s[0], m256s[1], m256s[2], m256s[3],
+				    m256s[4], m256s[5], m256s[6], m256s[7]);
+  WRAP_CALL (check_struct_passing2)(m256_2s);
+
+  clear_struct_registers;
+  for (i = 0; i < 8; i++)
+    (&fregs.ymm0)[i]._m256h[0] = m256hs[i].x;
+  num_fregs = 8;
+  WRAP_CALL (check_struct_passing1h)(m256hs[0], m256hs[1], m256hs[2], m256hs[3],
+				    m256hs[4], m256hs[5], m256hs[6], m256hs[7]);
+  WRAP_CALL (check_struct_passing2h)(m256h_2s);
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_passing_unions.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_passing_unions.c
new file mode 100644
index 00000000000..76f300c3e5d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_passing_unions.c
@@ -0,0 +1,337 @@
+#include "avx512fp16-ymm-check.h"
+#include "args.h"
+
+struct IntegerRegisters iregs;
+struct FloatRegisters fregs;
+unsigned int num_iregs, num_fregs;
+
+union un1
+{
+  __m256 x;
+  float f;
+};
+
+union un2
+{
+  __m256 x;
+  double d;
+};
+
+union un3
+{
+  __m256 x;
+  __m128 v;
+};
+
+union un4
+{
+  __m256 x;
+  long double ld;
+};
+
+union un5
+{
+  __m256 x;
+  int i;
+};
+
+union un1a
+{
+  __m256 x;
+  _Float16 f;
+};
+
+union un1h
+{
+  __m256h x;
+  float f;
+};
+
+union un1hh
+{
+  __m256h x;
+  _Float16 f;
+};
+
+union un2h
+{
+  __m256h x;
+  double d;
+};
+
+union un3h
+{
+  __m256h x;
+  __m128 v;
+};
+
+union un4h
+{
+  __m256h x;
+  long double ld;
+};
+
+union un5h
+{
+  __m256h x;
+  int i;
+};
+
+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_m256_arguments;
+}
+
+void
+check_union_passing1a(union un1a u1 ATTRIBUTE_UNUSED,
+		      union un1a u2 ATTRIBUTE_UNUSED,
+		      union un1a u3 ATTRIBUTE_UNUSED,
+		      union un1a u4 ATTRIBUTE_UNUSED,
+		      union un1a u5 ATTRIBUTE_UNUSED,
+		      union un1a u6 ATTRIBUTE_UNUSED,
+		      union un1a u7 ATTRIBUTE_UNUSED,
+		      union un1a u8 ATTRIBUTE_UNUSED)
+{
+  check_m256_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_m256_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_m256_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_m256_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_m256_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_m256_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_m256_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);
+}
+
+#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_passing1h WRAP_CALL(check_union_passing1h)
+#define check_union_passing1a WRAP_CALL(check_union_passing1a)
+#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)
+
+static void
+do_test (void)
+{
+  union un1 u1[8];
+  union un2 u2[8];
+  union un3 u3[8];
+  union un4 u4;
+  union un5 u5;
+  union un1a u1a[8];
+  union un1h u1h[8];
+  union un1hh u1hh[8];
+  union un2h u2h[8];
+  union un3h u3h[8];
+  union un4h u4h;
+  union un5h u5h;
+  int i;
+
+  for (i = 0; i < 8; i++)
+    {
+      u1[i].x = (__m256){32+i, 0, i, 0, -i, 0, i - 12, i + 8};
+      u1h[i].x = (__m256h){32+i, 0, i, 0, -i, 0, i - 12, i + 8,
+                           33+i, 1, i, 2, -i, 4, i - 11, i + 9};
+    }
+
+  clear_struct_registers;
+  for (i = 0; i < 8; i++)
+    (&fregs.ymm0)[i]._m256[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++)
+    {
+      u1a[i].x = u1[i].x;
+      (&fregs.ymm0)[i]._m256[0] = u1a[i].x;
+    }
+  num_fregs = 8;
+  check_union_passing1a(u1a[0], u1a[1], u1a[2], u1a[3],
+		        u1a[4], u1a[5], u1a[6], u1a[7]);
+
+  clear_struct_registers;
+  for (i = 0; i < 8; i++)
+    (&fregs.ymm0)[i]._m256h[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++)
+    {
+      u1hh[i].x = u1h[i].x;
+      (&fregs.ymm0)[i]._m256h[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.ymm0)[i]._m256[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 = u1h[i].x;
+      (&fregs.ymm0)[i]._m256h[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.ymm0)[i]._m256[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 = u1h[i].x;
+      (&fregs.ymm0)[i]._m256h[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);
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_varargs-m256.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_varargs-m256.c
new file mode 100644
index 00000000000..f15adb4a33b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_varargs-m256.c
@@ -0,0 +1,160 @@
+/* Test variable number of 256-bit vector arguments passed to functions.  */
+
+#include <stdio.h>
+#include "avx512fp16-ymm-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);
+}
+
+void
+fun_check_passing_m256h_varargs (__m256h i0, __m256h i1, __m256h i2,
+				 __m256h i3, ...)
+{
+  /* Check argument values.  */
+  void **fp = __builtin_frame_address (0);
+  void *ra = __builtin_return_address (0);
+  __m256h *argp;
+
+  compare (values.i0, i0, __m256h);
+  compare (values.i1, i1, __m256h);
+  compare (values.i2, i2, __m256h);
+  compare (values.i3, i3, __m256h);
+
+  /* Get the pointer to the return address on stack.  */
+  while (*fp != ra)
+    fp++;
+
+  /* Skip the return address stack slot.  */
+  argp = (__m256h *)(((char *) fp) + 8);
+
+  /* Check __m256h arguments passed on stack.  */
+  compare (values.i4, argp[0], __m256h);
+  compare (values.i5, argp[1], __m256h);
+  compare (values.i6, argp[2], __m256h);
+  compare (values.i7, argp[3], __m256h);
+  compare (values.i8, argp[4], __m256h);
+  compare (values.i9, argp[5], __m256h);
+
+  /* Check register contents.  */
+  compare (fregs.ymm0, ymm_regs[0], __m256h);
+  compare (fregs.ymm1, ymm_regs[1], __m256h);
+  compare (fregs.ymm2, ymm_regs[2], __m256h);
+  compare (fregs.ymm3, ymm_regs[3], __m256h);
+}
+
+#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
+test_m256h_varargs (void)
+{
+  __m256h x[10];
+  int i;
+  for (i = 0; i < 10; i++)
+    x[i] = (__m256h) {
+        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
+    };
+  pass = "m256h-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_m256h_varargs,
+				 _m256h);
+}
+
+void
+do_test (void)
+{
+  test_m256_varargs ();
+  test_m256h_varargs ();
+  if (failed)
+    abort ();
+}
-- 
2.18.1



More information about the Gcc-patches mailing list