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);
}
#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 *);
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
unsigned int
ix86_local_alignment (tree exp, machine_mode mode,
- unsigned int align)
+ unsigned int align, bool may_lower)
{
tree type, decl;
/* 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))
#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
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);
}
@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}
@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})
#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\
--- /dev/null
+/* { 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;
+}
--- /dev/null
+/* { 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;
+}
--- /dev/null
+/* { 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;
+}
--- /dev/null
+/* { 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;
+}
--- /dev/null
+/* { 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;
+}
--- /dev/null
+/* { 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;
+}
--- /dev/null
+/* { 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;
+}
--- /dev/null
+/* { 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;
+}
--- /dev/null
+/* { 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;
+}