aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/cfgexpand.c3
-rw-r--r--gcc/config/i386/i386.c34
-rw-r--r--gcc/config/i386/i386.h13
-rw-r--r--gcc/defaults.h5
-rw-r--r--gcc/doc/tm.texi12
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.target/i386/stackalign/longlong-1.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/stackalign/longlong-2.c33
9 files changed, 127 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 838bd34..c4cccf2 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,16 @@
+2009-03-11 Jakub Jelinek <jakub@redhat.com>
+
+ 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 <nickc@redhat.com>
PR target/5362
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index c73bba7..4bfdc5f 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 e7dd5be..9a34912 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 f2f4448..8035e84 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 fbb13ac..217c0d9 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 b4fcc2d..f4680b6 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 af958c3..f8a7b2d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2009-03-11 Jakub Jelinek <jakub@redhat.com>
+
+ 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 <Ulrich.Weigand@de.ibm.com>
* 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 0000000..225d0c5
--- /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 0000000..027d2ad
--- /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);
+}