Commit a8800687 by H.J. Lu Committed by H.J. Lu

re PR target/39119 (Update classification of aggregates with __m256)

gcc/

2009-02-10  H.J. Lu  <hongjiu.lu@intel.com>

	PR target/39119
	* config/i386/i386.c (x86_64_reg_class): Remove X86_64_AVX_CLASS.
	(x86_64_reg_class_name): Removed.
	(classify_argument): Return 0 if bytes > 32.  Return 0 if the
	first one isn't X86_64_SSE_CLASS or any other ones aren't
	X86_64_SSEUP_CLASS when size > 16bytes.  Don't turn
	X86_64_SSEUP_CLASS into X86_64_SSE_CLASS if the preceded one
	is X86_64_SSEUP_CLASS.  Set AVX modes to 1 X86_64_SSE_CLASS
	and 3 X86_64_SSEUP_CLASS.
	(construct_container): Remove X86_64_AVX_CLASS.  Handle 4
	registers with 1 X86_64_SSE_CLASS and 3 X86_64_SSEUP_CLASS.

gcc/testsuite/

2009-02-10  H.J. Lu  <hongjiu.lu@intel.com>

	PR target/39119
	* gcc.target/x86_64/abi/avx/abi-avx.exp: New.
	* gcc.target/x86_64/abi/avx/args.h: Likewise.
	* gcc.target/x86_64/abi/avx/asm-support.S: Likewise.
	* gcc.target/x86_64/abi/avx/avx-check.h: Likewise.
	* gcc.target/x86_64/abi/avx/test_m256_returning.c: Likewise.
	* gcc.target/x86_64/abi/avx/test_passing_m256.c: Likewise.
	* gcc.target/x86_64/abi/avx/test_passing_structs.c: Likewise.
	* gcc.target/x86_64/abi/avx/test_passing_unions.c: Likewise.

From-SVN: r144058
parent f7459b6c
2009-02-10 H.J. Lu <hongjiu.lu@intel.com>
PR target/39119
* config/i386/i386.c (x86_64_reg_class): Remove X86_64_AVX_CLASS.
(x86_64_reg_class_name): Removed.
(classify_argument): Return 0 if bytes > 32. Return 0 if the
first one isn't X86_64_SSE_CLASS or any other ones aren't
X86_64_SSEUP_CLASS when size > 16bytes. Don't turn
X86_64_SSEUP_CLASS into X86_64_SSE_CLASS if the preceded one
is X86_64_SSEUP_CLASS. Set AVX modes to 1 X86_64_SSE_CLASS
and 3 X86_64_SSEUP_CLASS.
(construct_container): Remove X86_64_AVX_CLASS. Handle 4
registers with 1 X86_64_SSE_CLASS and 3 X86_64_SSEUP_CLASS.
2009-02-10 Ben Elliston <bje@au.ibm.com>
* config/rs6000/rs6000.md (allocate_stack): Always use an update
......
......@@ -1773,7 +1773,6 @@ enum x86_64_reg_class
X86_64_NO_CLASS,
X86_64_INTEGER_CLASS,
X86_64_INTEGERSI_CLASS,
X86_64_AVX_CLASS,
X86_64_SSE_CLASS,
X86_64_SSESF_CLASS,
X86_64_SSEDF_CLASS,
......@@ -1783,11 +1782,6 @@ enum x86_64_reg_class
X86_64_COMPLEX_X87_CLASS,
X86_64_MEMORY_CLASS
};
static const char * const x86_64_reg_class_name[] =
{
"no", "integer", "integerSI", "sse", "sseSF", "sseDF",
"sseup", "x87", "x87up", "cplx87", "no"
};
#define MAX_CLASSES 4
......@@ -4863,8 +4857,8 @@ classify_argument (enum machine_mode mode, const_tree type,
tree field;
enum x86_64_reg_class subclasses[MAX_CLASSES];
/* On x86-64 we pass structures larger than 16 bytes on the stack. */
if (bytes > 16)
/* On x86-64 we pass structures larger than 32 bytes on the stack. */
if (bytes > 32)
return 0;
for (i = 0; i < words; i++)
......@@ -4974,6 +4968,20 @@ classify_argument (enum machine_mode mode, const_tree type,
gcc_unreachable ();
}
if (words > 2)
{
/* When size > 16 bytes, if the first one isn't
X86_64_SSE_CLASS or any other ones aren't
X86_64_SSEUP_CLASS, everything should be passed in
memory. */
if (classes[0] != X86_64_SSE_CLASS)
return 0;
for (i = 1; i < words; i++)
if (classes[i] != X86_64_SSEUP_CLASS)
return 0;
}
/* Final merger cleanup. */
for (i = 0; i < words; i++)
{
......@@ -4983,10 +4991,15 @@ classify_argument (enum machine_mode mode, const_tree type,
return 0;
/* The X86_64_SSEUP_CLASS should be always preceded by
X86_64_SSE_CLASS. */
X86_64_SSE_CLASS or X86_64_SSEUP_CLASS. */
if (classes[i] == X86_64_SSEUP_CLASS
&& (i == 0 || classes[i - 1] != X86_64_SSE_CLASS))
classes[i] = X86_64_SSE_CLASS;
&& classes[i - 1] != X86_64_SSE_CLASS
&& classes[i - 1] != X86_64_SSEUP_CLASS)
{
/* The first one should never be X86_64_SSEUP_CLASS. */
gcc_assert (i != 0);
classes[i] = X86_64_SSE_CLASS;
}
/* X86_64_X87UP_CLASS should be preceded by X86_64_X87_CLASS. */
if (classes[i] == X86_64_X87UP_CLASS
......@@ -5107,8 +5120,11 @@ classify_argument (enum machine_mode mode, const_tree type,
case V16HImode:
case V4DFmode:
case V4DImode:
classes[0] = X86_64_AVX_CLASS;
return 1;
classes[0] = X86_64_SSE_CLASS;
classes[1] = X86_64_SSEUP_CLASS;
classes[2] = X86_64_SSEUP_CLASS;
classes[3] = X86_64_SSEUP_CLASS;
return 4;
case V4SFmode:
case V4SImode:
case V16QImode:
......@@ -5165,7 +5181,6 @@ examine_argument (enum machine_mode mode, const_tree type, int in_return,
case X86_64_INTEGERSI_CLASS:
(*int_nregs)++;
break;
case X86_64_AVX_CLASS:
case X86_64_SSE_CLASS:
case X86_64_SSESF_CLASS:
case X86_64_SSEDF_CLASS:
......@@ -5264,7 +5279,6 @@ construct_container (enum machine_mode mode, enum machine_mode orig_mode,
case X86_64_INTEGER_CLASS:
case X86_64_INTEGERSI_CLASS:
return gen_rtx_REG (mode, intreg[0]);
case X86_64_AVX_CLASS:
case X86_64_SSE_CLASS:
case X86_64_SSESF_CLASS:
case X86_64_SSEDF_CLASS:
......@@ -5281,6 +5295,13 @@ construct_container (enum machine_mode mode, enum machine_mode orig_mode,
if (n == 2 && regclass[0] == X86_64_SSE_CLASS
&& regclass[1] == X86_64_SSEUP_CLASS && mode != BLKmode)
return gen_rtx_REG (mode, SSE_REGNO (sse_regno));
if (n == 4
&& regclass[0] == X86_64_SSE_CLASS
&& regclass[1] == X86_64_SSEUP_CLASS
&& regclass[2] == X86_64_SSEUP_CLASS
&& regclass[3] == X86_64_SSEUP_CLASS
&& mode != BLKmode)
return gen_rtx_REG (mode, SSE_REGNO (sse_regno));
if (n == 2
&& regclass[0] == X86_64_X87_CLASS && regclass[1] == X86_64_X87UP_CLASS)
......@@ -5331,14 +5352,22 @@ construct_container (enum machine_mode mode, enum machine_mode orig_mode,
break;
case X86_64_SSE_CLASS:
if (i < n - 1 && regclass[i + 1] == X86_64_SSEUP_CLASS)
tmpmode = TImode;
{
if (regclass[i + 2] == X86_64_SSEUP_CLASS
|| regclass[i + 3] == X86_64_SSEUP_CLASS)
tmpmode = OImode;
else
tmpmode = TImode;
}
else
tmpmode = DImode;
exp [nexps++] = gen_rtx_EXPR_LIST (VOIDmode,
gen_rtx_REG (tmpmode,
SSE_REGNO (sse_regno)),
GEN_INT (i*8));
if (tmpmode == TImode)
if (tmpmode == OImode)
i += 3;
else if (tmpmode == TImode)
i++;
sse_regno++;
break;
......
2009-02-10 H.J. Lu <hongjiu.lu@intel.com>
PR target/39119
* gcc.target/x86_64/abi/avx/abi-avx.exp: New.
* gcc.target/x86_64/abi/avx/args.h: Likewise.
* gcc.target/x86_64/abi/avx/asm-support.S: Likewise.
* gcc.target/x86_64/abi/avx/avx-check.h: Likewise.
* gcc.target/x86_64/abi/avx/test_m256_returning.c: Likewise.
* gcc.target/x86_64/abi/avx/test_passing_m256.c: Likewise.
* gcc.target/x86_64/abi/avx/test_passing_structs.c: Likewise.
* gcc.target/x86_64/abi/avx/test_passing_unions.c: Likewise.
2009-02-09 Jason Merrill <jason@redhat.com>
PR c++/39109
......
# Copyright (C) 2009 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 AVX 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
if { (![istarget x86_64-*-*] && ![istarget i?86-*-*])
|| ![is-effective-target lp64]
|| ![is-effective-target avx] } then {
return
}
torture-init
set-torture-options $C_TORTURE_OPTIONS
set additional_flags "-W -Wall -mavx"
foreach src [lsort [glob -nocomplain $srcdir/$subdir/test_*.c]] {
if {[runtest_file_p $runtests $src]} {
if { ([istarget *-*-darwin*]) } then {
# FIXME: Darwin isn't tested.
c-torture-execute [list $src \
$srcdir/$subdir/asm-support-darwin.s] \
$additional_flags
} else {
c-torture-execute [list $src \
$srcdir/$subdir/asm-support.S] \
$additional_flags
}
}
}
torture-finish
#ifndef INCLUDED_ARGS_H
#define INCLUDED_ARGS_H
#include <immintrin.h>
#include <string.h>
/* Assertion macro. */
#define assert(test) if (!(test)) abort()
#ifdef __GNUC__
#define ATTRIBUTE_UNUSED __attribute__((__unused__))
#else
#define ATTRIBUTE_UNUSED
#endif
/* This defines the calling sequences for integers and floats. */
#define I0 rdi
#define I1 rsi
#define I2 rdx
#define I3 rcx
#define I4 r8
#define I5 r9
#define F0 ymm0
#define F1 ymm1
#define F2 ymm2
#define F3 ymm3
#define F4 ymm4
#define F5 ymm5
#define F6 ymm6
#define F7 ymm7
typedef union {
float _float[8];
double _double[4];
long _long[4];
int _int[8];
unsigned long _ulong[4];
__m64 _m64[4];
__m128 _m128[2];
__m256 _m256[1];
} YMM_T;
typedef union {
float _float;
double _double;
long double _ldouble;
unsigned long _ulong[2];
} X87_T;
extern void (*callthis)(void);
extern unsigned long rax,rbx,rcx,rdx,rsi,rdi,rsp,rbp,r8,r9,r10,r11,r12,r13,r14,r15;
YMM_T ymm_regs[16];
X87_T x87_regs[8];
extern volatile unsigned long volatile_var;
extern void snapshot (void);
extern void snapshot_ret (void);
#define WRAP_CALL(N) \
(callthis = (void (*)()) (N), (typeof (&N)) snapshot)
#define WRAP_RET(N) \
(callthis = (void (*)()) (N), (typeof (&N)) snapshot_ret)
/* Clear all integer registers. */
#define clear_int_hardware_registers \
asm __volatile__ ("xor %%rax, %%rax\n\t" \
"xor %%rbx, %%rbx\n\t" \
"xor %%rcx, %%rcx\n\t" \
"xor %%rdx, %%rdx\n\t" \
"xor %%rsi, %%rsi\n\t" \
"xor %%rdi, %%rdi\n\t" \
"xor %%r8, %%r8\n\t" \
"xor %%r9, %%r9\n\t" \
"xor %%r10, %%r10\n\t" \
"xor %%r11, %%r11\n\t" \
"xor %%r12, %%r12\n\t" \
"xor %%r13, %%r13\n\t" \
"xor %%r14, %%r14\n\t" \
"xor %%r15, %%r15\n\t" \
::: "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", \
"r9", "r10", "r11", "r12", "r13", "r14", "r15");
/* This is the list of registers available for passing arguments. Not all of
these are used or even really available. */
struct IntegerRegisters
{
unsigned long rax, rbx, rcx, rdx, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15;
};
struct FloatRegisters
{
double mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7;
long double st0, st1, st2, st3, st4, st5, st6, st7;
YMM_T ymm0, ymm1, ymm2, ymm3, ymm4, ymm5, ymm6, ymm7, ymm8, ymm9,
ymm10, ymm11, ymm12, ymm13, ymm14, ymm15;
};
/* Implemented in scalarargs.c */
extern struct IntegerRegisters iregs;
extern struct FloatRegisters fregs;
extern unsigned int num_iregs, num_fregs;
#define check_int_arguments do { \
assert (num_iregs <= 0 || iregs.I0 == I0); \
assert (num_iregs <= 1 || iregs.I1 == I1); \
assert (num_iregs <= 2 || iregs.I2 == I2); \
assert (num_iregs <= 3 || iregs.I3 == I3); \
assert (num_iregs <= 4 || iregs.I4 == I4); \
assert (num_iregs <= 5 || iregs.I5 == I5); \
} while (0)
#define check_char_arguments check_int_arguments
#define check_short_arguments check_int_arguments
#define check_long_arguments check_int_arguments
/* Clear register struct. */
#define clear_struct_registers \
rax = rbx = rcx = rdx = rdi = rsi = rbp = rsp \
= r8 = r9 = r10 = r11 = r12 = r13 = r14 = r15 = 0; \
memset (&iregs, 0, sizeof (iregs)); \
memset (&fregs, 0, sizeof (fregs)); \
memset (ymm_regs, 0, sizeof (ymm_regs)); \
memset (x87_regs, 0, sizeof (x87_regs));
/* Clear both hardware and register structs for integers. */
#define clear_int_registers \
clear_struct_registers \
clear_int_hardware_registers
/* TODO: Do the checking. */
#define check_f_arguments(T) do { \
assert (num_fregs <= 0 || fregs.ymm0._ ## T [0] == ymm_regs[0]._ ## T [0]); \
assert (num_fregs <= 1 || fregs.ymm1._ ## T [0] == ymm_regs[1]._ ## T [0]); \
assert (num_fregs <= 2 || fregs.ymm2._ ## T [0] == ymm_regs[2]._ ## T [0]); \
assert (num_fregs <= 3 || fregs.ymm3._ ## T [0] == ymm_regs[3]._ ## T [0]); \
assert (num_fregs <= 4 || fregs.ymm4._ ## T [0] == ymm_regs[4]._ ## T [0]); \
assert (num_fregs <= 5 || fregs.ymm5._ ## T [0] == ymm_regs[5]._ ## T [0]); \
assert (num_fregs <= 6 || fregs.ymm6._ ## T [0] == ymm_regs[6]._ ## T [0]); \
assert (num_fregs <= 7 || fregs.ymm7._ ## T [0] == ymm_regs[7]._ ## T [0]); \
} while (0)
#define check_float_arguments check_f_arguments(float)
#define check_double_arguments check_f_arguments(double)
#define check_vector_arguments(T,O) do { \
assert (num_fregs <= 0 \
|| memcmp (((char *) &fregs.ymm0) + (O), \
&ymm_regs[0], \
sizeof (__ ## T) - (O)) == 0); \
assert (num_fregs <= 1 \
|| memcmp (((char *) &fregs.ymm1) + (O), \
&ymm_regs[1], \
sizeof (__ ## T) - (O)) == 0); \
assert (num_fregs <= 2 \
|| memcmp (((char *) &fregs.ymm2) + (O), \
&ymm_regs[2], \
sizeof (__ ## T) - (O)) == 0); \
assert (num_fregs <= 3 \
|| memcmp (((char *) &fregs.ymm3) + (O), \
&ymm_regs[3], \
sizeof (__ ## T) - (O)) == 0); \
assert (num_fregs <= 4 \
|| memcmp (((char *) &fregs.ymm4) + (O), \
&ymm_regs[4], \
sizeof (__ ## T) - (O)) == 0); \
assert (num_fregs <= 5 \
|| memcmp (((char *) &fregs.ymm5) + (O), \
&ymm_regs[5], \
sizeof (__ ## T) - (O)) == 0); \
assert (num_fregs <= 6 \
|| memcmp (((char *) &fregs.ymm6) + (O), \
&ymm_regs[6], \
sizeof (__ ## T) - (O)) == 0); \
assert (num_fregs <= 7 \
|| memcmp (((char *) &fregs.ymm7) + (O), \
&ymm_regs[7], \
sizeof (__ ## T) - (O)) == 0); \
} while (0)
#define check_m64_arguments check_vector_arguments(m64, 0)
#define check_m128_arguments check_vector_arguments(m128, 0)
#define check_m256_arguments check_vector_arguments(m256, 0)
#endif /* INCLUDED_ARGS_H */
.file "snapshot.S"
.text
.p2align 4,,15
.globl snapshot
.type snapshot, @function
snapshot:
.LFB3:
movq %rax, rax(%rip)
movq %rbx, rbx(%rip)
movq %rcx, rcx(%rip)
movq %rdx, rdx(%rip)
movq %rdi, rdi(%rip)
movq %rsi, rsi(%rip)
movq %rbp, rbp(%rip)
movq %rsp, rsp(%rip)
movq %r8, r8(%rip)
movq %r9, r9(%rip)
movq %r10, r10(%rip)
movq %r11, r11(%rip)
movq %r12, r12(%rip)
movq %r13, r13(%rip)
movq %r14, r14(%rip)
movq %r15, r15(%rip)
vmovdqu %ymm0, ymm_regs+0(%rip)
vmovdqu %ymm1, ymm_regs+32(%rip)
vmovdqu %ymm2, ymm_regs+32*2(%rip)
vmovdqu %ymm3, ymm_regs+32*3(%rip)
vmovdqu %ymm4, ymm_regs+32*4(%rip)
vmovdqu %ymm5, ymm_regs+32*5(%rip)
vmovdqu %ymm6, ymm_regs+32*6(%rip)
vmovdqu %ymm7, ymm_regs+32*7(%rip)
vmovdqu %ymm8, ymm_regs+32*8(%rip)
vmovdqu %ymm9, ymm_regs+32*9(%rip)
vmovdqu %ymm10, ymm_regs+32*10(%rip)
vmovdqu %ymm11, ymm_regs+32*11(%rip)
vmovdqu %ymm12, ymm_regs+32*12(%rip)
vmovdqu %ymm13, ymm_regs+32*13(%rip)
vmovdqu %ymm14, ymm_regs+32*14(%rip)
vmovdqu %ymm15, ymm_regs+32*15(%rip)
jmp *callthis(%rip)
.LFE3:
.size snapshot, .-snapshot
.p2align 4,,15
.globl snapshot_ret
.type snapshot_ret, @function
snapshot_ret:
movq %rdi, rdi(%rip)
call *callthis(%rip)
movq %rax, rax(%rip)
movq %rdx, rdx(%rip)
vmovdqu %ymm0, ymm_regs+0(%rip)
vmovdqu %ymm1, ymm_regs+32(%rip)
fstpt x87_regs(%rip)
fstpt x87_regs+16(%rip)
fldt x87_regs+16(%rip)
fldt x87_regs(%rip)
ret
.size snapshot_ret, .-snapshot_ret
.comm callthis,8,8
.comm rax,8,8
.comm rbx,8,8
.comm rcx,8,8
.comm rdx,8,8
.comm rsi,8,8
.comm rdi,8,8
.comm rsp,8,8
.comm rbp,8,8
.comm r8,8,8
.comm r9,8,8
.comm r10,8,8
.comm r11,8,8
.comm r12,8,8
.comm r13,8,8
.comm r14,8,8
.comm r15,8,8
.comm ymm_regs,512,32
.comm x87_regs,128,32
.comm volatile_var,8,8
#include <stdlib.h>
#include "cpuid.h"
static void avx_test (void);
int
main ()
{
unsigned int eax, ebx, ecx, edx;
if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
return 0;
/* Run AVX test only if host has AVX support. */
if (ecx & bit_AVX)
{
avx_test ();
#ifdef DEBUG
printf ("PASSED\n");
#endif
}
#ifdef DEBUG
else
printf ("SKIPPED\n");
#endif
return 0;
}
#include <stdio.h>
#include "avx-check.h"
#include "args.h"
struct IntegerRegisters iregs;
struct FloatRegisters fregs;
unsigned int num_iregs, num_fregs;
__m256
fun_test_returning___m256 (void)
{
volatile_var++;
return (__m256){73,0,0,0,0,0,0,0};
}
__m256 test_256;
static void
avx_test (void)
{
unsigned failed = 0;
YMM_T ymmt1, ymmt2;
clear_struct_registers;
test_256 = (__m256){73,0,0,0,0,0,0,0};
ymmt1._m256[0] = test_256;
ymmt2._m256[0] = WRAP_RET (fun_test_returning___m256)();
if (memcmp (&ymmt1, &ymmt2, sizeof (ymmt2)) != 0)
printf ("fail m256\n"), failed++;
if (failed)
abort ();
}
#include <stdio.h>
#include "avx-check.h"
#include "args.h"
struct IntegerRegisters iregs;
struct FloatRegisters fregs;
unsigned int num_iregs, num_fregs;
/* This struct holds values for argument checking. */
struct
{
YMM_T i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15, i16, i17, i18, i19, i20, i21, i22, i23;
} values;
char *pass;
int failed = 0;
#undef assert
#define assert(c) do { \
if (!(c)) {failed++; printf ("failed %s\n", pass); } \
} while (0)
#define compare(X1,X2,T) do { \
assert (memcmp (&X1, &X2, sizeof (T)) == 0); \
} while (0)
fun_check_passing_m256_8_values (__m256 i0 ATTRIBUTE_UNUSED, __m256 i1 ATTRIBUTE_UNUSED, __m256 i2 ATTRIBUTE_UNUSED, __m256 i3 ATTRIBUTE_UNUSED, __m256 i4 ATTRIBUTE_UNUSED, __m256 i5 ATTRIBUTE_UNUSED, __m256 i6 ATTRIBUTE_UNUSED, __m256 i7 ATTRIBUTE_UNUSED)
{
/* Check argument values. */
compare (values.i0, i0, __m256);
compare (values.i1, i1, __m256);
compare (values.i2, i2, __m256);
compare (values.i3, i3, __m256);
compare (values.i4, i4, __m256);
compare (values.i5, i5, __m256);
compare (values.i6, i6, __m256);
compare (values.i7, i7, __m256);
}
void
fun_check_passing_m256_8_regs (__m256 i0 ATTRIBUTE_UNUSED, __m256 i1 ATTRIBUTE_UNUSED, __m256 i2 ATTRIBUTE_UNUSED, __m256 i3 ATTRIBUTE_UNUSED, __m256 i4 ATTRIBUTE_UNUSED, __m256 i5 ATTRIBUTE_UNUSED, __m256 i6 ATTRIBUTE_UNUSED, __m256 i7 ATTRIBUTE_UNUSED)
{
/* Check register contents. */
check_m256_arguments;
}
void
fun_check_passing_m256_20_values (__m256 i0 ATTRIBUTE_UNUSED, __m256 i1 ATTRIBUTE_UNUSED, __m256 i2 ATTRIBUTE_UNUSED, __m256 i3 ATTRIBUTE_UNUSED, __m256 i4 ATTRIBUTE_UNUSED, __m256 i5 ATTRIBUTE_UNUSED, __m256 i6 ATTRIBUTE_UNUSED, __m256 i7 ATTRIBUTE_UNUSED, __m256 i8 ATTRIBUTE_UNUSED, __m256 i9 ATTRIBUTE_UNUSED, __m256 i10 ATTRIBUTE_UNUSED, __m256 i11 ATTRIBUTE_UNUSED, __m256 i12 ATTRIBUTE_UNUSED, __m256 i13 ATTRIBUTE_UNUSED, __m256 i14 ATTRIBUTE_UNUSED, __m256 i15 ATTRIBUTE_UNUSED, __m256 i16 ATTRIBUTE_UNUSED, __m256 i17 ATTRIBUTE_UNUSED, __m256 i18 ATTRIBUTE_UNUSED, __m256 i19 ATTRIBUTE_UNUSED)
{
/* Check argument values. */
compare (values.i0, i0, __m256);
compare (values.i1, i1, __m256);
compare (values.i2, i2, __m256);
compare (values.i3, i3, __m256);
compare (values.i4, i4, __m256);
compare (values.i5, i5, __m256);
compare (values.i6, i6, __m256);
compare (values.i7, i7, __m256);
compare (values.i8, i8, __m256);
compare (values.i9, i9, __m256);
compare (values.i10, i10, __m256);
compare (values.i11, i11, __m256);
compare (values.i12, i12, __m256);
compare (values.i13, i13, __m256);
compare (values.i14, i14, __m256);
compare (values.i15, i15, __m256);
compare (values.i16, i16, __m256);
compare (values.i17, i17, __m256);
compare (values.i18, i18, __m256);
compare (values.i19, i19, __m256);
}
void
fun_check_passing_m256_20_regs (__m256 i0 ATTRIBUTE_UNUSED, __m256 i1 ATTRIBUTE_UNUSED, __m256 i2 ATTRIBUTE_UNUSED, __m256 i3 ATTRIBUTE_UNUSED, __m256 i4 ATTRIBUTE_UNUSED, __m256 i5 ATTRIBUTE_UNUSED, __m256 i6 ATTRIBUTE_UNUSED, __m256 i7 ATTRIBUTE_UNUSED, __m256 i8 ATTRIBUTE_UNUSED, __m256 i9 ATTRIBUTE_UNUSED, __m256 i10 ATTRIBUTE_UNUSED, __m256 i11 ATTRIBUTE_UNUSED, __m256 i12 ATTRIBUTE_UNUSED, __m256 i13 ATTRIBUTE_UNUSED, __m256 i14 ATTRIBUTE_UNUSED, __m256 i15 ATTRIBUTE_UNUSED, __m256 i16 ATTRIBUTE_UNUSED, __m256 i17 ATTRIBUTE_UNUSED, __m256 i18 ATTRIBUTE_UNUSED, __m256 i19 ATTRIBUTE_UNUSED)
{
/* Check register contents. */
check_m256_arguments;
}
#define def_check_passing8(_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _func1, _func2, TYPE) \
values.i0.TYPE[0] = _i0; \
values.i1.TYPE[0] = _i1; \
values.i2.TYPE[0] = _i2; \
values.i3.TYPE[0] = _i3; \
values.i4.TYPE[0] = _i4; \
values.i5.TYPE[0] = _i5; \
values.i6.TYPE[0] = _i6; \
values.i7.TYPE[0] = _i7; \
WRAP_CALL(_func1) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7); \
\
clear_struct_registers; \
fregs.F0.TYPE[0] = _i0; \
fregs.F1.TYPE[0] = _i1; \
fregs.F2.TYPE[0] = _i2; \
fregs.F3.TYPE[0] = _i3; \
fregs.F4.TYPE[0] = _i4; \
fregs.F5.TYPE[0] = _i5; \
fregs.F6.TYPE[0] = _i6; \
fregs.F7.TYPE[0] = _i7; \
num_fregs = 8; \
WRAP_CALL(_func2) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7);
#define def_check_passing20(_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9, _i10, _i11, _i12, _i13, _i14, _i15, _i16, _i17, _i18, _i19, _func1, _func2, TYPE) \
values.i0.TYPE[0] = _i0; \
values.i1.TYPE[0] = _i1; \
values.i2.TYPE[0] = _i2; \
values.i3.TYPE[0] = _i3; \
values.i4.TYPE[0] = _i4; \
values.i5.TYPE[0] = _i5; \
values.i6.TYPE[0] = _i6; \
values.i7.TYPE[0] = _i7; \
values.i8.TYPE[0] = _i8; \
values.i9.TYPE[0] = _i9; \
values.i10.TYPE[0] = _i10; \
values.i11.TYPE[0] = _i11; \
values.i12.TYPE[0] = _i12; \
values.i13.TYPE[0] = _i13; \
values.i14.TYPE[0] = _i14; \
values.i15.TYPE[0] = _i15; \
values.i16.TYPE[0] = _i16; \
values.i17.TYPE[0] = _i17; \
values.i18.TYPE[0] = _i18; \
values.i19.TYPE[0] = _i19; \
WRAP_CALL(_func1) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9, _i10, _i11, _i12, _i13, _i14, _i15, _i16, _i17, _i18, _i19); \
\
clear_struct_registers; \
fregs.F0.TYPE[0] = _i0; \
fregs.F1.TYPE[0] = _i1; \
fregs.F2.TYPE[0] = _i2; \
fregs.F3.TYPE[0] = _i3; \
fregs.F4.TYPE[0] = _i4; \
fregs.F5.TYPE[0] = _i5; \
fregs.F6.TYPE[0] = _i6; \
fregs.F7.TYPE[0] = _i7; \
num_fregs = 8; \
WRAP_CALL(_func2) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9, _i10, _i11, _i12, _i13, _i14, _i15, _i16, _i17, _i18, _i19);
void
test_m256_on_stack ()
{
__m256 x[8];
int i;
for (i = 0; i < 8; i++)
x[i] = (__m256){32+i, 0, 0, 0, 0, 0, 0, 0};
pass = "m256-8";
def_check_passing8(x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], fun_check_passing_m256_8_values, fun_check_passing_m256_8_regs, _m256);
}
void
test_too_many_m256 ()
{
__m256 x[20];
int i;
for (i = 0; i < 20; i++)
x[i] = (__m256){32+i, 0, 0, 0, 0, 0, 0, 0};
pass = "m256-20";
def_check_passing20(x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9], x[10], x[11], x[12], x[13], x[14], x[15], x[16], x[17], x[18], x[19], fun_check_passing_m256_20_values, fun_check_passing_m256_20_regs, _m256);
}
static void
avx_test (void)
{
test_m256_on_stack ();
test_too_many_m256 ();
if (failed)
abort ();
}
#include "avx-check.h"
#include "args.h"
struct IntegerRegisters iregs;
struct FloatRegisters fregs;
unsigned int num_iregs, num_fregs;
struct m256_struct
{
__m256 x;
};
struct m256_2_struct
{
__m256 x1, x2;
};
/* Check that the struct is passed as the individual members in fregs. */
void
check_struct_passing1 (struct m256_struct ms1 ATTRIBUTE_UNUSED,
struct m256_struct ms2 ATTRIBUTE_UNUSED,
struct m256_struct ms3 ATTRIBUTE_UNUSED,
struct m256_struct ms4 ATTRIBUTE_UNUSED,
struct m256_struct ms5 ATTRIBUTE_UNUSED,
struct m256_struct ms6 ATTRIBUTE_UNUSED,
struct m256_struct ms7 ATTRIBUTE_UNUSED,
struct m256_struct ms8 ATTRIBUTE_UNUSED)
{
check_m256_arguments;
}
void
check_struct_passing2 (struct m256_2_struct ms ATTRIBUTE_UNUSED)
{
/* Check the passing on the stack by comparing the address of the
stack elements to the expected place on the stack. */
assert ((unsigned long)&ms.x1 == rsp+8);
assert ((unsigned long)&ms.x2 == rsp+40);
}
static void
avx_test (void)
{
struct m256_struct m256s [8];
struct m256_2_struct m256_2s = {
{ 48.394, 39.3, -397.9, 3484.9, -8.394, -93.3, 7.9, 84.94 },
{ -8.394, -3.3, -39.9, 34.9, 7.9, 84.94, -48.394, 39.3 }
};
int i;
for (i = 0; i < 8; i++)
m256s[i].x = (__m256){32+i, 0, i, 0, -i, 0, i - 12, i + 8};
clear_struct_registers;
for (i = 0; i < 8; i++)
fregs.ymm0._m256[i] = m256s[i].x;
num_fregs = 8;
WRAP_CALL (check_struct_passing1)(m256s[0], m256s[1], m256s[2], m256s[3],
m256s[4], m256s[5], m256s[6], m256s[7]);
WRAP_CALL (check_struct_passing2)(m256_2s);
}
#include "avx-check.h"
#include "args.h"
struct IntegerRegisters iregs;
struct FloatRegisters fregs;
unsigned int num_iregs, num_fregs;
union un1
{
__m256 x;
float f;
};
union un2
{
__m256 x;
double d;
};
union un3
{
__m256 x;
__m128 v;
};
union un4
{
__m256 x;
long double ld;
};
union un5
{
__m256 x;
int i;
};
void
check_union_passing1(union un1 u1 ATTRIBUTE_UNUSED,
union un1 u2 ATTRIBUTE_UNUSED,
union un1 u3 ATTRIBUTE_UNUSED,
union un1 u4 ATTRIBUTE_UNUSED,
union un1 u5 ATTRIBUTE_UNUSED,
union un1 u6 ATTRIBUTE_UNUSED,
union un1 u7 ATTRIBUTE_UNUSED,
union un1 u8 ATTRIBUTE_UNUSED)
{
check_m256_arguments;
}
void
check_union_passing2(union un2 u1 ATTRIBUTE_UNUSED,
union un2 u2 ATTRIBUTE_UNUSED,
union un2 u3 ATTRIBUTE_UNUSED,
union un2 u4 ATTRIBUTE_UNUSED,
union un2 u5 ATTRIBUTE_UNUSED,
union un2 u6 ATTRIBUTE_UNUSED,
union un2 u7 ATTRIBUTE_UNUSED,
union un2 u8 ATTRIBUTE_UNUSED)
{
check_m256_arguments;
}
void
check_union_passing3(union un3 u1 ATTRIBUTE_UNUSED,
union un3 u2 ATTRIBUTE_UNUSED,
union un3 u3 ATTRIBUTE_UNUSED,
union un3 u4 ATTRIBUTE_UNUSED,
union un3 u5 ATTRIBUTE_UNUSED,
union un3 u6 ATTRIBUTE_UNUSED,
union un3 u7 ATTRIBUTE_UNUSED,
union un3 u8 ATTRIBUTE_UNUSED)
{
check_m256_arguments;
}
void
check_union_passing4(union un4 u ATTRIBUTE_UNUSED)
{
/* Check the passing on the stack by comparing the address of the
stack elements to the expected place on the stack. */
assert ((unsigned long)&u.x == rsp+8);
assert ((unsigned long)&u.ld == rsp+8);
}
void
check_union_passing5(union un5 u ATTRIBUTE_UNUSED)
{
/* Check the passing on the stack by comparing the address of the
stack elements to the expected place on the stack. */
assert ((unsigned long)&u.x == rsp+8);
assert ((unsigned long)&u.i == rsp+8);
}
#define check_union_passing1 WRAP_CALL(check_union_passing1)
#define check_union_passing2 WRAP_CALL(check_union_passing2)
#define check_union_passing3 WRAP_CALL(check_union_passing3)
#define check_union_passing4 WRAP_CALL(check_union_passing4)
#define check_union_passing5 WRAP_CALL(check_union_passing5)
static void
avx_test (void)
{
union un1 u1[8];
union un2 u2[8];
union un3 u3[8];
union un4 u4;
union un5 u5;
int i;
for (i = 0; i < 8; i++)
u1[i].x = (__m256){32+i, 0, i, 0, -i, 0, i - 12, i + 8};
clear_struct_registers;
for (i = 0; i < 8; i++)
fregs.ymm0._m256[i] = u1[i].x;
num_fregs = 8;
check_union_passing1(u1[0], u1[1], u1[2], u1[3],
u1[4], u1[5], u1[6], u1[7]);
clear_struct_registers;
for (i = 0; i < 8; i++)
{
u2[i].x = u1[i].x;
fregs.ymm0._m256[i] = u2[i].x;
}
num_fregs = 8;
check_union_passing2(u2[0], u2[1], u2[2], u2[3],
u2[4], u2[5], u2[6], u2[7]);
clear_struct_registers;
for (i = 0; i < 8; i++)
{
u3[i].x = u1[i].x;
fregs.ymm0._m256[i] = u3[i].x;
}
num_fregs = 8;
check_union_passing3(u3[0], u3[1], u3[2], u3[3],
u3[4], u3[5], u3[6], u3[7]);
check_union_passing4(u4);
check_union_passing5(u5);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment