diff options
author | Jakub Jelinek <jakub@redhat.com> | 2013-06-10 17:41:52 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2013-06-10 17:41:52 +0200 |
commit | df8a1d28a50fe32dc87f989ba0a72f00227a38ec (patch) | |
tree | 7f5e2fcbb34a0e22a4e842599006ba571e4aad8d /gcc | |
parent | 57b29ca675a87d5dd79371925f19f945990a2bea (diff) | |
download | gcc-df8a1d28a50fe32dc87f989ba0a72f00227a38ec.zip gcc-df8a1d28a50fe32dc87f989ba0a72f00227a38ec.tar.gz gcc-df8a1d28a50fe32dc87f989ba0a72f00227a38ec.tar.bz2 |
re PR target/56564 (movdqa on possibly-8-byte-aligned struct with -O3)
PR target/56564
* varasm.c (align_variable): Don't use DATA_ALIGNMENT or
CONSTANT_ALIGNMENT if !decl_binds_to_current_def_p (decl).
Use DATA_ABI_ALIGNMENT for that case instead if defined.
(get_variable_align): New function.
(get_variable_section, emit_bss, emit_common,
assemble_variable_contents, place_block_symbol): Use
get_variable_align instead of DECL_ALIGN.
(assemble_noswitch_variable): Add align argument, use it
instead of DECL_ALIGN.
(assemble_variable): Adjust caller. Use get_variable_align
instead of DECL_ALIGN.
* config/i386/i386.h (DATA_ALIGNMENT): Adjust x86_data_alignment
caller.
(DATA_ABI_ALIGNMENT): Define.
* config/i386/i386-protos.h (x86_data_alignment): Adjust prototype.
* config/i386/i386.c (x86_data_alignment): Add opt argument. If
opt is false, only return the psABI mandated alignment increase.
* config/c6x/c6x.h (DATA_ALIGNMENT): Renamed to...
(DATA_ABI_ALIGNMENT): ... this.
* config/mmix/mmix.h (DATA_ALIGNMENT): Renamed to...
(DATA_ABI_ALIGNMENT): ... this.
* config/mmix/mmix.c (mmix_data_alignment): Adjust function comment.
* config/s390/s390.h (DATA_ALIGNMENT): Renamed to...
(DATA_ABI_ALIGNMENT): ... this.
* doc/tm.texi.in (DATA_ABI_ALIGNMENT): Document.
* doc/tm.texi: Regenerated.
* gcc.target/i386/pr56564-1.c: New test.
* gcc.target/i386/pr56564-2.c: New test.
* gcc.target/i386/pr56564-3.c: New test.
* gcc.target/i386/pr56564-4.c: New test.
* gcc.target/i386/avx256-unaligned-load-4.c: Add -fno-common.
* gcc.target/i386/avx256-unaligned-store-1.c: Likewise.
* gcc.target/i386/avx256-unaligned-store-3.c: Likewise.
* gcc.target/i386/avx256-unaligned-store-4.c: Likewise.
* gcc.target/i386/vect-sizes-1.c: Likewise.
* gcc.target/i386/memcpy-1.c: Likewise.
* gcc.dg/vect/costmodel/i386/costmodel-vect-31.c (tmp): Initialize.
* gcc.dg/vect/costmodel/x86_64/costmodel-vect-31.c (tmp): Likewise.
From-SVN: r199898
Diffstat (limited to 'gcc')
24 files changed, 289 insertions, 38 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0176137..cf75717 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,33 @@ +2013-06-10 Jakub Jelinek <jakub@redhat.com> + + PR target/56564 + * varasm.c (align_variable): Don't use DATA_ALIGNMENT or + CONSTANT_ALIGNMENT if !decl_binds_to_current_def_p (decl). + Use DATA_ABI_ALIGNMENT for that case instead if defined. + (get_variable_align): New function. + (get_variable_section, emit_bss, emit_common, + assemble_variable_contents, place_block_symbol): Use + get_variable_align instead of DECL_ALIGN. + (assemble_noswitch_variable): Add align argument, use it + instead of DECL_ALIGN. + (assemble_variable): Adjust caller. Use get_variable_align + instead of DECL_ALIGN. + * config/i386/i386.h (DATA_ALIGNMENT): Adjust x86_data_alignment + caller. + (DATA_ABI_ALIGNMENT): Define. + * config/i386/i386-protos.h (x86_data_alignment): Adjust prototype. + * config/i386/i386.c (x86_data_alignment): Add opt argument. If + opt is false, only return the psABI mandated alignment increase. + * config/c6x/c6x.h (DATA_ALIGNMENT): Renamed to... + (DATA_ABI_ALIGNMENT): ... this. + * config/mmix/mmix.h (DATA_ALIGNMENT): Renamed to... + (DATA_ABI_ALIGNMENT): ... this. + * config/mmix/mmix.c (mmix_data_alignment): Adjust function comment. + * config/s390/s390.h (DATA_ALIGNMENT): Renamed to... + (DATA_ABI_ALIGNMENT): ... this. + * doc/tm.texi.in (DATA_ABI_ALIGNMENT): Document. + * doc/tm.texi: Regenerated. + 2013-06-10 Uros Bizjak <ubizjak@gmail.com> * config/alpha/alpha.c (alpha_emit_xfloating_compare): Also use diff --git a/gcc/config/c6x/c6x.h b/gcc/config/c6x/c6x.h index ce331cb..c30a971 100644 --- a/gcc/config/c6x/c6x.h +++ b/gcc/config/c6x/c6x.h @@ -134,7 +134,7 @@ extern c6x_cpu_t c6x_arch; Really only externally visible arrays must be aligned this way, as only those are directly visible from another compilation unit. But we don't have that information available here. */ -#define DATA_ALIGNMENT(TYPE, ALIGN) \ +#define DATA_ABI_ALIGNMENT(TYPE, ALIGN) \ (((ALIGN) < BITS_PER_UNIT * 8 && TREE_CODE (TYPE) == ARRAY_TYPE) \ ? BITS_PER_UNIT * 8 : (ALIGN)) diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index ef4dc76..f228e87 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -207,7 +207,7 @@ extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int); #endif /* RTX_CODE */ #ifdef TREE_CODE -extern int ix86_data_alignment (tree, int); +extern int ix86_data_alignment (tree, int, bool); extern unsigned int ix86_local_alignment (tree, enum machine_mode, unsigned int); extern unsigned int ix86_minimum_alignment (tree, enum machine_mode, diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 5f6a5d5..45e8899 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -25375,11 +25375,12 @@ ix86_constant_alignment (tree exp, int align) instead of that alignment to align the object. */ int -ix86_data_alignment (tree type, int align) +ix86_data_alignment (tree type, int align, bool opt) { int max_align = optimize_size ? BITS_PER_WORD : MIN (256, MAX_OFILE_ALIGNMENT); - if (AGGREGATE_TYPE_P (type) + if (opt + && AGGREGATE_TYPE_P (type) && TYPE_SIZE (type) && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST && (TREE_INT_CST_LOW (TYPE_SIZE (type)) >= (unsigned) max_align @@ -25391,14 +25392,17 @@ ix86_data_alignment (tree type, int align) to 16byte boundary. */ if (TARGET_64BIT) { - if (AGGREGATE_TYPE_P (type) - && TYPE_SIZE (type) - && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST - && (TREE_INT_CST_LOW (TYPE_SIZE (type)) >= 128 - || TREE_INT_CST_HIGH (TYPE_SIZE (type))) && align < 128) + if ((opt ? AGGREGATE_TYPE_P (type) : TREE_CODE (type) == ARRAY_TYPE) + && TYPE_SIZE (type) + && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST + && (TREE_INT_CST_LOW (TYPE_SIZE (type)) >= 128 + || TREE_INT_CST_HIGH (TYPE_SIZE (type))) && align < 128) return 128; } + if (!opt) + return align; + if (TREE_CODE (type) == ARRAY_TYPE) { if (TYPE_MODE (TREE_TYPE (type)) == DFmode && align < 64) diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 5dcd69f..7d940f9 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -859,7 +859,18 @@ enum target_cpu_default cause character arrays to be word-aligned so that `strcpy' calls that copy constants to character arrays can be done inline. */ -#define DATA_ALIGNMENT(TYPE, ALIGN) ix86_data_alignment ((TYPE), (ALIGN)) +#define DATA_ALIGNMENT(TYPE, ALIGN) \ + ix86_data_alignment ((TYPE), (ALIGN), true) + +/* Similar to DATA_ALIGNMENT, but for the cases where the ABI mandates + some alignment increase, instead of optimization only purposes. E.g. + AMD x86-64 psABI says that variables with array type larger than 15 bytes + must be aligned to 16 byte boundaries. + + If this macro is not defined, then ALIGN is used. */ + +#define DATA_ABI_ALIGNMENT(TYPE, ALIGN) \ + ix86_data_alignment ((TYPE), (ALIGN), false) /* If defined, a C expression to compute the alignment for a local variable. TYPE is the data type, and ALIGN is the alignment that diff --git a/gcc/config/mmix/mmix.c b/gcc/config/mmix/mmix.c index 1af09e5..bd37067 100644 --- a/gcc/config/mmix/mmix.c +++ b/gcc/config/mmix/mmix.c @@ -313,7 +313,7 @@ mmix_init_machine_status (void) return ggc_alloc_cleared_machine_function (); } -/* DATA_ALIGNMENT. +/* DATA_ABI_ALIGNMENT. We have trouble getting the address of stuff that is located at other than 32-bit alignments (GETA requirements), so try to give everything at least 32-bit alignment. */ diff --git a/gcc/config/mmix/mmix.h b/gcc/config/mmix/mmix.h index 4ca1a2b..c5edc57 100644 --- a/gcc/config/mmix/mmix.h +++ b/gcc/config/mmix/mmix.h @@ -164,7 +164,7 @@ struct GTY(()) machine_function /* Copied from elfos.h. */ #define MAX_OFILE_ALIGNMENT (32768 * 8) -#define DATA_ALIGNMENT(TYPE, BASIC_ALIGN) \ +#define DATA_ABI_ALIGNMENT(TYPE, BASIC_ALIGN) \ mmix_data_alignment (TYPE, BASIC_ALIGN) #define CONSTANT_ALIGNMENT(CONSTANT, BASIC_ALIGN) \ diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h index 43e24d5..b0e530f 100644 --- a/gcc/config/s390/s390.h +++ b/gcc/config/s390/s390.h @@ -221,7 +221,7 @@ enum processor_flags /* Alignment on even addresses for LARL instruction. */ #define CONSTANT_ALIGNMENT(EXP, ALIGN) (ALIGN) < 16 ? 16 : (ALIGN) -#define DATA_ALIGNMENT(TYPE, ALIGN) (ALIGN) < 16 ? 16 : (ALIGN) +#define DATA_ABI_ALIGNMENT(TYPE, ALIGN) (ALIGN) < 16 ? 16 : (ALIGN) /* Alignment is not required by the hardware. */ #define STRICT_ALIGNMENT 0 diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index f840481..f030b56 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -1078,6 +1078,15 @@ arrays to be word-aligned so that @code{strcpy} calls that copy constants to character arrays can be done inline. @end defmac +@defmac DATA_ABI_ALIGNMENT (@var{type}, @var{basic-align}) +Similar to @code{DATA_ALIGNMENT}, but for the cases where the ABI mandates +some alignment increase, instead of optimization only purposes. E.g.@ +AMD x86-64 psABI says that variables with array type larger than 15 bytes +must be aligned to 16 byte boundaries. + +If this macro is not defined, then @var{basic-align} is used. +@end defmac + @defmac CONSTANT_ALIGNMENT (@var{constant}, @var{basic-align}) If defined, a C expression to compute the alignment given to a constant that is being placed in memory. @var{constant} is the constant and diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index b08dece..cc25fec 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -1062,6 +1062,15 @@ arrays to be word-aligned so that @code{strcpy} calls that copy constants to character arrays can be done inline. @end defmac +@defmac DATA_ABI_ALIGNMENT (@var{type}, @var{basic-align}) +Similar to @code{DATA_ALIGNMENT}, but for the cases where the ABI mandates +some alignment increase, instead of optimization only purposes. E.g.@ +AMD x86-64 psABI says that variables with array type larger than 15 bytes +must be aligned to 16 byte boundaries. + +If this macro is not defined, then @var{basic-align} is used. +@end defmac + @defmac CONSTANT_ALIGNMENT (@var{constant}, @var{basic-align}) If defined, a C expression to compute the alignment given to a constant that is being placed in memory. @var{constant} is the constant and diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0a70b1a..1727138 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,19 @@ +2013-06-10 Jakub Jelinek <jakub@redhat.com> + + PR target/56564 + * gcc.target/i386/pr56564-1.c: New test. + * gcc.target/i386/pr56564-2.c: New test. + * gcc.target/i386/pr56564-3.c: New test. + * gcc.target/i386/pr56564-4.c: New test. + * gcc.target/i386/avx256-unaligned-load-4.c: Add -fno-common. + * gcc.target/i386/avx256-unaligned-store-1.c: Likewise. + * gcc.target/i386/avx256-unaligned-store-3.c: Likewise. + * gcc.target/i386/avx256-unaligned-store-4.c: Likewise. + * gcc.target/i386/vect-sizes-1.c: Likewise. + * gcc.target/i386/memcpy-1.c: Likewise. + * gcc.dg/vect/costmodel/i386/costmodel-vect-31.c (tmp): Initialize. + * gcc.dg/vect/costmodel/x86_64/costmodel-vect-31.c (tmp): Likewise. + 2013-06-10 Thomas Schwinge <thomas@codesourcery.com> * g++.dg/abi/forced.C: Extend current handling of Linux-based x86 diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/i386/costmodel-vect-31.c b/gcc/testsuite/gcc.dg/vect/costmodel/i386/costmodel-vect-31.c index b109be2..1372676 100644 --- a/gcc/testsuite/gcc.dg/vect/costmodel/i386/costmodel-vect-31.c +++ b/gcc/testsuite/gcc.dg/vect/costmodel/i386/costmodel-vect-31.c @@ -18,7 +18,7 @@ struct s{ struct t e; /* unaligned (offset 2N+4N+4 B) */ }; -struct s tmp; +struct s tmp = { 1 }; int main1 () { diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-vect-31.c b/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-vect-31.c index b109be2..1372676 100644 --- a/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-vect-31.c +++ b/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-vect-31.c @@ -18,7 +18,7 @@ struct s{ struct t e; /* unaligned (offset 2N+4N+4 B) */ }; -struct s tmp; +struct s tmp = { 1 }; int main1 () { diff --git a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-4.c b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-4.c index e0eb92b..c5afa06 100644 --- a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-4.c +++ b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-4.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O3 -dp -mavx -mno-avx256-split-unaligned-load -mno-avx256-split-unaligned-store" } */ +/* { dg-options "-O3 -dp -mavx -mno-avx256-split-unaligned-load -mno-avx256-split-unaligned-store -fno-common" } */ #define N 1024 diff --git a/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-1.c b/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-1.c index 1a53ba1..77eaa42 100644 --- a/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-1.c +++ b/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-1.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O3 -dp -mavx -mavx256-split-unaligned-store" } */ +/* { dg-options "-O3 -dp -mavx -mavx256-split-unaligned-store -fno-common" } */ #define N 1024 diff --git a/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-3.c b/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-3.c index 26c993b..e6744a8 100644 --- a/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-3.c +++ b/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-3.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O3 -dp -mavx -mavx256-split-unaligned-store -mtune=generic" } */ +/* { dg-options "-O3 -dp -mavx -mavx256-split-unaligned-store -mtune=generic -fno-common" } */ #define N 1024 diff --git a/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-4.c b/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-4.c index 6d734fa..8568245 100644 --- a/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-4.c +++ b/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-4.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O3 -dp -mavx -mno-avx256-split-unaligned-load -mno-avx256-split-unaligned-store" } */ +/* { dg-options "-O3 -dp -mavx -mno-avx256-split-unaligned-load -mno-avx256-split-unaligned-store -fno-common" } */ #define N 1024 diff --git a/gcc/testsuite/gcc.target/i386/memcpy-1.c b/gcc/testsuite/gcc.target/i386/memcpy-1.c index bc6f95a..b716c5d 100644 --- a/gcc/testsuite/gcc.target/i386/memcpy-1.c +++ b/gcc/testsuite/gcc.target/i386/memcpy-1.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target ia32 } */ -/* { dg-options "-O2 -march=pentiumpro -minline-all-stringops" } */ +/* { dg-options "-O2 -march=pentiumpro -minline-all-stringops -fno-common" } */ /* { dg-final { scan-assembler "rep" } } */ /* { dg-final { scan-assembler "movs" } } */ /* { dg-final { scan-assembler-not "test" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr56564-1.c b/gcc/testsuite/gcc.target/i386/pr56564-1.c new file mode 100644 index 0000000..7287de0 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr56564-1.c @@ -0,0 +1,25 @@ +/* PR target/56564 */ +/* { dg-do compile { target { fpic && lp64 } } } */ +/* { dg-options "-O3 -fpic -fdump-tree-optimized" } */ + +struct S { long a, b; } s = { 5, 6 }; +char t[16] = { 7 }; + +int +foo (void) +{ + return ((__UINTPTR_TYPE__) &s) & 15; +} + +int +bar (void) +{ + return ((__UINTPTR_TYPE__) &t[0]) & 15; +} + +/* { dg-final { scan-tree-dump-times "&s" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "&t" 0 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized" } } */ +/* { dg-final { scan-assembler ".align\[ \t]*16\[^:]*\[\n\r]s:" { target { *-*-linux* } } } } */ +/* { dg-final { scan-assembler ".align\[ \t]*16\[^:]*\[\n\r]t:" { target { *-*-linux* } } } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr56564-2.c b/gcc/testsuite/gcc.target/i386/pr56564-2.c new file mode 100644 index 0000000..fc89a4c --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr56564-2.c @@ -0,0 +1,25 @@ +/* PR target/56564 */ +/* { dg-do compile { target { *-*-linux* && lp64 } } } */ +/* { dg-options "-O3 -fno-pic -fdump-tree-optimized" } */ + +struct S { long a, b; } s = { 5, 6 }; +char t[16] = { 7 }; + +int +foo (void) +{ + return ((__UINTPTR_TYPE__) &s) & 15; +} + +int +bar (void) +{ + return ((__UINTPTR_TYPE__) &t[0]) & 15; +} + +/* { dg-final { scan-tree-dump-times "&s" 0 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "&t" 0 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "return 0" 2 "optimized" } } */ +/* { dg-final { scan-assembler ".align\[ \t]*16\[^:]*\[\n\r]s:" { target { *-*-linux* } } } } */ +/* { dg-final { scan-assembler ".align\[ \t]*16\[^:]*\[\n\r]t:" { target { *-*-linux* } } } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr56564-3.c b/gcc/testsuite/gcc.target/i386/pr56564-3.c new file mode 100644 index 0000000..cf39295 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr56564-3.c @@ -0,0 +1,28 @@ +/* PR target/56564 */ +/* { dg-do compile { target { fpic && lp64 } } } */ +/* { dg-options "-O3 -fpic -fdump-tree-optimized" } */ + +__thread struct S { long a, b; } s = { 5, 6 }; +__thread char t[16] = { 7 }; + +int +foo (void) +{ + return ((__UINTPTR_TYPE__) &s) & 15; +} + +/* For backwards compatibility we don't assume that t must + be aligned to 16 bytes, but align it anyway. */ + +int +bar (void) +{ + return ((__UINTPTR_TYPE__) &t[0]) & 15; +} + +/* { dg-final { scan-tree-dump-times "&s" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "&t" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "return 0" 0 "optimized" } } */ +/* { dg-final { scan-assembler-not ".align\[ \t]*16\[^:]*\[\n\r]s:" { target { *-*-linux* } } } } */ +/* { dg-final { scan-assembler ".align\[ \t]*16\[^:]*\[\n\r]t:" { target { *-*-linux* } } } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr56564-4.c b/gcc/testsuite/gcc.target/i386/pr56564-4.c new file mode 100644 index 0000000..a0b3d3d --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr56564-4.c @@ -0,0 +1,22 @@ +/* PR target/56564 */ +/* { dg-do compile { target { *-*-linux* && lp64 } } } */ +/* { dg-options "-O3 -fno-pic -fdump-tree-optimized" } */ + +__thread struct S { long a, b; } s = { 5, 6 }; +__thread char t[16] = { 7 }; + +int +foo (void) +{ + return ((__UINTPTR_TYPE__) &s) & 15; +} + +int +bar (void) +{ + return ((__UINTPTR_TYPE__) &t[0]) & 15; +} + +/* { dg-final { scan-assembler-not ".align\[ \t]*16\[^:]*\[\n\r]s:" { target { *-*-linux* } } } } */ +/* { dg-final { scan-assembler ".align\[ \t]*16\[^:]*\[\n\r]t:" { target { *-*-linux* } } } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.target/i386/vect-sizes-1.c b/gcc/testsuite/gcc.target/i386/vect-sizes-1.c index 3c18f3b..6ca38d2 100644 --- a/gcc/testsuite/gcc.target/i386/vect-sizes-1.c +++ b/gcc/testsuite/gcc.target/i386/vect-sizes-1.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O3 -ffast-math -mavx -mtune=generic" } */ +/* { dg-options "-O3 -ffast-math -mavx -mtune=generic -fno-common" } */ double a[1024]; diff --git a/gcc/varasm.c b/gcc/varasm.c index b43adae..cd0235f 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -966,13 +966,80 @@ align_variable (tree decl, bool dont_output_data) align = MAX_OFILE_ALIGNMENT; } - /* On some machines, it is good to increase alignment sometimes. */ if (! DECL_USER_ALIGN (decl)) { +#ifdef DATA_ABI_ALIGNMENT + unsigned int data_abi_align + = DATA_ABI_ALIGNMENT (TREE_TYPE (decl), align); + /* For backwards compatibility, don't assume the ABI alignment for + TLS variables. */ + if (! DECL_THREAD_LOCAL_P (decl) || data_abi_align <= BITS_PER_WORD) + align = data_abi_align; +#endif + + /* On some machines, it is good to increase alignment sometimes. + But as DECL_ALIGN is used both for actually emitting the variable + and for code accessing the variable as guaranteed alignment, we + can only increase the alignment if it is a performance optimization + if the references to it must bind to the current definition. */ + if (decl_binds_to_current_def_p (decl)) + { +#ifdef DATA_ALIGNMENT + unsigned int data_align = DATA_ALIGNMENT (TREE_TYPE (decl), align); + /* Don't increase alignment too much for TLS variables - TLS space + is too precious. */ + if (! DECL_THREAD_LOCAL_P (decl) || data_align <= BITS_PER_WORD) + align = data_align; +#endif +#ifdef CONSTANT_ALIGNMENT + if (DECL_INITIAL (decl) != 0 + && DECL_INITIAL (decl) != error_mark_node) + { + unsigned int const_align + = CONSTANT_ALIGNMENT (DECL_INITIAL (decl), align); + /* Don't increase alignment too much for TLS variables - TLS + space is too precious. */ + if (! DECL_THREAD_LOCAL_P (decl) || const_align <= BITS_PER_WORD) + align = const_align; + } +#endif + } + } + + /* Reset the alignment in case we have made it tighter, so we can benefit + from it in get_pointer_alignment. */ + DECL_ALIGN (decl) = align; +} + +/* Return DECL_ALIGN (decl), possibly increased for optimization purposes + beyond what align_variable returned. */ + +static unsigned int +get_variable_align (tree decl) +{ + unsigned int align = DECL_ALIGN (decl); + + /* For user aligned vars or static vars align_variable already did + everything. */ + if (DECL_USER_ALIGN (decl) || !TREE_PUBLIC (decl)) + return align; + +#ifdef DATA_ABI_ALIGNMENT + if (DECL_THREAD_LOCAL_P (decl)) + align = DATA_ABI_ALIGNMENT (TREE_TYPE (decl), align); +#endif + + /* For decls that bind to the current definition, align_variable + did also everything, except for not assuming ABI required alignment + of TLS variables. For other vars, increase the alignment here + as an optimization. */ + if (!decl_binds_to_current_def_p (decl)) + { + /* On some machines, it is good to increase alignment sometimes. */ #ifdef DATA_ALIGNMENT unsigned int data_align = DATA_ALIGNMENT (TREE_TYPE (decl), align); /* Don't increase alignment too much for TLS variables - TLS space - is too precious. */ + is too precious. */ if (! DECL_THREAD_LOCAL_P (decl) || data_align <= BITS_PER_WORD) align = data_align; #endif @@ -986,12 +1053,10 @@ align_variable (tree decl, bool dont_output_data) if (! DECL_THREAD_LOCAL_P (decl) || const_align <= BITS_PER_WORD) align = const_align; } -#endif } +#endif - /* Reset the alignment in case we have made it tighter, so we can benefit - from it in get_pointer_alignment. */ - DECL_ALIGN (decl) = align; + return align; } /* Return the section into which the given VAR_DECL or CONST_DECL @@ -1043,7 +1108,8 @@ get_variable_section (tree decl, bool prefer_noswitch_p) return bss_noswitch_section; } - return targetm.asm_out.select_section (decl, reloc, DECL_ALIGN (decl)); + return targetm.asm_out.select_section (decl, reloc, + get_variable_align (decl)); } /* Return the block into which object_block DECL should be placed. */ @@ -1780,7 +1846,8 @@ emit_bss (tree decl ATTRIBUTE_UNUSED, unsigned HOST_WIDE_INT rounded ATTRIBUTE_UNUSED) { #if defined ASM_OUTPUT_ALIGNED_BSS - ASM_OUTPUT_ALIGNED_BSS (asm_out_file, decl, name, size, DECL_ALIGN (decl)); + ASM_OUTPUT_ALIGNED_BSS (asm_out_file, decl, name, size, + get_variable_align (decl)); return true; #endif } @@ -1796,10 +1863,11 @@ emit_common (tree decl ATTRIBUTE_UNUSED, { #if defined ASM_OUTPUT_ALIGNED_DECL_COMMON ASM_OUTPUT_ALIGNED_DECL_COMMON (asm_out_file, decl, name, - size, DECL_ALIGN (decl)); + size, get_variable_align (decl)); return true; #elif defined ASM_OUTPUT_ALIGNED_COMMON - ASM_OUTPUT_ALIGNED_COMMON (asm_out_file, name, size, DECL_ALIGN (decl)); + ASM_OUTPUT_ALIGNED_COMMON (asm_out_file, name, size, + get_variable_align (decl)); return true; #else ASM_OUTPUT_COMMON (asm_out_file, name, size, rounded); @@ -1828,7 +1896,8 @@ emit_tls_common (tree decl ATTRIBUTE_UNUSED, NAME is the name of DECL's SYMBOL_REF. */ static void -assemble_noswitch_variable (tree decl, const char *name, section *sect) +assemble_noswitch_variable (tree decl, const char *name, section *sect, + unsigned int align) { unsigned HOST_WIDE_INT size, rounded; @@ -1850,7 +1919,7 @@ assemble_noswitch_variable (tree decl, const char *name, section *sect) * (BIGGEST_ALIGNMENT / BITS_PER_UNIT)); if (!sect->noswitch.callback (decl, name, size, rounded) - && (unsigned HOST_WIDE_INT) DECL_ALIGN_UNIT (decl) > rounded) + && (unsigned HOST_WIDE_INT) (align / BITS_PER_UNIT) > rounded) warning (0, "requested alignment for %q+D is greater than " "implemented alignment of %wu", decl, rounded); } @@ -1880,7 +1949,7 @@ assemble_variable_contents (tree decl, const char *name, /* Output the actual data. */ output_constant (DECL_INITIAL (decl), tree_low_cst (DECL_SIZE_UNIT (decl), 1), - DECL_ALIGN (decl)); + get_variable_align (decl)); else /* Leave space for it. */ assemble_zeros (tree_low_cst (DECL_SIZE_UNIT (decl), 1)); @@ -1904,6 +1973,7 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED, const char *name; rtx decl_rtl, symbol; section *sect; + unsigned int align; bool asan_protected = false; /* This function is supposed to handle VARIABLES. Ensure we have one. */ @@ -2003,6 +2073,8 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED, set_mem_align (decl_rtl, DECL_ALIGN (decl)); + align = get_variable_align (decl); + if (TREE_PUBLIC (decl)) maybe_assemble_visibility (decl); @@ -2032,12 +2104,12 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED, place_block_symbol (symbol); } else if (SECTION_STYLE (sect) == SECTION_NOSWITCH) - assemble_noswitch_variable (decl, name, sect); + assemble_noswitch_variable (decl, name, sect, align); else { switch_to_section (sect); - if (DECL_ALIGN (decl) > BITS_PER_UNIT) - ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (DECL_ALIGN_UNIT (decl))); + if (align > BITS_PER_UNIT) + ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT)); assemble_variable_contents (decl, name, dont_output_data); if (asan_protected) { @@ -6959,7 +7031,7 @@ place_block_symbol (rtx symbol) else { decl = SYMBOL_REF_DECL (symbol); - alignment = DECL_ALIGN (decl); + alignment = get_variable_align (decl); size = tree_low_cst (DECL_SIZE_UNIT (decl), 1); if (flag_asan && asan_protect_global (decl)) { |