S/390 Vector ABI GNU Attribute.
authorAndreas Krebbel <krebbel@linux.vnet.ibm.com>
Wed, 24 Jun 2015 06:36:46 +0000 (06:36 +0000)
committerAndreas Krebbel <krebbel@gcc.gnu.org>
Wed, 24 Jun 2015 06:36:46 +0000 (06:36 +0000)
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

12 files changed:
gcc/ChangeLog
gcc/config/s390/s390.c
gcc/configure
gcc/configure.ac
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/s390/vector/vec-abi-1.c
gcc/testsuite/gcc.target/s390/vector/vec-abi-attr-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/vector/vec-abi-attr-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/vector/vec-abi-attr-3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/vector/vec-abi-attr-4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/vector/vec-abi-attr-5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/vector/vec-abi-attr-6.c [new file with mode: 0644]

index cbd8d88eae5b1fa9ed6b758c4d6ecb514bddaf30..57ab9e8e29c6dae7c8d0e4188bd0143cb0c004ac 100644 (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
index 9807e64376c9f54565c184b028e6c578b00f4426..4408d4c9be0ae539314d29c19d68b0c7c0e558dd 100644 (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"
index b26a86f4802dd775868795a274775c5b65067f9a..3f3f5785d577682591ba04320d4119cd7ae74ec3 100755 (executable)
       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.
index c09f3ae5454a497e6b262dea280709311fe6f409..85f72d50dbfed0c342800f672b4210dd66bc9fe4 100644 (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.
index 5fe00e16862a29ef8596be4e0732fc598fc72591..d1431575ae8cb5e48f7a4da574f6be5e5782bc9a 100644 (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
index 5484664b122b3fe5d89e895430459134341113da..db18e5ec57b319a1179fdc64320a1ceefa1f80af 100644 (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)));
 
diff --git a/gcc/testsuite/gcc.target/s390/vector/vec-abi-attr-1.c b/gcc/testsuite/gcc.target/s390/vector/vec-abi-attr-1.c
new file mode 100644 (file)
index 0000000..a06b338
--- /dev/null
@@ -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;
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/vec-abi-attr-2.c b/gcc/testsuite/gcc.target/s390/vector/vec-abi-attr-2.c
new file mode 100644 (file)
index 0000000..97b9748
--- /dev/null
@@ -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;
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/vec-abi-attr-3.c b/gcc/testsuite/gcc.target/s390/vector/vec-abi-attr-3.c
new file mode 100644 (file)
index 0000000..f3dc368
--- /dev/null
@@ -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;
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/vec-abi-attr-4.c b/gcc/testsuite/gcc.target/s390/vector/vec-abi-attr-4.c
new file mode 100644 (file)
index 0000000..ad9b29a
--- /dev/null
@@ -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);
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/vec-abi-attr-5.c b/gcc/testsuite/gcc.target/s390/vector/vec-abi-attr-5.c
new file mode 100644 (file)
index 0000000..fb5de4e
--- /dev/null
@@ -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);
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/vec-abi-attr-6.c b/gcc/testsuite/gcc.target/s390/vector/vec-abi-attr-6.c
new file mode 100644 (file)
index 0000000..9134fa7
--- /dev/null
@@ -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;
+}