From 6a47847024dcca2bc071fecd241b5b8bd33c5f7a Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Mon, 6 Jul 2015 16:58:16 +0000 Subject: [PATCH] [ARM] PR/65956 AAPCS update for alignment attribute 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 --- gcc/ChangeLog | 6 +++ gcc/config/arm/arm.c | 19 +++++++- gcc/testsuite/ChangeLog | 13 ++++++ gcc/testsuite/gcc.target/arm/aapcs/align1.c | 29 +++++++++++++ gcc/testsuite/gcc.target/arm/aapcs/align2.c | 30 +++++++++++++ gcc/testsuite/gcc.target/arm/aapcs/align3.c | 42 ++++++++++++++++++ gcc/testsuite/gcc.target/arm/aapcs/align4.c | 29 +++++++++++++ .../gcc.target/arm/aapcs/align_rec1.c | 36 ++++++++++++++++ .../gcc.target/arm/aapcs/align_rec2.c | 41 ++++++++++++++++++ .../gcc.target/arm/aapcs/align_rec3.c | 43 +++++++++++++++++++ .../gcc.target/arm/aapcs/align_rec4.c | 33 ++++++++++++++ .../gcc.target/arm/aapcs/align_vaarg1.c | 36 ++++++++++++++++ .../gcc.target/arm/aapcs/align_vaarg2.c | 30 +++++++++++++ 13 files changed, 385 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.target/arm/aapcs/align1.c create mode 100644 gcc/testsuite/gcc.target/arm/aapcs/align2.c create mode 100644 gcc/testsuite/gcc.target/arm/aapcs/align3.c create mode 100644 gcc/testsuite/gcc.target/arm/aapcs/align4.c create mode 100644 gcc/testsuite/gcc.target/arm/aapcs/align_rec1.c create mode 100644 gcc/testsuite/gcc.target/arm/aapcs/align_rec2.c create mode 100644 gcc/testsuite/gcc.target/arm/aapcs/align_rec3.c create mode 100644 gcc/testsuite/gcc.target/arm/aapcs/align_rec4.c create mode 100644 gcc/testsuite/gcc.target/arm/aapcs/align_vaarg1.c create mode 100644 gcc/testsuite/gcc.target/arm/aapcs/align_vaarg2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b9785156595..fe64509b9af 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2015-07-06 Alan Lawrence + + 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 * config/i386/i386.md (extv): Rename from extv. Use SWI24 diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index c2dce95e611..9d697af5ef8 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -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; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1d26b14cf85..529c8637f90 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,16 @@ +2015-07-06 Alan Lawrence + + * 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 * 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 index 00000000000..8981d57c3ea --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/aapcs/align1.c @@ -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 index 00000000000..992da53c606 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/aapcs/align2.c @@ -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 index 00000000000..81ad3f587a9 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/aapcs/align3.c @@ -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 index 00000000000..5535c55b8ac --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/aapcs/align4.c @@ -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 + +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 index 00000000000..2e42baefb58 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/aapcs/align_rec1.c @@ -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 index 00000000000..a00da508443 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/aapcs/align_rec2.c @@ -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 index 00000000000..2184cb76a6a --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/aapcs/align_rec3.c @@ -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 index 00000000000..907b90af70f --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/aapcs/align_rec4.c @@ -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 + +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 index 00000000000..daa32141599 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/aapcs/align_vaarg1.c @@ -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 + +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 index 00000000000..b0c923b97ed --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/aapcs/align_vaarg2.c @@ -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 + +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; +} -- 2.30.2