From 20ecd6e4494d2d224ae3032444c945aadb757765 Mon Sep 17 00:00:00 2001 From: Sunil K Pandey Date: Fri, 17 Jul 2020 19:42:09 -0700 Subject: [PATCH] Add TARGET_LOWER_LOCAL_DECL_ALIGNMENT [PR95237] Default for this hook is NOP. For x86, in 32 bit mode, this hook sets alignment of long long on stack to 32 bits if preferred stack boundary is 32 bits. - This patch fixes gcc.target/i386/pr69454-2.c gcc.target/i386/stackalign/longlong-1.c - Regression test on x86-64, no new fail introduced. Tested on x86-64. gcc/c/ChangeLog: PR target/95237 * c-decl.c (finish_decl): Call target hook lower_local_decl_alignment to lower local decl alignment. gcc/ChangeLog: PR target/95237 * config/i386/i386-protos.h (ix86_local_alignment): Add another function parameter. * config/i386/i386.c (ix86_lower_local_decl_alignment): New function. (ix86_local_alignment): Amend ix86_local_alignment to accept another parameter may_lower. If may_lower is true, new align may be lower than incoming alignment. If may_lower is false, new align will be greater or equal to incoming alignment. (TARGET_LOWER_LOCAL_DECL_ALIGNMENT): Define. * config/i386/i386.h (LOCAL_ALIGNMENT): Add another function parameter. (STACK_SLOT_ALIGNMENT): Add another function parameter. (LOCAL_DECL_ALIGNMENT): Add another function parameter. * doc/tm.texi: Regenerate. * doc/tm.texi.in (TARGET_LOWER_LOCAL_DECL_ALIGNMENT): New hook. * target.def (lower_local_decl_alignment): New hook. gcc/cp/ChangeLog: PR target/95237 * decl.c (cp_finish_decl): Call target hook lower_local_decl_alignment to lower local decl alignment. gcc/testsuite/ChangeLog: PR target/95237 * c-c++-common/pr95237-1.c: New test. * c-c++-common/pr95237-2.c: New test. * c-c++-common/pr95237-3.c: New test. * c-c++-common/pr95237-4.c: New test. * c-c++-common/pr95237-5.c: New test. * c-c++-common/pr95237-6.c: New test. * c-c++-common/pr95237-7.c: New test. * c-c++-common/pr95237-8.c: New test. * c-c++-common/pr95237-9.c: New test. --- gcc/c/c-decl.c | 7 +++++++ gcc/config/i386/i386-protos.h | 2 +- gcc/config/i386/i386.c | 19 +++++++++++++++++-- gcc/config/i386/i386.h | 6 +++--- gcc/cp/decl.c | 7 +++++++ gcc/doc/tm.texi | 5 +++++ gcc/doc/tm.texi.in | 2 ++ gcc/target.def | 7 +++++++ gcc/testsuite/c-c++-common/pr95237-1.c | 16 ++++++++++++++++ gcc/testsuite/c-c++-common/pr95237-2.c | 10 ++++++++++ gcc/testsuite/c-c++-common/pr95237-3.c | 10 ++++++++++ gcc/testsuite/c-c++-common/pr95237-4.c | 10 ++++++++++ gcc/testsuite/c-c++-common/pr95237-5.c | 16 ++++++++++++++++ gcc/testsuite/c-c++-common/pr95237-6.c | 24 ++++++++++++++++++++++++ gcc/testsuite/c-c++-common/pr95237-7.c | 19 +++++++++++++++++++ gcc/testsuite/c-c++-common/pr95237-8.c | 10 ++++++++++ gcc/testsuite/c-c++-common/pr95237-9.c | 10 ++++++++++ 17 files changed, 174 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/pr95237-1.c create mode 100644 gcc/testsuite/c-c++-common/pr95237-2.c create mode 100644 gcc/testsuite/c-c++-common/pr95237-3.c create mode 100644 gcc/testsuite/c-c++-common/pr95237-4.c create mode 100644 gcc/testsuite/c-c++-common/pr95237-5.c create mode 100644 gcc/testsuite/c-c++-common/pr95237-6.c create mode 100644 gcc/testsuite/c-c++-common/pr95237-7.c create mode 100644 gcc/testsuite/c-c++-common/pr95237-8.c create mode 100644 gcc/testsuite/c-c++-common/pr95237-9.c diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index 81bd2ee94f0..4ee9e02d35d 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)); } + /* Lower local decl alignment. */ + + 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 7c2ce618f3f..034276ebb99 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); 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 5c373c091ce..6a8f575404e 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -16768,6 +16768,17 @@ 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) +{ + /* Lower decl alignment. */ + 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 @@ -16776,7 +16787,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; @@ -16793,7 +16804,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)) @@ -23521,6 +23533,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/config/i386/i386.h b/gcc/config/i386/i386.h index f4a8f1391fa..23cb6fbf1c6 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -994,7 +994,7 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); data to make it all fit in fewer cache lines. */ #define LOCAL_ALIGNMENT(TYPE, ALIGN) \ - ix86_local_alignment ((TYPE), VOIDmode, (ALIGN)) + ix86_local_alignment ((TYPE), VOIDmode, (ALIGN), true) /* If defined, a C expression to compute the alignment for stack slot. TYPE is the data type, MODE is the widest mode available, and ALIGN @@ -1008,7 +1008,7 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); maximum alignment of all possible modes which the slot may have. */ #define STACK_SLOT_ALIGNMENT(TYPE, MODE, ALIGN) \ - ix86_local_alignment ((TYPE), (MODE), (ALIGN)) + ix86_local_alignment ((TYPE), (MODE), (ALIGN), true) /* If defined, a C expression to compute the alignment for a local variable DECL. @@ -1020,7 +1020,7 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); data to make it all fit in fewer cache lines. */ #define LOCAL_DECL_ALIGNMENT(DECL) \ - ix86_local_alignment ((DECL), VOIDmode, DECL_ALIGN (DECL)) + ix86_local_alignment ((DECL), VOIDmode, DECL_ALIGN (DECL), true) /* If defined, a C expression to compute the minimum required alignment for dynamic stack realignment purposes for EXP (a TYPE or DECL), diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 6e4d546d55e..67aa7b7602e 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)); } + /* Lower local decl alignment. */ + + 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 6e7d9dc54a9..1058221842d 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 3be984bbd5c..d76c85d5800 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 07059a87caf..e122d3c32c2 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -3348,6 +3348,13 @@ HOOK_VECTOR_END (addr_space) #undef HOOK_PREFIX #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\ 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 00000000000..8947a9fed26 --- /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 00000000000..87949a9e122 --- /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 00000000000..6941b6f154b --- /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 00000000000..deace53cc26 --- /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 00000000000..9dc5cfcd739 --- /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 00000000000..ce1568fa282 --- /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 +#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 00000000000..8410009d00e --- /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 +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 00000000000..8ba98abafc9 --- /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 00000000000..687517cbc0a --- /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; +} -- 2.25.4