From 9bfaf89d4f07272d60824efcbcbdb2d7f1dd4d6e Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 11 Mar 2009 22:12:33 +0100 Subject: [PATCH] re PR target/39137 (-mpreferred-stack-boundary=2 causes lots of dynamic realign) PR target/39137 * cfgexpand.c (get_decl_align_unit): Use LOCAL_DECL_ALIGNMENT macro. * defaults.h (LOCAL_DECL_ALIGNMENT): Define if not yet defined. * config/i386/i386.h (LOCAL_DECL_ALIGNMENT): Define. * config/i386/i386.c (ix86_local_alignment): For -m32 -mpreferred-stack-boundary=2 use 32-bit alignment for long long variables on the stack to avoid dynamic realignment. Allow the first argument to be a decl rather than type. * doc/tm.texi (LOCAL_DECL_ALIGNMENT): Document. * gcc.target/i386/stackalign/longlong-1.c: New test. * gcc.target/i386/stackalign/longlong-2.c: New test. From-SVN: r144792 --- gcc/ChangeLog | 13 +++++++ gcc/cfgexpand.c | 3 +- gcc/config/i386/i386.c | 34 ++++++++++++++++--- gcc/config/i386/i386.h | 13 +++++++ gcc/defaults.h | 5 +++ gcc/doc/tm.texi | 12 +++++++ gcc/testsuite/ChangeLog | 6 ++++ .../gcc.target/i386/stackalign/longlong-1.c | 15 ++++++++ .../gcc.target/i386/stackalign/longlong-2.c | 33 ++++++++++++++++++ 9 files changed, 127 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/stackalign/longlong-1.c create mode 100644 gcc/testsuite/gcc.target/i386/stackalign/longlong-2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 838bd3407bf..c4cccf25b44 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2009-03-11 Jakub Jelinek + + PR target/39137 + * cfgexpand.c (get_decl_align_unit): Use LOCAL_DECL_ALIGNMENT + macro. + * defaults.h (LOCAL_DECL_ALIGNMENT): Define if not yet defined. + * config/i386/i386.h (LOCAL_DECL_ALIGNMENT): Define. + * config/i386/i386.c (ix86_local_alignment): For + -m32 -mpreferred-stack-boundary=2 use 32-bit alignment for + long long variables on the stack to avoid dynamic realignment. + Allow the first argument to be a decl rather than type. + * doc/tm.texi (LOCAL_DECL_ALIGNMENT): Document. + 2009-03-11 Nick Clifton PR target/5362 diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index c73bba7d9a9..4bfdc5fed74 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -488,8 +488,7 @@ get_decl_align_unit (tree decl) { unsigned int align; - align = DECL_ALIGN (decl); - align = LOCAL_ALIGNMENT (TREE_TYPE (decl), align); + align = LOCAL_DECL_ALIGNMENT (decl); if (align > MAX_SUPPORTED_STACK_ALIGNMENT) align = MAX_SUPPORTED_STACK_ALIGNMENT; diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index e7dd5bebaec..9a34912c313 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -19347,15 +19347,39 @@ ix86_data_alignment (tree type, int align) return align; } -/* Compute the alignment for a local variable or a stack slot. TYPE is - the data type, MODE is the widest mode available and ALIGN is the - alignment that the object would ordinarily have. The value of this - macro is used instead of that alignment to align the object. */ +/* Compute the alignment for a local variable or a stack slot. EXP is + the data type or decl itself, MODE is the widest mode available and + ALIGN is the alignment that the object would ordinarily have. The + value of this macro is used instead of that alignment to align the + object. */ unsigned int -ix86_local_alignment (tree type, enum machine_mode mode, +ix86_local_alignment (tree exp, enum machine_mode mode, unsigned int align) { + tree type, decl; + + if (exp && DECL_P (exp)) + { + type = TREE_TYPE (exp); + decl = exp; + } + else + { + type = exp; + decl = NULL; + } + + /* Don't do dynamic stack realignment for long long objects with + -mpreferred-stack-boundary=2. */ + if (!TARGET_64BIT + && align == 64 + && ix86_preferred_stack_boundary < 64 + && (mode == DImode || (type && TYPE_MODE (type) == DImode)) + && (!type || !TYPE_USER_ALIGN (type)) + && (!decl || !DECL_USER_ALIGN (decl))) + align = 32; + /* If TYPE is NULL, we are allocating a stack slot for caller-save register in MODE. We will return the largest alignment of XF and DF. */ diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index f2f4448d15e..8035e84a2f8 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -791,6 +791,19 @@ enum target_cpu_default #define STACK_SLOT_ALIGNMENT(TYPE, MODE, ALIGN) \ ix86_local_alignment ((TYPE), (MODE), (ALIGN)) +/* If defined, a C expression to compute the alignment for a local + variable DECL. + + If this macro is not defined, then + LOCAL_ALIGNMENT (TREE_TYPE (DECL), DECL_ALIGN (DECL)) will be used. + + One use of this macro is to increase alignment of medium-size + data to make it all fit in fewer cache lines. */ + +#define LOCAL_DECL_ALIGNMENT(DECL) \ + ix86_local_alignment ((DECL), VOIDmode, DECL_ALIGN (DECL)) + + /* If defined, a C expression that gives the alignment boundary, in bits, of an argument with the specified mode and type. If it is not defined, `PARM_BOUNDARY' is used for all arguments. */ diff --git a/gcc/defaults.h b/gcc/defaults.h index fbb13accc08..217c0d94a56 100644 --- a/gcc/defaults.h +++ b/gcc/defaults.h @@ -944,6 +944,11 @@ along with GCC; see the file COPYING3. If not see ((TYPE) ? LOCAL_ALIGNMENT ((TYPE), (ALIGN)) : (ALIGN)) #endif +#ifndef LOCAL_DECL_ALIGNMENT +#define LOCAL_DECL_ALIGNMENT(DECL) \ + LOCAL_ALIGNMENT (TREE_TYPE (DECL), DECL_ALIGN (DECL)) +#endif + /* Alignment value for attribute ((aligned)). */ #ifndef ATTRIBUTE_ALIGNED_VALUE #define ATTRIBUTE_ALIGNED_VALUE BIGGEST_ALIGNMENT diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index b4fcc2de94d..f4680b69391 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -1215,6 +1215,18 @@ This macro is to set alignment of stack slot to the maximum alignment of all possible modes which the slot may have. @end defmac +@defmac LOCAL_DECL_ALIGNMENT (@var{decl}) +If defined, a C expression to compute the alignment for a local +variable @var{decl}. + +If this macro is not defined, then +@code{LOCAL_ALIGNMENT (TREE_TYPE (@var{decl}), DECL_ALIGN (@var{decl}))} +is used. + +One use of this macro is to increase alignment of medium-size data to +make it all fit in fewer cache lines. +@end defmac + @defmac EMPTY_FIELD_BOUNDARY Alignment in bits to be given to a structure bit-field that follows an empty field such as @code{int : 0;}. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index af958c33701..f8a7b2dc8c3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2009-03-11 Jakub Jelinek + + PR target/39137 + * gcc.target/i386/stackalign/longlong-1.c: New test. + * gcc.target/i386/stackalign/longlong-2.c: New test. + 2009-03-11 Ulrich Weigand * g++.old-deja/g++.jason/thunk2.C: Skip on SPU. diff --git a/gcc/testsuite/gcc.target/i386/stackalign/longlong-1.c b/gcc/testsuite/gcc.target/i386/stackalign/longlong-1.c new file mode 100644 index 00000000000..225d0c5e558 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/stackalign/longlong-1.c @@ -0,0 +1,15 @@ +/* PR target/39137 */ +/* { dg-do compile } */ +/* { dg-require-effective-target ilp32 } */ +/* { dg-options "-O2 -mpreferred-stack-boundary=2" } */ +/* Make sure dynamic stack realignment isn't performed just because there + are long long variables. */ +/* { dg-final { scan-assembler-not "and\[lq\]?\[^\\n\]*-8,\[^\\n\]*sp" } } */ + +void fn (void *); + +void f1 (void) +{ + unsigned long long a; + fn (&a); +} diff --git a/gcc/testsuite/gcc.target/i386/stackalign/longlong-2.c b/gcc/testsuite/gcc.target/i386/stackalign/longlong-2.c new file mode 100644 index 00000000000..027d2ad836a --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/stackalign/longlong-2.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target ilp32 } */ +/* { dg-options "-O2 -mpreferred-stack-boundary=2" } */ +/* { dg-final { scan-assembler-times "and\[lq\]?\[^\\n\]*-8,\[^\\n\]*sp" 2 } } */ +/* { dg-final { scan-assembler-times "and\[lq\]?\[^\\n\]*-16,\[^\\n\]*sp" 2 } } */ + +void fn (void *); + +void f2 (void) +{ + unsigned long long a __attribute__((aligned (8))); + fn (&a); +} + +void f3 (void) +{ + typedef unsigned long long L __attribute__((aligned (8))); + L a; + fn (&a); +} + +void f4 (void) +{ + unsigned long long a __attribute__((aligned (16))); + fn (&a); +} + +void f5 (void) +{ + typedef unsigned long long L __attribute__((aligned (16))); + L a; + fn (&a); +} -- 2.30.2