S/390 Vector ABI GNU Attribute.

gcc/
	* config/s390/s390.c (s390_vector_abi): New variable definition.
	(s390_check_type_for_vector_abi): New function.
	(TARGET_ASM_FILE_END): New macro definition.
	(s390_asm_file_end): New function.
	(s390_function_arg): Call s390_check_type_for_vector_abi.
	(s390_gimplify_va_arg): Likewise.
	* configure: Regenerate.
	* configure.ac: Check for .gnu_attribute Binutils feature.

gcc/testsuite/
	* gcc.target/s390/vector/vec-abi-1.c: Add gnu attribute check.
	* gcc.target/s390/vector/vec-abi-attr-1.c: New test.
	* gcc.target/s390/vector/vec-abi-attr-2.c: New test.
	* gcc.target/s390/vector/vec-abi-attr-3.c: New test.
	* gcc.target/s390/vector/vec-abi-attr-4.c: New test.
	* gcc.target/s390/vector/vec-abi-attr-5.c: New test.
	* gcc.target/s390/vector/vec-abi-attr-6.c: New test.

From-SVN: r224867
This commit is contained in:
Andreas Krebbel 2015-06-24 06:36:46 +00:00 committed by Andreas Krebbel
parent 5a5c3debfe
commit 45901378cd
12 changed files with 335 additions and 0 deletions

View File

@ -1,3 +1,14 @@
2015-06-24 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
* config/s390/s390.c (s390_vector_abi): New variable definition.
(s390_check_type_for_vector_abi): New function.
(TARGET_ASM_FILE_END): New macro definition.
(s390_asm_file_end): New function.
(s390_function_arg): Call s390_check_type_for_vector_abi.
(s390_gimplify_va_arg): Likewise.
* configure: Regenerate.
* configure.ac: Check for .gnu_attribute Binutils feature.
2015-06-23 Chen Gang <gang.chen.5i5j@gmail.com>
PR target/65803

View File

@ -452,6 +452,97 @@ struct GTY(()) machine_function
#define PREDICT_DISTANCE (TARGET_Z10 ? 384 : 2048)
/* Indicate which ABI has been used for passing vector args.
0 - no vector type arguments have been passed where the ABI is relevant
1 - the old ABI has been used
2 - a vector type argument has been passed either in a vector register
or on the stack by value */
static int s390_vector_abi = 0;
/* Set the vector ABI marker if TYPE is subject to the vector ABI
switch. The vector ABI affects only vector data types. There are
two aspects of the vector ABI relevant here:
1. vectors >= 16 bytes have an alignment of 8 bytes with the new
ABI and natural alignment with the old.
2. vector <= 16 bytes are passed in VRs or by value on the stack
with the new ABI but by reference on the stack with the old.
If ARG_P is true TYPE is used for a function argument or return
value. The ABI marker then is set for all vector data types. If
ARG_P is false only type 1 vectors are being checked. */
static void
s390_check_type_for_vector_abi (const_tree type, bool arg_p, bool in_struct_p)
{
static hash_set<const_tree> visited_types_hash;
if (s390_vector_abi)
return;
if (type == NULL_TREE || TREE_CODE (type) == ERROR_MARK)
return;
if (visited_types_hash.contains (type))
return;
visited_types_hash.add (type);
if (VECTOR_TYPE_P (type))
{
int type_size = int_size_in_bytes (type);
/* Outside arguments only the alignment is changing and this
only happens for vector types >= 16 bytes. */
if (!arg_p && type_size < 16)
return;
/* In arguments vector types > 16 are passed as before (GCC
never enforced the bigger alignment for arguments which was
required by the old vector ABI). However, it might still be
ABI relevant due to the changed alignment if it is a struct
member. */
if (arg_p && type_size > 16 && !in_struct_p)
return;
s390_vector_abi = TARGET_VX_ABI ? 2 : 1;
}
else if (POINTER_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE)
{
/* ARRAY_TYPE: Since with neither of the ABIs we have more than
natural alignment there will never be ABI dependent padding
in an array type. That's why we do not set in_struct_p to
true here. */
s390_check_type_for_vector_abi (TREE_TYPE (type), arg_p, in_struct_p);
}
else if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
{
tree arg_chain;
/* Check the return type. */
s390_check_type_for_vector_abi (TREE_TYPE (type), true, false);
for (arg_chain = TYPE_ARG_TYPES (type);
arg_chain;
arg_chain = TREE_CHAIN (arg_chain))
s390_check_type_for_vector_abi (TREE_VALUE (arg_chain), true, false);
}
else if (RECORD_OR_UNION_TYPE_P (type))
{
tree field;
for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
{
if (TREE_CODE (field) != FIELD_DECL)
continue;
s390_check_type_for_vector_abi (TREE_TYPE (field), arg_p, true);
}
}
}
/* System z builtins. */
#include "s390-builtins.h"
@ -10889,6 +10980,8 @@ s390_function_arg (cumulative_args_t cum_v, machine_mode mode,
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
if (!named)
s390_check_type_for_vector_abi (type, true, false);
if (s390_function_arg_vector (mode, type))
{
@ -11280,6 +11373,8 @@ s390_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
size = int_size_in_bytes (type);
s390_check_type_for_vector_abi (type, true, false);
if (pass_by_reference (NULL, TYPE_MODE (type), type, false))
{
if (TARGET_DEBUG_ARG)
@ -13642,6 +13737,29 @@ s390_vector_alignment (const_tree type)
return MIN (64, tree_to_shwi (TYPE_SIZE (type)));
}
/* Implement TARGET_ASM_FILE_END. */
static void
s390_asm_file_end (void)
{
#ifdef HAVE_AS_GNU_ATTRIBUTE
varpool_node *vnode;
cgraph_node *cnode;
FOR_EACH_VARIABLE (vnode)
if (TREE_PUBLIC (vnode->decl))
s390_check_type_for_vector_abi (TREE_TYPE (vnode->decl), false, false);
FOR_EACH_FUNCTION (cnode)
if (TREE_PUBLIC (cnode->decl))
s390_check_type_for_vector_abi (TREE_TYPE (cnode->decl), false, false);
if (s390_vector_abi != 0)
fprintf (asm_out_file, "\t.gnu_attribute 8, %d\n",
s390_vector_abi);
#endif
file_end_indicate_exec_stack ();
}
/* Return true if TYPE is a vector bool type. */
static inline bool
@ -13918,6 +14036,9 @@ s390_invalid_binary_op (int op ATTRIBUTE_UNUSED, const_tree type1, const_tree ty
#undef TARGET_INVALID_BINARY_OP
#define TARGET_INVALID_BINARY_OP s390_invalid_binary_op
#undef TARGET_ASM_FILE_END
#define TARGET_ASM_FILE_END s390_asm_file_end
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-s390.h"

36
gcc/configure vendored
View File

@ -26708,6 +26708,42 @@ fi
as_fn_error "Requesting --with-nan= requires assembler support for -mnan=" "$LINENO" 5
fi
;;
s390*-*-*)
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .gnu_attribute support" >&5
$as_echo_n "checking assembler for .gnu_attribute support... " >&6; }
if test "${gcc_cv_as_s390_gnu_attribute+set}" = set; then :
$as_echo_n "(cached) " >&6
else
gcc_cv_as_s390_gnu_attribute=no
if test $in_tree_gas = yes; then
if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 18 \) \* 1000 + 0`
then gcc_cv_as_s390_gnu_attribute=yes
fi
elif test x$gcc_cv_as != x; then
$as_echo '.gnu_attribute 8,1' > conftest.s
if { ac_try='$gcc_cv_as $gcc_cv_as_flags -o conftest.o conftest.s >&5'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
(eval $ac_try) 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }
then
gcc_cv_as_s390_gnu_attribute=yes
else
echo "configure: failed program was" >&5
cat conftest.s >&5
fi
rm -f conftest.o conftest.s
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_s390_gnu_attribute" >&5
$as_echo "$gcc_cv_as_s390_gnu_attribute" >&6; }
if test $gcc_cv_as_s390_gnu_attribute = yes; then
$as_echo "#define HAVE_AS_GNU_ATTRIBUTE 1" >>confdefs.h
fi
;;
esac
# Mips and HP-UX need the GNU assembler.

View File

@ -4442,6 +4442,13 @@ pointers into PC-relative form.])
[Requesting --with-nan= requires assembler support for -mnan=])
fi
;;
s390*-*-*)
gcc_GAS_CHECK_FEATURE([.gnu_attribute support],
gcc_cv_as_s390_gnu_attribute, [2,18,0],,
[.gnu_attribute 8,1],,
[AC_DEFINE(HAVE_AS_GNU_ATTRIBUTE, 1,
[Define if your assembler supports .gnu_attribute.])])
;;
esac
# Mips and HP-UX need the GNU assembler.

View File

@ -1,3 +1,13 @@
2015-06-24 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
* gcc.target/s390/vector/vec-abi-1.c: Add gnu attribute check.
* gcc.target/s390/vector/vec-abi-attr-1.c: New test.
* gcc.target/s390/vector/vec-abi-attr-2.c: New test.
* gcc.target/s390/vector/vec-abi-attr-3.c: New test.
* gcc.target/s390/vector/vec-abi-attr-4.c: New test.
* gcc.target/s390/vector/vec-abi-attr-5.c: New test.
* gcc.target/s390/vector/vec-abi-attr-6.c: New test.
2015-06-23 Chen Gang <gang.chen.5i5j@gmail.com>
PR target/65803

View File

@ -6,6 +6,7 @@
/* Make sure the last argument is fetched from the argument overflow area. */
/* { dg-final { scan-assembler "vl\t%v\[0-9\]*,160\\(%r15\\)" { target lp64 } } } */
/* { dg-final { scan-assembler "vl\t%v\[0-9\]*,96\\(%r15\\)" { target ilp32 } } } */
/* { dg-final { scan-assembler "gnu_attribute 8, 2" } } */
typedef double v2df __attribute__((vector_size(16)));

View File

@ -0,0 +1,18 @@
/* Check calling convention in the vector ABI. */
/* { dg-do compile { target { s390*-*-* } } } */
/* { dg-options "-O3 -mzarch -march=z13 -mno-vx" } */
/* The function passes arguments whose calling conventions change with
-mvx/-mno-vx. In that case GCC has to emit the ABI attribute to
allow GDB and Binutils to detect this. */
/* { dg-final { scan-assembler "gnu_attribute 8, 1" } } */
typedef double v2df __attribute__((vector_size(16)));
v2df
add (v2df a, v2df b, v2df c, v2df d,
v2df e, v2df f, v2df g, v2df h, v2df i)
{
return a + b + c + d + e + f + g + h + i;
}

View File

@ -0,0 +1,53 @@
/* Check calling convention in the vector ABI. */
/* { dg-do compile { target { s390*-*-* } } } */
/* { dg-options "-O3 -mzarch -march=z13" } */
/* No abi attribute should be emitted when nothing relevant happened. */
/* { dg-final { scan-assembler-not "gnu_attribute" } } */
#include <stdarg.h>
/* Local use is ok. */
typedef int v4si __attribute__((vector_size(16)));
static
v4si __attribute__((__noinline__))
foo (v4si a)
{
return a + (v4si){ 1, 2, 3, 4 };
}
int
bar (int a)
{
return foo ((v4si){ 1, 1, 1, 1 })[1];
}
/* Big vector type only used as function argument and return value
without being a struct/union member. The alignment change is not
relevant here. */
typedef double v4df __attribute__((vector_size(32)));
v4df
add (v4df a, v4df b, v4df c, v4df d,
v4df e, v4df f, v4df g, v4df h, v4df i)
{
return a + b + c + d + e + f + g + h + i;
}
double
bar2 (int n, ...)
{
double ret;
v4df a;
va_list va;
va_start (va, n);
ret = va_arg (va, v4df)[2];
va_end (va);
return ret;
}

View File

@ -0,0 +1,18 @@
/* Check calling convention in the vector ABI. */
/* { dg-do compile { target { s390*-*-* } } } */
/* { dg-options "-O3 -mzarch -march=z13" } */
/* { dg-final { scan-assembler "gnu_attribute 8, 2" } } */
typedef double v4df __attribute__((vector_size(32)));
typedef struct { v4df a; } s;
s
add (v4df a, v4df b, v4df c, v4df d,
v4df e, v4df f, v4df g, v4df h, v4df i)
{
s t;
t.a = a + b + c + d + e + f + g + h + i;
return t;
}

View File

@ -0,0 +1,17 @@
/* Check calling convention in the vector ABI. */
/* { dg-do compile { target { s390*-*-* } } } */
/* { dg-options "-O3 -mzarch -march=z13" } */
/* { dg-final { scan-assembler "gnu_attribute 8, 2" } } */
typedef int __attribute__((vector_size(16))) v4si;
extern void bar (v4si);
void
foo (int a)
{
v4si b = (v4si){ a, a, a, a };
bar (b);
}

View File

@ -0,0 +1,19 @@
/* Check calling convention in the vector ABI. */
/* { dg-do compile { target { s390*-*-* } } } */
/* { dg-options "-O3 -mzarch -march=z13" } */
/* { dg-final { scan-assembler "gnu_attribute 8, 2" } } */
#include <stdarg.h>
typedef int __attribute__((vector_size(16))) v4si;
extern void bar (int, ...);
void
foo (int a)
{
v4si b = (v4si){ a, a, a, a };
bar (1, b);
}

View File

@ -0,0 +1,24 @@
/* Check calling convention in the vector ABI. */
/* { dg-do compile { target { s390*-*-* } } } */
/* { dg-options "-O3 -mzarch -march=z13" } */
/* { dg-final { scan-assembler "gnu_attribute 8, 2" } } */
#include <stdarg.h>
typedef int __attribute__((vector_size(16))) v4si;
int
bar (int n, ...)
{
int ret;
v4si a;
va_list va;
va_start (va, n);
ret = va_arg (va, v4si)[2];
va_end (va);
return ret;
}