Add TARGET_LOWER_LOCAL_DECL_ALIGNMENT [PR95237]
authorSunil K Pandey <skpgkp2@gmail.com>
Sat, 18 Jul 2020 02:42:09 +0000 (19:42 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Tue, 21 Jul 2020 23:25:43 +0000 (16:25 -0700)
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 prevents lowering of alignment from following macros.
LOCAL_ALIGNMENT
STACK_SLOT_ALIGNMENT
LOCAL_DECL_ALIGNMENT
  - 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 may_lower alignment. Default is
false.
* 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.
* 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.

16 files changed:
gcc/c/c-decl.c
gcc/config/i386/i386-protos.h
gcc/config/i386/i386.c
gcc/cp/decl.c
gcc/doc/tm.texi
gcc/doc/tm.texi.in
gcc/target.def
gcc/testsuite/c-c++-common/pr95237-1.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/pr95237-2.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/pr95237-3.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/pr95237-4.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/pr95237-5.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/pr95237-6.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/pr95237-7.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/pr95237-8.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/pr95237-9.c [new file with mode: 0644]

index 81bd2ee94f02dd465a9ecf51916204c1ddcdfec2..5d6b504fe783b46aa67db11d1de70b3dc5089701 100644 (file)
@@ -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);
 }
 
index 7c2ce618f3fcd142617a1278e6ad8ab8b6943b00..0b95c57b1a0f3133de1aa2c50b85b614c26e20b2 100644 (file)
@@ -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 *);
index 31757b044c8850cfa63aec10f780592b2ce31496..8ea6a4d7ea7ad184942283da3036b274a793ab04 100644 (file)
@@ -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
index db91b50a4f0d36d58868575c9c3e2597f52c7c38..7d717451dc9b0ebe3ceb1fc5df8e7eaf6a4bbc6b 100644 (file)
@@ -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);
 }
 
index 41b9e10c8561f408aacbc2c88447e226bd6b3a9e..437187694b67e8016aaaa310adf6d2aa32cbc0a8 100644 (file)
@@ -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}
index 3be984bbd5cdacb19bcf40588ea370a7a7ccf377..d76c85d580096866d47836de75cd8437080ddfbb 100644 (file)
@@ -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})
index f2f314ed89c94aa527e89e33af8963ab1bf857ac..c11cab8891f9bf3c4c9b4357d7b4b0442560bb41 100644 (file)
@@ -3350,6 +3350,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 (file)
index 0000000..8947a9f
--- /dev/null
@@ -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 (file)
index 0000000..87949a9
--- /dev/null
@@ -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 (file)
index 0000000..6941b6f
--- /dev/null
@@ -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 (file)
index 0000000..deace53
--- /dev/null
@@ -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 (file)
index 0000000..9dc5cfc
--- /dev/null
@@ -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 (file)
index 0000000..ce1568f
--- /dev/null
@@ -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 (file)
index 0000000..8410009
--- /dev/null
@@ -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 (file)
index 0000000..8ba98ab
--- /dev/null
@@ -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 (file)
index 0000000..687517c
--- /dev/null
@@ -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;
+}