PR target/56564
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 10 Jun 2013 15:41:52 +0000 (15:41 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 10 Jun 2013 15:41:52 +0000 (15:41 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@199898 138bc75d-0d04-0410-961f-82ee72b054a4

24 files changed:
gcc/ChangeLog
gcc/config/c6x/c6x.h
gcc/config/i386/i386-protos.h
gcc/config/i386/i386.c
gcc/config/i386/i386.h
gcc/config/mmix/mmix.c
gcc/config/mmix/mmix.h
gcc/config/s390/s390.h
gcc/doc/tm.texi
gcc/doc/tm.texi.in
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/vect/costmodel/i386/costmodel-vect-31.c
gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-vect-31.c
gcc/testsuite/gcc.target/i386/avx256-unaligned-load-4.c
gcc/testsuite/gcc.target/i386/avx256-unaligned-store-1.c
gcc/testsuite/gcc.target/i386/avx256-unaligned-store-3.c
gcc/testsuite/gcc.target/i386/avx256-unaligned-store-4.c
gcc/testsuite/gcc.target/i386/memcpy-1.c
gcc/testsuite/gcc.target/i386/pr56564-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr56564-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr56564-3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr56564-4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/vect-sizes-1.c
gcc/varasm.c

index 0176137..cf75717 100644 (file)
@@ -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
index ce331cb..c30a971 100644 (file)
@@ -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))
 
index ef4dc76..f228e87 100644 (file)
@@ -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,
index 5f6a5d5..45e8899 100644 (file)
@@ -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)
index 5dcd69f..7d940f9 100644 (file)
@@ -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
index 1af09e5..bd37067 100644 (file)
@@ -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.  */
index 4ca1a2b..c5edc57 100644 (file)
@@ -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) \
index 43e24d5..b0e530f 100644 (file)
@@ -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
index f840481..f030b56 100644 (file)
@@ -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
index b08dece..cc25fec 100644 (file)
@@ -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
index 0a70b1a..1727138 100644 (file)
@@ -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
index b109be2..1372676 100644 (file)
@@ -18,7 +18,7 @@ struct s{
   struct t e;   /* unaligned (offset 2N+4N+4 B) */
 };
  
-struct s tmp;
+struct s tmp = { 1 };
 
 int main1 ()
 {  
index b109be2..1372676 100644 (file)
@@ -18,7 +18,7 @@ struct s{
   struct t e;   /* unaligned (offset 2N+4N+4 B) */
 };
  
-struct s tmp;
+struct s tmp = { 1 };
 
 int main1 ()
 {  
index e0eb92b..c5afa06 100644 (file)
@@ -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
 
index 1a53ba1..77eaa42 100644 (file)
@@ -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
 
index 26c993b..e6744a8 100644 (file)
@@ -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
 
index 6d734fa..8568245 100644 (file)
@@ -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
 
index bc6f95a..b716c5d 100644 (file)
@@ -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 (file)
index 0000000..7287de0
--- /dev/null
@@ -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 (file)
index 0000000..fc89a4c
--- /dev/null
@@ -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 (file)
index 0000000..cf39295
--- /dev/null
@@ -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 (file)
index 0000000..a0b3d3d
--- /dev/null
@@ -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" } } */
index 3c18f3b..6ca38d2 100644 (file)
@@ -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];
 
index b43adae..cd0235f 100644 (file)
@@ -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))
        {