aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/c/c-decl.c7
-rw-r--r--gcc/config/i386/i386-protos.h2
-rw-r--r--gcc/config/i386/i386.c18
-rw-r--r--gcc/cp/decl.c7
-rw-r--r--gcc/doc/tm.texi5
-rw-r--r--gcc/doc/tm.texi.in2
-rw-r--r--gcc/target.def7
-rw-r--r--gcc/testsuite/c-c++-common/pr95237-1.c16
-rw-r--r--gcc/testsuite/c-c++-common/pr95237-2.c10
-rw-r--r--gcc/testsuite/c-c++-common/pr95237-3.c10
-rw-r--r--gcc/testsuite/c-c++-common/pr95237-4.c10
-rw-r--r--gcc/testsuite/c-c++-common/pr95237-5.c16
-rw-r--r--gcc/testsuite/c-c++-common/pr95237-6.c24
-rw-r--r--gcc/testsuite/c-c++-common/pr95237-7.c19
-rw-r--r--gcc/testsuite/c-c++-common/pr95237-8.c10
-rw-r--r--gcc/testsuite/c-c++-common/pr95237-9.c10
16 files changed, 170 insertions, 3 deletions
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 81bd2ee..5d6b504 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -5600,6 +5600,13 @@ finish_decl (tree decl, location_t init_loc, tree init,
NULL_TREE, DECL_ATTRIBUTES (decl));
}
+ /* This is the last point we can lower alignment so give the target the
+ chance to do so. */
+ if (VAR_P (decl)
+ && !is_global_var (decl)
+ && !DECL_HARD_REGISTER (decl))
+ targetm.lower_local_decl_alignment (decl);
+
invoke_plugin_callbacks (PLUGIN_FINISH_DECL, decl);
}
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 7c2ce61..0b95c57 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -223,7 +223,7 @@ extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int);
#ifdef TREE_CODE
extern int ix86_data_alignment (tree, unsigned int, bool);
extern unsigned int ix86_local_alignment (tree, machine_mode,
- unsigned int);
+ unsigned int, bool = false);
extern unsigned int ix86_minimum_alignment (tree, machine_mode,
unsigned int);
extern tree ix86_handle_shared_attribute (tree *, tree, tree, int, bool *);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 31757b0..8ea6a4d 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -16633,6 +16633,16 @@ ix86_data_alignment (tree type, unsigned int align, bool opt)
return align;
}
+/* Implememnt TARGET_LOWER_LOCAL_DECL_ALIGNMENT. */
+static void
+ix86_lower_local_decl_alignment (tree decl)
+{
+ unsigned int new_align = ix86_local_alignment (decl, VOIDmode,
+ DECL_ALIGN (decl), true);
+ if (new_align < DECL_ALIGN (decl))
+ SET_DECL_ALIGN (decl, new_align);
+}
+
/* 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
@@ -16641,7 +16651,7 @@ ix86_data_alignment (tree type, unsigned int align, bool opt)
unsigned int
ix86_local_alignment (tree exp, machine_mode mode,
- unsigned int align)
+ unsigned int align, bool may_lower)
{
tree type, decl;
@@ -16658,7 +16668,8 @@ ix86_local_alignment (tree exp, machine_mode mode,
/* Don't do dynamic stack realignment for long long objects with
-mpreferred-stack-boundary=2. */
- if (!TARGET_64BIT
+ if (may_lower
+ && !TARGET_64BIT
&& align == 64
&& ix86_preferred_stack_boundary < 64
&& (mode == DImode || (type && TYPE_MODE (type) == DImode))
@@ -23386,6 +23397,9 @@ ix86_run_selftests (void)
#undef TARGET_CAN_CHANGE_MODE_CLASS
#define TARGET_CAN_CHANGE_MODE_CLASS ix86_can_change_mode_class
+#undef TARGET_LOWER_LOCAL_DECL_ALIGNMENT
+#define TARGET_LOWER_LOCAL_DECL_ALIGNMENT ix86_lower_local_decl_alignment
+
#undef TARGET_STATIC_RTX_ALIGNMENT
#define TARGET_STATIC_RTX_ALIGNMENT ix86_static_rtx_alignment
#undef TARGET_CONSTANT_ALIGNMENT
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index db91b50..7d71745 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -8012,6 +8012,13 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
NULL_TREE, DECL_ATTRIBUTES (decl));
}
+ /* This is the last point we can lower alignment so give the target the
+ chance to do so. */
+ if (VAR_P (decl)
+ && !is_global_var (decl)
+ && !DECL_HARD_REGISTER (decl))
+ targetm.lower_local_decl_alignment (decl);
+
invoke_plugin_callbacks (PLUGIN_FINISH_DECL, decl);
}
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 41b9e10..4371876 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -1086,6 +1086,11 @@ On 32-bit ELF the largest supported section alignment in bits is
@samp{(0x80000000 * 8)}, but this is not representable on 32-bit hosts.
@end defmac
+@deftypefn {Target Hook} void TARGET_LOWER_LOCAL_DECL_ALIGNMENT (tree @var{decl})
+Define this hook to lower alignment of local, parm or result
+decl @samp{(@var{decl})}.
+@end deftypefn
+
@deftypefn {Target Hook} HOST_WIDE_INT TARGET_STATIC_RTX_ALIGNMENT (machine_mode @var{mode})
This hook returns the preferred alignment in bits for a
statically-allocated rtx, such as a constant pool entry. @var{mode}
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 3be984b..d76c85d 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -1036,6 +1036,8 @@ On 32-bit ELF the largest supported section alignment in bits is
@samp{(0x80000000 * 8)}, but this is not representable on 32-bit hosts.
@end defmac
+@hook TARGET_LOWER_LOCAL_DECL_ALIGNMENT
+
@hook TARGET_STATIC_RTX_ALIGNMENT
@defmac DATA_ALIGNMENT (@var{type}, @var{basic-align})
diff --git a/gcc/target.def b/gcc/target.def
index f2f314e..c11cab8 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -3351,6 +3351,13 @@ HOOK_VECTOR_END (addr_space)
#define HOOK_PREFIX "TARGET_"
DEFHOOK
+(lower_local_decl_alignment,
+ "Define this hook to lower alignment of local, parm or result\n\
+decl @samp{(@var{decl})}.",
+ void, (tree decl),
+ hook_void_tree)
+
+DEFHOOK
(static_rtx_alignment,
"This hook returns the preferred alignment in bits for a\n\
statically-allocated rtx, such as a constant pool entry. @var{mode}\n\
diff --git a/gcc/testsuite/c-c++-common/pr95237-1.c b/gcc/testsuite/c-c++-common/pr95237-1.c
new file mode 100644
index 0000000..8947a9f
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr95237-1.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-require-effective-target ia32 } */
+/* { dg-options "-mpreferred-stack-boundary=2" { target { i?86-*-* x86_64-*-* } } } */
+typedef __UINTPTR_TYPE__ uintptr_t;
+void __attribute__((noipa)) foo (long long *p, uintptr_t a)
+{
+ if ((uintptr_t)p & (a-1))
+ __builtin_abort ();
+}
+int main()
+{
+ long long x;
+ uintptr_t a = __alignof__(x);
+ foo(&x, a);
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/pr95237-2.c b/gcc/testsuite/c-c++-common/pr95237-2.c
new file mode 100644
index 0000000..87949a9
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr95237-2.c
@@ -0,0 +1,10 @@
+/* { dg-do run } */
+/* { dg-require-effective-target ia32 } */
+/* { dg-options "-mpreferred-stack-boundary=2" { target { i?86-*-* x86_64-*-* } } } */
+long long x;
+int main()
+{
+ if (__alignof__(x) != 8)
+ __builtin_abort();
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/pr95237-3.c b/gcc/testsuite/c-c++-common/pr95237-3.c
new file mode 100644
index 0000000..6941b6f
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr95237-3.c
@@ -0,0 +1,10 @@
+/* { dg-do run } */
+/* { dg-require-effective-target ia32 } */
+/* { dg-options "-mpreferred-stack-boundary=2" { target { i?86-*-* x86_64-*-* } } } */
+int main()
+{
+ long long x;
+ if (__alignof__(x) != 4)
+ __builtin_abort();
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/pr95237-4.c b/gcc/testsuite/c-c++-common/pr95237-4.c
new file mode 100644
index 0000000..deace53
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr95237-4.c
@@ -0,0 +1,10 @@
+/* { dg-do run } */
+/* { dg-require-effective-target ia32 } */
+/* { dg-options "-mpreferred-stack-boundary=4" { target { i?86-*-* x86_64-*-* } } } */
+int main()
+{
+ long long x;
+ if (__alignof__(x) != 8)
+ __builtin_abort();
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/pr95237-5.c b/gcc/testsuite/c-c++-common/pr95237-5.c
new file mode 100644
index 0000000..9dc5cfc
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr95237-5.c
@@ -0,0 +1,16 @@
+/* { dg-do compile { target ia32 } } */
+/* { dg-options "-mpreferred-stack-boundary=2 -Os -w" { target { i?86-*-* x86_64-*-* } } } */
+
+int a;
+
+long long __attribute__((noinline))
+b (void)
+{
+}
+
+void
+c (void)
+{
+ if (b())
+ a = 1;
+}
diff --git a/gcc/testsuite/c-c++-common/pr95237-6.c b/gcc/testsuite/c-c++-common/pr95237-6.c
new file mode 100644
index 0000000..ce1568f
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr95237-6.c
@@ -0,0 +1,24 @@
+/* { dg-do run } */
+/* { dg-options "-O2" { target { i?86-*-* x86_64-*-* } } } */
+#include <stddef.h>
+#ifdef __x86_64__
+# define EXP_ALIGN 8
+#else
+# define EXP_ALIGN 4
+#endif
+
+struct test
+{
+ char a;
+ long long b;
+};
+struct test global_var;
+int main()
+{
+ struct test local_var;
+ if (__alignof__(global_var) != EXP_ALIGN
+ || __alignof__(local_var) != EXP_ALIGN
+ || offsetof(struct test, b) != EXP_ALIGN)
+ __builtin_abort();
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/pr95237-7.c b/gcc/testsuite/c-c++-common/pr95237-7.c
new file mode 100644
index 0000000..8410009
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr95237-7.c
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+/* { dg-require-effective-target ia32 } */
+/* { dg-options "-mpreferred-stack-boundary=2" { target { i?86-*-* x86_64-*-* } } } */
+#include <stddef.h>
+struct test
+{
+ char a;
+ long long b;
+};
+struct test global_var;
+int main()
+{
+ struct test local_var;
+ if (__alignof__(global_var) != 4
+ || __alignof__(local_var) != 4
+ || offsetof(struct test, b) != 4)
+ __builtin_abort();
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/pr95237-8.c b/gcc/testsuite/c-c++-common/pr95237-8.c
new file mode 100644
index 0000000..8ba98ab
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr95237-8.c
@@ -0,0 +1,10 @@
+/* { dg-do run } */
+/* { dg-require-effective-target ia32 } */
+/* { dg-options "-mpreferred-stack-boundary=2" { target { i?86-*-* x86_64-*-* } } } */
+int main()
+{
+ extern long long x;
+ if (__alignof__(x) != 8)
+ __builtin_abort();
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/pr95237-9.c b/gcc/testsuite/c-c++-common/pr95237-9.c
new file mode 100644
index 0000000..687517c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr95237-9.c
@@ -0,0 +1,10 @@
+/* { dg-do run } */
+/* { dg-require-effective-target ia32 } */
+/* { dg-options "-mpreferred-stack-boundary=2" { target { i?86-*-* x86_64-*-* } } } */
+int main()
+{
+ static long long x;
+ if (__alignof__(x) != 8)
+ __builtin_abort();
+ return 0;
+}