Commit 45901378 by Andreas Krebbel Committed by Andreas Krebbel

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
parent 5a5c3deb
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> 2015-06-23 Chen Gang <gang.chen.5i5j@gmail.com>
PR target/65803 PR target/65803
......
...@@ -452,6 +452,97 @@ struct GTY(()) machine_function ...@@ -452,6 +452,97 @@ struct GTY(()) machine_function
#define PREDICT_DISTANCE (TARGET_Z10 ? 384 : 2048) #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. */ /* System z builtins. */
#include "s390-builtins.h" #include "s390-builtins.h"
...@@ -10889,6 +10980,8 @@ s390_function_arg (cumulative_args_t cum_v, machine_mode mode, ...@@ -10889,6 +10980,8 @@ s390_function_arg (cumulative_args_t cum_v, machine_mode mode,
{ {
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); 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)) if (s390_function_arg_vector (mode, type))
{ {
...@@ -11280,6 +11373,8 @@ s390_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p, ...@@ -11280,6 +11373,8 @@ s390_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
size = int_size_in_bytes (type); 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 (pass_by_reference (NULL, TYPE_MODE (type), type, false))
{ {
if (TARGET_DEBUG_ARG) if (TARGET_DEBUG_ARG)
...@@ -13642,6 +13737,29 @@ s390_vector_alignment (const_tree type) ...@@ -13642,6 +13737,29 @@ s390_vector_alignment (const_tree type)
return MIN (64, tree_to_shwi (TYPE_SIZE (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. */ /* Return true if TYPE is a vector bool type. */
static inline bool static inline bool
...@@ -13918,6 +14036,9 @@ s390_invalid_binary_op (int op ATTRIBUTE_UNUSED, const_tree type1, const_tree ty ...@@ -13918,6 +14036,9 @@ s390_invalid_binary_op (int op ATTRIBUTE_UNUSED, const_tree type1, const_tree ty
#undef TARGET_INVALID_BINARY_OP #undef TARGET_INVALID_BINARY_OP
#define TARGET_INVALID_BINARY_OP s390_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; struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-s390.h" #include "gt-s390.h"
...@@ -26708,6 +26708,42 @@ fi ...@@ -26708,6 +26708,42 @@ fi
as_fn_error "Requesting --with-nan= requires assembler support for -mnan=" "$LINENO" 5 as_fn_error "Requesting --with-nan= requires assembler support for -mnan=" "$LINENO" 5
fi 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 esac
# Mips and HP-UX need the GNU assembler. # Mips and HP-UX need the GNU assembler.
......
...@@ -4442,6 +4442,13 @@ pointers into PC-relative form.]) ...@@ -4442,6 +4442,13 @@ pointers into PC-relative form.])
[Requesting --with-nan= requires assembler support for -mnan=]) [Requesting --with-nan= requires assembler support for -mnan=])
fi 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 esac
# Mips and HP-UX need the GNU assembler. # Mips and HP-UX need the GNU assembler.
......
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> 2015-06-23 Chen Gang <gang.chen.5i5j@gmail.com>
PR target/65803 PR target/65803
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
/* Make sure the last argument is fetched from the argument overflow area. */ /* 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\]*,160\\(%r15\\)" { target lp64 } } } */
/* { dg-final { scan-assembler "vl\t%v\[0-9\]*,96\\(%r15\\)" { target ilp32 } } } */ /* { 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))); typedef double v2df __attribute__((vector_size(16)));
......
/* 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;
}
/* 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;
}
/* 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;
}
/* 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);
}
/* 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);
}
/* 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;
}
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