[ARM] PR/65956 AAPCS update for alignment attribute
authorAlan Lawrence <alan.lawrence@arm.com>
Mon, 6 Jul 2015 16:58:16 +0000 (16:58 +0000)
committerAlan Lawrence <alalaw01@gcc.gnu.org>
Mon, 6 Jul 2015 16:58:16 +0000 (16:58 +0000)
gcc/:
PR target/65956
* config/arm/arm.c (arm_needs_doubleword_align): Drop any outer
alignment attribute, exploring one level down for records and arrays.

gcc/testsuite/:

* gcc.target/arm/aapcs/align1.c: New.
* gcc.target/arm/aapcs/align_rec1.c: New.
* gcc.target/arm/aapcs/align2.c: New.
* gcc.target/arm/aapcs/align_rec2.c: New.
* gcc.target/arm/aapcs/align3.c: New.
* gcc.target/arm/aapcs/align_rec3.c: New.
* gcc.target/arm/aapcs/align4.c: New.
* gcc.target/arm/aapcs/align_rec4.c: New.
* gcc.target/arm/aapcs/align_vararg1.c: New.
* gcc.target/arm/aapcs/align_vararg2.c: New.

From-SVN: r225465

13 files changed:
gcc/ChangeLog
gcc/config/arm/arm.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/arm/aapcs/align1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/aapcs/align2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/aapcs/align3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/aapcs/align4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/aapcs/align_rec1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/aapcs/align_rec2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/aapcs/align_rec3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/aapcs/align_rec4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/aapcs/align_vaarg1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/aapcs/align_vaarg2.c [new file with mode: 0644]

index b978515..fe64509 100644 (file)
@@ -1,3 +1,9 @@
+2015-07-06  Alan Lawrence  <alan.lawrence@arm.com>
+
+       PR target/65956
+       * config/arm/arm.c (arm_needs_doubleword_align): Drop any outer
+       alignment attribute, exploring one level down for records and arrays.
+
 2015-07-06  Uros Bizjak  <ubizjak@gmail.com>
 
        * config/i386/i386.md (extv<mode>): Rename from extv.  Use SWI24
index c2dce95..9d697af 100644 (file)
@@ -6161,8 +6161,23 @@ arm_init_cumulative_args (CUMULATIVE_ARGS *pcum, tree fntype,
 static bool
 arm_needs_doubleword_align (machine_mode mode, const_tree type)
 {
-  return (GET_MODE_ALIGNMENT (mode) > PARM_BOUNDARY
-         || (type && TYPE_ALIGN (type) > PARM_BOUNDARY));
+  if (!type)
+    return PARM_BOUNDARY < GET_MODE_ALIGNMENT (mode);
+
+  /* Scalar and vector types: Use natural alignment, i.e. of base type.  */
+  if (!AGGREGATE_TYPE_P (type))
+    return TYPE_ALIGN (TYPE_MAIN_VARIANT (type)) > PARM_BOUNDARY;
+
+  /* Array types: Use member alignment of element type.  */
+  if (TREE_CODE (type) == ARRAY_TYPE)
+    return TYPE_ALIGN (TREE_TYPE (type)) > PARM_BOUNDARY;
+
+  /* Record/aggregate types: Use greatest member alignment of any member.  */ 
+  for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
+    if (DECL_ALIGN (field) > PARM_BOUNDARY)
+      return true;
+
+  return false;
 }
 
 
index 1d26b14..529c863 100644 (file)
@@ -1,3 +1,16 @@
+2015-07-06  Alan Lawrence  <alan.lawrence@arm.com>
+
+       * gcc.target/arm/aapcs/align1.c: New.
+       * gcc.target/arm/aapcs/align_rec1.c: New.
+       * gcc.target/arm/aapcs/align2.c: New.
+       * gcc.target/arm/aapcs/align_rec2.c: New.
+       * gcc.target/arm/aapcs/align3.c: New.
+       * gcc.target/arm/aapcs/align_rec3.c: New.
+       * gcc.target/arm/aapcs/align4.c: New.
+       * gcc.target/arm/aapcs/align_rec4.c: New.
+       * gcc.target/arm/aapcs/align_vararg1.c: New.
+       * gcc.target/arm/aapcs/align_vararg2.c: New.
+
 2015-07-06  Steven G. Kargl  <kargl@gcc.gnu.org>
 
        * gfortran.dg/iomsg_2.f90: New test.
diff --git a/gcc/testsuite/gcc.target/arm/aapcs/align1.c b/gcc/testsuite/gcc.target/arm/aapcs/align1.c
new file mode 100644 (file)
index 0000000..8981d57
--- /dev/null
@@ -0,0 +1,29 @@
+/* Test AAPCS layout (alignment).  */
+
+/* { dg-do run { target arm_eabi } } */
+/* { dg-require-effective-target arm32 } */
+/* { dg-options "-O" } */
+
+#ifndef IN_FRAMEWORK
+#define TESTFILE "align1.c"
+
+typedef __attribute__((aligned (8))) int alignedint;
+
+alignedint a = 11;
+alignedint b = 13;
+alignedint c = 17;
+alignedint d = 19;
+alignedint e = 23;
+alignedint f = 29;
+
+#include "abitest.h"
+#else
+  ARG (alignedint, a, R0)
+  /* Attribute suggests R2, but we should use only natural alignment:  */
+  ARG (alignedint, b, R1)
+  ARG (alignedint, c, R2)
+  ARG (alignedint, d, R3)
+  ARG (alignedint, e, STACK)
+  /* Attribute would suggest STACK + 8 but should be ignored:  */
+  LAST_ARG (alignedint, f, STACK + 4)
+#endif
diff --git a/gcc/testsuite/gcc.target/arm/aapcs/align2.c b/gcc/testsuite/gcc.target/arm/aapcs/align2.c
new file mode 100644 (file)
index 0000000..992da53
--- /dev/null
@@ -0,0 +1,30 @@
+/* Test AAPCS layout (alignment).  */
+
+/* { dg-do run { target arm_eabi } } */
+/* { dg-require-effective-target arm32 } */
+/* { dg-options "-O" } */
+
+#ifndef IN_FRAMEWORK
+#define TESTFILE "align2.c"
+
+/* The underlying struct here has alignment 4.  */
+typedef struct __attribute__((aligned (8)))
+  {
+    int x;
+    int y;
+  } overaligned;
+
+/* A couple of instances, at 8-byte-aligned memory locations.  */
+overaligned a = { 2, 3 };
+overaligned b = { 5, 8 };
+
+#include "abitest.h"
+#else
+  ARG (int, 7, R0)
+  /* Alignment should be 4.  */
+  ARG (overaligned, a, R1)
+  ARG (int, 9, R3)
+  ARG (int, 10, STACK)
+  /* Alignment should be 4.  */
+  LAST_ARG (overaligned, b, STACK + 4)
+#endif
diff --git a/gcc/testsuite/gcc.target/arm/aapcs/align3.c b/gcc/testsuite/gcc.target/arm/aapcs/align3.c
new file mode 100644 (file)
index 0000000..81ad3f5
--- /dev/null
@@ -0,0 +1,42 @@
+/* Test AAPCS layout (alignment).  */
+
+/* { dg-do run { target arm_eabi } } */
+/* { dg-require-effective-target arm32 } */
+/* { dg-options "-O3" } */
+
+#ifndef IN_FRAMEWORK
+#define TESTFILE "align3.c"
+
+/* Struct will be aligned to 8.  */
+struct s
+  {
+    int x;
+    /* 4 bytes padding here.  */
+    __attribute__((aligned (8))) int y;
+    /* 4 bytes padding here.  */
+  };
+
+typedef struct s __attribute__((aligned (4))) underaligned;
+
+#define EXPECTED_STRUCT_SIZE 16
+extern void link_failure (void);
+int
+foo ()
+{
+  /* Optimization gets rid of this before linking.  */
+  if (sizeof (struct s) != EXPECTED_STRUCT_SIZE)
+    link_failure ();
+}
+
+underaligned a = { 1, 4 };
+underaligned b = { 9, 16 };
+
+#include "abitest.h"
+#else
+  ARG (int, 3, R0)
+  /* Object alignment is 8, so split between 2 regs and 8 on stack.  */
+  ARG (underaligned, a, R2)
+  ARG (int, 6, STACK + 8)
+  /* Object alignment is 8, so skip over STACK + 12.  */
+  LAST_ARG (underaligned, b, STACK + 16)
+#endif
diff --git a/gcc/testsuite/gcc.target/arm/aapcs/align4.c b/gcc/testsuite/gcc.target/arm/aapcs/align4.c
new file mode 100644 (file)
index 0000000..5535c55
--- /dev/null
@@ -0,0 +1,29 @@
+/* Test AAPCS layout (alignment) - passing vectors in GPRs.  */
+
+/* { dg-do run { target arm_eabi } } */
+/* { dg-require-effective-target arm32 } */
+/* { dg-require-effective-target arm_neon_ok  } */
+/* { dg-options "-O" } */
+/* { dg-add-options arm_neon } */
+
+#ifndef IN_FRAMEWORK
+#define TESTFILE "align4.c"
+
+#define PCSATTR __attribute__((pcs("aapcs")))
+
+#include <arm_neon.h>
+
+typedef __attribute__((aligned (4))) int32x2_t unalignedvec;
+
+unalignedvec a = {11, 13};
+unalignedvec b = {17, 19};
+
+#include "abitest.h"
+#else
+  ARG (int, 2, R0)
+  /* Attribute suggests R1, but we should use natural alignment:  */
+  ARG (unalignedvec, a, R2)
+  ARG (int, 6, STACK)
+  /* Attribute would suggest STACK + 4 but should be ignored:  */
+  LAST_ARG (unalignedvec, b, STACK + 8)
+#endif
diff --git a/gcc/testsuite/gcc.target/arm/aapcs/align_rec1.c b/gcc/testsuite/gcc.target/arm/aapcs/align_rec1.c
new file mode 100644 (file)
index 0000000..2e42bae
--- /dev/null
@@ -0,0 +1,36 @@
+/* Test AAPCS layout (alignment) for callee.  */
+
+/* { dg-do run { target arm_eabi } } */
+/* { dg-require-effective-target arm32 } */
+/* { dg-options "-O2 -fno-inline" } */
+
+extern void abort (void);
+
+typedef __attribute__((aligned (8))) int alignedint;
+
+alignedint a = 11;
+alignedint b = 13;
+alignedint c = 17;
+alignedint d = 19;
+alignedint e = 23;
+alignedint f = 29;
+
+void
+foo (alignedint r0, alignedint r1, alignedint r2, alignedint r3,
+     alignedint stack, alignedint stack4)
+{
+  if (r0 != a
+      || r1 != b
+      || r2 != c
+      || r3 != d
+      || stack != e
+      || stack4 !=f)
+    abort ();
+}
+
+int
+main (int argc, char **argv)
+{
+  foo (a, b, c, d, e, f);
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/arm/aapcs/align_rec2.c b/gcc/testsuite/gcc.target/arm/aapcs/align_rec2.c
new file mode 100644 (file)
index 0000000..a00da50
--- /dev/null
@@ -0,0 +1,41 @@
+/* Test AAPCS layout (alignment) for callee.  */
+
+/* { dg-do run { target arm_eabi } } */
+/* { dg-require-effective-target arm32 } */
+/* { dg-options "-O2 -fno-inline" } */
+
+extern int memcmp (const void *s1, const void *s2, __SIZE_TYPE__ n);
+extern void abort (void);
+
+typedef struct __attribute__((aligned (8)))
+  {
+    int x;
+    int y;
+  } overaligned;
+
+overaligned a = { 2, 3 };
+overaligned b = { 5, 8 };
+
+void
+f (int r0, overaligned r1, int r3, int stack, overaligned stack4)
+{
+  if (r0 != 7 || r3 != 9 || stack != 10)
+    abort ();
+  if (memcmp ((void *) &r1, (void *)&a, sizeof (overaligned)))
+    abort ();
+  if (memcmp ((void *)&stack4, (void *)&b, sizeof (overaligned)))
+    abort ();
+  int addr = ((int) &stack4) & 7;
+  if (addr != 0)
+    {
+      __builtin_printf ("Alignment was %d\n", addr);
+      abort ();
+    }
+}
+
+int
+main (int argc, char **argv)
+{
+  f (7, a, 9, 10, b);
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/arm/aapcs/align_rec3.c b/gcc/testsuite/gcc.target/arm/aapcs/align_rec3.c
new file mode 100644 (file)
index 0000000..2184cb7
--- /dev/null
@@ -0,0 +1,43 @@
+/* Test AAPCS layout (alignment) for callee.  */
+
+/* { dg-do run { target arm_eabi } } */
+/* { dg-require-effective-target arm32 } */
+/* { dg-options "-O2 -fno-inline" } */
+
+/* Test AAPCS layout (alignment) for callee.  */
+
+extern int memcmp (const void *s1, const void *s2, __SIZE_TYPE__ n);
+extern void abort (void);
+
+
+/* Struct will be aligned to 8.  */
+struct s
+  {
+    int x;
+    /* 4 bytes padding here.  */
+    __attribute__((aligned (8))) int y;
+    /* 4 bytes padding here.  */
+  };
+
+typedef struct s __attribute__((aligned (4))) underaligned;
+
+underaligned a = { 1, 4 };
+underaligned b = { 9, 16 };
+
+void
+f (int r0, underaligned r2, int stack8, underaligned stack16)
+{
+  if (r0 != 3 || stack8 != 6)
+    abort ();
+  if (memcmp ((void *) &r2, (void *)&a, sizeof (underaligned)))
+    abort ();
+  if (memcmp ((void *)&stack16, (void *)&b, sizeof (underaligned)))
+    abort ();
+}
+
+int
+main (int argc, char **argv)
+{
+  f (3, a, 6, b);
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/arm/aapcs/align_rec4.c b/gcc/testsuite/gcc.target/arm/aapcs/align_rec4.c
new file mode 100644 (file)
index 0000000..907b90a
--- /dev/null
@@ -0,0 +1,33 @@
+/* Test AAPCS layout (alignment) for callee.  */
+
+/* { dg-do run { target arm_eabi } } */
+/* { dg-require-effective-target arm32 } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-O -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include <arm_neon.h>
+
+extern int memcmp (const void *s1, const void *s2, __SIZE_TYPE__ n);
+extern void abort (void);
+
+typedef __attribute__((aligned (4))) int32x4_t unalignedvec;
+
+unalignedvec a = {11, 13};
+unalignedvec b = {17, 19};
+
+void
+foo (int r0, unalignedvec r2, int s0, unalignedvec s8)
+{
+  if (r0 != 2 || s0 != 6
+      || memcmp ( (void *) &r2, (void *) &a, 16)
+      || memcmp ( (void *) &s8, (void *) &b, 16))
+    abort ();
+}
+
+int
+main (int argc, char **argv)
+{
+  foo (2, a, 6, b);
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/arm/aapcs/align_vaarg1.c b/gcc/testsuite/gcc.target/arm/aapcs/align_vaarg1.c
new file mode 100644 (file)
index 0000000..daa3214
--- /dev/null
@@ -0,0 +1,36 @@
+/* Test AAPCS layout (alignment of varargs) for callee.  */
+
+/* { dg-do run { target arm_eabi } } */
+/* { dg-require-effective-target arm32 } */
+/* { dg-options "-O2 -fno-inline" } */
+
+#include <stdarg.h>
+
+extern void abort (void);
+
+typedef __attribute__((aligned (8))) int alignedint;
+
+void
+foo (int i, ...)
+{
+  va_list va;
+  va_start (va, i);
+  /* Arguments should be passed in the same registers as if they were ints.  */
+  while (i-- > 0)
+    if (va_arg (va, int) != i)
+      abort ();
+  va_end (va);
+}
+
+int
+main (int argc, char **argv)
+{
+  alignedint a = 5;
+  alignedint b = 4;
+  alignedint c = 3;
+  alignedint d = 2;
+  alignedint e = 1;
+  alignedint f = 0;
+  foo (a, b, c, d, e, f);
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/arm/aapcs/align_vaarg2.c b/gcc/testsuite/gcc.target/arm/aapcs/align_vaarg2.c
new file mode 100644 (file)
index 0000000..b0c923b
--- /dev/null
@@ -0,0 +1,30 @@
+/* Test AAPCS layout (alignment of varargs) for callee.  */
+
+/* { dg-do run { target arm_eabi } } */
+/* { dg-require-effective-target arm32 } */
+/* { dg-options "-O2 -fno-inline" } */
+
+#include <stdarg.h>
+
+extern void abort (void);
+
+typedef __attribute__((aligned (8))) int alignedint;
+
+void
+foo (int i, ...)
+{
+  va_list va;
+  va_start (va, i);
+  /* alignedint should be pulled out of regs/stack just like an int.  */
+  while (i-- > 0)
+    if (va_arg (va, alignedint) != i)
+      abort ();
+  va_end (va);
+}
+
+int
+main (int argc, char **argv)
+{
+  foo (5, 4, 3, 2, 1, 0);
+  return 0;
+}