[08/10] AVX512FP16: Add ABI tests for xmm.

Message ID 20210721074347.7689-9-hongtao.liu@intel.com
State New
Headers show
Series
  • Initial support for AVX512FP16
Related show

Commit Message

Ian Lance Taylor via Gcc-patches July 21, 2021, 7:43 a.m.
From: "H.J. Lu" <hjl.tools@gmail.com>


Copied from regular XMM ABI tests. Only run AVX512FP16 ABI tests for ELF
targets.

gcc/testsuite/ChangeLog:

	* gcc.target/x86_64/abi/avx512fp16/abi-avx512fp16-xmm.exp: New exp
	file for abi test.
	* gcc.target/x86_64/abi/avx512fp16/args.h: New header file for abi test.
	* gcc.target/x86_64/abi/avx512fp16/avx512fp16-check.h: Likewise.
	* gcc.target/x86_64/abi/avx512fp16/avx512fp16-xmm-check.h: Likewise.
	* gcc.target/x86_64/abi/avx512fp16/defines.h: Likewise.
	* gcc.target/x86_64/abi/avx512fp16/macros.h: Likewise.
	* gcc.target/x86_64/abi/avx512fp16/asm-support.S: New asm for abi check.
	* gcc.target/x86_64/abi/avx512fp16/test_3_element_struct_and_unions.c:
	New test.
	* gcc.target/x86_64/abi/avx512fp16/test_basic_alignment.c: Likewise.
	* gcc.target/x86_64/abi/avx512fp16/test_basic_array_size_and_align.c:
	Likewise.
	* gcc.target/x86_64/abi/avx512fp16/test_basic_returning.c: Likewise.
	* gcc.target/x86_64/abi/avx512fp16/test_basic_sizes.c: Likewise.
	* gcc.target/x86_64/abi/avx512fp16/test_basic_struct_size_and_align.c:
	Likewise.
	* gcc.target/x86_64/abi/avx512fp16/test_basic_union_size_and_align.c:
	Likewise.
	* gcc.target/x86_64/abi/avx512fp16/test_complex_returning.c: Likewise.
	* gcc.target/x86_64/abi/avx512fp16/test_m64m128_returning.c: Likewise.
	* gcc.target/x86_64/abi/avx512fp16/test_passing_floats.c: Likewise.
	* gcc.target/x86_64/abi/avx512fp16/test_passing_m64m128.c: Likewise.
	* gcc.target/x86_64/abi/avx512fp16/test_passing_structs.c: Likewise.
	* gcc.target/x86_64/abi/avx512fp16/test_passing_unions.c: Likewise.
	* gcc.target/x86_64/abi/avx512fp16/test_struct_returning.c: Likewise.
	* gcc.target/x86_64/abi/avx512fp16/test_varargs-m128.c: Likewise.
---
 .../abi/avx512fp16/abi-avx512fp16-xmm.exp     |   48 +
 .../gcc.target/x86_64/abi/avx512fp16/args.h   |  190 +++
 .../x86_64/abi/avx512fp16/asm-support.S       |   81 ++
 .../x86_64/abi/avx512fp16/avx512fp16-check.h  |   74 ++
 .../abi/avx512fp16/avx512fp16-xmm-check.h     |    3 +
 .../x86_64/abi/avx512fp16/defines.h           |  150 +++
 .../gcc.target/x86_64/abi/avx512fp16/macros.h |   53 +
 .../test_3_element_struct_and_unions.c        |  692 +++++++++++
 .../abi/avx512fp16/test_basic_alignment.c     |   45 +
 .../test_basic_array_size_and_align.c         |   43 +
 .../abi/avx512fp16/test_basic_returning.c     |   87 ++
 .../x86_64/abi/avx512fp16/test_basic_sizes.c  |   43 +
 .../test_basic_struct_size_and_align.c        |   42 +
 .../test_basic_union_size_and_align.c         |   40 +
 .../abi/avx512fp16/test_complex_returning.c   |  104 ++
 .../abi/avx512fp16/test_m64m128_returning.c   |   73 ++
 .../abi/avx512fp16/test_passing_floats.c      | 1066 +++++++++++++++++
 .../abi/avx512fp16/test_passing_m64m128.c     |  510 ++++++++
 .../abi/avx512fp16/test_passing_structs.c     |  332 +++++
 .../abi/avx512fp16/test_passing_unions.c      |  335 ++++++
 .../abi/avx512fp16/test_struct_returning.c    |  274 +++++
 .../x86_64/abi/avx512fp16/test_varargs-m128.c |  164 +++
 22 files changed, 4449 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/abi-avx512fp16-xmm.exp
 create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/args.h
 create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/asm-support.S
 create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/avx512fp16-check.h
 create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/avx512fp16-xmm-check.h
 create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/defines.h
 create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/macros.h
 create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_3_element_struct_and_unions.c
 create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_alignment.c
 create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_array_size_and_align.c
 create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_returning.c
 create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_sizes.c
 create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_struct_size_and_align.c
 create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_union_size_and_align.c
 create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_complex_returning.c
 create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_m64m128_returning.c
 create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_passing_floats.c
 create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_passing_m64m128.c
 create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_passing_structs.c
 create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_passing_unions.c
 create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_struct_returning.c
 create mode 100644 gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_varargs-m128.c

-- 
2.18.1

Patch

diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/abi-avx512fp16-xmm.exp b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/abi-avx512fp16-xmm.exp
new file mode 100644
index 00000000000..33d24762788
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/abi-avx512fp16-xmm.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
+# <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 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/args.h b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/args.h
new file mode 100644
index 00000000000..4a7b9a90fbe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/args.h
@@ -0,0 +1,190 @@ 
+#ifndef INCLUDED_ARGS_H
+#define INCLUDED_ARGS_H
+
+#include <string.h>
+
+/* 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 xmm0
+#define F1 xmm1
+#define F2 xmm2
+#define F3 xmm3
+#define F4 xmm4
+#define F5 xmm5
+#define F6 xmm6
+#define F7 xmm7
+
+typedef union {
+  _Float16 __Float16[8];
+  float _float[4];
+  double _double[2];
+  long _long[2];
+  int _int[4];
+  unsigned long _ulong[2];
+#ifdef CHECK_M64_M128
+  __m64 _m64[2];
+  __m128 _m128[1];
+  __m128h _m128h[1];
+#endif
+} XMM_T;
+
+typedef union {
+  _Float16 __Float16;
+  float _float;
+  double _double;
+  ldouble _ldouble;
+  ulong _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;
+XMM_T xmm_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;
+  ldouble st0, st1, st2, st3, st4, st5, st6, st7;
+  XMM_T xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9,
+        xmm10, xmm11, xmm12, xmm13, xmm14, xmm15;
+};
+
+/* 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 (xmm_regs, 0, sizeof (xmm_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.xmm0._ ## T [0] == xmm_regs[0]._ ## T [0]); \
+  assert (num_fregs <= 1 || fregs.xmm1._ ## T [0] == xmm_regs[1]._ ## T [0]); \
+  assert (num_fregs <= 2 || fregs.xmm2._ ## T [0] == xmm_regs[2]._ ## T [0]); \
+  assert (num_fregs <= 3 || fregs.xmm3._ ## T [0] == xmm_regs[3]._ ## T [0]); \
+  assert (num_fregs <= 4 || fregs.xmm4._ ## T [0] == xmm_regs[4]._ ## T [0]); \
+  assert (num_fregs <= 5 || fregs.xmm5._ ## T [0] == xmm_regs[5]._ ## T [0]); \
+  assert (num_fregs <= 6 || fregs.xmm6._ ## T [0] == xmm_regs[6]._ ## T [0]); \
+  assert (num_fregs <= 7 || fregs.xmm7._ ## T [0] == xmm_regs[7]._ ## T [0]); \
+  } while (0)
+
+#define check_float16_arguments check_f_arguments(_Float16)
+#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.xmm0) + (O), \
+		     &xmm_regs[0], \
+		     sizeof (__ ## T) - (O)) == 0); \
+  assert (num_fregs <= 1 \
+	  || memcmp (((char *) &fregs.xmm1) + (O), \
+		     &xmm_regs[1], \
+		     sizeof (__ ## T) - (O)) == 0); \
+  assert (num_fregs <= 2 \
+	  || memcmp (((char *) &fregs.xmm2) + (O), \
+		     &xmm_regs[2], \
+		     sizeof (__ ## T) - (O)) == 0); \
+  assert (num_fregs <= 3 \
+	  || memcmp (((char *) &fregs.xmm3) + (O), \
+		     &xmm_regs[3], \
+		     sizeof (__ ## T) - (O)) == 0); \
+  assert (num_fregs <= 4 \
+	  || memcmp (((char *) &fregs.xmm4) + (O), \
+		     &xmm_regs[4], \
+		     sizeof (__ ## T) - (O)) == 0); \
+  assert (num_fregs <= 5 \
+	  || memcmp (((char *) &fregs.xmm5) + (O), \
+		     &xmm_regs[5], \
+		     sizeof (__ ## T) - (O)) == 0); \
+  assert (num_fregs <= 6 \
+	  || memcmp (((char *) &fregs.xmm6) + (O), \
+		     &xmm_regs[6], \
+		     sizeof (__ ## T) - (O)) == 0); \
+  assert (num_fregs <= 7 \
+	  || memcmp (((char *) &fregs.xmm7) + (O), \
+		     &xmm_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)
+
+/* ldoubles are not passed in registers */
+#define check_ldouble_arguments
+
+/* TODO: Do the clearing.  */
+#define clear_float_hardware_registers
+#define clear_x87_hardware_registers
+
+#define clear_float_registers \
+  clear_struct_registers \
+  clear_float_hardware_registers
+
+#define clear_x87_registers \
+  clear_struct_registers \
+  clear_x87_hardware_registers
+
+
+#endif /* INCLUDED_ARGS_H  */
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/asm-support.S b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/asm-support.S
new file mode 100644
index 00000000000..7849acd2649
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/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	%xmm0, xmm_regs+0(%rip)
+	vmovdqu	%xmm1, xmm_regs+16(%rip)
+	vmovdqu	%xmm2, xmm_regs+32(%rip)
+	vmovdqu	%xmm3, xmm_regs+48(%rip)
+	vmovdqu	%xmm4, xmm_regs+64(%rip)
+	vmovdqu	%xmm5, xmm_regs+80(%rip)
+	vmovdqu	%xmm6, xmm_regs+96(%rip)
+	vmovdqu	%xmm7, xmm_regs+112(%rip)
+	vmovdqu	%xmm8, xmm_regs+128(%rip)
+	vmovdqu	%xmm9, xmm_regs+144(%rip)
+	vmovdqu	%xmm10, xmm_regs+160(%rip)
+	vmovdqu	%xmm11, xmm_regs+176(%rip)
+	vmovdqu	%xmm12, xmm_regs+192(%rip)
+	vmovdqu	%xmm13, xmm_regs+208(%rip)
+	vmovdqu	%xmm14, xmm_regs+224(%rip)
+	vmovdqu	%xmm15, xmm_regs+240(%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	%xmm0, xmm_regs+0(%rip)
+	vmovdqu	%xmm1, xmm_regs+16(%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	xmm_regs,256,32
+	.comm	x87_regs,128,32
+	.comm   volatile_var,8,8
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/avx512fp16-check.h b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/avx512fp16-check.h
new file mode 100644
index 00000000000..9fbec9d03ff
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/avx512fp16-check.h
@@ -0,0 +1,74 @@ 
+#include <stdlib.h>
+#include <cpuid.h>
+
+/* Check if the OS supports executing AVX512FP16 instructions.  */
+
+#define XCR_XFEATURE_ENABLED_MASK	0x0
+
+#define XSTATE_FP	0x1
+#define XSTATE_SSE	0x2
+#define XSTATE_YMM	0x4
+#define XSTATE_OPMASK	0x20
+#define XSTATE_ZMM	0x40
+#define XSTATE_HI_ZMM	0x80
+
+static int
+check_osxsave (void)
+{
+  unsigned int eax, ebx, ecx, edx;
+
+  if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
+    return 0;
+
+  return (ecx & bit_OSXSAVE) != 0;
+}
+
+static int
+avx512fp16_os_support (void)
+{
+  unsigned int eax, edx;
+  unsigned int ecx = XCR_XFEATURE_ENABLED_MASK;
+  unsigned int mask = XSTATE_MASK;
+
+  if (!check_osxsave ())
+    return 0;
+
+  __asm__ ("xgetbv" : "=a" (eax), "=d" (edx) : "c" (ecx));
+
+  return ((eax & mask) == mask);
+}
+
+static void do_test (void);
+
+int
+main ()
+{
+  unsigned int eax, ebx, ecx, edx;
+
+  if (!avx512fp16_os_support ())
+    return 0;
+
+  if (__get_cpuid_max (0, NULL) < 7)
+    return 0;
+
+  __cpuid_count (7, 0, eax, ebx, ecx, edx);
+
+    /* Run AVX512FP16 test only if host has ISA support.  */
+  if (((ebx & (bit_AVX512F | bit_AVX512BW))
+       == (bit_AVX512F | bit_AVX512BW))
+      && (edx & bit_AVX512FP16)
+      && AVX512VL (ebx))
+    {
+      do_test ();
+#ifdef DEBUG
+      printf ("PASSED\n");
+#endif
+      return 0;
+    }
+
+#ifdef DEBUG
+  printf ("SKIPPED\n");
+#endif
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/avx512fp16-xmm-check.h b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/avx512fp16-xmm-check.h
new file mode 100644
index 00000000000..0abe09f1166
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/avx512fp16-xmm-check.h
@@ -0,0 +1,3 @@ 
+#define AVX512VL(ebx) (ebx & bit_AVX512VL)
+#define XSTATE_MASK (XSTATE_SSE | XSTATE_OPMASK)
+#include "avx512fp16-check.h"
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/defines.h b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/defines.h
new file mode 100644
index 00000000000..17f2c27edc6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/defines.h
@@ -0,0 +1,150 @@ 
+#ifndef DEFINED_DEFINES_H
+#define DEFINED_DEFINES_H
+
+/* Get __m64 and __m128. */
+#include <immintrin.h>
+
+typedef unsigned long ulong;
+typedef long double ldouble;
+
+/* These defines determines what part of the test should be run.  When
+   GCC implements these parts, the defines should be uncommented to
+   enable testing.  */
+
+/* Scalar type __int128.  */
+/* #define CHECK_INT128 */
+
+/* Scalar type long double.  */
+#define CHECK_LONG_DOUBLE
+
+/* Scalar type __float128.  */
+/* #define CHECK_FLOAT128 */
+
+/* Scalar types __m64 and __m128.  */
+#define CHECK_M64_M128
+
+/* Returning of complex type.  */
+#define CHECK_COMPLEX
+
+/* Structs with size >= 16.  */
+#define CHECK_LARGER_STRUCTS
+
+/* Checks for passing floats and doubles.  */
+#define CHECK_FLOAT_DOUBLE_PASSING
+
+/* Union passing with not-extremely-simple unions.  */
+#define CHECK_LARGER_UNION_PASSING
+
+/* Variable args.  */
+#define CHECK_VARARGS
+
+/* Check argument passing and returning for scalar types with sizeof = 16.  */
+/* TODO: Implement these tests. Don't activate them for now.  */
+#define CHECK_LARGE_SCALAR_PASSING
+
+/* Defines for sizing and alignment.  */
+
+#define TYPE_SIZE_CHAR         1
+#define TYPE_SIZE_SHORT        2
+#define TYPE_SIZE_INT          4
+#define TYPE_SIZE_LONG         8
+#define TYPE_SIZE_LONG_LONG    8
+#define TYPE_SIZE_INT128       16
+#define TYPE_SIZE_FLOAT16      2
+#define TYPE_SIZE_FLOAT        4
+#define TYPE_SIZE_DOUBLE       8
+#define TYPE_SIZE_LONG_DOUBLE  16
+#define TYPE_SIZE_FLOAT128     16
+#define TYPE_SIZE_M64          8
+#define TYPE_SIZE_M128         16
+#define TYPE_SIZE_ENUM         4
+#define TYPE_SIZE_POINTER      8
+
+#define TYPE_ALIGN_CHAR        1
+#define TYPE_ALIGN_SHORT       2
+#define TYPE_ALIGN_INT         4
+#define TYPE_ALIGN_LONG        8
+#define TYPE_ALIGN_LONG_LONG   8
+#define TYPE_ALIGN_INT128      16
+#define TYPE_ALIGN_FLOAT16     2
+#define TYPE_ALIGN_FLOAT       4
+#define TYPE_ALIGN_DOUBLE      8
+#define TYPE_ALIGN_LONG_DOUBLE 16
+#define TYPE_ALIGN_FLOAT128    16
+#define TYPE_ALIGN_M64         8
+#define TYPE_ALIGN_M128        16
+#define TYPE_ALIGN_ENUM        4
+#define TYPE_ALIGN_POINTER     8
+
+/* These defines control the building of the list of types to check. There
+   is a string identifying the type (with a comma after), a size of the type
+   (also with a comma and an integer for adding to the total amount of types)
+   and an alignment of the type (which is currently not really needed since
+   the abi specifies that alignof == sizeof for all scalar types).  */
+#ifdef CHECK_INT128
+#define CI128_STR "__int128",
+#define CI128_SIZ TYPE_SIZE_INT128,
+#define CI128_ALI TYPE_ALIGN_INT128,
+#define CI128_RET "???",
+#else
+#define CI128_STR
+#define CI128_SIZ
+#define CI128_ALI
+#define CI128_RET
+#endif
+#ifdef CHECK_LONG_DOUBLE
+#define CLD_STR "long double",
+#define CLD_SIZ TYPE_SIZE_LONG_DOUBLE,
+#define CLD_ALI TYPE_ALIGN_LONG_DOUBLE,
+#define CLD_RET "x87_regs[0]._ldouble",
+#else
+#define CLD_STR
+#define CLD_SIZ
+#define CLD_ALI
+#define CLD_RET
+#endif
+#ifdef CHECK_FLOAT128
+#define CF128_STR "__float128",
+#define CF128_SIZ TYPE_SIZE_FLOAT128,
+#define CF128_ALI TYPE_ALIGN_FLOAT128, 
+#define CF128_RET "???",
+#else
+#define CF128_STR
+#define CF128_SIZ
+#define CF128_ALI
+#define CF128_RET
+#endif
+#ifdef CHECK_M64_M128
+#define CMM_STR "__m64", "__m128",
+#define CMM_SIZ TYPE_SIZE_M64, TYPE_SIZE_M128,
+#define CMM_ALI TYPE_ALIGN_M64, TYPE_ALIGN_M128,
+#define CMM_RET "???", "???",
+#else
+#define CMM_STR
+#define CMM_SIZ
+#define CMM_ALI
+#define CMM_RET
+#endif
+
+/* Used in size and alignment tests.  */
+enum dummytype { enumtype };
+
+extern void abort (void);
+
+/* Assertion macro.  */
+#define assert(test) if (!(test)) abort()
+
+#ifdef __GNUC__
+#define ATTRIBUTE_UNUSED __attribute__((__unused__))
+#else
+#define ATTRIBUTE_UNUSED
+#endif
+
+#ifdef __GNUC__
+#define PACKED __attribute__((__packed__))
+#else
+#warning Some tests will fail due to missing __packed__ support
+#define PACKED
+#endif
+
+#endif /* DEFINED_DEFINES_H */
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/macros.h b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/macros.h
new file mode 100644
index 00000000000..98fbc660f27
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/macros.h
@@ -0,0 +1,53 @@ 
+#ifndef MACROS_H
+
+#define check_size(_t, _size) assert(sizeof(_t) == (_size))
+
+#define check_align(_t, _align) assert(__alignof__(_t) == (_align))
+
+#define check_align_lv(_t, _align) assert(__alignof__(_t) == (_align) \
+					  && (((unsigned long)&(_t)) & ((_align) - 1) ) == 0)
+
+#define check_basic_struct_size_and_align(_type, _size, _align) { \
+  struct _str { _type dummy; } _t; \
+  check_size(_t, _size); \
+  check_align_lv(_t, _align); \
+}
+
+#define check_array_size_and_align(_type, _size, _align) { \
+  _type _a[1]; _type _b[2]; _type _c[16]; \
+  struct _str { _type _a[1]; } _s; \
+  check_align_lv(_a[0], _align); \
+  check_size(_a, _size); \
+  check_size(_b, (_size*2)); \
+  check_size(_c, (_size*16)); \
+  check_size(_s, _size); \
+  check_align_lv(_s._a[0], _align); \
+}
+
+#define check_basic_union_size_and_align(_type, _size, _align) { \
+  union _union { _type dummy; } _u; \
+  check_size(_u, _size); \
+  check_align_lv(_u, _align); \
+}
+
+#define run_signed_tests2(_function, _arg1, _arg2) \
+  _function(_arg1, _arg2); \
+  _function(signed _arg1, _arg2); \
+  _function(unsigned _arg1, _arg2);
+
+#define run_signed_tests3(_function, _arg1, _arg2, _arg3) \
+  _function(_arg1, _arg2, _arg3); \
+  _function(signed _arg1, _arg2, _arg3); \
+  _function(unsigned _arg1, _arg2, _arg3);
+
+/* Check size of a struct and a union of three types.  */
+
+#define check_struct_and_union3(type1, type2, type3, struct_size, align_size) \
+{ \
+  struct _str { type1 t1; type2 t2; type3 t3; } _t; \
+  union _uni { type1 t1; type2 t2; type3 t3; } _u; \
+  check_size(_t, struct_size); \
+  check_size(_u, align_size); \
+}
+
+#endif // MACROS_H
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_3_element_struct_and_unions.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_3_element_struct_and_unions.c
new file mode 100644
index 00000000000..cc94e0fe0e9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_3_element_struct_and_unions.c
@@ -0,0 +1,692 @@ 
+/* This is an autogenerated file. Do not edit.  */
+
+#include "defines.h"
+#include "macros.h"
+
+/* Check structs and unions of all permutations of 3 basic types.  */
+int
+main (void)
+{
+  check_struct_and_union3(char, char, char, 3, 1);
+  check_struct_and_union3(char, char, short, 4, 2);
+  check_struct_and_union3(char, char, int, 8, 4);
+  check_struct_and_union3(char, char, long, 16, 8);
+  check_struct_and_union3(char, char, long long, 16, 8);
+  check_struct_and_union3(char, char, float, 8, 4);
+  check_struct_and_union3(char, char, double, 16, 8);
+  check_struct_and_union3(char, char, long double, 32, 16);
+  check_struct_and_union3(char, short, char, 6, 2);
+  check_struct_and_union3(char, short, short, 6, 2);
+  check_struct_and_union3(char, short, int, 8, 4);
+  check_struct_and_union3(char, short, long, 16, 8);
+  check_struct_and_union3(char, short, long long, 16, 8);
+  check_struct_and_union3(char, short, float, 8, 4);
+  check_struct_and_union3(char, short, double, 16, 8);
+  check_struct_and_union3(char, short, long double, 32, 16);
+  check_struct_and_union3(char, int, char, 12, 4);
+  check_struct_and_union3(char, int, short, 12, 4);
+  check_struct_and_union3(char, int, int, 12, 4);
+  check_struct_and_union3(char, int, long, 16, 8);
+  check_struct_and_union3(char, int, long long, 16, 8);
+  check_struct_and_union3(char, int, float, 12, 4);
+  check_struct_and_union3(char, int, double, 16, 8);
+  check_struct_and_union3(char, int, long double, 32, 16);
+  check_struct_and_union3(char, long, char, 24, 8);
+  check_struct_and_union3(char, long, short, 24, 8);
+  check_struct_and_union3(char, long, int, 24, 8);
+  check_struct_and_union3(char, long, long, 24, 8);
+  check_struct_and_union3(char, long, long long, 24, 8);
+  check_struct_and_union3(char, long, float, 24, 8);
+  check_struct_and_union3(char, long, double, 24, 8);
+  check_struct_and_union3(char, long, long double, 32, 16);
+  check_struct_and_union3(char, long long, char, 24, 8);
+  check_struct_and_union3(char, long long, short, 24, 8);
+  check_struct_and_union3(char, long long, int, 24, 8);
+  check_struct_and_union3(char, long long, long, 24, 8);
+  check_struct_and_union3(char, long long, long long, 24, 8);
+  check_struct_and_union3(char, long long, float, 24, 8);
+  check_struct_and_union3(char, long long, double, 24, 8);
+  check_struct_and_union3(char, long long, long double, 32, 16);
+  check_struct_and_union3(char, float, char, 12, 4);
+  check_struct_and_union3(char, float, short, 12, 4);
+  check_struct_and_union3(char, float, int, 12, 4);
+  check_struct_and_union3(char, float, long, 16, 8);
+  check_struct_and_union3(char, float, long long, 16, 8);
+  check_struct_and_union3(char, float, float, 12, 4);
+  check_struct_and_union3(char, float, double, 16, 8);
+  check_struct_and_union3(char, float, long double, 32, 16);
+  check_struct_and_union3(char, double, char, 24, 8);
+  check_struct_and_union3(char, double, short, 24, 8);
+  check_struct_and_union3(char, double, int, 24, 8);
+  check_struct_and_union3(char, double, long, 24, 8);
+  check_struct_and_union3(char, double, long long, 24, 8);
+  check_struct_and_union3(char, double, float, 24, 8);
+  check_struct_and_union3(char, double, double, 24, 8);
+  check_struct_and_union3(char, double, long double, 32, 16);
+  check_struct_and_union3(char, long double, char, 48, 16);
+  check_struct_and_union3(char, long double, short, 48, 16);
+  check_struct_and_union3(char, long double, int, 48, 16);
+  check_struct_and_union3(char, long double, long, 48, 16);
+  check_struct_and_union3(char, long double, long long, 48, 16);
+  check_struct_and_union3(char, long double, float, 48, 16);
+  check_struct_and_union3(char, long double, double, 48, 16);
+  check_struct_and_union3(char, long double, long double, 48, 16);
+  check_struct_and_union3(short, char, char, 4, 2);
+  check_struct_and_union3(short, char, short, 6, 2);
+  check_struct_and_union3(short, char, int, 8, 4);
+  check_struct_and_union3(short, char, long, 16, 8);
+  check_struct_and_union3(short, char, long long, 16, 8);
+  check_struct_and_union3(short, char, float, 8, 4);
+  check_struct_and_union3(short, char, double, 16, 8);
+  check_struct_and_union3(short, char, long double, 32, 16);
+  check_struct_and_union3(short, short, char, 6, 2);
+  check_struct_and_union3(short, short, short, 6, 2);
+  check_struct_and_union3(short, short, int, 8, 4);
+  check_struct_and_union3(short, short, long, 16, 8);
+  check_struct_and_union3(short, short, long long, 16, 8);
+  check_struct_and_union3(short, short, float, 8, 4);
+  check_struct_and_union3(short, short, double, 16, 8);
+  check_struct_and_union3(short, short, long double, 32, 16);
+  check_struct_and_union3(short, int, char, 12, 4);
+  check_struct_and_union3(short, int, short, 12, 4);
+  check_struct_and_union3(short, int, int, 12, 4);
+  check_struct_and_union3(short, int, long, 16, 8);
+  check_struct_and_union3(short, int, long long, 16, 8);
+  check_struct_and_union3(short, int, float, 12, 4);
+  check_struct_and_union3(short, int, double, 16, 8);
+  check_struct_and_union3(short, int, long double, 32, 16);
+  check_struct_and_union3(short, long, char, 24, 8);
+  check_struct_and_union3(short, long, short, 24, 8);
+  check_struct_and_union3(short, long, int, 24, 8);
+  check_struct_and_union3(short, long, long, 24, 8);
+  check_struct_and_union3(short, long, long long, 24, 8);
+  check_struct_and_union3(short, long, float, 24, 8);
+  check_struct_and_union3(short, long, double, 24, 8);
+  check_struct_and_union3(short, long, long double, 32, 16);
+  check_struct_and_union3(short, long long, char, 24, 8);
+  check_struct_and_union3(short, long long, short, 24, 8);
+  check_struct_and_union3(short, long long, int, 24, 8);
+  check_struct_and_union3(short, long long, long, 24, 8);
+  check_struct_and_union3(short, long long, long long, 24, 8);
+  check_struct_and_union3(short, long long, float, 24, 8);
+  check_struct_and_union3(short, long long, double, 24, 8);
+  check_struct_and_union3(short, long long, long double, 32, 16);
+  check_struct_and_union3(short, float, char, 12, 4);
+  check_struct_and_union3(short, float, short, 12, 4);
+  check_struct_and_union3(short, float, int, 12, 4);
+  check_struct_and_union3(short, float, long, 16, 8);
+  check_struct_and_union3(short, float, long long, 16, 8);
+  check_struct_and_union3(short, float, float, 12, 4);
+  check_struct_and_union3(short, float, double, 16, 8);
+  check_struct_and_union3(short, float, long double, 32, 16);
+  check_struct_and_union3(short, double, char, 24, 8);
+  check_struct_and_union3(short, double, short, 24, 8);
+  check_struct_and_union3(short, double, int, 24, 8);
+  check_struct_and_union3(short, double, long, 24, 8);
+  check_struct_and_union3(short, double, long long, 24, 8);
+  check_struct_and_union3(short, double, float, 24, 8);
+  check_struct_and_union3(short, double, double, 24, 8);
+  check_struct_and_union3(short, double, long double, 32, 16);
+  check_struct_and_union3(short, long double, char, 48, 16);
+  check_struct_and_union3(short, long double, short, 48, 16);
+  check_struct_and_union3(short, long double, int, 48, 16);
+  check_struct_and_union3(short, long double, long, 48, 16);
+  check_struct_and_union3(short, long double, long long, 48, 16);
+  check_struct_and_union3(short, long double, float, 48, 16);
+  check_struct_and_union3(short, long double, double, 48, 16);
+  check_struct_and_union3(short, long double, long double, 48, 16);
+  check_struct_and_union3(int, char, char, 8, 4);
+  check_struct_and_union3(int, char, short, 8, 4);
+  check_struct_and_union3(int, char, int, 12, 4);
+  check_struct_and_union3(int, char, long, 16, 8);
+  check_struct_and_union3(int, char, long long, 16, 8);
+  check_struct_and_union3(int, char, float, 12, 4);
+  check_struct_and_union3(int, char, double, 16, 8);
+  check_struct_and_union3(int, char, long double, 32, 16);
+  check_struct_and_union3(int, short, char, 8, 4);
+  check_struct_and_union3(int, short, short, 8, 4);
+  check_struct_and_union3(int, short, int, 12, 4);
+  check_struct_and_union3(int, short, long, 16, 8);
+  check_struct_and_union3(int, short, long long, 16, 8);
+  check_struct_and_union3(int, short, float, 12, 4);
+  check_struct_and_union3(int, short, double, 16, 8);
+  check_struct_and_union3(int, short, long double, 32, 16);
+  check_struct_and_union3(int, int, char, 12, 4);
+  check_struct_and_union3(int, int, short, 12, 4);
+  check_struct_and_union3(int, int, int, 12, 4);
+  check_struct_and_union3(int, int, long, 16, 8);
+  check_struct_and_union3(int, int, long long, 16, 8);
+  check_struct_and_union3(int, int, float, 12, 4);
+  check_struct_and_union3(int, int, double, 16, 8);
+  check_struct_and_union3(int, int, long double, 32, 16);
+  check_struct_and_union3(int, long, char, 24, 8);
+  check_struct_and_union3(int, long, short, 24, 8);
+  check_struct_and_union3(int, long, int, 24, 8);
+  check_struct_and_union3(int, long, long, 24, 8);
+  check_struct_and_union3(int, long, long long, 24, 8);
+  check_struct_and_union3(int, long, float, 24, 8);
+  check_struct_and_union3(int, long, double, 24, 8);
+  check_struct_and_union3(int, long, long double, 32, 16);
+  check_struct_and_union3(int, long long, char, 24, 8);
+  check_struct_and_union3(int, long long, short, 24, 8);
+  check_struct_and_union3(int, long long, int, 24, 8);
+  check_struct_and_union3(int, long long, long, 24, 8);
+  check_struct_and_union3(int, long long, long long, 24, 8);
+  check_struct_and_union3(int, long long, float, 24, 8);
+  check_struct_and_union3(int, long long, double, 24, 8);
+  check_struct_and_union3(int, long long, long double, 32, 16);
+  check_struct_and_union3(int, float, char, 12, 4);
+  check_struct_and_union3(int, float, short, 12, 4);
+  check_struct_and_union3(int, float, int, 12, 4);
+  check_struct_and_union3(int, float, long, 16, 8);
+  check_struct_and_union3(int, float, long long, 16, 8);
+  check_struct_and_union3(int, float, float, 12, 4);
+  check_struct_and_union3(int, float, double, 16, 8);
+  check_struct_and_union3(int, float, long double, 32, 16);
+  check_struct_and_union3(int, double, char, 24, 8);
+  check_struct_and_union3(int, double, short, 24, 8);
+  check_struct_and_union3(int, double, int, 24, 8);
+  check_struct_and_union3(int, double, long, 24, 8);
+  check_struct_and_union3(int, double, long long, 24, 8);
+  check_struct_and_union3(int, double, float, 24, 8);
+  check_struct_and_union3(int, double, double, 24, 8);
+  check_struct_and_union3(int, double, long double, 32, 16);
+  check_struct_and_union3(int, long double, char, 48, 16);
+  check_struct_and_union3(int, long double, short, 48, 16);
+  check_struct_and_union3(int, long double, int, 48, 16);
+  check_struct_and_union3(int, long double, long, 48, 16);
+  check_struct_and_union3(int, long double, long long, 48, 16);
+  check_struct_and_union3(int, long double, float, 48, 16);
+  check_struct_and_union3(int, long double, double, 48, 16);
+  check_struct_and_union3(int, long double, long double, 48, 16);
+  check_struct_and_union3(long, char, char, 16, 8);
+  check_struct_and_union3(long, char, short, 16, 8);
+  check_struct_and_union3(long, char, int, 16, 8);
+  check_struct_and_union3(long, char, long, 24, 8);
+  check_struct_and_union3(long, char, long long, 24, 8);
+  check_struct_and_union3(long, char, float, 16, 8);
+  check_struct_and_union3(long, char, double, 24, 8);
+  check_struct_and_union3(long, char, long double, 32, 16);
+  check_struct_and_union3(long, short, char, 16, 8);
+  check_struct_and_union3(long, short, short, 16, 8);
+  check_struct_and_union3(long, short, int, 16, 8);
+  check_struct_and_union3(long, short, long, 24, 8);
+  check_struct_and_union3(long, short, long long, 24, 8);
+  check_struct_and_union3(long, short, float, 16, 8);
+  check_struct_and_union3(long, short, double, 24, 8);
+  check_struct_and_union3(long, short, long double, 32, 16);
+  check_struct_and_union3(long, int, char, 16, 8);
+  check_struct_and_union3(long, int, short, 16, 8);
+  check_struct_and_union3(long, int, int, 16, 8);
+  check_struct_and_union3(long, int, long, 24, 8);
+  check_struct_and_union3(long, int, long long, 24, 8);
+  check_struct_and_union3(long, int, float, 16, 8);
+  check_struct_and_union3(long, int, double, 24, 8);
+  check_struct_and_union3(long, int, long double, 32, 16);
+  check_struct_and_union3(long, long, char, 24, 8);
+  check_struct_and_union3(long, long, short, 24, 8);
+  check_struct_and_union3(long, long, int, 24, 8);
+  check_struct_and_union3(long, long, long, 24, 8);
+  check_struct_and_union3(long, long, long long, 24, 8);
+  check_struct_and_union3(long, long, float, 24, 8);
+  check_struct_and_union3(long, long, double, 24, 8);
+  check_struct_and_union3(long, long, long double, 32, 16);
+  check_struct_and_union3(long, long long, char, 24, 8);
+  check_struct_and_union3(long, long long, short, 24, 8);
+  check_struct_and_union3(long, long long, int, 24, 8);
+  check_struct_and_union3(long, long long, long, 24, 8);
+  check_struct_and_union3(long, long long, long long, 24, 8);
+  check_struct_and_union3(long, long long, float, 24, 8);
+  check_struct_and_union3(long, long long, double, 24, 8);
+  check_struct_and_union3(long, long long, long double, 32, 16);
+  check_struct_and_union3(long, float, char, 16, 8);
+  check_struct_and_union3(long, float, short, 16, 8);
+  check_struct_and_union3(long, float, int, 16, 8);
+  check_struct_and_union3(long, float, long, 24, 8);
+  check_struct_and_union3(long, float, long long, 24, 8);
+  check_struct_and_union3(long, float, float, 16, 8);
+  check_struct_and_union3(long, float, double, 24, 8);
+  check_struct_and_union3(long, float, long double, 32, 16);
+  check_struct_and_union3(long, double, char, 24, 8);
+  check_struct_and_union3(long, double, short, 24, 8);
+  check_struct_and_union3(long, double, int, 24, 8);
+  check_struct_and_union3(long, double, long, 24, 8);
+  check_struct_and_union3(long, double, long long, 24, 8);
+  check_struct_and_union3(long, double, float, 24, 8);
+  check_struct_and_union3(long, double, double, 24, 8);
+  check_struct_and_union3(long, double, long double, 32, 16);
+  check_struct_and_union3(long, long double, char, 48, 16);
+  check_struct_and_union3(long, long double, short, 48, 16);
+  check_struct_and_union3(long, long double, int, 48, 16);
+  check_struct_and_union3(long, long double, long, 48, 16);
+  check_struct_and_union3(long, long double, long long, 48, 16);
+  check_struct_and_union3(long, long double, float, 48, 16);
+  check_struct_and_union3(long, long double, double, 48, 16);
+  check_struct_and_union3(long, long double, long double, 48, 16);
+  check_struct_and_union3(long long, char, char, 16, 8);
+  check_struct_and_union3(long long, char, short, 16, 8);
+  check_struct_and_union3(long long, char, int, 16, 8);
+  check_struct_and_union3(long long, char, long, 24, 8);
+  check_struct_and_union3(long long, char, long long, 24, 8);
+  check_struct_and_union3(long long, char, float, 16, 8);
+  check_struct_and_union3(long long, char, double, 24, 8);
+  check_struct_and_union3(long long, char, long double, 32, 16);
+  check_struct_and_union3(long long, short, char, 16, 8);
+  check_struct_and_union3(long long, short, short, 16, 8);
+  check_struct_and_union3(long long, short, int, 16, 8);
+  check_struct_and_union3(long long, short, long, 24, 8);
+  check_struct_and_union3(long long, short, long long, 24, 8);
+  check_struct_and_union3(long long, short, float, 16, 8);
+  check_struct_and_union3(long long, short, double, 24, 8);
+  check_struct_and_union3(long long, short, long double, 32, 16);
+  check_struct_and_union3(long long, int, char, 16, 8);
+  check_struct_and_union3(long long, int, short, 16, 8);
+  check_struct_and_union3(long long, int, int, 16, 8);
+  check_struct_and_union3(long long, int, long, 24, 8);
+  check_struct_and_union3(long long, int, long long, 24, 8);
+  check_struct_and_union3(long long, int, float, 16, 8);
+  check_struct_and_union3(long long, int, double, 24, 8);
+  check_struct_and_union3(long long, int, long double, 32, 16);
+  check_struct_and_union3(long long, long, char, 24, 8);
+  check_struct_and_union3(long long, long, short, 24, 8);
+  check_struct_and_union3(long long, long, int, 24, 8);
+  check_struct_and_union3(long long, long, long, 24, 8);
+  check_struct_and_union3(long long, long, long long, 24, 8);
+  check_struct_and_union3(long long, long, float, 24, 8);
+  check_struct_and_union3(long long, long, double, 24, 8);
+  check_struct_and_union3(long long, long, long double, 32, 16);
+  check_struct_and_union3(long long, long long, char, 24, 8);
+  check_struct_and_union3(long long, long long, short, 24, 8);
+  check_struct_and_union3(long long, long long, int, 24, 8);
+  check_struct_and_union3(long long, long long, long, 24, 8);
+  check_struct_and_union3(long long, long long, long long, 24, 8);
+  check_struct_and_union3(long long, long long, float, 24, 8);
+  check_struct_and_union3(long long, long long, double, 24, 8);
+  check_struct_and_union3(long long, long long, long double, 32, 16);
+  check_struct_and_union3(long long, float, char, 16, 8);
+  check_struct_and_union3(long long, float, short, 16, 8);
+  check_struct_and_union3(long long, float, int, 16, 8);
+  check_struct_and_union3(long long, float, long, 24, 8);
+  check_struct_and_union3(long long, float, long long, 24, 8);
+  check_struct_and_union3(long long, float, float, 16, 8);
+  check_struct_and_union3(long long, float, double, 24, 8);
+  check_struct_and_union3(long long, float, long double, 32, 16);
+  check_struct_and_union3(long long, double, char, 24, 8);
+  check_struct_and_union3(long long, double, short, 24, 8);
+  check_struct_and_union3(long long, double, int, 24, 8);
+  check_struct_and_union3(long long, double, long, 24, 8);
+  check_struct_and_union3(long long, double, long long, 24, 8);
+  check_struct_and_union3(long long, double, float, 24, 8);
+  check_struct_and_union3(long long, double, double, 24, 8);
+  check_struct_and_union3(long long, double, long double, 32, 16);
+  check_struct_and_union3(long long, long double, char, 48, 16);
+  check_struct_and_union3(long long, long double, short, 48, 16);
+  check_struct_and_union3(long long, long double, int, 48, 16);
+  check_struct_and_union3(long long, long double, long, 48, 16);
+  check_struct_and_union3(long long, long double, long long, 48, 16);
+  check_struct_and_union3(long long, long double, float, 48, 16);
+  check_struct_and_union3(long long, long double, double, 48, 16);
+  check_struct_and_union3(long long, long double, long double, 48, 16);
+  check_struct_and_union3(float, char, char, 8, 4);
+  check_struct_and_union3(float, char, short, 8, 4);
+  check_struct_and_union3(float, char, int, 12, 4);
+  check_struct_and_union3(float, char, long, 16, 8);
+  check_struct_and_union3(float, char, long long, 16, 8);
+  check_struct_and_union3(float, char, float, 12, 4);
+  check_struct_and_union3(float, char, double, 16, 8);
+  check_struct_and_union3(float, char, long double, 32, 16);
+  check_struct_and_union3(float, short, char, 8, 4);
+  check_struct_and_union3(float, short, short, 8, 4);
+  check_struct_and_union3(float, short, int, 12, 4);
+  check_struct_and_union3(float, short, long, 16, 8);
+  check_struct_and_union3(float, short, long long, 16, 8);
+  check_struct_and_union3(float, short, float, 12, 4);
+  check_struct_and_union3(float, short, double, 16, 8);
+  check_struct_and_union3(float, short, long double, 32, 16);
+  check_struct_and_union3(float, int, char, 12, 4);
+  check_struct_and_union3(float, int, short, 12, 4);
+  check_struct_and_union3(float, int, int, 12, 4);
+  check_struct_and_union3(float, int, long, 16, 8);
+  check_struct_and_union3(float, int, long long, 16, 8);
+  check_struct_and_union3(float, int, float, 12, 4);
+  check_struct_and_union3(float, int, double, 16, 8);
+  check_struct_and_union3(float, int, long double, 32, 16);
+  check_struct_and_union3(float, long, char, 24, 8);
+  check_struct_and_union3(float, long, short, 24, 8);
+  check_struct_and_union3(float, long, int, 24, 8);
+  check_struct_and_union3(float, long, long, 24, 8);
+  check_struct_and_union3(float, long, long long, 24, 8);
+  check_struct_and_union3(float, long, float, 24, 8);
+  check_struct_and_union3(float, long, double, 24, 8);
+  check_struct_and_union3(float, long, long double, 32, 16);
+  check_struct_and_union3(float, long long, char, 24, 8);
+  check_struct_and_union3(float, long long, short, 24, 8);
+  check_struct_and_union3(float, long long, int, 24, 8);
+  check_struct_and_union3(float, long long, long, 24, 8);
+  check_struct_and_union3(float, long long, long long, 24, 8);
+  check_struct_and_union3(float, long long, float, 24, 8);
+  check_struct_and_union3(float, long long, double, 24, 8);
+  check_struct_and_union3(float, long long, long double, 32, 16);
+  check_struct_and_union3(float, float, char, 12, 4);
+  check_struct_and_union3(float, float, short, 12, 4);
+  check_struct_and_union3(float, float, int, 12, 4);
+  check_struct_and_union3(float, float, long, 16, 8);
+  check_struct_and_union3(float, float, long long, 16, 8);
+  check_struct_and_union3(float, float, float, 12, 4);
+  check_struct_and_union3(float, float, double, 16, 8);
+  check_struct_and_union3(float, float, long double, 32, 16);
+  check_struct_and_union3(float, double, char, 24, 8);
+  check_struct_and_union3(float, double, short, 24, 8);
+  check_struct_and_union3(float, double, int, 24, 8);
+  check_struct_and_union3(float, double, long, 24, 8);
+  check_struct_and_union3(float, double, long long, 24, 8);
+  check_struct_and_union3(float, double, float, 24, 8);
+  check_struct_and_union3(float, double, double, 24, 8);
+  check_struct_and_union3(float, double, long double, 32, 16);
+  check_struct_and_union3(float, long double, char, 48, 16);
+  check_struct_and_union3(float, long double, short, 48, 16);
+  check_struct_and_union3(float, long double, int, 48, 16);
+  check_struct_and_union3(float, long double, long, 48, 16);
+  check_struct_and_union3(float, long double, long long, 48, 16);
+  check_struct_and_union3(float, long double, float, 48, 16);
+  check_struct_and_union3(float, long double, double, 48, 16);
+  check_struct_and_union3(float, long double, long double, 48, 16);
+  check_struct_and_union3(double, char, char, 16, 8);
+  check_struct_and_union3(double, char, short, 16, 8);
+  check_struct_and_union3(double, char, int, 16, 8);
+  check_struct_and_union3(double, char, long, 24, 8);
+  check_struct_and_union3(double, char, long long, 24, 8);
+  check_struct_and_union3(double, char, float, 16, 8);
+  check_struct_and_union3(double, char, double, 24, 8);
+  check_struct_and_union3(double, char, long double, 32, 16);
+  check_struct_and_union3(double, short, char, 16, 8);
+  check_struct_and_union3(double, short, short, 16, 8);
+  check_struct_and_union3(double, short, int, 16, 8);
+  check_struct_and_union3(double, short, long, 24, 8);
+  check_struct_and_union3(double, short, long long, 24, 8);
+  check_struct_and_union3(double, short, float, 16, 8);
+  check_struct_and_union3(double, short, double, 24, 8);
+  check_struct_and_union3(double, short, long double, 32, 16);
+  check_struct_and_union3(double, int, char, 16, 8);
+  check_struct_and_union3(double, int, short, 16, 8);
+  check_struct_and_union3(double, int, int, 16, 8);
+  check_struct_and_union3(double, int, long, 24, 8);
+  check_struct_and_union3(double, int, long long, 24, 8);
+  check_struct_and_union3(double, int, float, 16, 8);
+  check_struct_and_union3(double, int, double, 24, 8);
+  check_struct_and_union3(double, int, long double, 32, 16);
+  check_struct_and_union3(double, long, char, 24, 8);
+  check_struct_and_union3(double, long, short, 24, 8);
+  check_struct_and_union3(double, long, int, 24, 8);
+  check_struct_and_union3(double, long, long, 24, 8);
+  check_struct_and_union3(double, long, long long, 24, 8);
+  check_struct_and_union3(double, long, float, 24, 8);
+  check_struct_and_union3(double, long, double, 24, 8);
+  check_struct_and_union3(double, long, long double, 32, 16);
+  check_struct_and_union3(double, long long, char, 24, 8);
+  check_struct_and_union3(double, long long, short, 24, 8);
+  check_struct_and_union3(double, long long, int, 24, 8);
+  check_struct_and_union3(double, long long, long, 24, 8);
+  check_struct_and_union3(double, long long, long long, 24, 8);
+  check_struct_and_union3(double, long long, float, 24, 8);
+  check_struct_and_union3(double, long long, double, 24, 8);
+  check_struct_and_union3(double, long long, long double, 32, 16);
+  check_struct_and_union3(double, float, char, 16, 8);
+  check_struct_and_union3(double, float, short, 16, 8);
+  check_struct_and_union3(double, float, int, 16, 8);
+  check_struct_and_union3(double, float, long, 24, 8);
+  check_struct_and_union3(double, float, long long, 24, 8);
+  check_struct_and_union3(double, float, float, 16, 8);
+  check_struct_and_union3(double, float, double, 24, 8);
+  check_struct_and_union3(double, float, long double, 32, 16);
+  check_struct_and_union3(double, double, char, 24, 8);
+  check_struct_and_union3(double, double, short, 24, 8);
+  check_struct_and_union3(double, double, int, 24, 8);
+  check_struct_and_union3(double, double, long, 24, 8);
+  check_struct_and_union3(double, double, long long, 24, 8);
+  check_struct_and_union3(double, double, float, 24, 8);
+  check_struct_and_union3(double, double, double, 24, 8);
+  check_struct_and_union3(double, double, long double, 32, 16);
+  check_struct_and_union3(double, long double, char, 48, 16);
+  check_struct_and_union3(double, long double, short, 48, 16);
+  check_struct_and_union3(double, long double, int, 48, 16);
+  check_struct_and_union3(double, long double, long, 48, 16);
+  check_struct_and_union3(double, long double, long long, 48, 16);
+  check_struct_and_union3(double, long double, float, 48, 16);
+  check_struct_and_union3(double, long double, double, 48, 16);
+  check_struct_and_union3(double, long double, long double, 48, 16);
+  check_struct_and_union3(long double, char, char, 32, 16);
+  check_struct_and_union3(long double, char, short, 32, 16);
+  check_struct_and_union3(long double, char, int, 32, 16);
+  check_struct_and_union3(long double, char, long, 32, 16);
+  check_struct_and_union3(long double, char, long long, 32, 16);
+  check_struct_and_union3(long double, char, float, 32, 16);
+  check_struct_and_union3(long double, char, double, 32, 16);
+  check_struct_and_union3(long double, char, long double, 48, 16);
+  check_struct_and_union3(long double, short, char, 32, 16);
+  check_struct_and_union3(long double, short, short, 32, 16);
+  check_struct_and_union3(long double, short, int, 32, 16);
+  check_struct_and_union3(long double, short, long, 32, 16);
+  check_struct_and_union3(long double, short, long long, 32, 16);
+  check_struct_and_union3(long double, short, float, 32, 16);
+  check_struct_and_union3(long double, short, double, 32, 16);
+  check_struct_and_union3(long double, short, long double, 48, 16);
+  check_struct_and_union3(long double, int, char, 32, 16);
+  check_struct_and_union3(long double, int, short, 32, 16);
+  check_struct_and_union3(long double, int, int, 32, 16);
+  check_struct_and_union3(long double, int, long, 32, 16);
+  check_struct_and_union3(long double, int, long long, 32, 16);
+  check_struct_and_union3(long double, int, float, 32, 16);
+  check_struct_and_union3(long double, int, double, 32, 16);
+  check_struct_and_union3(long double, int, long double, 48, 16);
+  check_struct_and_union3(long double, long, char, 32, 16);
+  check_struct_and_union3(long double, long, short, 32, 16);
+  check_struct_and_union3(long double, long, int, 32, 16);
+  check_struct_and_union3(long double, long, long, 32, 16);
+  check_struct_and_union3(long double, long, long long, 32, 16);
+  check_struct_and_union3(long double, long, float, 32, 16);
+  check_struct_and_union3(long double, long, double, 32, 16);
+  check_struct_and_union3(long double, long, long double, 48, 16);
+  check_struct_and_union3(long double, long long, char, 32, 16);
+  check_struct_and_union3(long double, long long, short, 32, 16);
+  check_struct_and_union3(long double, long long, int, 32, 16);
+  check_struct_and_union3(long double, long long, long, 32, 16);
+  check_struct_and_union3(long double, long long, long long, 32, 16);
+  check_struct_and_union3(long double, long long, float, 32, 16);
+  check_struct_and_union3(long double, long long, double, 32, 16);
+  check_struct_and_union3(long double, long long, long double, 48, 16);
+  check_struct_and_union3(long double, float, char, 32, 16);
+  check_struct_and_union3(long double, float, short, 32, 16);
+  check_struct_and_union3(long double, float, int, 32, 16);
+  check_struct_and_union3(long double, float, long, 32, 16);
+  check_struct_and_union3(long double, float, long long, 32, 16);
+  check_struct_and_union3(long double, float, float, 32, 16);
+  check_struct_and_union3(long double, float, double, 32, 16);
+  check_struct_and_union3(long double, float, long double, 48, 16);
+  check_struct_and_union3(long double, double, char, 32, 16);
+  check_struct_and_union3(long double, double, short, 32, 16);
+  check_struct_and_union3(long double, double, int, 32, 16);
+  check_struct_and_union3(long double, double, long, 32, 16);
+  check_struct_and_union3(long double, double, long long, 32, 16);
+  check_struct_and_union3(long double, double, float, 32, 16);
+  check_struct_and_union3(long double, double, double, 32, 16);
+  check_struct_and_union3(long double, double, long double, 48, 16);
+  check_struct_and_union3(long double, long double, char, 48, 16);
+  check_struct_and_union3(long double, long double, short, 48, 16);
+  check_struct_and_union3(long double, long double, int, 48, 16);
+  check_struct_and_union3(long double, long double, long, 48, 16);
+  check_struct_and_union3(long double, long double, long long, 48, 16);
+  check_struct_and_union3(long double, long double, float, 48, 16);
+  check_struct_and_union3(long double, long double, double, 48, 16);
+  check_struct_and_union3(long double, long double, long double, 48, 16);
+  check_struct_and_union3(char, char, _Float16, 4, 2);
+  check_struct_and_union3(char, _Float16, char, 6, 2);
+  check_struct_and_union3(char, _Float16, _Float16, 6, 2);
+  check_struct_and_union3(char, _Float16, int, 8, 4);
+  check_struct_and_union3(char, _Float16, long, 16, 8);
+  check_struct_and_union3(char, _Float16, long long, 16, 8);
+  check_struct_and_union3(char, _Float16, float, 8, 4);
+  check_struct_and_union3(char, _Float16, double, 16, 8);
+  check_struct_and_union3(char, _Float16, long double, 32, 16);
+  check_struct_and_union3(char, int, _Float16, 12, 4);
+  check_struct_and_union3(char, long, _Float16, 24, 8);
+  check_struct_and_union3(char, long long, _Float16, 24, 8);
+  check_struct_and_union3(char, float, _Float16, 12, 4);
+  check_struct_and_union3(char, double, _Float16, 24, 8);
+  check_struct_and_union3(char, long double, _Float16, 48, 16);
+  check_struct_and_union3(_Float16, char, char, 4, 2);
+  check_struct_and_union3(_Float16, char, _Float16, 6, 2);
+  check_struct_and_union3(_Float16, char, int, 8, 4);
+  check_struct_and_union3(_Float16, char, long, 16, 8);
+  check_struct_and_union3(_Float16, char, long long, 16, 8);
+  check_struct_and_union3(_Float16, char, float, 8, 4);
+  check_struct_and_union3(_Float16, char, double, 16, 8);
+  check_struct_and_union3(_Float16, char, long double, 32, 16);
+  check_struct_and_union3(_Float16, _Float16, char, 6, 2);
+  check_struct_and_union3(_Float16, _Float16, _Float16, 6, 2);
+  check_struct_and_union3(_Float16, _Float16, int, 8, 4);
+  check_struct_and_union3(_Float16, _Float16, long, 16, 8);
+  check_struct_and_union3(_Float16, _Float16, long long, 16, 8);
+  check_struct_and_union3(_Float16, _Float16, float, 8, 4);
+  check_struct_and_union3(_Float16, _Float16, double, 16, 8);
+  check_struct_and_union3(_Float16, _Float16, long double, 32, 16);
+  check_struct_and_union3(_Float16, int, char, 12, 4);
+  check_struct_and_union3(_Float16, int, _Float16, 12, 4);
+  check_struct_and_union3(_Float16, int, int, 12, 4);
+  check_struct_and_union3(_Float16, int, long, 16, 8);
+  check_struct_and_union3(_Float16, int, long long, 16, 8);
+  check_struct_and_union3(_Float16, int, float, 12, 4);
+  check_struct_and_union3(_Float16, int, double, 16, 8);
+  check_struct_and_union3(_Float16, int, long double, 32, 16);
+  check_struct_and_union3(_Float16, long, char, 24, 8);
+  check_struct_and_union3(_Float16, long, _Float16, 24, 8);
+  check_struct_and_union3(_Float16, long, int, 24, 8);
+  check_struct_and_union3(_Float16, long, long, 24, 8);
+  check_struct_and_union3(_Float16, long, long long, 24, 8);
+  check_struct_and_union3(_Float16, long, float, 24, 8);
+  check_struct_and_union3(_Float16, long, double, 24, 8);
+  check_struct_and_union3(_Float16, long, long double, 32, 16);
+  check_struct_and_union3(_Float16, long long, char, 24, 8);
+  check_struct_and_union3(_Float16, long long, _Float16, 24, 8);
+  check_struct_and_union3(_Float16, long long, int, 24, 8);
+  check_struct_and_union3(_Float16, long long, long, 24, 8);
+  check_struct_and_union3(_Float16, long long, long long, 24, 8);
+  check_struct_and_union3(_Float16, long long, float, 24, 8);
+  check_struct_and_union3(_Float16, long long, double, 24, 8);
+  check_struct_and_union3(_Float16, long long, long double, 32, 16);
+  check_struct_and_union3(_Float16, float, char, 12, 4);
+  check_struct_and_union3(_Float16, float, _Float16, 12, 4);
+  check_struct_and_union3(_Float16, float, int, 12, 4);
+  check_struct_and_union3(_Float16, float, long, 16, 8);
+  check_struct_and_union3(_Float16, float, long long, 16, 8);
+  check_struct_and_union3(_Float16, float, float, 12, 4);
+  check_struct_and_union3(_Float16, float, double, 16, 8);
+  check_struct_and_union3(_Float16, float, long double, 32, 16);
+  check_struct_and_union3(_Float16, double, char, 24, 8);
+  check_struct_and_union3(_Float16, double, _Float16, 24, 8);
+  check_struct_and_union3(_Float16, double, int, 24, 8);
+  check_struct_and_union3(_Float16, double, long, 24, 8);
+  check_struct_and_union3(_Float16, double, long long, 24, 8);
+  check_struct_and_union3(_Float16, double, float, 24, 8);
+  check_struct_and_union3(_Float16, double, double, 24, 8);
+  check_struct_and_union3(_Float16, double, long double, 32, 16);
+  check_struct_and_union3(_Float16, long double, char, 48, 16);
+  check_struct_and_union3(_Float16, long double, _Float16, 48, 16);
+  check_struct_and_union3(_Float16, long double, int, 48, 16);
+  check_struct_and_union3(_Float16, long double, long, 48, 16);
+  check_struct_and_union3(_Float16, long double, long long, 48, 16);
+  check_struct_and_union3(_Float16, long double, float, 48, 16);
+  check_struct_and_union3(_Float16, long double, double, 48, 16);
+  check_struct_and_union3(_Float16, long double, long double, 48, 16);
+  check_struct_and_union3(int, char, _Float16, 8, 4);
+  check_struct_and_union3(int, _Float16, char, 8, 4);
+  check_struct_and_union3(int, _Float16, _Float16, 8, 4);
+  check_struct_and_union3(int, _Float16, int, 12, 4);
+  check_struct_and_union3(int, _Float16, long, 16, 8);
+  check_struct_and_union3(int, _Float16, long long, 16, 8);
+  check_struct_and_union3(int, _Float16, float, 12, 4);
+  check_struct_and_union3(int, _Float16, double, 16, 8);
+  check_struct_and_union3(int, _Float16, long double, 32, 16);
+  check_struct_and_union3(int, int, _Float16, 12, 4);
+  check_struct_and_union3(int, long, _Float16, 24, 8);
+  check_struct_and_union3(int, long long, _Float16, 24, 8);
+  check_struct_and_union3(int, float, _Float16, 12, 4);
+  check_struct_and_union3(int, double, _Float16, 24, 8);
+  check_struct_and_union3(int, long double, _Float16, 48, 16);
+  check_struct_and_union3(long, char, _Float16, 16, 8);
+  check_struct_and_union3(long, _Float16, char, 16, 8);
+  check_struct_and_union3(long, _Float16, _Float16, 16, 8);
+  check_struct_and_union3(long, _Float16, int, 16, 8);
+  check_struct_and_union3(long, _Float16, long, 24, 8);
+  check_struct_and_union3(long, _Float16, long long, 24, 8);
+  check_struct_and_union3(long, _Float16, float, 16, 8);
+  check_struct_and_union3(long, _Float16, double, 24, 8);
+  check_struct_and_union3(long, _Float16, long double, 32, 16);
+  check_struct_and_union3(long, int, _Float16, 16, 8);
+  check_struct_and_union3(long, long, _Float16, 24, 8);
+  check_struct_and_union3(long, long long, _Float16, 24, 8);
+  check_struct_and_union3(long, float, _Float16, 16, 8);
+  check_struct_and_union3(long, double, _Float16, 24, 8);
+  check_struct_and_union3(long, long double, _Float16, 48, 16);
+  check_struct_and_union3(long long, char, _Float16, 16, 8);
+  check_struct_and_union3(long long, _Float16, char, 16, 8);
+  check_struct_and_union3(long long, _Float16, _Float16, 16, 8);
+  check_struct_and_union3(long long, _Float16, int, 16, 8);
+  check_struct_and_union3(long long, _Float16, long, 24, 8);
+  check_struct_and_union3(long long, _Float16, long long, 24, 8);
+  check_struct_and_union3(long long, _Float16, float, 16, 8);
+  check_struct_and_union3(long long, _Float16, double, 24, 8);
+  check_struct_and_union3(long long, _Float16, long double, 32, 16);
+  check_struct_and_union3(long long, int, _Float16, 16, 8);
+  check_struct_and_union3(long long, long, _Float16, 24, 8);
+  check_struct_and_union3(long long, long long, _Float16, 24, 8);
+  check_struct_and_union3(long long, float, _Float16, 16, 8);
+  check_struct_and_union3(long long, double, _Float16, 24, 8);
+  check_struct_and_union3(long long, long double, _Float16, 48, 16);
+  check_struct_and_union3(float, char, _Float16, 8, 4);
+  check_struct_and_union3(float, _Float16, char, 8, 4);
+  check_struct_and_union3(float, _Float16, _Float16, 8, 4);
+  check_struct_and_union3(float, _Float16, int, 12, 4);
+  check_struct_and_union3(float, _Float16, long, 16, 8);
+  check_struct_and_union3(float, _Float16, long long, 16, 8);
+  check_struct_and_union3(float, _Float16, float, 12, 4);
+  check_struct_and_union3(float, _Float16, double, 16, 8);
+  check_struct_and_union3(float, _Float16, long double, 32, 16);
+  check_struct_and_union3(float, int, _Float16, 12, 4);
+  check_struct_and_union3(float, long, _Float16, 24, 8);
+  check_struct_and_union3(float, long long, _Float16, 24, 8);
+  check_struct_and_union3(float, float, _Float16, 12, 4);
+  check_struct_and_union3(float, double, _Float16, 24, 8);
+  check_struct_and_union3(float, long double, _Float16, 48, 16);
+  check_struct_and_union3(double, char, _Float16, 16, 8);
+  check_struct_and_union3(double, _Float16, char, 16, 8);
+  check_struct_and_union3(double, _Float16, _Float16, 16, 8);
+  check_struct_and_union3(double, _Float16, int, 16, 8);
+  check_struct_and_union3(double, _Float16, long, 24, 8);
+  check_struct_and_union3(double, _Float16, long long, 24, 8);
+  check_struct_and_union3(double, _Float16, float, 16, 8);
+  check_struct_and_union3(double, _Float16, double, 24, 8);
+  check_struct_and_union3(double, _Float16, long double, 32, 16);
+  check_struct_and_union3(double, int, _Float16, 16, 8);
+  check_struct_and_union3(double, long, _Float16, 24, 8);
+  check_struct_and_union3(double, long long, _Float16, 24, 8);
+  check_struct_and_union3(double, float, _Float16, 16, 8);
+  check_struct_and_union3(double, double, _Float16, 24, 8);
+  check_struct_and_union3(double, long double, _Float16, 48, 16);
+  check_struct_and_union3(long double, char, _Float16, 32, 16);
+  check_struct_and_union3(long double, _Float16, char, 32, 16);
+  check_struct_and_union3(long double, _Float16, _Float16, 32, 16);
+  check_struct_and_union3(long double, _Float16, int, 32, 16);
+  check_struct_and_union3(long double, _Float16, long, 32, 16);
+  check_struct_and_union3(long double, _Float16, long long, 32, 16);
+  check_struct_and_union3(long double, _Float16, float, 32, 16);
+  check_struct_and_union3(long double, _Float16, double, 32, 16);
+  check_struct_and_union3(long double, _Float16, long double, 48, 16);
+  check_struct_and_union3(long double, int, _Float16, 32, 16);
+  check_struct_and_union3(long double, long, _Float16, 32, 16);
+  check_struct_and_union3(long double, long long, _Float16, 32, 16);
+  check_struct_and_union3(long double, float, _Float16, 32, 16);
+  check_struct_and_union3(long double, double, _Float16, 32, 16);
+  check_struct_and_union3(long double, long double, _Float16, 48, 16);
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_alignment.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_alignment.c
new file mode 100644
index 00000000000..2a72b5c9e18
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_alignment.c
@@ -0,0 +1,45 @@ 
+/* This checks alignment of basic types.  */
+
+#include "defines.h"
+#include "macros.h"
+
+
+int
+main (void)
+{
+  /* Integral types.  */
+  run_signed_tests2(check_align, char, TYPE_ALIGN_CHAR);
+  run_signed_tests2(check_align, short, TYPE_ALIGN_SHORT);
+  run_signed_tests2(check_align, int, TYPE_ALIGN_INT);
+  run_signed_tests2(check_align, long, TYPE_ALIGN_LONG);
+  run_signed_tests2(check_align, long long, TYPE_ALIGN_LONG_LONG);
+#ifdef CHECK_INT128
+  run_signed_tests2(check_align, __int128, TYPE_ALIGN_INT128);
+#endif
+  check_align(enumtype, TYPE_ALIGN_ENUM);
+
+  /* Floating point types.  */
+  check_align(float, TYPE_ALIGN_FLOAT);
+  check_align(double, TYPE_ALIGN_DOUBLE);
+#ifdef CHECK_LONG_DOUBLE
+  check_align(long double, TYPE_ALIGN_LONG_DOUBLE);
+#endif
+#ifdef CHECK_FLOAT128
+  check_align(__float128, TYPE_ALIGN_FLOAT128);
+#endif
+
+  /* Packed types - MMX, 3DNow!, SSE and SSE2.  */
+#ifdef CHECK_M64_M128
+  check_align(__m64, TYPE_ALIGN_M64);
+  check_align(__m128, TYPE_ALIGN_M128);
+#endif
+
+  /* _Float16 point types.  */
+  check_align(_Float16, TYPE_ALIGN_FLOAT16);
+
+  /* Pointer types.  */
+  check_align(void *, TYPE_ALIGN_POINTER);
+  check_align(void (*)(), TYPE_ALIGN_POINTER);
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_array_size_and_align.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_array_size_and_align.c
new file mode 100644
index 00000000000..d58b9d1c43c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_array_size_and_align.c
@@ -0,0 +1,43 @@ 
+/* This checks .  */
+
+#include "defines.h"
+#include "macros.h"
+
+
+int
+main (void)
+{
+  /* Integral types.  */
+  run_signed_tests3(check_array_size_and_align, char, TYPE_SIZE_CHAR, TYPE_ALIGN_CHAR);
+  run_signed_tests3(check_array_size_and_align, short, TYPE_SIZE_SHORT, TYPE_ALIGN_SHORT);
+  run_signed_tests3(check_array_size_and_align, int, TYPE_SIZE_INT, TYPE_ALIGN_INT);
+  run_signed_tests3(check_array_size_and_align, long, TYPE_SIZE_LONG, TYPE_ALIGN_LONG);
+  run_signed_tests3(check_array_size_and_align, long long, TYPE_SIZE_LONG_LONG, TYPE_ALIGN_LONG_LONG);
+#ifdef CHECK_INT128
+  run_signed_tests3(check_array_size_and_align, __int128, TYPE_SIZE_INT128, TYPE_ALIGN_INT128);
+#endif
+  check_array_size_and_align(enum dummytype, TYPE_SIZE_ENUM, TYPE_ALIGN_ENUM);
+
+  /* Floating point types.  */
+  check_array_size_and_align(float, TYPE_SIZE_FLOAT, TYPE_ALIGN_FLOAT);
+  check_array_size_and_align(double, TYPE_SIZE_DOUBLE, TYPE_ALIGN_DOUBLE);
+#ifdef CHECK_LONG_DOUBLE
+  check_array_size_and_align(long double, TYPE_SIZE_LONG_DOUBLE, TYPE_ALIGN_LONG_DOUBLE);
+#endif
+#ifdef CHECK_FLOAT128
+  check_array_size_and_align(__float128, TYPE_SIZE_FLOAT128, TYPE_ALIGN_FLOAT128);
+#endif
+
+  /* Packed types - MMX, 3DNow!, SSE and SSE2.  */
+#ifdef CHECK_M64_M128
+  check_array_size_and_align(__m64, TYPE_SIZE_M64, TYPE_ALIGN_M64);
+  check_array_size_and_align(__m128, TYPE_SIZE_M128, TYPE_ALIGN_M128);
+#endif
+
+  /* Pointer types. The function pointer doesn't work with these macros.  */
+  check_array_size_and_align(void *, TYPE_SIZE_POINTER, TYPE_ALIGN_POINTER);
+
+  check_array_size_and_align(_Float16, TYPE_SIZE_FLOAT16, TYPE_ALIGN_FLOAT16);
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_returning.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_returning.c
new file mode 100644
index 00000000000..36fb24e6250
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_returning.c
@@ -0,0 +1,87 @@ 
+/* This is an autogenerated file. Do not edit.  */
+
+#include "avx512fp16-xmm-check.h"
+#include "defines.h"
+#include "macros.h"
+#include "args.h"
+
+char
+fun_test_returning_char (void)
+{
+  volatile_var++;
+  return 64;
+}
+
+short
+fun_test_returning_short (void)
+{
+  volatile_var++;
+  return 65;
+}
+
+int
+fun_test_returning_int (void)
+{
+  volatile_var++;
+  return 66;
+}
+
+long
+fun_test_returning_long (void)
+{
+  volatile_var++;
+  return 67;
+}
+
+long long
+fun_test_returning_long_long (void)
+{
+  volatile_var++;
+  return 68;
+}
+
+float
+fun_test_returning_float (void)
+{
+  volatile_var++;
+  return 69;
+}
+
+double
+fun_test_returning_double (void)
+{
+  volatile_var++;
+  return 70;
+}
+
+long double
+fun_test_returning_long_double (void)
+{
+  volatile_var++;
+  return 71;
+}
+
+_Float16
+fun_test_returning_float16 (void)
+{
+  volatile_var++;
+  return 72;
+}
+
+#define def_test_returning_type_xmm(fun, type, ret, reg) \
+  { type var = WRAP_RET (fun) (); \
+  assert (ret == (type) reg && ret == var); }
+
+static void
+do_test (void)
+{
+  def_test_returning_type_xmm(fun_test_returning_char, char, 64, rax);
+  def_test_returning_type_xmm(fun_test_returning_short, short, 65, rax);
+  def_test_returning_type_xmm(fun_test_returning_int, int, 66, rax);
+  def_test_returning_type_xmm(fun_test_returning_long, long, 67, rax);
+  def_test_returning_type_xmm(fun_test_returning_long_long, long long, 68, rax);
+  def_test_returning_type_xmm(fun_test_returning_float, float, 69, xmm_regs[0]._float[0]);
+  def_test_returning_type_xmm(fun_test_returning_double, double, 70, xmm_regs[0]._double[0]);
+  def_test_returning_type_xmm(fun_test_returning_long_double, long double, 71, x87_regs[0]._ldouble);
+  def_test_returning_type_xmm(fun_test_returning_float16, _Float16, 72, xmm_regs[0].__Float16[0]);
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_sizes.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_sizes.c
new file mode 100644
index 00000000000..47f3a5e87ca
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_sizes.c
@@ -0,0 +1,43 @@ 
+/* This checks sizes of basic types.  */
+
+#include "defines.h"
+#include "macros.h"
+
+
+int
+main (void)
+{
+  /* Integral types.  */
+  run_signed_tests2(check_size, char, TYPE_SIZE_CHAR);
+  run_signed_tests2(check_size, short, TYPE_SIZE_SHORT);
+  run_signed_tests2(check_size, int, TYPE_SIZE_INT);
+  run_signed_tests2(check_size, long, TYPE_SIZE_LONG);
+  run_signed_tests2(check_size, long long, TYPE_SIZE_LONG_LONG);
+#ifdef CHECK_INT128
+  run_signed_tests2(check_size, __int128, TYPE_SIZE_INT128);
+#endif
+  check_size(enumtype, TYPE_SIZE_ENUM);
+
+  /* Floating point types.  */
+  check_size(_Float16, TYPE_SIZE_FLOAT16);
+  check_size(float, TYPE_SIZE_FLOAT);
+  check_size(double, TYPE_SIZE_DOUBLE);
+#ifdef CHECK_LONG_DOUBLE
+  check_size(long double, TYPE_SIZE_LONG_DOUBLE);
+#endif
+#ifdef CHECK_FLOAT128
+  check_size(__float128, TYPE_SIZE_FLOAT128);
+#endif
+
+  /* Packed types - MMX, 3DNow!, SSE and SSE2.  */
+#ifdef CHECK_M64_M128
+  check_size(__m64, TYPE_SIZE_M64);
+  check_size(__m128, TYPE_SIZE_M128);
+#endif
+
+  /* Pointer types.  */
+  check_size(void *, TYPE_SIZE_POINTER);
+  check_size(void (*)(), TYPE_SIZE_POINTER);
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_struct_size_and_align.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_struct_size_and_align.c
new file mode 100644
index 00000000000..3d1add464a2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_struct_size_and_align.c
@@ -0,0 +1,42 @@ 
+/* This checks size and alignment of structs with a single basic type
+   element. All basic types are checked.  */
+
+#include "avx512fp16-xmm-check.h"
+#include "defines.h"
+#include "macros.h"
+
+
+static void
+do_test (void)
+{
+  /* Integral types.  */
+  run_signed_tests3(check_basic_struct_size_and_align, char, TYPE_SIZE_CHAR, TYPE_ALIGN_CHAR);
+  run_signed_tests3(check_basic_struct_size_and_align, short, TYPE_SIZE_SHORT, TYPE_ALIGN_SHORT);
+  run_signed_tests3(check_basic_struct_size_and_align, int, TYPE_SIZE_INT, TYPE_ALIGN_INT);
+  run_signed_tests3(check_basic_struct_size_and_align, long, TYPE_SIZE_LONG, TYPE_ALIGN_LONG);
+  run_signed_tests3(check_basic_struct_size_and_align, long long, TYPE_SIZE_LONG_LONG, TYPE_ALIGN_LONG_LONG);
+#ifdef CHECK_INT128
+  run_signed_tests3(check_basic_struct_size_and_align, __int128, TYPE_SIZE_INT128, TYPE_ALIGN_INT128);
+#endif
+  check_basic_struct_size_and_align(enum dummytype, TYPE_SIZE_ENUM, TYPE_ALIGN_ENUM);
+
+  /* Floating point types.  */
+  check_basic_struct_size_and_align(_Float16, TYPE_SIZE_FLOAT16, TYPE_ALIGN_FLOAT16);
+  check_basic_struct_size_and_align(float, TYPE_SIZE_FLOAT, TYPE_ALIGN_FLOAT);
+  check_basic_struct_size_and_align(double, TYPE_SIZE_DOUBLE, TYPE_ALIGN_DOUBLE);
+#ifdef CHECK_LONG_DOUBLE
+  check_basic_struct_size_and_align(long double, TYPE_SIZE_LONG_DOUBLE, TYPE_ALIGN_LONG_DOUBLE);
+#endif
+#ifdef CHECK_FLOAT128
+  check_basic_struct_size_and_align(__float128, TYPE_SIZE_FLOAT128, TYPE_ALIGN_FLOAT128);
+#endif
+
+  /* Packed types - MMX, 3DNow!, SSE and SSE2.  */
+#ifdef CHECK_M64_M128
+  check_basic_struct_size_and_align(__m64, TYPE_SIZE_M64, TYPE_ALIGN_M64);
+  check_basic_struct_size_and_align(__m128, TYPE_SIZE_M128, TYPE_ALIGN_M128);
+#endif
+
+  /* Pointer types. The function pointer doesn't work with these macros.  */
+  check_basic_struct_size_and_align(void *, TYPE_SIZE_POINTER, TYPE_ALIGN_POINTER);
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_union_size_and_align.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_union_size_and_align.c
new file mode 100644
index 00000000000..632feebe920
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_union_size_and_align.c
@@ -0,0 +1,40 @@ 
+/* Test of simple unions, size and alignment.  */
+
+#include "avx512fp16-xmm-check.h"
+#include "defines.h"
+#include "macros.h"
+
+static void
+do_test (void)
+{
+  /* Integral types.  */
+  run_signed_tests3(check_basic_union_size_and_align, char, TYPE_SIZE_CHAR, TYPE_ALIGN_CHAR);
+  run_signed_tests3(check_basic_union_size_and_align, short, TYPE_SIZE_SHORT, TYPE_ALIGN_SHORT);
+  run_signed_tests3(check_basic_union_size_and_align, int, TYPE_SIZE_INT, TYPE_ALIGN_INT);
+  run_signed_tests3(check_basic_union_size_and_align, long, TYPE_SIZE_LONG, TYPE_ALIGN_LONG);
+  run_signed_tests3(check_basic_union_size_and_align, long long, TYPE_SIZE_LONG_LONG, TYPE_ALIGN_LONG_LONG);
+#ifdef CHECK_INT128
+  run_signed_tests3(check_basic_union_size_and_align, __int128, TYPE_SIZE_INT128, TYPE_ALIGN_INT128);
+#endif
+  check_basic_union_size_and_align(enum dummytype, TYPE_SIZE_ENUM, TYPE_ALIGN_ENUM);
+
+  /* Floating point types.  */
+  check_basic_union_size_and_align(_Float16, TYPE_SIZE_FLOAT16, TYPE_ALIGN_FLOAT16);
+  check_basic_union_size_and_align(float, TYPE_SIZE_FLOAT, TYPE_ALIGN_FLOAT);
+  check_basic_union_size_and_align(double, TYPE_SIZE_DOUBLE, TYPE_ALIGN_DOUBLE);
+#ifdef CHECK_LONG_DOUBLE
+  check_basic_union_size_and_align(long double, TYPE_SIZE_LONG_DOUBLE, TYPE_ALIGN_LONG_DOUBLE);
+#endif
+#ifdef CHECK_FLOAT128
+  check_basic_union_size_and_align(__float128, TYPE_SIZE_FLOAT128, TYPE_ALIGN_FLOAT128);
+#endif
+
+  /* Packed types - MMX, 3DNow!, SSE and SSE2.  */
+#ifdef CHECK_M64_M128
+  check_basic_union_size_and_align(__m64, TYPE_SIZE_M64, TYPE_ALIGN_M64);
+  check_basic_union_size_and_align(__m128, TYPE_SIZE_M128, TYPE_ALIGN_M128);
+#endif
+
+  /* Pointer types. The function pointer doesn't work with these macros.  */
+  check_basic_union_size_and_align(void *, TYPE_SIZE_POINTER, TYPE_ALIGN_POINTER);
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_complex_returning.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_complex_returning.c
new file mode 100644
index 00000000000..829d86e9ee7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_complex_returning.c
@@ -0,0 +1,104 @@ 
+/* This is a small test case for returning a complex number. Written by
+   Andreas Jaeger.  */
+
+#include "avx512fp16-xmm-check.h"
+#include "defines.h"
+
+#define BUILD_F16_COMPLEX(real, imag) \
+  ({ __complex__ _Float16 __retval; \
+     __real__ __retval = (real); \
+     __imag__ __retval = (imag); \
+     __retval; })
+
+__complex__ _Float16
+aj_f16_times2 (__complex__ _Float16 x)
+{
+  __complex__ _Float16 res;
+
+  __real__ res = (2.0 * __real__ x);
+  __imag__ res = (2.0 * __imag__ x);
+
+  return res;
+}
+
+#define BUILD_F_COMPLEX(real, imag) \
+  ({ __complex__ float __retval; \
+     __real__ __retval = (real); \
+     __imag__ __retval = (imag); \
+     __retval; })
+
+#define BUILD_D_COMPLEX(real, imag) \
+  ({ __complex__ double __retval; \
+     __real__ __retval = (real); \
+     __imag__ __retval = (imag); \
+     __retval; })
+
+#define BUILD_LD_COMPLEX(real, imag) \
+  ({ __complex__ long double __retval; \
+     __real__ __retval = (real); \
+     __imag__ __retval = (imag); \
+     __retval; })
+
+__complex__ float
+aj_f_times2 (__complex__ float x)
+{
+  __complex__ float res;
+
+  __real__ res = (2.0 * __real__ x);
+  __imag__ res = (2.0 * __imag__ x);
+
+  return res;
+}
+
+__complex__ double
+aj_d_times2 (__complex__ double x)
+{
+  __complex__ double res;
+
+  __real__ res = (2.0 * __real__ x);
+  __imag__ res = (2.0 * __imag__ x);
+
+  return res;
+}
+
+__complex__ long double
+aj_ld_times2 (__complex__ long double x)
+{
+  __complex__ long double res;
+
+  __real__ res = (2.0 * __real__ x);
+  __imag__ res = (2.0 * __imag__ x);
+
+  return res;
+}
+
+static void
+do_test (void)
+{
+#ifdef CHECK_COMPLEX
+  _Complex _Float16 f16c, f16d;
+  _Complex float fc, fd;
+  _Complex double dc, dd;
+  _Complex long double ldc, ldd;
+
+  f16c = BUILD_F16_COMPLEX (2.0, 3.0);
+  f16d = aj_f16_times2 (f16c);
+
+  assert (__real__ f16d == 4.0f16 && __imag__ f16d == 6.0f16);
+
+  fc = BUILD_LD_COMPLEX (2.0f, 3.0f);
+  fd = aj_f_times2 (fc);
+
+  assert (__real__ fd == 4.0f && __imag__ fd == 6.0f);
+
+  dc = BUILD_LD_COMPLEX (2.0, 3.0);
+  dd = aj_ld_times2 (dc);
+
+  assert (__real__ dd == 4.0 && __imag__ dd == 6.0);
+
+  ldc = BUILD_LD_COMPLEX (2.0L, 3.0L);
+  ldd = aj_ld_times2 (ldc);
+
+  assert (__real__ ldd == 4.0L && __imag__ ldd == 6.0L);
+#endif
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_m64m128_returning.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_m64m128_returning.c
new file mode 100644
index 00000000000..34afee66586
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_m64m128_returning.c
@@ -0,0 +1,73 @@ 
+#include <stdio.h>
+#include "avx512fp16-xmm-check.h"
+#include "defines.h"
+#include "macros.h"
+#include "args.h"
+
+struct IntegerRegisters iregs;
+struct FloatRegisters fregs;
+unsigned int num_iregs, num_fregs;
+
+__m64
+fun_test_returning___m64 (void)
+{
+  volatile_var++;
+  return (__m64){72,0};
+}
+
+__m128
+fun_test_returning___m128 (void)
+{
+  volatile_var++;
+  return (__m128){73,0,0,0};
+}
+
+__m128h
+fun_test_returning___m128h (void)
+{
+  volatile_var++;
+  return (__m128h){1.1f16, 2.2f16, 3.3f16, 4.4f16, 5.5f16,
+                   6.6f16, 7.7f16, 8.8f16};
+}
+
+__m64 test_64;
+__m128 test_128;
+__m128h test_128h;
+
+static void
+do_test (void)
+{
+  unsigned failed = 0;
+  XMM_T xmmt1, xmmt2;
+
+  /* We jump through hoops to compare the results as gcc 3.3 does throw
+     an ICE when trying to generate a compare for a == b, when a and b
+     are of __m64 or __m128 type :-(  */
+  clear_struct_registers;
+  test_64 = (__m64){72,0};
+  xmmt1._m64[0] = test_64;
+  xmmt2._m64[0] = WRAP_RET (fun_test_returning___m64)();
+  if (xmmt1._long[0] != xmmt2._long[0]
+      || xmmt1._long[0] != xmm_regs[0]._long[0])
+    printf ("fail m64\n"), failed++;
+
+  clear_struct_registers;
+  test_128 = (__m128){73,0};
+  xmmt1._m128[0] = test_128;
+  xmmt2._m128[0] = WRAP_RET (fun_test_returning___m128)();
+  if (xmmt1._long[0] != xmmt2._long[0]
+      || xmmt1._long[0] != xmm_regs[0]._long[0])
+    printf ("fail m128\n"), failed++;
+
+  clear_struct_registers;
+  test_128h = (__m128h){1.1f16, 2.2f16, 3.3f16, 4.4f16, 5.5f16,
+                        6.6f16, 7.7f16, 8.8f16};
+  xmmt1._m128h[0] = test_128h;
+  xmmt2._m128h[0] = WRAP_RET (fun_test_returning___m128h)();
+  if (xmmt1._long[0] != xmmt2._long[0]
+      || xmmt1._long[0] != xmm_regs[0]._long[0])
+    printf ("fail m128h\n"), failed++;
+
+  if (failed)
+    abort ();
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_passing_floats.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_passing_floats.c
new file mode 100644
index 00000000000..678b25c14d3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_passing_floats.c
@@ -0,0 +1,1066 @@ 
+/* This is an autogenerated file. Do not edit.  */
+
+#include "avx512fp16-xmm-check.h"
+#include "defines.h"
+#include "macros.h"
+#include "args.h"
+
+struct IntegerRegisters iregs;
+struct FloatRegisters fregs;
+unsigned int num_iregs, num_fregs;
+
+/* This struct holds values for argument checking.  */
+struct
+{
+  _Float16 f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14,
+    f15, f16, f17, f18, f19, f20, f21, f22, f23;
+} values__Float16;
+
+struct
+{
+  float f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+    f16, f17, f18, f19, f20, f21, f22, f23;
+} values_float;
+
+struct
+{
+  double f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+    f16, f17, f18, f19, f20, f21, f22, f23;
+} values_double;
+
+struct
+{
+  ldouble f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14,
+    f15, f16, f17, f18, f19, f20, f21, f22, f23;
+} values_ldouble;
+
+void
+fun_check_float16_passing_8_values (_Float16 f0 ATTRIBUTE_UNUSED,
+				    _Float16 f1 ATTRIBUTE_UNUSED,
+				    _Float16 f2 ATTRIBUTE_UNUSED,
+				    _Float16 f3 ATTRIBUTE_UNUSED,
+				    _Float16 f4 ATTRIBUTE_UNUSED,
+				    _Float16 f5 ATTRIBUTE_UNUSED,
+				    _Float16 f6 ATTRIBUTE_UNUSED,
+				    _Float16 f7 ATTRIBUTE_UNUSED)
+{
+  /* Check argument values.  */
+  assert (values__Float16.f0 == f0);
+  assert (values__Float16.f1 == f1);
+  assert (values__Float16.f2 == f2);
+  assert (values__Float16.f3 == f3);
+  assert (values__Float16.f4 == f4);
+  assert (values__Float16.f5 == f5);
+  assert (values__Float16.f6 == f6);
+  assert (values__Float16.f7 == f7);
+}
+
+void
+fun_check_float16_passing_8_regs (_Float16 f0 ATTRIBUTE_UNUSED,
+				  _Float16 f1 ATTRIBUTE_UNUSED,
+				  _Float16 f2 ATTRIBUTE_UNUSED,
+				  _Float16 f3 ATTRIBUTE_UNUSED,
+				  _Float16 f4 ATTRIBUTE_UNUSED,
+				  _Float16 f5 ATTRIBUTE_UNUSED,
+				  _Float16 f6 ATTRIBUTE_UNUSED,
+				  _Float16 f7 ATTRIBUTE_UNUSED)
+{
+  /* Check register contents.  */
+  check_float16_arguments;
+}
+
+void
+fun_check_float16_passing_16_values (_Float16 f0 ATTRIBUTE_UNUSED,
+				     _Float16 f1 ATTRIBUTE_UNUSED,
+				     _Float16 f2 ATTRIBUTE_UNUSED,
+				     _Float16 f3 ATTRIBUTE_UNUSED,
+				     _Float16 f4 ATTRIBUTE_UNUSED,
+				     _Float16 f5 ATTRIBUTE_UNUSED,
+				     _Float16 f6 ATTRIBUTE_UNUSED,
+				     _Float16 f7 ATTRIBUTE_UNUSED,
+				     _Float16 f8 ATTRIBUTE_UNUSED,
+				     _Float16 f9 ATTRIBUTE_UNUSED,
+				     _Float16 f10 ATTRIBUTE_UNUSED,
+				     _Float16 f11 ATTRIBUTE_UNUSED,
+				     _Float16 f12 ATTRIBUTE_UNUSED,
+				     _Float16 f13 ATTRIBUTE_UNUSED,
+				     _Float16 f14 ATTRIBUTE_UNUSED,
+				     _Float16 f15 ATTRIBUTE_UNUSED)
+{
+  /* Check argument values.  */
+  assert (values__Float16.f0 == f0);
+  assert (values__Float16.f1 == f1);
+  assert (values__Float16.f2 == f2);
+  assert (values__Float16.f3 == f3);
+  assert (values__Float16.f4 == f4);
+  assert (values__Float16.f5 == f5);
+  assert (values__Float16.f6 == f6);
+  assert (values__Float16.f7 == f7);
+  assert (values__Float16.f8 == f8);
+  assert (values__Float16.f9 == f9);
+  assert (values__Float16.f10 == f10);
+  assert (values__Float16.f11 == f11);
+  assert (values__Float16.f12 == f12);
+  assert (values__Float16.f13 == f13);
+  assert (values__Float16.f14 == f14);
+  assert (values__Float16.f15 == f15);
+}
+
+void
+fun_check_float16_passing_16_regs (_Float16 f0 ATTRIBUTE_UNUSED,
+				   _Float16 f1 ATTRIBUTE_UNUSED,
+				   _Float16 f2 ATTRIBUTE_UNUSED,
+				   _Float16 f3 ATTRIBUTE_UNUSED,
+				   _Float16 f4 ATTRIBUTE_UNUSED,
+				   _Float16 f5 ATTRIBUTE_UNUSED,
+				   _Float16 f6 ATTRIBUTE_UNUSED,
+				   _Float16 f7 ATTRIBUTE_UNUSED,
+				   _Float16 f8 ATTRIBUTE_UNUSED,
+				   _Float16 f9 ATTRIBUTE_UNUSED,
+				   _Float16 f10 ATTRIBUTE_UNUSED,
+				   _Float16 f11 ATTRIBUTE_UNUSED,
+				   _Float16 f12 ATTRIBUTE_UNUSED,
+				   _Float16 f13 ATTRIBUTE_UNUSED,
+				   _Float16 f14 ATTRIBUTE_UNUSED,
+				   _Float16 f15 ATTRIBUTE_UNUSED)
+{
+  /* Check register contents.  */
+  check_float16_arguments;
+}
+
+void
+fun_check_float16_passing_20_values (_Float16 f0 ATTRIBUTE_UNUSED,
+				     _Float16 f1 ATTRIBUTE_UNUSED,
+				     _Float16 f2 ATTRIBUTE_UNUSED,
+				     _Float16 f3 ATTRIBUTE_UNUSED,
+				     _Float16 f4 ATTRIBUTE_UNUSED,
+				     _Float16 f5 ATTRIBUTE_UNUSED,
+				     _Float16 f6 ATTRIBUTE_UNUSED,
+				     _Float16 f7 ATTRIBUTE_UNUSED,
+				     _Float16 f8 ATTRIBUTE_UNUSED,
+				     _Float16 f9 ATTRIBUTE_UNUSED,
+				     _Float16 f10 ATTRIBUTE_UNUSED,
+				     _Float16 f11 ATTRIBUTE_UNUSED,
+				     _Float16 f12 ATTRIBUTE_UNUSED,
+				     _Float16 f13 ATTRIBUTE_UNUSED,
+				     _Float16 f14 ATTRIBUTE_UNUSED,
+				     _Float16 f15 ATTRIBUTE_UNUSED,
+				     _Float16 f16 ATTRIBUTE_UNUSED,
+				     _Float16 f17 ATTRIBUTE_UNUSED,
+				     _Float16 f18 ATTRIBUTE_UNUSED,
+				     _Float16 f19 ATTRIBUTE_UNUSED)
+{
+  /* Check argument values.  */
+  assert (values__Float16.f0 == f0);
+  assert (values__Float16.f1 == f1);
+  assert (values__Float16.f2 == f2);
+  assert (values__Float16.f3 == f3);
+  assert (values__Float16.f4 == f4);
+  assert (values__Float16.f5 == f5);
+  assert (values__Float16.f6 == f6);
+  assert (values__Float16.f7 == f7);
+  assert (values__Float16.f8 == f8);
+  assert (values__Float16.f9 == f9);
+  assert (values__Float16.f10 == f10);
+  assert (values__Float16.f11 == f11);
+  assert (values__Float16.f12 == f12);
+  assert (values__Float16.f13 == f13);
+  assert (values__Float16.f14 == f14);
+  assert (values__Float16.f15 == f15);
+  assert (values__Float16.f16 == f16);
+  assert (values__Float16.f17 == f17);
+  assert (values__Float16.f18 == f18);
+  assert (values__Float16.f19 == f19);
+}
+
+void
+fun_check_float16_passing_20_regs (_Float16 f0 ATTRIBUTE_UNUSED,
+				   _Float16 f1 ATTRIBUTE_UNUSED,
+				   _Float16 f2 ATTRIBUTE_UNUSED,
+				   _Float16 f3 ATTRIBUTE_UNUSED,
+				   _Float16 f4 ATTRIBUTE_UNUSED,
+				   _Float16 f5 ATTRIBUTE_UNUSED,
+				   _Float16 f6 ATTRIBUTE_UNUSED,
+				   _Float16 f7 ATTRIBUTE_UNUSED,
+				   _Float16 f8 ATTRIBUTE_UNUSED,
+				   _Float16 f9 ATTRIBUTE_UNUSED,
+				   _Float16 f10 ATTRIBUTE_UNUSED,
+				   _Float16 f11 ATTRIBUTE_UNUSED,
+				   _Float16 f12 ATTRIBUTE_UNUSED,
+				   _Float16 f13 ATTRIBUTE_UNUSED,
+				   _Float16 f14 ATTRIBUTE_UNUSED,
+				   _Float16 f15 ATTRIBUTE_UNUSED,
+				   _Float16 f16 ATTRIBUTE_UNUSED,
+				   _Float16 f17 ATTRIBUTE_UNUSED,
+				   _Float16 f18 ATTRIBUTE_UNUSED,
+				   _Float16 f19 ATTRIBUTE_UNUSED)
+{
+  /* Check register contents.  */
+  check_float16_arguments;
+}
+
+void
+fun_check_float_passing_float8_values (float f0 ATTRIBUTE_UNUSED,
+				       float f1 ATTRIBUTE_UNUSED,
+				       float f2 ATTRIBUTE_UNUSED,
+				       float f3 ATTRIBUTE_UNUSED,
+				       float f4 ATTRIBUTE_UNUSED,
+				       float f5 ATTRIBUTE_UNUSED,
+				       float f6 ATTRIBUTE_UNUSED,
+				       float f7 ATTRIBUTE_UNUSED)
+{
+  /* Check argument values.  */
+  assert (values_float.f0 == f0);
+  assert (values_float.f1 == f1);
+  assert (values_float.f2 == f2);
+  assert (values_float.f3 == f3);
+  assert (values_float.f4 == f4);
+  assert (values_float.f5 == f5);
+  assert (values_float.f6 == f6);
+  assert (values_float.f7 == f7);
+
+}
+
+void
+fun_check_float_passing_float8_regs (float f0 ATTRIBUTE_UNUSED,
+				     float f1 ATTRIBUTE_UNUSED,
+				     float f2 ATTRIBUTE_UNUSED,
+				     float f3 ATTRIBUTE_UNUSED,
+				     float f4 ATTRIBUTE_UNUSED,
+				     float f5 ATTRIBUTE_UNUSED,
+				     float f6 ATTRIBUTE_UNUSED,
+				     float f7 ATTRIBUTE_UNUSED)
+{
+  /* Check register contents.  */
+  check_float_arguments;
+}
+
+void
+fun_check_float_passing_float16_values (float f0 ATTRIBUTE_UNUSED,
+					float f1 ATTRIBUTE_UNUSED,
+					float f2 ATTRIBUTE_UNUSED,
+					float f3 ATTRIBUTE_UNUSED,
+					float f4 ATTRIBUTE_UNUSED,
+					float f5 ATTRIBUTE_UNUSED,
+					float f6 ATTRIBUTE_UNUSED,
+					float f7 ATTRIBUTE_UNUSED,
+					float f8 ATTRIBUTE_UNUSED,
+					float f9 ATTRIBUTE_UNUSED,
+					float f10 ATTRIBUTE_UNUSED,
+					float f11 ATTRIBUTE_UNUSED,
+					float f12 ATTRIBUTE_UNUSED,
+					float f13 ATTRIBUTE_UNUSED,
+					float f14 ATTRIBUTE_UNUSED,
+					float f15 ATTRIBUTE_UNUSED)
+{
+  /* Check argument values.  */
+  assert (values_float.f0 == f0);
+  assert (values_float.f1 == f1);
+  assert (values_float.f2 == f2);
+  assert (values_float.f3 == f3);
+  assert (values_float.f4 == f4);
+  assert (values_float.f5 == f5);
+  assert (values_float.f6 == f6);
+  assert (values_float.f7 == f7);
+  assert (values_float.f8 == f8);
+  assert (values_float.f9 == f9);
+  assert (values_float.f10 == f10);
+  assert (values_float.f11 == f11);
+  assert (values_float.f12 == f12);
+  assert (values_float.f13 == f13);
+  assert (values_float.f14 == f14);
+  assert (values_float.f15 == f15);
+
+}
+
+void
+fun_check_float_passing_float16_regs (float f0 ATTRIBUTE_UNUSED,
+				      float f1 ATTRIBUTE_UNUSED,
+				      float f2 ATTRIBUTE_UNUSED,
+				      float f3 ATTRIBUTE_UNUSED,
+				      float f4 ATTRIBUTE_UNUSED,
+				      float f5 ATTRIBUTE_UNUSED,
+				      float f6 ATTRIBUTE_UNUSED,
+				      float f7 ATTRIBUTE_UNUSED,
+				      float f8 ATTRIBUTE_UNUSED,
+				      float f9 ATTRIBUTE_UNUSED,
+				      float f10 ATTRIBUTE_UNUSED,
+				      float f11 ATTRIBUTE_UNUSED,
+				      float f12 ATTRIBUTE_UNUSED,
+				      float f13 ATTRIBUTE_UNUSED,
+				      float f14 ATTRIBUTE_UNUSED,
+				      float f15 ATTRIBUTE_UNUSED)
+{
+  /* Check register contents.  */
+  check_float_arguments;
+}
+
+void
+fun_check_float_passing_float20_values (float f0 ATTRIBUTE_UNUSED,
+					float f1 ATTRIBUTE_UNUSED,
+					float f2 ATTRIBUTE_UNUSED,
+					float f3 ATTRIBUTE_UNUSED,
+					float f4 ATTRIBUTE_UNUSED,
+					float f5 ATTRIBUTE_UNUSED,
+					float f6 ATTRIBUTE_UNUSED,
+					float f7 ATTRIBUTE_UNUSED,
+					float f8 ATTRIBUTE_UNUSED,
+					float f9 ATTRIBUTE_UNUSED,
+					float f10 ATTRIBUTE_UNUSED,
+					float f11 ATTRIBUTE_UNUSED,
+					float f12 ATTRIBUTE_UNUSED,
+					float f13 ATTRIBUTE_UNUSED,
+					float f14 ATTRIBUTE_UNUSED,
+					float f15 ATTRIBUTE_UNUSED,
+					float f16 ATTRIBUTE_UNUSED,
+					float f17 ATTRIBUTE_UNUSED,
+					float f18 ATTRIBUTE_UNUSED,
+					float f19 ATTRIBUTE_UNUSED)
+{
+  /* Check argument values.  */
+  assert (values_float.f0 == f0);
+  assert (values_float.f1 == f1);
+  assert (values_float.f2 == f2);
+  assert (values_float.f3 == f3);
+  assert (values_float.f4 == f4);
+  assert (values_float.f5 == f5);
+  assert (values_float.f6 == f6);
+  assert (values_float.f7 == f7);
+  assert (values_float.f8 == f8);
+  assert (values_float.f9 == f9);
+  assert (values_float.f10 == f10);
+  assert (values_float.f11 == f11);
+  assert (values_float.f12 == f12);
+  assert (values_float.f13 == f13);
+  assert (values_float.f14 == f14);
+  assert (values_float.f15 == f15);
+  assert (values_float.f16 == f16);
+  assert (values_float.f17 == f17);
+  assert (values_float.f18 == f18);
+  assert (values_float.f19 == f19);
+
+}
+
+void
+fun_check_float_passing_float20_regs (float f0 ATTRIBUTE_UNUSED,
+				      float f1 ATTRIBUTE_UNUSED,
+				      float f2 ATTRIBUTE_UNUSED,
+				      float f3 ATTRIBUTE_UNUSED,
+				      float f4 ATTRIBUTE_UNUSED,
+				      float f5 ATTRIBUTE_UNUSED,
+				      float f6 ATTRIBUTE_UNUSED,
+				      float f7 ATTRIBUTE_UNUSED,
+				      float f8 ATTRIBUTE_UNUSED,
+				      float f9 ATTRIBUTE_UNUSED,
+				      float f10 ATTRIBUTE_UNUSED,
+				      float f11 ATTRIBUTE_UNUSED,
+				      float f12 ATTRIBUTE_UNUSED,
+				      float f13 ATTRIBUTE_UNUSED,
+				      float f14 ATTRIBUTE_UNUSED,
+				      float f15 ATTRIBUTE_UNUSED,
+				      float f16 ATTRIBUTE_UNUSED,
+				      float f17 ATTRIBUTE_UNUSED,
+				      float f18 ATTRIBUTE_UNUSED,
+				      float f19 ATTRIBUTE_UNUSED)
+{
+  /* Check register contents.  */
+  check_float_arguments;
+}
+
+void
+fun_check_float_passing_double8_values (double f0 ATTRIBUTE_UNUSED,
+					double f1 ATTRIBUTE_UNUSED,
+					double f2 ATTRIBUTE_UNUSED,
+					double f3 ATTRIBUTE_UNUSED,
+					double f4 ATTRIBUTE_UNUSED,
+					double f5 ATTRIBUTE_UNUSED,
+					double f6 ATTRIBUTE_UNUSED,
+					double f7 ATTRIBUTE_UNUSED)
+{
+  /* Check argument values.  */
+  assert (values_double.f0 == f0);
+  assert (values_double.f1 == f1);
+  assert (values_double.f2 == f2);
+  assert (values_double.f3 == f3);
+  assert (values_double.f4 == f4);
+  assert (values_double.f5 == f5);
+  assert (values_double.f6 == f6);
+  assert (values_double.f7 == f7);
+
+}
+
+void
+fun_check_float_passing_double8_regs (double f0 ATTRIBUTE_UNUSED,
+				      double f1 ATTRIBUTE_UNUSED,
+				      double f2 ATTRIBUTE_UNUSED,
+				      double f3 ATTRIBUTE_UNUSED,
+				      double f4 ATTRIBUTE_UNUSED,
+				      double f5 ATTRIBUTE_UNUSED,
+				      double f6 ATTRIBUTE_UNUSED,
+				      double f7 ATTRIBUTE_UNUSED)
+{
+  /* Check register contents.  */
+  check_double_arguments;
+}
+
+void
+fun_check_float_passing_double16_values (double f0 ATTRIBUTE_UNUSED,
+					 double f1 ATTRIBUTE_UNUSED,
+					 double f2 ATTRIBUTE_UNUSED,
+					 double f3 ATTRIBUTE_UNUSED,
+					 double f4 ATTRIBUTE_UNUSED,
+					 double f5 ATTRIBUTE_UNUSED,
+					 double f6 ATTRIBUTE_UNUSED,
+					 double f7 ATTRIBUTE_UNUSED,
+					 double f8 ATTRIBUTE_UNUSED,
+					 double f9 ATTRIBUTE_UNUSED,
+					 double f10 ATTRIBUTE_UNUSED,
+					 double f11 ATTRIBUTE_UNUSED,
+					 double f12 ATTRIBUTE_UNUSED,
+					 double f13 ATTRIBUTE_UNUSED,
+					 double f14 ATTRIBUTE_UNUSED,
+					 double f15 ATTRIBUTE_UNUSED)
+{
+  /* Check argument values.  */
+  assert (values_double.f0 == f0);
+  assert (values_double.f1 == f1);
+  assert (values_double.f2 == f2);
+  assert (values_double.f3 == f3);
+  assert (values_double.f4 == f4);
+  assert (values_double.f5 == f5);
+  assert (values_double.f6 == f6);
+  assert (values_double.f7 == f7);
+  assert (values_double.f8 == f8);
+  assert (values_double.f9 == f9);
+  assert (values_double.f10 == f10);
+  assert (values_double.f11 == f11);
+  assert (values_double.f12 == f12);
+  assert (values_double.f13 == f13);
+  assert (values_double.f14 == f14);
+  assert (values_double.f15 == f15);
+
+}
+
+void
+fun_check_float_passing_double16_regs (double f0 ATTRIBUTE_UNUSED,
+				       double f1 ATTRIBUTE_UNUSED,
+				       double f2 ATTRIBUTE_UNUSED,
+				       double f3 ATTRIBUTE_UNUSED,
+				       double f4 ATTRIBUTE_UNUSED,
+				       double f5 ATTRIBUTE_UNUSED,
+				       double f6 ATTRIBUTE_UNUSED,
+				       double f7 ATTRIBUTE_UNUSED,
+				       double f8 ATTRIBUTE_UNUSED,
+				       double f9 ATTRIBUTE_UNUSED,
+				       double f10 ATTRIBUTE_UNUSED,
+				       double f11 ATTRIBUTE_UNUSED,
+				       double f12 ATTRIBUTE_UNUSED,
+				       double f13 ATTRIBUTE_UNUSED,
+				       double f14 ATTRIBUTE_UNUSED,
+				       double f15 ATTRIBUTE_UNUSED)
+{
+  /* Check register contents.  */
+  check_double_arguments;
+}
+
+void
+fun_check_float_passing_double20_values (double f0 ATTRIBUTE_UNUSED,
+					 double f1 ATTRIBUTE_UNUSED,
+					 double f2 ATTRIBUTE_UNUSED,
+					 double f3 ATTRIBUTE_UNUSED,
+					 double f4 ATTRIBUTE_UNUSED,
+					 double f5 ATTRIBUTE_UNUSED,
+					 double f6 ATTRIBUTE_UNUSED,
+					 double f7 ATTRIBUTE_UNUSED,
+					 double f8 ATTRIBUTE_UNUSED,
+					 double f9 ATTRIBUTE_UNUSED,
+					 double f10 ATTRIBUTE_UNUSED,
+					 double f11 ATTRIBUTE_UNUSED,
+					 double f12 ATTRIBUTE_UNUSED,
+					 double f13 ATTRIBUTE_UNUSED,
+					 double f14 ATTRIBUTE_UNUSED,
+					 double f15 ATTRIBUTE_UNUSED,
+					 double f16 ATTRIBUTE_UNUSED,
+					 double f17 ATTRIBUTE_UNUSED,
+					 double f18 ATTRIBUTE_UNUSED,
+					 double f19 ATTRIBUTE_UNUSED)
+{
+  /* Check argument values.  */
+  assert (values_double.f0 == f0);
+  assert (values_double.f1 == f1);
+  assert (values_double.f2 == f2);
+  assert (values_double.f3 == f3);
+  assert (values_double.f4 == f4);
+  assert (values_double.f5 == f5);
+  assert (values_double.f6 == f6);
+  assert (values_double.f7 == f7);
+  assert (values_double.f8 == f8);
+  assert (values_double.f9 == f9);
+  assert (values_double.f10 == f10);
+  assert (values_double.f11 == f11);
+  assert (values_double.f12 == f12);
+  assert (values_double.f13 == f13);
+  assert (values_double.f14 == f14);
+  assert (values_double.f15 == f15);
+  assert (values_double.f16 == f16);
+  assert (values_double.f17 == f17);
+  assert (values_double.f18 == f18);
+  assert (values_double.f19 == f19);
+
+}
+
+void
+fun_check_float_passing_double20_regs (double f0 ATTRIBUTE_UNUSED,
+				       double f1 ATTRIBUTE_UNUSED,
+				       double f2 ATTRIBUTE_UNUSED,
+				       double f3 ATTRIBUTE_UNUSED,
+				       double f4 ATTRIBUTE_UNUSED,
+				       double f5 ATTRIBUTE_UNUSED,
+				       double f6 ATTRIBUTE_UNUSED,
+				       double f7 ATTRIBUTE_UNUSED,
+				       double f8 ATTRIBUTE_UNUSED,
+				       double f9 ATTRIBUTE_UNUSED,
+				       double f10 ATTRIBUTE_UNUSED,
+				       double f11 ATTRIBUTE_UNUSED,
+				       double f12 ATTRIBUTE_UNUSED,
+				       double f13 ATTRIBUTE_UNUSED,
+				       double f14 ATTRIBUTE_UNUSED,
+				       double f15 ATTRIBUTE_UNUSED,
+				       double f16 ATTRIBUTE_UNUSED,
+				       double f17 ATTRIBUTE_UNUSED,
+				       double f18 ATTRIBUTE_UNUSED,
+				       double f19 ATTRIBUTE_UNUSED)
+{
+  /* Check register contents.  */
+  check_double_arguments;
+}
+
+void
+fun_check_x87_passing_ldouble8_values (ldouble f0 ATTRIBUTE_UNUSED,
+				       ldouble f1 ATTRIBUTE_UNUSED,
+				       ldouble f2 ATTRIBUTE_UNUSED,
+				       ldouble f3 ATTRIBUTE_UNUSED,
+				       ldouble f4 ATTRIBUTE_UNUSED,
+				       ldouble f5 ATTRIBUTE_UNUSED,
+				       ldouble f6 ATTRIBUTE_UNUSED,
+				       ldouble f7 ATTRIBUTE_UNUSED)
+{
+  /* Check argument values.  */
+  assert (values_ldouble.f0 == f0);
+  assert (values_ldouble.f1 == f1);
+  assert (values_ldouble.f2 == f2);
+  assert (values_ldouble.f3 == f3);
+  assert (values_ldouble.f4 == f4);
+  assert (values_ldouble.f5 == f5);
+  assert (values_ldouble.f6 == f6);
+  assert (values_ldouble.f7 == f7);
+
+}
+
+void
+fun_check_x87_passing_ldouble8_regs (ldouble f0 ATTRIBUTE_UNUSED,
+				     ldouble f1 ATTRIBUTE_UNUSED,
+				     ldouble f2 ATTRIBUTE_UNUSED,
+				     ldouble f3 ATTRIBUTE_UNUSED,
+				     ldouble f4 ATTRIBUTE_UNUSED,
+				     ldouble f5 ATTRIBUTE_UNUSED,
+				     ldouble f6 ATTRIBUTE_UNUSED,
+				     ldouble f7 ATTRIBUTE_UNUSED)
+{
+  /* Check register contents.  */
+  check_ldouble_arguments;
+}
+
+void
+fun_check_x87_passing_ldouble16_values (ldouble f0 ATTRIBUTE_UNUSED,
+					ldouble f1 ATTRIBUTE_UNUSED,
+					ldouble f2 ATTRIBUTE_UNUSED,
+					ldouble f3 ATTRIBUTE_UNUSED,
+					ldouble f4 ATTRIBUTE_UNUSED,
+					ldouble f5 ATTRIBUTE_UNUSED,
+					ldouble f6 ATTRIBUTE_UNUSED,
+					ldouble f7 ATTRIBUTE_UNUSED,
+					ldouble f8 ATTRIBUTE_UNUSED,
+					ldouble f9 ATTRIBUTE_UNUSED,
+					ldouble f10 ATTRIBUTE_UNUSED,
+					ldouble f11 ATTRIBUTE_UNUSED,
+					ldouble f12 ATTRIBUTE_UNUSED,
+					ldouble f13 ATTRIBUTE_UNUSED,
+					ldouble f14 ATTRIBUTE_UNUSED,
+					ldouble f15 ATTRIBUTE_UNUSED)
+{
+  /* Check argument values.  */
+  assert (values_ldouble.f0 == f0);
+  assert (values_ldouble.f1 == f1);
+  assert (values_ldouble.f2 == f2);
+  assert (values_ldouble.f3 == f3);
+  assert (values_ldouble.f4 == f4);
+  assert (values_ldouble.f5 == f5);
+  assert (values_ldouble.f6 == f6);
+  assert (values_ldouble.f7 == f7);
+  assert (values_ldouble.f8 == f8);
+  assert (values_ldouble.f9 == f9);
+  assert (values_ldouble.f10 == f10);
+  assert (values_ldouble.f11 == f11);
+  assert (values_ldouble.f12 == f12);
+  assert (values_ldouble.f13 == f13);
+  assert (values_ldouble.f14 == f14);
+  assert (values_ldouble.f15 == f15);
+
+}
+
+void
+fun_check_x87_passing_ldouble16_regs (ldouble f0 ATTRIBUTE_UNUSED,
+				      ldouble f1 ATTRIBUTE_UNUSED,
+				      ldouble f2 ATTRIBUTE_UNUSED,
+				      ldouble f3 ATTRIBUTE_UNUSED,
+				      ldouble f4 ATTRIBUTE_UNUSED,
+				      ldouble f5 ATTRIBUTE_UNUSED,
+				      ldouble f6 ATTRIBUTE_UNUSED,
+				      ldouble f7 ATTRIBUTE_UNUSED,
+				      ldouble f8 ATTRIBUTE_UNUSED,
+				      ldouble f9 ATTRIBUTE_UNUSED,
+				      ldouble f10 ATTRIBUTE_UNUSED,
+				      ldouble f11 ATTRIBUTE_UNUSED,
+				      ldouble f12 ATTRIBUTE_UNUSED,
+				      ldouble f13 ATTRIBUTE_UNUSED,
+				      ldouble f14 ATTRIBUTE_UNUSED,
+				      ldouble f15 ATTRIBUTE_UNUSED)
+{
+  /* Check register contents.  */
+  check_ldouble_arguments;
+}
+
+void
+fun_check_x87_passing_ldouble20_values (ldouble f0 ATTRIBUTE_UNUSED,
+					ldouble f1 ATTRIBUTE_UNUSED,
+					ldouble f2 ATTRIBUTE_UNUSED,
+					ldouble f3 ATTRIBUTE_UNUSED,
+					ldouble f4 ATTRIBUTE_UNUSED,
+					ldouble f5 ATTRIBUTE_UNUSED,
+					ldouble f6 ATTRIBUTE_UNUSED,
+					ldouble f7 ATTRIBUTE_UNUSED,
+					ldouble f8 ATTRIBUTE_UNUSED,
+					ldouble f9 ATTRIBUTE_UNUSED,
+					ldouble f10 ATTRIBUTE_UNUSED,
+					ldouble f11 ATTRIBUTE_UNUSED,
+					ldouble f12 ATTRIBUTE_UNUSED,
+					ldouble f13 ATTRIBUTE_UNUSED,
+					ldouble f14 ATTRIBUTE_UNUSED,
+					ldouble f15 ATTRIBUTE_UNUSED,
+					ldouble f16 ATTRIBUTE_UNUSED,
+					ldouble f17 ATTRIBUTE_UNUSED,
+					ldouble f18 ATTRIBUTE_UNUSED,
+					ldouble f19 ATTRIBUTE_UNUSED)
+{
+  /* Check argument values.  */
+  assert (values_ldouble.f0 == f0);
+  assert (values_ldouble.f1 == f1);
+  assert (values_ldouble.f2 == f2);
+  assert (values_ldouble.f3 == f3);
+  assert (values_ldouble.f4 == f4);
+  assert (values_ldouble.f5 == f5);
+  assert (values_ldouble.f6 == f6);
+  assert (values_ldouble.f7 == f7);
+  assert (values_ldouble.f8 == f8);
+  assert (values_ldouble.f9 == f9);
+  assert (values_ldouble.f10 == f10);
+  assert (values_ldouble.f11 == f11);
+  assert (values_ldouble.f12 == f12);
+  assert (values_ldouble.f13 == f13);
+  assert (values_ldouble.f14 == f14);
+  assert (values_ldouble.f15 == f15);
+  assert (values_ldouble.f16 == f16);
+  assert (values_ldouble.f17 == f17);
+  assert (values_ldouble.f18 == f18);
+  assert (values_ldouble.f19 == f19);
+
+}
+
+void
+fun_check_x87_passing_ldouble20_regs (ldouble f0 ATTRIBUTE_UNUSED,
+				      ldouble f1 ATTRIBUTE_UNUSED,
+				      ldouble f2 ATTRIBUTE_UNUSED,
+				      ldouble f3 ATTRIBUTE_UNUSED,
+				      ldouble f4 ATTRIBUTE_UNUSED,
+				      ldouble f5 ATTRIBUTE_UNUSED,
+				      ldouble f6 ATTRIBUTE_UNUSED,
+				      ldouble f7 ATTRIBUTE_UNUSED,
+				      ldouble f8 ATTRIBUTE_UNUSED,
+				      ldouble f9 ATTRIBUTE_UNUSED,
+				      ldouble f10 ATTRIBUTE_UNUSED,
+				      ldouble f11 ATTRIBUTE_UNUSED,
+				      ldouble f12 ATTRIBUTE_UNUSED,
+				      ldouble f13 ATTRIBUTE_UNUSED,
+				      ldouble f14 ATTRIBUTE_UNUSED,
+				      ldouble f15 ATTRIBUTE_UNUSED,
+				      ldouble f16 ATTRIBUTE_UNUSED,
+				      ldouble f17 ATTRIBUTE_UNUSED,
+				      ldouble f18 ATTRIBUTE_UNUSED,
+				      ldouble f19 ATTRIBUTE_UNUSED)
+{
+  /* Check register contents.  */
+  check_ldouble_arguments;
+}
+
+#define def_check_float16_passing8(_f0, _f1, _f2, _f3, _f4, _f5, _f6,\
+				   _f7, _func1, _func2, TYPE) \
+  values_ ## TYPE .f0 = _f0; \
+  values_ ## TYPE .f1 = _f1; \
+  values_ ## TYPE .f2 = _f2; \
+  values_ ## TYPE .f3 = _f3; \
+  values_ ## TYPE .f4 = _f4; \
+  values_ ## TYPE .f5 = _f5; \
+  values_ ## TYPE .f6 = _f6; \
+  values_ ## TYPE .f7 = _f7; \
+  WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7); \
+  clear_float_registers; \
+  fregs.F0._ ## TYPE [0] = _f0; \
+  fregs.F1._ ## TYPE [0] = _f1; \
+  fregs.F2._ ## TYPE [0] = _f2; \
+  fregs.F3._ ## TYPE [0] = _f3; \
+  fregs.F4._ ## TYPE [0] = _f4; \
+  fregs.F5._ ## TYPE [0] = _f5; \
+  fregs.F6._ ## TYPE [0] = _f6; \
+  fregs.F7._ ## TYPE [0] = _f7; \
+  num_fregs = 8; \
+  WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7);
+
+#define def_check_float16_passing16(_f0, _f1, _f2, _f3, _f4, _f5, _f6, \
+				    _f7, _f8, _f9, _f10, _f11, _f12, _f13, \
+				    _f14, _f15, _func1, _func2, TYPE) \
+  values_ ## TYPE .f0 = _f0; \
+  values_ ## TYPE .f1 = _f1; \
+  values_ ## TYPE .f2 = _f2; \
+  values_ ## TYPE .f3 = _f3; \
+  values_ ## TYPE .f4 = _f4; \
+  values_ ## TYPE .f5 = _f5; \
+  values_ ## TYPE .f6 = _f6; \
+  values_ ## TYPE .f7 = _f7; \
+  values_ ## TYPE .f8 = _f8; \
+  values_ ## TYPE .f9 = _f9; \
+  values_ ## TYPE .f10 = _f10; \
+  values_ ## TYPE .f11 = _f11; \
+  values_ ## TYPE .f12 = _f12; \
+  values_ ## TYPE .f13 = _f13; \
+  values_ ## TYPE .f14 = _f14; \
+  values_ ## TYPE .f15 = _f15; \
+  WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, \
+		     _f10, _f11, _f12, _f13, _f14, _f15); \
+  clear_float_registers; \
+  fregs.F0._ ## TYPE [0] = _f0; \
+  fregs.F1._ ## TYPE [0] = _f1; \
+  fregs.F2._ ## TYPE [0] = _f2; \
+  fregs.F3._ ## TYPE [0] = _f3; \
+  fregs.F4._ ## TYPE [0] = _f4; \
+  fregs.F5._ ## TYPE [0] = _f5; \
+  fregs.F6._ ## TYPE [0] = _f6; \
+  fregs.F7._ ## TYPE [0] = _f7; \
+  num_fregs = 8; \
+  WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, \
+		     _f10, _f11, _f12, _f13, _f14, _f15);
+
+#define def_check_float16_passing20(_f0, _f1, _f2, _f3, _f4, _f5, _f6, \
+				    _f7, _f8, _f9, _f10, _f11, _f12, \
+				    _f13, _f14, _f15, _f16, _f17, \
+				    _f18, _f19, _func1, _func2, TYPE) \
+  values_ ## TYPE .f0 = _f0; \
+  values_ ## TYPE .f1 = _f1; \
+  values_ ## TYPE .f2 = _f2; \
+  values_ ## TYPE .f3 = _f3; \
+  values_ ## TYPE .f4 = _f4; \
+  values_ ## TYPE .f5 = _f5; \
+  values_ ## TYPE .f6 = _f6; \
+  values_ ## TYPE .f7 = _f7; \
+  values_ ## TYPE .f8 = _f8; \
+  values_ ## TYPE .f9 = _f9; \
+  values_ ## TYPE .f10 = _f10; \
+  values_ ## TYPE .f11 = _f11; \
+  values_ ## TYPE .f12 = _f12; \
+  values_ ## TYPE .f13 = _f13; \
+  values_ ## TYPE .f14 = _f14; \
+  values_ ## TYPE .f15 = _f15; \
+  values_ ## TYPE .f16 = _f16; \
+  values_ ## TYPE .f17 = _f17; \
+  values_ ## TYPE .f18 = _f18; \
+  values_ ## TYPE .f19 = _f19; \
+  WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, \
+		     _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, \
+		     _f17, _f18, _f19); \
+  clear_float_registers; \
+  fregs.F0._ ## TYPE [0] = _f0; \
+  fregs.F1._ ## TYPE [0] = _f1; \
+  fregs.F2._ ## TYPE [0] = _f2; \
+  fregs.F3._ ## TYPE [0] = _f3; \
+  fregs.F4._ ## TYPE [0] = _f4; \
+  fregs.F5._ ## TYPE [0] = _f5; \
+  fregs.F6._ ## TYPE [0] = _f6; \
+  fregs.F7._ ## TYPE [0] = _f7; \
+  num_fregs = 8; \
+  WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, \
+		     _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, \
+		     _f18, _f19);
+
+
+#define def_check_float_passing8(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _func1, _func2, TYPE) \
+  values_ ## TYPE .f0 = _f0; \
+  values_ ## TYPE .f1 = _f1; \
+  values_ ## TYPE .f2 = _f2; \
+  values_ ## TYPE .f3 = _f3; \
+  values_ ## TYPE .f4 = _f4; \
+  values_ ## TYPE .f5 = _f5; \
+  values_ ## TYPE .f6 = _f6; \
+  values_ ## TYPE .f7 = _f7; \
+  WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7); \
+  \
+  clear_float_registers; \
+  fregs.F0._ ## TYPE [0] = _f0; \
+  fregs.F1._ ## TYPE [0] = _f1; \
+  fregs.F2._ ## TYPE [0] = _f2; \
+  fregs.F3._ ## TYPE [0] = _f3; \
+  fregs.F4._ ## TYPE [0] = _f4; \
+  fregs.F5._ ## TYPE [0] = _f5; \
+  fregs.F6._ ## TYPE [0] = _f6; \
+  fregs.F7._ ## TYPE [0] = _f7; \
+  num_fregs = 8; \
+  WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7);
+
+#define def_check_float_passing16(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _func1, _func2, TYPE) \
+  values_ ## TYPE .f0 = _f0; \
+  values_ ## TYPE .f1 = _f1; \
+  values_ ## TYPE .f2 = _f2; \
+  values_ ## TYPE .f3 = _f3; \
+  values_ ## TYPE .f4 = _f4; \
+  values_ ## TYPE .f5 = _f5; \
+  values_ ## TYPE .f6 = _f6; \
+  values_ ## TYPE .f7 = _f7; \
+  values_ ## TYPE .f8 = _f8; \
+  values_ ## TYPE .f9 = _f9; \
+  values_ ## TYPE .f10 = _f10; \
+  values_ ## TYPE .f11 = _f11; \
+  values_ ## TYPE .f12 = _f12; \
+  values_ ## TYPE .f13 = _f13; \
+  values_ ## TYPE .f14 = _f14; \
+  values_ ## TYPE .f15 = _f15; \
+  WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15); \
+  \
+  clear_float_registers; \
+  fregs.F0._ ## TYPE [0] = _f0; \
+  fregs.F1._ ## TYPE [0] = _f1; \
+  fregs.F2._ ## TYPE [0] = _f2; \
+  fregs.F3._ ## TYPE [0] = _f3; \
+  fregs.F4._ ## TYPE [0] = _f4; \
+  fregs.F5._ ## TYPE [0] = _f5; \
+  fregs.F6._ ## TYPE [0] = _f6; \
+  fregs.F7._ ## TYPE [0] = _f7; \
+  num_fregs = 8; \
+  WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15);
+
+#define def_check_float_passing20(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19, _func1, _func2, TYPE) \
+  values_ ## TYPE .f0 = _f0; \
+  values_ ## TYPE .f1 = _f1; \
+  values_ ## TYPE .f2 = _f2; \
+  values_ ## TYPE .f3 = _f3; \
+  values_ ## TYPE .f4 = _f4; \
+  values_ ## TYPE .f5 = _f5; \
+  values_ ## TYPE .f6 = _f6; \
+  values_ ## TYPE .f7 = _f7; \
+  values_ ## TYPE .f8 = _f8; \
+  values_ ## TYPE .f9 = _f9; \
+  values_ ## TYPE .f10 = _f10; \
+  values_ ## TYPE .f11 = _f11; \
+  values_ ## TYPE .f12 = _f12; \
+  values_ ## TYPE .f13 = _f13; \
+  values_ ## TYPE .f14 = _f14; \
+  values_ ## TYPE .f15 = _f15; \
+  values_ ## TYPE .f16 = _f16; \
+  values_ ## TYPE .f17 = _f17; \
+  values_ ## TYPE .f18 = _f18; \
+  values_ ## TYPE .f19 = _f19; \
+  WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19); \
+  \
+  clear_float_registers; \
+  fregs.F0._ ## TYPE [0] = _f0; \
+  fregs.F1._ ## TYPE [0] = _f1; \
+  fregs.F2._ ## TYPE [0] = _f2; \
+  fregs.F3._ ## TYPE [0] = _f3; \
+  fregs.F4._ ## TYPE [0] = _f4; \
+  fregs.F5._ ## TYPE [0] = _f5; \
+  fregs.F6._ ## TYPE [0] = _f6; \
+  fregs.F7._ ## TYPE [0] = _f7; \
+  num_fregs = 8; \
+  WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19);
+
+#define def_check_x87_passing8(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _func1, _func2, TYPE) \
+  values_ ## TYPE .f0 = _f0; \
+  values_ ## TYPE .f1 = _f1; \
+  values_ ## TYPE .f2 = _f2; \
+  values_ ## TYPE .f3 = _f3; \
+  values_ ## TYPE .f4 = _f4; \
+  values_ ## TYPE .f5 = _f5; \
+  values_ ## TYPE .f6 = _f6; \
+  values_ ## TYPE .f7 = _f7; \
+  WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7); \
+  \
+  clear_x87_registers; \
+  num_fregs = 0; \
+  WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7);
+
+#define def_check_x87_passing16(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _func1, _func2, TYPE) \
+  values_ ## TYPE .f0 = _f0; \
+  values_ ## TYPE .f1 = _f1; \
+  values_ ## TYPE .f2 = _f2; \
+  values_ ## TYPE .f3 = _f3; \
+  values_ ## TYPE .f4 = _f4; \
+  values_ ## TYPE .f5 = _f5; \
+  values_ ## TYPE .f6 = _f6; \
+  values_ ## TYPE .f7 = _f7; \
+  values_ ## TYPE .f8 = _f8; \
+  values_ ## TYPE .f9 = _f9; \
+  values_ ## TYPE .f10 = _f10; \
+  values_ ## TYPE .f11 = _f11; \
+  values_ ## TYPE .f12 = _f12; \
+  values_ ## TYPE .f13 = _f13; \
+  values_ ## TYPE .f14 = _f14; \
+  values_ ## TYPE .f15 = _f15; \
+  WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15); \
+  \
+  clear_x87_registers; \
+  num_fregs = 0; \
+  WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15);
+
+#define def_check_x87_passing20(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19, _func1, _func2, TYPE) \
+  values_ ## TYPE .f0 = _f0; \
+  values_ ## TYPE .f1 = _f1; \
+  values_ ## TYPE .f2 = _f2; \
+  values_ ## TYPE .f3 = _f3; \
+  values_ ## TYPE .f4 = _f4; \
+  values_ ## TYPE .f5 = _f5; \
+  values_ ## TYPE .f6 = _f6; \
+  values_ ## TYPE .f7 = _f7; \
+  values_ ## TYPE .f8 = _f8; \
+  values_ ## TYPE .f9 = _f9; \
+  values_ ## TYPE .f10 = _f10; \
+  values_ ## TYPE .f11 = _f11; \
+  values_ ## TYPE .f12 = _f12; \
+  values_ ## TYPE .f13 = _f13; \
+  values_ ## TYPE .f14 = _f14; \
+  values_ ## TYPE .f15 = _f15; \
+  values_ ## TYPE .f16 = _f16; \
+  values_ ## TYPE .f17 = _f17; \
+  values_ ## TYPE .f18 = _f18; \
+  values_ ## TYPE .f19 = _f19; \
+  WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19); \
+  \
+  clear_x87_registers; \
+  num_fregs = 0; \
+  WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19);
+
+void
+test_float16_on_stack ()
+{
+  def_check_float16_passing8 (32, 33, 34, 35, 36, 37, 38, 39,
+			      fun_check_float16_passing_8_values,
+			      fun_check_float16_passing_8_regs, _Float16);
+
+  def_check_float16_passing16 (32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+			       44, 45, 46, 47,
+			       fun_check_float16_passing_16_values,
+			       fun_check_float16_passing_16_regs, _Float16);
+}
+
+void
+test_too_many_float16 ()
+{
+  def_check_float16_passing20 (32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+			       44, 45, 46, 47, 48, 49, 50, 51,
+			       fun_check_float16_passing_20_values,
+			       fun_check_float16_passing_20_regs, _Float16);
+}
+
+void
+test_floats_on_stack ()
+{
+  def_check_float_passing8 (32, 33, 34, 35, 36, 37, 38, 39,
+			    fun_check_float_passing_float8_values,
+			    fun_check_float_passing_float8_regs, float);
+
+  def_check_float_passing16 (32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+			     44, 45, 46, 47,
+			     fun_check_float_passing_float16_values,
+			     fun_check_float_passing_float16_regs, float);
+}
+
+void
+test_too_many_floats ()
+{
+  def_check_float_passing20 (32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+			     44, 45, 46, 47, 48, 49, 50, 51,
+			     fun_check_float_passing_float20_values,
+			     fun_check_float_passing_float20_regs, float);
+}
+
+void
+test_doubles_on_stack ()
+{
+  def_check_float_passing8 (32, 33, 34, 35, 36, 37, 38, 39,
+			    fun_check_float_passing_double8_values,
+			    fun_check_float_passing_double8_regs, double);
+
+  def_check_float_passing16 (32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+			     44, 45, 46, 47,
+			     fun_check_float_passing_double16_values,
+			     fun_check_float_passing_double16_regs, double);
+}
+
+void
+test_too_many_doubles ()
+{
+  def_check_float_passing20 (32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+			     44, 45, 46, 47, 48, 49, 50, 51,
+			     fun_check_float_passing_double20_values,
+			     fun_check_float_passing_double20_regs, double);
+}
+
+void
+test_long_doubles_on_stack ()
+{
+  def_check_x87_passing8 (32, 33, 34, 35, 36, 37, 38, 39,
+			  fun_check_x87_passing_ldouble8_values,
+			  fun_check_x87_passing_ldouble8_regs, ldouble);
+}
+
+void
+test_too_many_long_doubles ()
+{
+  def_check_x87_passing20 (32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+			   45, 46, 47, 48, 49, 50, 51,
+			   fun_check_x87_passing_ldouble20_values,
+			   fun_check_x87_passing_ldouble20_regs, ldouble);
+}
+
+void
+test_float128s_on_stack ()
+{
+}
+
+void
+test_too_many_float128s ()
+{
+}
+
+
+static void
+do_test (void)
+{
+  test_float16_on_stack ();
+  test_too_many_float16 ();
+  test_floats_on_stack ();
+  test_too_many_floats ();
+  test_doubles_on_stack ();
+  test_too_many_doubles ();
+  test_long_doubles_on_stack ();
+  test_too_many_long_doubles ();
+  test_float128s_on_stack ();
+  test_too_many_float128s ();
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_passing_m64m128.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_passing_m64m128.c
new file mode 100644
index 00000000000..66c27aef7af
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_passing_m64m128.c
@@ -0,0 +1,510 @@ 
+#include <stdio.h>
+#include "avx512fp16-xmm-check.h"
+#include "defines.h"
+#include "macros.h"
+#include "args.h"
+
+struct IntegerRegisters iregs;
+struct FloatRegisters fregs;
+unsigned int num_iregs, num_fregs;
+
+/* This struct holds values for argument checking.  */
+struct
+{
+  XMM_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)
+
+void
+fun_check_passing_m64_8_values (__m64 i0 ATTRIBUTE_UNUSED,
+				__m64 i1 ATTRIBUTE_UNUSED,
+				__m64 i2 ATTRIBUTE_UNUSED,
+				__m64 i3 ATTRIBUTE_UNUSED,
+				__m64 i4 ATTRIBUTE_UNUSED,
+				__m64 i5 ATTRIBUTE_UNUSED,
+				__m64 i6 ATTRIBUTE_UNUSED,
+				__m64 i7 ATTRIBUTE_UNUSED)
+{
+  /* Check argument values.  */
+  compare (values.i0, i0, __m64);
+  compare (values.i1, i1, __m64);
+  compare (values.i2, i2, __m64);
+  compare (values.i3, i3, __m64);
+  compare (values.i4, i4, __m64);
+  compare (values.i5, i5, __m64);
+  compare (values.i6, i6, __m64);
+  compare (values.i7, i7, __m64);
+}
+
+void
+fun_check_passing_m64_8_regs (__m64 i0 ATTRIBUTE_UNUSED,
+			      __m64 i1 ATTRIBUTE_UNUSED,
+			      __m64 i2 ATTRIBUTE_UNUSED,
+			      __m64 i3 ATTRIBUTE_UNUSED,
+			      __m64 i4 ATTRIBUTE_UNUSED,
+			      __m64 i5 ATTRIBUTE_UNUSED,
+			      __m64 i6 ATTRIBUTE_UNUSED,
+			      __m64 i7 ATTRIBUTE_UNUSED)
+{
+  /* Check register contents.  */
+  check_m64_arguments;
+}
+
+void
+fun_check_passing_m64_20_values (__m64 i0 ATTRIBUTE_UNUSED,
+				 __m64 i1 ATTRIBUTE_UNUSED,
+				 __m64 i2 ATTRIBUTE_UNUSED,
+				 __m64 i3 ATTRIBUTE_UNUSED,
+				 __m64 i4 ATTRIBUTE_UNUSED,
+				 __m64 i5 ATTRIBUTE_UNUSED,
+				 __m64 i6 ATTRIBUTE_UNUSED,
+				 __m64 i7 ATTRIBUTE_UNUSED,
+				 __m64 i8 ATTRIBUTE_UNUSED,
+				 __m64 i9 ATTRIBUTE_UNUSED,
+				 __m64 i10 ATTRIBUTE_UNUSED,
+				 __m64 i11 ATTRIBUTE_UNUSED,
+				 __m64 i12 ATTRIBUTE_UNUSED,
+				 __m64 i13 ATTRIBUTE_UNUSED,
+				 __m64 i14 ATTRIBUTE_UNUSED,
+				 __m64 i15 ATTRIBUTE_UNUSED,
+				 __m64 i16 ATTRIBUTE_UNUSED,
+				 __m64 i17 ATTRIBUTE_UNUSED,
+				 __m64 i18 ATTRIBUTE_UNUSED,
+				 __m64 i19 ATTRIBUTE_UNUSED)
+{
+  /* Check argument values.  */
+  compare (values.i0, i0, __m64);
+  compare (values.i1, i1, __m64);
+  compare (values.i2, i2, __m64);
+  compare (values.i3, i3, __m64);
+  compare (values.i4, i4, __m64);
+  compare (values.i5, i5, __m64);
+  compare (values.i6, i6, __m64);
+  compare (values.i7, i7, __m64);
+  compare (values.i8, i8, __m64);
+  compare (values.i9, i9, __m64);
+  compare (values.i10, i10, __m64);
+  compare (values.i11, i11, __m64);
+  compare (values.i12, i12, __m64);
+  compare (values.i13, i13, __m64);
+  compare (values.i14, i14, __m64);
+  compare (values.i15, i15, __m64);
+  compare (values.i16, i16, __m64);
+  compare (values.i17, i17, __m64);
+  compare (values.i18, i18, __m64);
+  compare (values.i19, i19, __m64);
+}
+
+void
+fun_check_passing_m64_20_regs (__m64 i0 ATTRIBUTE_UNUSED,
+			       __m64 i1 ATTRIBUTE_UNUSED,
+			       __m64 i2 ATTRIBUTE_UNUSED,
+			       __m64 i3 ATTRIBUTE_UNUSED,
+			       __m64 i4 ATTRIBUTE_UNUSED,
+			       __m64 i5 ATTRIBUTE_UNUSED,
+			       __m64 i6 ATTRIBUTE_UNUSED,
+			       __m64 i7 ATTRIBUTE_UNUSED,
+			       __m64 i8 ATTRIBUTE_UNUSED,
+			       __m64 i9 ATTRIBUTE_UNUSED,
+			       __m64 i10 ATTRIBUTE_UNUSED,
+			       __m64 i11 ATTRIBUTE_UNUSED,
+			       __m64 i12 ATTRIBUTE_UNUSED,
+			       __m64 i13 ATTRIBUTE_UNUSED,
+			       __m64 i14 ATTRIBUTE_UNUSED,
+			       __m64 i15 ATTRIBUTE_UNUSED,
+			       __m64 i16 ATTRIBUTE_UNUSED,
+			       __m64 i17 ATTRIBUTE_UNUSED,
+			       __m64 i18 ATTRIBUTE_UNUSED,
+			       __m64 i19 ATTRIBUTE_UNUSED)
+{
+  /* Check register contents.  */
+  check_m64_arguments;
+}
+
+void
+fun_check_passing_m128_8_values (__m128 i0 ATTRIBUTE_UNUSED,
+				 __m128 i1 ATTRIBUTE_UNUSED,
+				 __m128 i2 ATTRIBUTE_UNUSED,
+				 __m128 i3 ATTRIBUTE_UNUSED,
+				 __m128 i4 ATTRIBUTE_UNUSED,
+				 __m128 i5 ATTRIBUTE_UNUSED,
+				 __m128 i6 ATTRIBUTE_UNUSED,
+				 __m128 i7 ATTRIBUTE_UNUSED)
+{
+  /* Check argument values.  */
+  compare (values.i0, i0, __m128);
+  compare (values.i1, i1, __m128);
+  compare (values.i2, i2, __m128);
+  compare (values.i3, i3, __m128);
+  compare (values.i4, i4, __m128);
+  compare (values.i5, i5, __m128);
+  compare (values.i6, i6, __m128);
+  compare (values.i7, i7, __m128);
+}
+
+void
+fun_check_passing_m128h_8_values (__m128h i0 ATTRIBUTE_UNUSED,
+				  __m128h i1 ATTRIBUTE_UNUSED,
+				  __m128h i2 ATTRIBUTE_UNUSED,
+				  __m128h i3 ATTRIBUTE_UNUSED,
+				  __m128h i4 ATTRIBUTE_UNUSED,
+				  __m128h i5 ATTRIBUTE_UNUSED,
+				  __m128h i6 ATTRIBUTE_UNUSED,
+				  __m128h i7 ATTRIBUTE_UNUSED)
+{
+  /* Check argument values.  */
+  compare (values.i0, i0, __m128h);
+  compare (values.i1, i1, __m128h);
+  compare (values.i2, i2, __m128h);
+  compare (values.i3, i3, __m128h);
+  compare (values.i4, i4, __m128h);
+  compare (values.i5, i5, __m128h);
+  compare (values.i6, i6, __m128h);
+  compare (values.i7, i7, __m128h);
+}
+
+void
+fun_check_passing_m128_8_regs (__m128 i0 ATTRIBUTE_UNUSED,
+			       __m128 i1 ATTRIBUTE_UNUSED,
+			       __m128 i2 ATTRIBUTE_UNUSED,
+			       __m128 i3 ATTRIBUTE_UNUSED,
+			       __m128 i4 ATTRIBUTE_UNUSED,
+			       __m128 i5 ATTRIBUTE_UNUSED,
+			       __m128 i6 ATTRIBUTE_UNUSED,
+			       __m128 i7 ATTRIBUTE_UNUSED)
+{
+  /* Check register contents.  */
+  check_m128_arguments;
+}
+
+void
+fun_check_passing_m128h_8_regs (__m128h i0 ATTRIBUTE_UNUSED,
+			        __m128h i1 ATTRIBUTE_UNUSED,
+			        __m128h i2 ATTRIBUTE_UNUSED,
+			        __m128h i3 ATTRIBUTE_UNUSED,
+			        __m128h i4 ATTRIBUTE_UNUSED,
+			        __m128h i5 ATTRIBUTE_UNUSED,
+			        __m128h i6 ATTRIBUTE_UNUSED,
+			        __m128h i7 ATTRIBUTE_UNUSED)
+{
+  /* Check register contents.  */
+  check_m128_arguments;
+}
+
+void
+fun_check_passing_m128_20_values (__m128 i0 ATTRIBUTE_UNUSED,
+				  __m128 i1 ATTRIBUTE_UNUSED,
+				  __m128 i2 ATTRIBUTE_UNUSED,
+				  __m128 i3 ATTRIBUTE_UNUSED,
+				  __m128 i4 ATTRIBUTE_UNUSED,
+				  __m128 i5 ATTRIBUTE_UNUSED,
+				  __m128 i6 ATTRIBUTE_UNUSED,
+				  __m128 i7 ATTRIBUTE_UNUSED,
+				  __m128 i8 ATTRIBUTE_UNUSED,
+				  __m128 i9 ATTRIBUTE_UNUSED,
+				  __m128 i10 ATTRIBUTE_UNUSED,
+				  __m128 i11 ATTRIBUTE_UNUSED,
+				  __m128 i12 ATTRIBUTE_UNUSED,
+				  __m128 i13 ATTRIBUTE_UNUSED,
+				  __m128 i14 ATTRIBUTE_UNUSED,
+				  __m128 i15 ATTRIBUTE_UNUSED,
+				  __m128 i16 ATTRIBUTE_UNUSED,
+				  __m128 i17 ATTRIBUTE_UNUSED,
+				  __m128 i18 ATTRIBUTE_UNUSED,
+				  __m128 i19 ATTRIBUTE_UNUSED)
+{
+  /* Check argument values.  */
+  compare (values.i0, i0, __m128);
+  compare (values.i1, i1, __m128);
+  compare (values.i2, i2, __m128);
+  compare (values.i3, i3, __m128);
+  compare (values.i4, i4, __m128);
+  compare (values.i5, i5, __m128);
+  compare (values.i6, i6, __m128);
+  compare (values.i7, i7, __m128);
+  compare (values.i8, i8, __m128);
+  compare (values.i9, i9, __m128);
+  compare (values.i10, i10, __m128);
+  compare (values.i11, i11, __m128);
+  compare (values.i12, i12, __m128);
+  compare (values.i13, i13, __m128);
+  compare (values.i14, i14, __m128);
+  compare (values.i15, i15, __m128);
+  compare (values.i16, i16, __m128);
+  compare (values.i17, i17, __m128);
+  compare (values.i18, i18, __m128);
+  compare (values.i19, i19, __m128);
+}
+
+void
+fun_check_passing_m128h_20_values (__m128h i0 ATTRIBUTE_UNUSED,
+				   __m128h i1 ATTRIBUTE_UNUSED,
+				   __m128h i2 ATTRIBUTE_UNUSED,
+				   __m128h i3 ATTRIBUTE_UNUSED,
+				   __m128h i4 ATTRIBUTE_UNUSED,
+				   __m128h i5 ATTRIBUTE_UNUSED,
+				   __m128h i6 ATTRIBUTE_UNUSED,
+				   __m128h i7 ATTRIBUTE_UNUSED,
+				   __m128h i8 ATTRIBUTE_UNUSED,
+				   __m128h i9 ATTRIBUTE_UNUSED,
+				   __m128h i10 ATTRIBUTE_UNUSED,
+				   __m128h i11 ATTRIBUTE_UNUSED,
+				   __m128h i12 ATTRIBUTE_UNUSED,
+				   __m128h i13 ATTRIBUTE_UNUSED,
+				   __m128h i14 ATTRIBUTE_UNUSED,
+				   __m128h i15 ATTRIBUTE_UNUSED,
+				   __m128h i16 ATTRIBUTE_UNUSED,
+				   __m128h i17 ATTRIBUTE_UNUSED,
+				   __m128h i18 ATTRIBUTE_UNUSED,
+				   __m128h i19 ATTRIBUTE_UNUSED)
+{
+  /* Check argument values.  */
+  compare (values.i0, i0, __m128h);
+  compare (values.i1, i1, __m128h);
+  compare (values.i2, i2, __m128h);
+  compare (values.i3, i3, __m128h);
+  compare (values.i4, i4, __m128h);
+  compare (values.i5, i5, __m128h);
+  compare (values.i6, i6, __m128h);
+  compare (values.i7, i7, __m128h);
+  compare (values.i8, i8, __m128h);
+  compare (values.i9, i9, __m128h);
+  compare (values.i10, i10, __m128h);
+  compare (values.i11, i11, __m128h);
+  compare (values.i12, i12, __m128h);
+  compare (values.i13, i13, __m128h);
+  compare (values.i14, i14, __m128h);
+  compare (values.i15, i15, __m128h);
+  compare (values.i16, i16, __m128h);
+  compare (values.i17, i17, __m128h);
+  compare (values.i18, i18, __m128h);
+  compare (values.i19, i19, __m128h);
+}
+
+void
+fun_check_passing_m128_20_regs (__m128 i0 ATTRIBUTE_UNUSED,
+				__m128 i1 ATTRIBUTE_UNUSED,
+				__m128 i2 ATTRIBUTE_UNUSED,
+				__m128 i3 ATTRIBUTE_UNUSED,
+				__m128 i4 ATTRIBUTE_UNUSED,
+				__m128 i5 ATTRIBUTE_UNUSED,
+				__m128 i6 ATTRIBUTE_UNUSED,
+				__m128 i7 ATTRIBUTE_UNUSED,
+				__m128 i8 ATTRIBUTE_UNUSED,
+				__m128 i9 ATTRIBUTE_UNUSED,
+				__m128 i10 ATTRIBUTE_UNUSED,
+				__m128 i11 ATTRIBUTE_UNUSED,
+				__m128 i12 ATTRIBUTE_UNUSED,
+				__m128 i13 ATTRIBUTE_UNUSED,
+				__m128 i14 ATTRIBUTE_UNUSED,
+				__m128 i15 ATTRIBUTE_UNUSED,
+				__m128 i16 ATTRIBUTE_UNUSED,
+				__m128 i17 ATTRIBUTE_UNUSED,
+				__m128 i18 ATTRIBUTE_UNUSED,
+				__m128 i19 ATTRIBUTE_UNUSED)
+{
+  /* Check register contents.  */
+  check_m128_arguments;
+}
+
+void
+fun_check_passing_m128h_20_regs (__m128h i0 ATTRIBUTE_UNUSED,
+				 __m128h i1 ATTRIBUTE_UNUSED,
+				 __m128h i2 ATTRIBUTE_UNUSED,
+				 __m128h i3 ATTRIBUTE_UNUSED,
+				 __m128h i4 ATTRIBUTE_UNUSED,
+				 __m128h i5 ATTRIBUTE_UNUSED,
+				 __m128h i6 ATTRIBUTE_UNUSED,
+				 __m128h i7 ATTRIBUTE_UNUSED,
+				 __m128h i8 ATTRIBUTE_UNUSED,
+				 __m128h i9 ATTRIBUTE_UNUSED,
+				 __m128h i10 ATTRIBUTE_UNUSED,
+				 __m128h i11 ATTRIBUTE_UNUSED,
+				 __m128h i12 ATTRIBUTE_UNUSED,
+				 __m128h i13 ATTRIBUTE_UNUSED,
+				 __m128h i14 ATTRIBUTE_UNUSED,
+				 __m128h i15 ATTRIBUTE_UNUSED,
+				 __m128h i16 ATTRIBUTE_UNUSED,
+				 __m128h i17 ATTRIBUTE_UNUSED,
+				 __m128h i18 ATTRIBUTE_UNUSED,
+				 __m128h i19 ATTRIBUTE_UNUSED)
+{
+  /* Check register contents.  */
+  check_m128_arguments;
+}
+
+#define def_check_int_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_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; \
+  num_fregs = 8; \
+  WRAP_CALL(_func2) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7);
+
+#define def_check_int_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_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; \
+  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_m64_on_stack ()
+{
+  __m64 x[8];
+  int i;
+  for (i = 0; i < 8; i++)
+    x[i] = (__m64){32 + i, 0};
+  pass = "m64-8";
+  def_check_int_passing8 (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7],
+			  fun_check_passing_m64_8_values,
+			  fun_check_passing_m64_8_regs, _m64);
+}
+
+void
+test_too_many_m64 ()
+{
+  __m64 x[20];
+  int i;
+  for (i = 0; i < 20; i++)
+    x[i] = (__m64){32 + i, 0};
+  pass = "m64-20";
+  def_check_int_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_m64_20_values,
+			   fun_check_passing_m64_20_regs, _m64);
+}
+
+void
+test_m128_on_stack ()
+{
+  __m128 x[8];
+  int i;
+  for (i = 0; i < 8; i++)
+    x[i] = (__m128){32 + i, 0, 0, 0};
+  pass = "m128-8";
+  def_check_int_passing8 (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7],
+			  fun_check_passing_m128_8_values,
+			  fun_check_passing_m128_8_regs, _m128);
+}
+
+void
+test_m128h_on_stack ()
+{
+  __m128h x[8];
+  int i;
+  for (i = 0; i < 8; i++)
+    x[i] = (__m128h){1.1f16, 2.2f16, 3.3f16, 4.4f16, 5.5f16,
+	             6.6f16, 7.7f16, 8.8f16};
+  pass = "m128h-8";
+  def_check_int_passing8 (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7],
+			  fun_check_passing_m128h_8_values,
+			  fun_check_passing_m128h_8_regs, _m128h);
+}
+
+void
+test_too_many_m128 ()
+{
+  __m128 x[20];
+  int i;
+  for (i = 0; i < 20; i++)
+    x[i] = (__m128){32 + i, 0, 0, 0};
+  pass = "m128-20";
+  def_check_int_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_m128_20_values,
+			   fun_check_passing_m128_20_regs, _m128);
+}
+
+void
+test_too_many_m128h ()
+{
+  __m128h x[20];
+  int i;
+  for (i = 0; i < 20; i++)
+    x[i] = (__m128h){1.1f16, 2.2f16, 3.3f16, 4.4f16, 5.5f16,
+	             6.6f16, 7.7f16, 8.8f16};
+  pass = "m128h-20";
+  def_check_int_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_m128h_20_values,
+			   fun_check_passing_m128h_20_regs, _m128h);
+}
+
+static void
+do_test (void)
+{
+  test_m64_on_stack ();
+  test_too_many_m64 ();
+  test_m128_on_stack ();
+  test_too_many_m128 ();
+  test_m128h_on_stack ();
+  test_too_many_m128h ();
+  if (failed)
+    abort ();
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_passing_structs.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_passing_structs.c
new file mode 100644
index 00000000000..4d1956a846d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_passing_structs.c
@@ -0,0 +1,332 @@ 
+/* This tests passing of structs. */
+
+#include "avx512fp16-xmm-check.h"
+#include "defines.h"
+#include "args.h"
+#include <complex.h>
+
+struct IntegerRegisters iregs;
+struct FloatRegisters fregs;
+unsigned int num_iregs, num_fregs;
+
+struct int_struct
+{
+  int i;
+};
+
+struct long_struct
+{
+  long long l;
+};
+
+struct long2_struct
+{
+  long long l1, l2;
+};
+
+struct long3_struct
+{
+  long long l1, l2, l3;
+};
+
+
+/* Check that the struct is passed as the individual members in iregs.  */
+void
+check_struct_passing1 (struct int_struct is ATTRIBUTE_UNUSED)
+{
+  check_int_arguments;
+}
+
+void
+check_struct_passing2 (struct long_struct ls ATTRIBUTE_UNUSED)
+{
+  check_int_arguments;
+}
+
+void
+check_struct_passing3 (struct long2_struct ls ATTRIBUTE_UNUSED)
+{
+  check_int_arguments;
+}
+
+void
+check_struct_passing4 (struct long3_struct ls 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)&ls.l1 == rsp+8);
+  assert ((unsigned long)&ls.l2 == rsp+16);
+  assert ((unsigned long)&ls.l3 == rsp+24);
+}
+
+#ifdef CHECK_M64_M128
+struct m128_struct
+{
+  __m128 x;
+};
+
+struct m128_2_struct
+{
+  __m128 x1, x2;
+};
+
+/* Check that the struct is passed as the individual members in fregs.  */
+void
+check_struct_passing5 (struct m128_struct ms1 ATTRIBUTE_UNUSED,
+		       struct m128_struct ms2 ATTRIBUTE_UNUSED,
+		       struct m128_struct ms3 ATTRIBUTE_UNUSED,
+		       struct m128_struct ms4 ATTRIBUTE_UNUSED,
+		       struct m128_struct ms5 ATTRIBUTE_UNUSED,
+		       struct m128_struct ms6 ATTRIBUTE_UNUSED,
+		       struct m128_struct ms7 ATTRIBUTE_UNUSED,
+		       struct m128_struct ms8 ATTRIBUTE_UNUSED)
+{
+  check_m128_arguments;
+}
+
+void
+check_struct_passing6 (struct m128_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+24);
+}
+#endif
+
+struct flex1_struct
+{
+  long long i;
+  long long flex[];
+};
+
+struct flex2_struct
+{
+  long long i;
+  long long flex[0];
+};
+
+void
+check_struct_passing7 (struct flex1_struct is ATTRIBUTE_UNUSED)
+{
+  check_int_arguments;
+}
+
+void
+check_struct_passing8 (struct flex2_struct is ATTRIBUTE_UNUSED)
+{
+  check_int_arguments;
+}
+
+struct complex1_struct
+{
+  int c;
+  __complex__ float x;
+};
+
+struct complex1a_struct
+{
+  long long l;
+  float f;
+};
+
+struct complex2_struct
+{
+  int c;
+  __complex__ float x;
+  float y;
+};
+
+struct complex2a_struct
+{
+  long long l;
+  double d;
+};
+
+struct complex3_struct
+{
+  int c;
+  __complex__ _Float16 x;
+};
+
+struct complex3a_struct
+{
+  long long l;
+  _Float16 f;
+};
+
+struct complex4_struct
+{
+  int c;
+  __complex__ _Float16 x;
+  _Float16 y;
+};
+
+struct complex4a_struct
+{
+  long long l;
+  _Float16 f;
+};
+
+void
+check_struct_passing9 (struct complex1_struct is ATTRIBUTE_UNUSED)
+{
+  check_int_arguments;
+  check_float_arguments;
+}
+
+void
+check_struct_passing10 (struct complex2_struct is ATTRIBUTE_UNUSED)
+{
+  check_int_arguments;
+  check_double_arguments;
+}
+
+void
+check_struct_passing11 (struct complex3_struct is ATTRIBUTE_UNUSED)
+{
+  check_int_arguments;
+  check_float16_arguments;
+}
+
+void
+check_struct_passing12 (struct complex4_struct is ATTRIBUTE_UNUSED)
+{
+  check_int_arguments;
+  check_float16_arguments;
+}
+
+static struct flex1_struct f1s = { 60, { } };
+static struct flex2_struct f2s = { 61, { } };
+
+static void
+do_test (void)
+{
+  struct int_struct is = { 48 };
+  struct long_struct ls = { 49 };
+#ifdef CHECK_LARGER_STRUCTS
+  struct long2_struct l2s = { 50, 51 };
+  struct long3_struct l3s = { 52, 53, 54 };
+#endif
+#ifdef CHECK_M64_M128
+  struct m128_struct m128s[8];
+  struct m128_2_struct m128_2s = { 
+      { 48.394, 39.3, -397.9, 3484.9 },
+      { -8.394, -93.3, 7.9, 84.94 }
+  };
+  int i;
+#endif
+  struct complex1_struct c1s = { 4, ( -13.4 + 3.5*I ) };
+  union
+    {
+      struct complex1_struct c;
+      struct complex1a_struct u;
+    } c1u;
+  struct complex2_struct c2s = { 4, ( -13.4 + 3.5*I ), -34.5 };
+  union
+    {
+      struct complex2_struct c;
+      struct complex2a_struct u;
+    } c2u;
+
+  struct complex3_struct c3s = { 4, ( -13.4 + 3.5*I ) };
+  union
+    {
+      struct complex3_struct c;
+      struct complex3a_struct u;
+    } c3u;
+
+  struct complex4_struct c4s = { 4, ( -13.4 + 3.5*I ), -34.5 };
+  union
+    {
+      struct complex4_struct c;
+      struct complex4a_struct u;
+    } c4u;
+
+  clear_struct_registers;
+  iregs.I0 = is.i;
+  num_iregs = 1;
+  clear_int_hardware_registers;
+  WRAP_CALL (check_struct_passing1)(is);
+
+  clear_struct_registers;
+  iregs.I0 = ls.l;
+  num_iregs = 1;
+  clear_int_hardware_registers;
+  WRAP_CALL (check_struct_passing2)(ls);
+
+#ifdef CHECK_LARGER_STRUCTS
+  clear_struct_registers;
+  iregs.I0 = l2s.l1;
+  iregs.I1 = l2s.l2;
+  num_iregs = 2;
+  clear_int_hardware_registers;
+  WRAP_CALL (check_struct_passing3)(l2s);
+  WRAP_CALL (check_struct_passing4)(l3s);
+#endif
+
+#ifdef CHECK_M64_M128
+  clear_struct_registers;
+  for (i = 0; i < 8; i++)
+    {
+      m128s[i].x = (__m128){32+i, 0, i, 0};
+      (&fregs.xmm0)[i]._m128[0] = m128s[i].x;
+    }
+  num_fregs = 8;
+  clear_float_hardware_registers;
+  WRAP_CALL (check_struct_passing5)(m128s[0], m128s[1], m128s[2], m128s[3],
+				    m128s[4], m128s[5], m128s[6], m128s[7]);
+  WRAP_CALL (check_struct_passing6)(m128_2s);
+#endif
+
+  clear_struct_registers;
+  iregs.I0 = f1s.i;
+  num_iregs = 1;
+  clear_int_hardware_registers;
+  WRAP_CALL (check_struct_passing7)(f1s);
+
+  clear_struct_registers;
+  iregs.I0 = f2s.i;
+  num_iregs = 1;
+  clear_int_hardware_registers;
+  WRAP_CALL (check_struct_passing8)(f2s);
+
+  clear_struct_registers;
+  c1u.c = c1s;
+  iregs.I0 = c1u.u.l;
+  num_iregs = 1;
+  fregs.xmm0._float [0] = c1u.u.f;
+  num_fregs = 1;
+  clear_int_hardware_registers;
+  clear_float_hardware_registers;
+  WRAP_CALL (check_struct_passing9)(c1s);
+
+  clear_struct_registers;
+  c2u.c = c2s;
+  iregs.I0 = c2u.u.l;
+  num_iregs = 1;
+  fregs.xmm0._double[0] = c2u.u.d;
+  num_fregs = 1;
+  clear_int_hardware_registers;
+  clear_float_hardware_registers;
+  WRAP_CALL (check_struct_passing10)(c2s);
+
+  clear_struct_registers;
+  c3u.c = c3s;
+  iregs.I0 = c3u.u.l;
+  num_iregs = 1;
+  num_fregs = 0;
+  clear_int_hardware_registers;
+  clear_float_hardware_registers;
+  WRAP_CALL (check_struct_passing11)(c3s);
+
+  clear_struct_registers;
+  c4u.c = c4s;
+  iregs.I0 = c4u.u.l;
+  num_iregs = 1;
+  fregs.xmm0.__Float16 [0] = c4u.u.f;
+  num_fregs = 1;
+  clear_int_hardware_registers;
+  clear_float_hardware_registers;
+  WRAP_CALL (check_struct_passing12)(c4s);
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_passing_unions.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_passing_unions.c
new file mode 100644
index 00000000000..640b3057f93
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_passing_unions.c
@@ -0,0 +1,335 @@ 
+/* This tests passing of structs.  */
+
+#include "avx512fp16-xmm-check.h"
+#include "defines.h"
+#include "args.h"
+
+struct IntegerRegisters iregs;
+struct FloatRegisters fregs;
+unsigned int num_iregs, num_fregs;
+
+struct int_struct
+{
+  int i;
+};
+
+struct long_struct
+{
+  long l;
+};
+
+union un1
+{
+  char c;
+  int i;
+};
+
+union un2
+{
+  char c1;
+  long l;
+  char c2;
+};
+
+union un3
+{
+  struct int_struct is;
+  struct long_struct ls;
+  union un1 un;
+};
+
+
+void
+check_union_passing1(union un1 u ATTRIBUTE_UNUSED)
+{
+  check_int_arguments;
+}
+
+void
+check_union_passing2(union un2 u1 ATTRIBUTE_UNUSED)
+{
+  check_int_arguments;
+}
+
+void
+check_union_passing3(union un3 u ATTRIBUTE_UNUSED)
+{
+  check_int_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)
+
+#ifdef CHECK_M64_M128
+union un4
+{
+  __m128 x;
+  float f;
+};
+
+union un5
+{
+  __m128 x;
+  long i;
+};
+
+void
+check_union_passing4(union un4 u1 ATTRIBUTE_UNUSED,
+		     union un4 u2 ATTRIBUTE_UNUSED,
+		     union un4 u3 ATTRIBUTE_UNUSED,
+		     union un4 u4 ATTRIBUTE_UNUSED,
+		     union un4 u5 ATTRIBUTE_UNUSED,
+		     union un4 u6 ATTRIBUTE_UNUSED,
+		     union un4 u7 ATTRIBUTE_UNUSED,
+		     union un4 u8 ATTRIBUTE_UNUSED)
+{
+  check_m128_arguments;
+}
+
+void
+check_union_passing5(union un5 u ATTRIBUTE_UNUSED)
+{
+  check_int_arguments;
+  check_vector_arguments(m128, 8);
+}
+
+union un4a
+{
+  __m128 x;
+  _Float16 f;
+};
+
+void
+check_union_passing4a(union un4a u1 ATTRIBUTE_UNUSED,
+		      union un4a u2 ATTRIBUTE_UNUSED,
+		      union un4a u3 ATTRIBUTE_UNUSED,
+		      union un4a u4 ATTRIBUTE_UNUSED,
+		      union un4a u5 ATTRIBUTE_UNUSED,
+		      union un4a u6 ATTRIBUTE_UNUSED,
+		      union un4a u7 ATTRIBUTE_UNUSED,
+		      union un4a u8 ATTRIBUTE_UNUSED)
+{
+  check_m128_arguments;
+}
+
+union un4b
+{
+  __m128h x;
+  _Float16 f;
+};
+
+void
+check_union_passing4b(union un4b u1 ATTRIBUTE_UNUSED,
+		      union un4b u2 ATTRIBUTE_UNUSED,
+		      union un4b u3 ATTRIBUTE_UNUSED,
+		      union un4b u4 ATTRIBUTE_UNUSED,
+		      union un4b u5 ATTRIBUTE_UNUSED,
+		      union un4b u6 ATTRIBUTE_UNUSED,
+		      union un4b u7 ATTRIBUTE_UNUSED,
+		      union un4b u8 ATTRIBUTE_UNUSED)
+{
+  check_m128_arguments;
+}
+
+#define check_union_passing4 WRAP_CALL(check_union_passing4)
+#define check_union_passing4a WRAP_CALL(check_union_passing4a)
+#define check_union_passing4b WRAP_CALL(check_union_passing4b)
+#define check_union_passing5 WRAP_CALL(check_union_passing5)
+#endif
+
+union un6
+{
+  long double ld;
+  int i;
+};
+
+
+void
+check_union_passing6(union un6 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.ld == rsp+8);
+  assert ((unsigned long)&u.i == rsp+8);
+}
+
+#define check_union_passing6 WRAP_CALL(check_union_passing6)
+
+union un7
+{
+  long double ld;
+  _Float16 f;
+};
+
+void
+check_union_passing7(union un7 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.ld == rsp+8);
+  assert ((unsigned long)&u.f == rsp+8);
+}
+
+#define check_union_passing7 WRAP_CALL(check_union_passing7)
+
+union un8
+{
+  _Float16 f;
+  int i;
+};
+
+void
+check_union_passing8(union un8 u ATTRIBUTE_UNUSED)
+{
+  check_int_arguments;
+}
+
+#define check_union_passing8 WRAP_CALL(check_union_passing8)
+
+static void
+do_test (void)
+{
+  union un1 u1;
+#ifdef CHECK_LARGER_UNION_PASSING
+  union un2 u2;
+  union un3 u3;
+  struct int_struct is;
+  struct long_struct ls;
+#endif /* CHECK_LARGER_UNION_PASSING */
+#ifdef CHECK_M64_M128
+  union un4 u4[8];
+  union un4a u4a[8];
+  union un4b u4b[8];
+  union un5 u5 = { { 48.394, 39.3, -397.9, 3484.9 } };
+  int i;
+#endif
+  union un6 u6;
+  union un7 u7;
+  union un8 u8;
+
+  /* Check a union with char, int.  */
+  clear_struct_registers;
+  u1.i = 0;  /* clear the struct to not have high bits left */
+  u1.c = 32;
+  iregs.I0 = 32;
+  num_iregs = 1;
+  clear_int_hardware_registers;
+  check_union_passing1(u1);
+  u1.i = 0;  /* clear the struct to not have high bits left */
+  u1.i = 33;
+  iregs.I0 = 33;
+  num_iregs = 1;
+  clear_int_hardware_registers;
+  check_union_passing1(u1);
+
+  /* Check a union with char, long, char.  */
+#ifdef CHECK_LARGER_UNION_PASSING
+  clear_struct_registers;
+  u2.l = 0;  /* clear the struct to not have high bits left */
+  u2.c1 = 34;
+  iregs.I0 = 34;
+  num_iregs = 1;
+  clear_int_hardware_registers;
+  check_union_passing2(u2);
+  u2.l = 0;  /* clear the struct to not have high bits left */
+  u2.l = 35;
+  iregs.I0 = 35;
+  num_iregs = 1;
+  clear_int_hardware_registers;
+  check_union_passing2(u2);
+  u2.l = 0;  /* clear the struct to not have high bits left */
+  u2.c2 = 36;
+  iregs.I0 = 36;
+  num_iregs = 1;
+  clear_int_hardware_registers;
+  check_union_passing2(u2);
+
+  /* check a union containing two structs and a union.  */
+  clear_struct_registers;
+  is.i = 37;
+  u3.ls.l = 0;  /* clear the struct to not have high bits left */
+  u3.is = is;
+  iregs.I0 = 37;
+  num_iregs = 1;
+  clear_int_hardware_registers;
+  check_union_passing3(u3);
+  ls.l = 38;
+  u3.ls.l = 0;  /* clear the struct to not have high bits left */
+  u3.ls = ls;
+  iregs.I0 = 38;
+  num_iregs = 1;
+  clear_int_hardware_registers;
+  check_union_passing3(u3);
+  u1.c = 39;
+  u3.ls.l = 0;  /* clear the struct to not have high bits left */
+  u3.un = u1;
+  iregs.I0 = 39;
+  num_iregs = 1;
+  clear_int_hardware_registers;
+  check_union_passing3(u3);
+  u1.i = 40;
+  u3.ls.l = 0;  /* clear the struct to not have high bits left */
+  u3.un = u1;
+  iregs.I0 = 40;
+  num_iregs = 1;
+  clear_int_hardware_registers;
+  check_union_passing3(u3);
+#endif /* CHECK_LARGER_UNION_PASSING */
+
+#ifdef CHECK_M64_M128
+  clear_struct_registers;
+  for (i = 0; i < 8; i++)
+    {
+      u4[i].x = (__m128){32+i, 0, i, 0};
+      (&fregs.xmm0)[i]._m128[0] = u4[i].x;
+    }
+  num_fregs = 8;
+  clear_float_hardware_registers;
+  check_union_passing4(u4[0], u4[1], u4[2], u4[3],
+		       u4[4], u4[5], u4[6], u4[7]);
+
+  clear_struct_registers;
+  for (i = 0; i < 8; i++)
+    {
+      u4a[i].x = (__m128){32+i, 0, i, 0};
+      (&fregs.xmm0)[i]._m128[0] = u4[i].x;
+    }
+  num_fregs = 8;
+  clear_float_hardware_registers;
+  check_union_passing4a(u4a[0], u4a[1], u4a[2], u4a[3],
+		       u4a[4], u4a[5], u4a[6], u4a[7]);
+
+  clear_struct_registers;
+  for (i = 0; i < 8; i++)
+    {
+      u4b[i].x = (__m128h){33+i, 0, i, 0, -i, 1, 2 * i, i + 8};
+      (&fregs.xmm0)[i]._m128h[0] = u4b[i].x;
+    }
+  num_fregs = 8;
+  clear_float_hardware_registers;
+  check_union_passing4b(u4b[0], u4b[1], u4b[2], u4b[3],
+		        u4b[4], u4b[5], u4b[6], u4b[7]);
+
+  clear_struct_registers;
+  fregs.xmm0._m128[0] = u5.x;
+  num_fregs = 1;
+  num_iregs = 1;
+  iregs.I0 = u5.i;
+  clear_float_hardware_registers;
+  check_union_passing5(u5);
+#endif
+
+  u6.i = 2;
+  check_union_passing6(u6);
+
+  u7.f = 2.0f16;
+  check_union_passing7(u7);
+
+  clear_struct_registers;
+  u8.i = 8;
+  num_iregs = 1;
+  iregs.I0 = u8.i;
+  clear_int_hardware_registers;
+  check_union_passing8(u8);
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_struct_returning.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_struct_returning.c
new file mode 100644
index 00000000000..92578127be7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_struct_returning.c
@@ -0,0 +1,274 @@ 
+/* This tests returning of structures.  */
+
+#include <stdio.h>
+#include "avx512fp16-xmm-check.h"
+#include "defines.h"
+#include "macros.h"
+#include "args.h"
+
+struct IntegerRegisters iregs;
+struct FloatRegisters fregs;
+unsigned int num_iregs, num_fregs;
+
+int current_test;
+int num_failed = 0;
+
+#undef assert
+#define assert(test) do { if (!(test)) {fprintf (stderr, "failed in test %d\n", current_test); num_failed++; } } while (0)
+
+#define xmm0h xmm_regs[0].__Float16
+#define xmm1h xmm_regs[1].__Float16
+#define xmm0f xmm_regs[0]._float
+#define xmm0d xmm_regs[0]._double
+#define xmm1f xmm_regs[1]._float
+#define xmm1d xmm_regs[1]._double
+
+typedef enum {
+  INT = 0,
+  SSE_H,
+  SSE_F,
+  SSE_D,
+  X87,
+  MEM,
+  INT_SSE,
+  SSE_INT,
+  SSE_F_V,
+  SSE_F_H,
+  SSE_F_H8
+} Type;
+
+/* Structures which should be returned in INTEGER.  */
+#define D(I,MEMBERS,B) struct S_ ## I { MEMBERS ; }; Type class_ ## I = INT; \
+struct S_ ## I f_ ## I (void) { struct S_ ## I s; memset (&s, 0, sizeof(s)); B; return s; }
+
+D(1,char m1, s.m1=42)
+D(2,short m1, s.m1=42)
+D(3,int m1, s.m1=42)
+D(4,long m1, s.m1=42)
+D(5,long long m1, s.m1=42)
+D(6,char m1;short s, s.m1=42)
+D(7,char m1;int i, s.m1=42)
+D(8,char m1; long l, s.m1=42)
+D(9,char m1; long long l, s.m1=42)
+D(10,char m1[16], s.m1[0]=42)
+D(11,short m1[8], s.m1[0]=42)
+D(12,int m1[4], s.m1[0]=42)
+D(13,long m1[2], s.m1[0]=42)
+D(14,long long m1[2], s.m1[0]=42)
+
+#undef D
+
+/* Structures which should be returned in SSE.  */
+#define D(I,MEMBERS,C,B) struct S_ ## I { MEMBERS ; }; Type class_ ## I = C; \
+struct S_ ## I f_ ## I (void) { struct S_ ## I s; memset (&s, 0, sizeof(s)); B; return s; }
+
+D(100,float f,SSE_F, s.f=42)
+D(101,double d,SSE_D, s.d=42)
+D(102,float f;float f2,SSE_F, s.f=42)
+D(103,float f;double d,SSE_F, s.f=42)
+D(104,double d; float f,SSE_D, s.d=42)
+D(105,double d; double d2,SSE_D, s.d=42)
+D(106,float f[2],SSE_F, s.f[0]=42)
+D(107,float f[3],SSE_F, s.f[0]=42)
+D(108,float f[4],SSE_F, s.f[0]=42)
+D(109,double d[2],SSE_D, s.d[0]=42)
+D(110,float f[2]; double d,SSE_F, s.f[0]=42)
+D(111,double d;float f[2],SSE_D, s.d=42)
+
+D(120,_Float16 f,SSE_H, s.f=42)
+D(121,_Float16 f;_Float16 f2,SSE_H, s.f=42)
+D(122,_Float16 f;float d,SSE_H, s.f=42)
+D(123,_Float16 f;double d,SSE_H, s.f=42)
+D(124,double d; _Float16 f,SSE_D, s.d=42)
+D(125,_Float16 f[2],SSE_H, s.f[0]=42)
+D(126,_Float16 f[3],SSE_H, s.f[0]=42)
+D(127,_Float16 f[4],SSE_H, s.f[0]=42)
+D(128,_Float16 f[2]; double d,SSE_H, s.f[0]=42)
+D(129,double d;_Float16 f[2],SSE_D, s.d=42)
+
+#undef D
+
+/* Structures which should be returned on x87 stack.  */
+#define D(I,MEMBERS) struct S_ ## I { MEMBERS ; }; Type class_ ## I = X87; \
+struct S_ ## I f_ ## I (void) { struct S_ ## I s = { 42 }; return s; }
+
+/* The only struct containing a long double, which is returned in
+   registers at all, is the singleton struct.  All others are too large.
+   This includes a struct containing complex long double, which is passed
+   in memory, although a complex long double type itself is returned in
+   two registers.  */
+D(200,long double ld)
+
+#undef D
+
+/* Structures which should be returned in INT (low) and SSE (high).  */
+#define D(I,MEMBERS) struct S_ ## I { MEMBERS ; }; Type class_ ## I = INT_SSE; \
+struct S_ ## I f_ ## I (void) { struct S_ ## I s = { 42,43 }; return s; }
+
+D(300,char m1; float m2)
+D(301,char m1; double m2)
+D(302,short m1; float m2)
+D(303,short m1; double m2)
+D(304,int m1; float m2)
+D(305,int m1; double m2)
+D(306,long long m1; float m2)
+D(307,long long m1; double m2)
+
+D(310,char m1; _Float16 m2)
+D(311,short m1; _Float16 m2)
+D(312,int m1; _Float16 m2)
+D(313,long long m1; _Float16 m2)
+
+#undef D
+
+void check_300 (void)
+{
+  XMM_T x;
+  x._ulong[0] = rax;
+  switch (current_test) {
+    case 300: assert ((rax & 0xff) == 42 && x._float[1] == 43); break;
+    case 301: assert ((rax & 0xff) == 42 && xmm0d[0] == 43); break;
+    case 302: assert ((rax & 0xffff) == 42 && x._float[1] == 43); break;
+    case 303: assert ((rax & 0xffff) == 42 && xmm0d[0] == 43); break;
+    case 304: assert ((rax & 0xffffffff) == 42 && x._float[1] == 43); break;
+    case 305: assert ((rax & 0xffffffff) == 42 && xmm0d[0] == 43); break;
+    case 306: assert (rax == 42 && xmm0f[0] == 43); break;
+    case 307: assert (rax == 42 && xmm0d[0] == 43); break;
+    case 310: assert ((rax & 0xff) == 42 && x.__Float16[1] == 43); break;
+    case 311: assert ((rax & 0xffff) == 42 && x.__Float16[1] == 43); break;
+    case 312: assert ((rax & 0xffffffff) == 42 && x.__Float16[2] == 43); break;
+    case 313: assert (rax == 42 && xmm0h[0] == 43); break;
+
+    default: assert (0); break;
+  }
+}
+
+/* Structures which should be returned in SSE (low) and INT (high).  */
+#define D(I,MEMBERS,B) struct S_ ## I { MEMBERS ; }; Type class_ ## I = SSE_INT; \
+struct S_ ## I f_ ## I (void) { struct S_ ## I s; memset (&s, 0, sizeof(s));  B; return s; }
+
+D(400,float f[2];char c, s.f[0]=42; s.c=43)
+D(401,double d;char c, s.d=42; s.c=43)
+
+D(402,_Float16 f[4];char c, s.f[0]=42; s.c=43)
+
+#undef D
+
+void check_400 (void)
+{
+  switch (current_test) {
+    case 400: assert (xmm0f[0] == 42 && (rax & 0xff) == 43); break;
+    case 401: assert (xmm0d[0] == 42 && (rax & 0xff) == 43); break;
+    case 402: assert (xmm0h[0] == 42 && (rax & 0xff) == 43); break;
+
+    default: assert (0); break;
+  }
+}
+
+/* Structures which should be returned in MEM.  */
+void *struct_addr;
+#define D(I,MEMBERS) struct S_ ## I { MEMBERS ; }; Type class_ ## I = MEM; \
+struct S_ ## I f_ ## I (void) { union {unsigned char c; struct S_ ## I s;} u; memset (&u.s, 0, sizeof(u.s)); u.c = 42; return u.s; }
+
+/* Too large.  */
+D(500,char m1[17])
+D(501,short m1[9])
+D(502,int m1[5])
+D(503,long m1[3])
+D(504,short m1[8];char c)
+D(505,char m1[1];int i[4])
+D(506,float m1[5])
+D(507,double m1[3])
+D(508,char m1[1];float f[4])
+D(509,char m1[1];double d[2])
+D(510,__complex long double m1[1])
+
+/* Too large due to padding.  */
+D(520,char m1[1];int i;char c2; int i2; char c3)
+
+/* Unnaturally aligned members.  */
+D(530,short m1[1];int i PACKED)
+
+D(540,_Float16 m1[10])
+D(541,char m1[1];_Float16 f[8])
+
+#undef D
+
+
+/* Special tests.  */
+#define D(I,MEMBERS,C,B) struct S_ ## I { MEMBERS ; }; Type class_ ## I = C; \
+struct S_ ## I f_ ## I (void) { struct S_ ## I s; B; return s; }
+D(600,float f[4], SSE_F_V, s.f[0] = s.f[1] = s.f[2] = s.f[3] = 42)
+D(601,_Float16 f[4], SSE_F_H, s.f[0] = s.f[1] = s.f[2] = s.f[3] = 42)
+D(602,_Float16 f[8], SSE_F_H8,
+  s.f[0] = s.f[1] = s.f[2] = s.f[3] = s.f[4] = s.f[5] = s.f[6] = s.f[7] = 42)
+#undef D
+
+void clear_all (void)
+{
+  clear_int_registers;
+  clear_float_registers;
+  clear_x87_registers;
+}
+
+void check_all (Type class, unsigned long size)
+{
+  switch (class) {
+    case INT: if (size < 8) rax &= ~0UL >> (64-8*size); assert (rax == 42); break;
+    case SSE_H: assert (xmm0h[0] == 42); break;
+    case SSE_F: assert (xmm0f[0] == 42); break;
+    case SSE_D: assert (xmm0d[0] == 42); break;
+    case SSE_F_V: assert (xmm0f[0] == 42 && xmm0f[1]==42 && xmm1f[0] == 42 && xmm1f[1] == 42); break;
+    case SSE_F_H: assert (xmm0h[0] == 42 && xmm0h[1]==42 && xmm0h[2] == 42 && xmm0h[3] == 42); break;
+    case SSE_F_H8: assert (xmm0h[0] == 42 && xmm0h[1]==42 && xmm0h[2] == 42 && xmm0h[3] == 42
+			   && xmm1h[0] == 42 && xmm1h[1]==42 && xmm1h[2] == 42 && xmm1h[3] == 42); break;
+    case X87: assert (x87_regs[0]._ldouble == 42); break;
+    case INT_SSE: check_300(); break;
+    case SSE_INT: check_400(); break;
+    /* Ideally we would like to check that rax == struct_addr.
+       Unfortunately the address of the target struct escapes (for setting
+       struct_addr), so the return struct is a temporary one whose address
+       is given to the f_* functions, otherwise a conforming program
+       could notice the struct changing already before the function returns.
+       This temporary struct could be anywhere.  For GCC it will be on
+       stack, but no one is forbidding that it could be a static variable
+       if there's no threading or proper locking.  Nobody in his right mind
+       will not use the stack for that.  */
+    case MEM: assert (*(unsigned char*)struct_addr == 42 && rdi == rax); break;
+  }
+}
+
+#define D(I) { struct S_ ## I s; current_test = I; struct_addr = (void*)&s; \
+  clear_all(); \
+  s = WRAP_RET(f_ ## I) (); \
+  check_all(class_ ## I, sizeof(s)); \
+}
+
+static void
+do_test (void)
+{
+  D(1) D(2) D(3) D(4) D(5) D(6) D(7) D(8) D(9) D(10) D(11) D(12) D(13) D(14)
+  
+  D(100) D(101) D(102) D(103) D(104) D(105) D(106) D(107) D(108) D(109) D(110)
+  D(111)
+  
+  D(120) D(121) D(122) D(123) D(124) D(125) D(126) D(127) D(128) D(129)
+
+  D(200)
+
+  D(300) D(301) D(302) D(303) D(304) D(305) D(306) D(307)
+  D(310) D(311) D(312) D(313)
+
+  D(400) D(401) D(402)
+
+  D(500) D(501) D(502) D(503) D(504) D(505) D(506) D(507) D(508) D(509)
+  D(520)
+  D(530)
+
+  D(540) D(541)
+
+  D(600) D(601) D(602)
+  if (num_failed)
+    abort ();
+}
+#undef D
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_varargs-m128.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_varargs-m128.c
new file mode 100644
index 00000000000..5bdc44db5f4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_varargs-m128.c
@@ -0,0 +1,164 @@ 
+/* Test variable number of 128-bit vector arguments passed to functions.  */
+
+#include <stdio.h>
+#include "avx512fp16-xmm-check.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++;
+
+  /* Skip the return address stack slot.  */
+  argp = (__m128 *) (((char *) fp) + 8);
+
+  /* Check __m128 arguments passed on stack.  */
+  compare (values.i8, argp[0], __m128);
+  compare (values.i9, argp[1], __m128);
+
+  /* Check register contents.  */
+  compare (fregs.xmm0, xmm_regs[0], __m128);
+  compare (fregs.xmm1, xmm_regs[1], __m128);
+  compare (fregs.xmm2, xmm_regs[2], __m128);
+  compare (fregs.xmm3, xmm_regs[3], __m128);
+  compare (fregs.xmm4, xmm_regs[4], __m128);
+  compare (fregs.xmm5, xmm_regs[5], __m128);
+  compare (fregs.xmm6, xmm_regs[6], __m128);
+  compare (fregs.xmm7, xmm_regs[7], __m128);
+}
+
+void
+fun_check_passing_m128h_varargs (__m128h i0, __m128h i1, __m128h i2,
+				 __m128h i3, ...)
+{
+  /* Check argument values.  */
+  void **fp = __builtin_frame_address (0);
+  void *ra = __builtin_return_address (0);
+  __m128h *argp;
+
+  compare (values.i0, i0, __m128h);
+  compare (values.i1, i1, __m128h);
+  compare (values.i2, i2, __m128h);
+  compare (values.i3, i3, __m128h);
+
+  /* Get the pointer to the return address on stack.  */
+  while (*fp != ra)
+    fp++;
+
+  /* Skip the return address stack slot.  */
+  argp = (__m128h *) (((char *) fp) + 8);
+
+  /* Check __m128h arguments passed on stack.  */
+  compare (values.i8, argp[0], __m128h);
+  compare (values.i9, argp[1], __m128h);
+
+  /* Check register contents.  */
+  compare (fregs.xmm0, xmm_regs[0], __m128h);
+  compare (fregs.xmm1, xmm_regs[1], __m128h);
+  compare (fregs.xmm2, xmm_regs[2], __m128h);
+  compare (fregs.xmm3, xmm_regs[3], __m128h);
+  compare (fregs.xmm4, xmm_regs[4], __m128h);
+  compare (fregs.xmm5, xmm_regs[5], __m128h);
+  compare (fregs.xmm6, xmm_regs[6], __m128h);
+  compare (fregs.xmm7, xmm_regs[7], __m128h);
+}
+
+#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);
+}
+
+void
+test_m128h_varargs (void)
+{
+  __m128h x[10];
+  int i;
+  for (i = 0; i < 10; i++)
+    x[i] = (__m128h) {
+        1.1f16 + i, 2.2f16 + i, 3.3f16 + i, 4.4f16 + i,
+	5.5f16 + i, 6.6f16 + i, 7.7f16 + i, 8.8f16 + i
+    };
+  pass = "m128h-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_m128h_varargs,
+				 _m128h);
+}
+
+static void
+do_test (void)
+{
+  test_m128_varargs ();
+  test_m128h_varargs ();
+  if (failed)
+    abort ();
+}