On Sun, Oct 4, 2015 at 5:26 PM, Uros Bizjak <ubiz...@gmail.com> wrote:
> As shown in PR 66697 [1] and WineHQ bug [2], an application can > misalign incoming stack to less than ABI mandated 16 bytes. While it > is possible to use -mincoming-stack-boundary=2 (= 4 bytes) for 32 bit > targets to emit stack realignment code, this option is artificially > limited to 4 (= 16 bytes) for 64bit targets. Attached v2 patch goes all the way to enable -mstackrealign and 'force_align_arg_pointer' attribute for x86_64. In addition to -mincoming-stack-boundary changes, the patch changes MIN_STACK_BOUNDARY definition to 8bytes on 64bit targets, as this is really the minimum supported stack boundary. This patch is also needed to allow stack realignment in the interrupt handler. 2015-10-05 Uros Bizjak <ubiz...@gmail.com> PR target/66697 * config/i386/i386.h (MIN_STACK_BOUNDARY): Redefine as BITS_PER_WORD. * config/i386/i386.c (ix86_option_override_internal): Lower minimum allowed incoming stack boundary to 3 for 64bit SSE targets. (ix86_minimum_incoming_stack_boundary): Also initialize incoming_stack_boundary to MIN_STACK_BOUNDARY for 64bit targets when -mstackrealign or force_align_arg_pointer attribute is used. (ix86_handle_force_align_arg_pointer_attribute): New function. (ix86_attribute_table): Use it for force_align_arg_pointer attribute. testsuite/ChangeLog: 2015-10-05 Uros Bizjak <ubiz...@gmail.com> PR target/66697 * gcc.target/i386/20060512-1.c: Also run on 64bit targets. (PUSH, POP): New defines. (sse2_test): Use PUSH and POP to misalign runtime stack. * gcc.target/i386/20060512-2.c: Also compile on 64bit targets. Patch was bootstrapped and regression tested on x86_64-linux-gnu {,-m32}. I plan to commit this patch to SVN tomorrow, and also to backport the patch to gcc-5 branch, but no soon that a couple of weeks without problems in mainline, and after receiving confirmation from Cygwin people that the patch cures their problems. Uros.
Index: config/i386/i386.c =================================================================== --- config/i386/i386.c (revision 228488) +++ config/i386/i386.c (working copy) @@ -5102,8 +5102,7 @@ ix86_option_override_internal (bool main_args_p, ix86_incoming_stack_boundary = ix86_default_incoming_stack_boundary; if (opts_set->x_ix86_incoming_stack_boundary_arg) { - int min = (TARGET_64BIT_P (opts->x_ix86_isa_flags) - ? (TARGET_SSE_P (opts->x_ix86_isa_flags) ? 4 : 3) : 2); + int min = TARGET_64BIT_P (opts->x_ix86_isa_flags) ? 3 : 2; if (opts->x_ix86_incoming_stack_boundary_arg < min || opts->x_ix86_incoming_stack_boundary_arg > 12) @@ -11779,6 +11778,25 @@ find_drap_reg (void) } } +/* Handle a "force_align_arg_pointer" attribute. */ + +static tree +ix86_handle_force_align_arg_pointer_attribute (tree *node, tree name, + tree, int, bool *no_add_attrs) +{ + if (TREE_CODE (*node) != FUNCTION_TYPE + && TREE_CODE (*node) != METHOD_TYPE + && TREE_CODE (*node) != FIELD_DECL + && TREE_CODE (*node) != TYPE_DECL) + { + warning (OPT_Wattributes, "%qE attribute only applies to functions", + name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + /* Return minimum incoming stack alignment. */ static unsigned int @@ -11789,11 +11807,10 @@ ix86_minimum_incoming_stack_boundary (bool sibcall /* Prefer the one specified at command line. */ if (ix86_user_incoming_stack_boundary) incoming_stack_boundary = ix86_user_incoming_stack_boundary; - /* In 32bit, use MIN_STACK_BOUNDARY for incoming stack boundary + /* Use MIN_STACK_BOUNDARY for incoming stack boundary if -mstackrealign is used, it isn't used for sibcall check and estimated stack alignment is 128bit. */ else if (!sibcall - && !TARGET_64BIT && ix86_force_align_arg_pointer && crtl->stack_alignment_estimated == 128) incoming_stack_boundary = MIN_STACK_BOUNDARY; @@ -48050,7 +48067,7 @@ static const struct attribute_spec ix86_attribute_ true }, /* force_align_arg_pointer says this function realigns the stack at entry. */ { (const char *)&ix86_force_align_arg_pointer_string, 0, 0, - false, true, true, ix86_handle_cconv_attribute, false }, + false, true, true, ix86_handle_force_align_arg_pointer_attribute, false }, #if TARGET_DLLIMPORT_DECL_ATTRIBUTES { "dllimport", 0, 0, false, false, false, handle_dll_attribute, false }, { "dllexport", 0, 0, false, false, false, handle_dll_attribute, false }, Index: config/i386/i386.h =================================================================== --- config/i386/i386.h (revision 228488) +++ config/i386/i386.h (working copy) @@ -752,7 +752,7 @@ extern const char *host_detect_local_cpu (int argc #define MAIN_STACK_BOUNDARY (TARGET_64BIT ? 128 : 32) /* Minimum stack boundary. */ -#define MIN_STACK_BOUNDARY (TARGET_64BIT ? (TARGET_SSE ? 128 : 64) : 32) +#define MIN_STACK_BOUNDARY BITS_PER_WORD /* Boundary (in *bits*) on which the stack pointer prefers to be aligned; the compiler cannot rely on having this alignment. */ Index: testsuite/gcc.target/i386/20060512-1.c =================================================================== --- testsuite/gcc.target/i386/20060512-1.c (revision 228488) +++ testsuite/gcc.target/i386/20060512-1.c (working copy) @@ -1,5 +1,4 @@ /* { dg-do run } */ -/* { dg-require-effective-target ia32 } */ /* { dg-options "-std=gnu99 -msse2 -mpreferred-stack-boundary=4" } */ /* { dg-require-effective-target sse2 } */ @@ -7,6 +6,14 @@ #include <emmintrin.h> +#ifdef __x86_64__ +# define PUSH "pushq %rsi" +# define POP "popq %rsi" +#else +# define PUSH "pushl %esi" +# define POP "popl %esi" +#endif + __m128i __attribute__ ((__noinline__)) vector_using_function () { @@ -27,9 +34,9 @@ static void sse2_test (void) { int result; - asm ("pushl %esi"); /* Disalign runtime stack. */ + asm (PUSH); /* Misalign runtime stack. */ result = self_aligning_function (g_1, g_2); if (result != 42) abort (); - asm ("popl %esi"); + asm (POP); } Index: testsuite/gcc.target/i386/20060512-2.c =================================================================== --- testsuite/gcc.target/i386/20060512-2.c (revision 228488) +++ testsuite/gcc.target/i386/20060512-2.c (working copy) @@ -1,5 +1,4 @@ /* { dg-do compile } */ -/* { dg-require-effective-target ia32 } */ /* { dg-options "-std=gnu99 -mpreferred-stack-boundary=4" } */ int outer_function (int x, int y)