i386.opt (-mstackrealign): New flag.

* gcc/config/i386/i386.opt (-mstackrealign): New flag.  *
	gcc/config/i386/i386.c (force_align_arg_pointer): New attribute.
	(ix86_handle_cconv_attribute): Emit error when
	force_align_arg_pointer attribute collides with too many regparms.
	(ix86_function_regparm): Limit regparms when used with
	force_align_arg_pointer attribute.  (ix86_internal_arg_pointer):
	Support stack-realigning prologue in non-main functions.  Emit
	warning for nested functions under -mstackrealign, emit error for
	nested functions with force_align_arg_pointer attribute.
	* gcc/doc/extend.texi (force_align_arg_pointer): Document it.
	* gcc/doc/invoke.texi (-mstackrealign): Document it.
	* testsuite/gcc.target/i386/20060512-1.c: New.
	* testsuite/gcc.target/i386/20060512-2.c: New.
	* testsuite/gcc.target/i386/20060512-3.c: New.
	* testsuite/gcc.target/i386/20060512-4.c: New.

From-SVN: r113880
This commit is contained in:
Stuart Hastings 2006-05-18 00:34:44 +00:00 committed by Stuart Hastings
parent 71abbf1620
commit 3393294636
10 changed files with 184 additions and 4 deletions

View File

@ -1,3 +1,17 @@
2006-05-12 Stuart Hastings <stuart@apple.com>
* gcc/config/i386/i386.opt (-mstackrealign): New flag. *
gcc/config/i386/i386.c (force_align_arg_pointer): New attribute.
(ix86_handle_cconv_attribute): Emit error when
force_align_arg_pointer attribute collides with too many regparms.
(ix86_function_regparm): Limit regparms when used with
force_align_arg_pointer attribute. (ix86_internal_arg_pointer):
Support stack-realigning prologue in non-main functions. Emit
warning for nested functions under -mstackrealign, emit error for
nested functions with force_align_arg_pointer attribute.
* gcc/doc/extend.texi (force_align_arg_pointer): Document it.
* gcc/doc/invoke.texi (-mstackrealign): Document it.
2006-05-17 Kazu Hirata <kazu@codesourcery.com>
PR rtl-optimization/27477

View File

@ -1049,6 +1049,10 @@ int x86_prefetch_sse;
/* ix86_regparm_string as a number */
static int ix86_regparm;
/* -mstackrealign option */
extern int ix86_force_align_arg_pointer;
static const char ix86_force_align_arg_pointer_string[] = "force_align_arg_pointer";
/* Preferred alignment for stack boundary in bits. */
unsigned int ix86_preferred_stack_boundary;
@ -2225,6 +2229,9 @@ const struct attribute_spec ix86_attribute_table[] =
/* Sseregparm attribute says we are using x86_64 calling conventions
for FP arguments. */
{ "sseregparm", 0, 0, false, true, true, ix86_handle_cconv_attribute },
/* 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 },
#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
{ "dllimport", 0, 0, false, false, false, handle_dll_attribute },
{ "dllexport", 0, 0, false, false, false, handle_dll_attribute },
@ -2367,6 +2374,15 @@ ix86_handle_cconv_attribute (tree *node, tree name,
*no_add_attrs = true;
}
if (!TARGET_64BIT
&& lookup_attribute (ix86_force_align_arg_pointer_string,
TYPE_ATTRIBUTES (*node))
&& compare_tree_int (cst, REGPARM_MAX-1))
{
error ("%s functions limited to %d register parameters",
ix86_force_align_arg_pointer_string, REGPARM_MAX-1);
}
return NULL_TREE;
}
@ -2506,6 +2522,18 @@ ix86_function_regparm (tree type, tree decl)
&& decl_function_context (decl)
&& !DECL_NO_STATIC_CHAIN (decl))
local_regparm = 2;
/* If the function realigns its stackpointer, the
prologue will clobber %ecx. If we've already
generated code for the callee, the callee
DECL_STRUCT_FUNCTION is gone, so we fall back to
scanning the attributes for the self-realigning
property. */
if ((DECL_STRUCT_FUNCTION (decl)
&& DECL_STRUCT_FUNCTION (decl)->machine->force_align_arg_pointer)
|| (!DECL_STRUCT_FUNCTION (decl)
&& lookup_attribute (ix86_force_align_arg_pointer_string,
TYPE_ATTRIBUTES (TREE_TYPE (decl)))))
local_regparm = 2;
/* Each global register variable increases register preassure,
so the more global reg vars there are, the smaller regparm
optimization use, unless requested by the user explicitly. */
@ -5181,11 +5209,28 @@ pro_epilogue_adjust_stack (rtx dest, rtx src, rtx offset, int style)
static rtx
ix86_internal_arg_pointer (void)
{
if (FORCE_PREFERRED_STACK_BOUNDARY_IN_MAIN
&& DECL_NAME (current_function_decl)
&& MAIN_NAME_P (DECL_NAME (current_function_decl))
&& DECL_FILE_SCOPE_P (current_function_decl))
bool has_force_align_arg_pointer =
(0 != lookup_attribute (ix86_force_align_arg_pointer_string,
TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))));
if ((FORCE_PREFERRED_STACK_BOUNDARY_IN_MAIN
&& DECL_NAME (current_function_decl)
&& MAIN_NAME_P (DECL_NAME (current_function_decl))
&& DECL_FILE_SCOPE_P (current_function_decl))
|| ix86_force_align_arg_pointer
|| has_force_align_arg_pointer)
{
/* Nested functions can't realign the stack due to a register
conflict. */
if (DECL_CONTEXT (current_function_decl)
&& TREE_CODE (DECL_CONTEXT (current_function_decl)) == FUNCTION_DECL)
{
if (ix86_force_align_arg_pointer)
warning (0, "-mstackrealign ignored for nested functions");
if (has_force_align_arg_pointer)
error ("%s not supported for nested functions",
ix86_force_align_arg_pointer_string);
return virtual_incoming_args_rtx;
}
cfun->machine->force_align_arg_pointer = gen_rtx_REG (Pmode, 2);
return copy_to_reg (cfun->machine->force_align_arg_pointer);
}

View File

@ -205,6 +205,10 @@ msselibm
Target Mask(SSELIBM)
Use SSE2 ABI libgcc-math routines if using SSE math
mstackrealign
Target Report Var(ix86_force_align_arg_pointer)
Realign stack in prologue
msvr3-shlib
Target Report Mask(SVR3_SHLIB)
Uninitialized locals in .bss

View File

@ -2207,6 +2207,20 @@ SSE registers instead of on the stack. Functions that take a
variable number of arguments will continue to pass all of their
floating point arguments on the stack.
@item force_align_arg_pointer
@cindex @code{force_align_arg_pointer} attribute
On the Intel x86, the @code{force_align_arg_pointer} attribute may be
applied to individual function definitions, generating an alternate
prologue and epilogue that realigns the runtime stack. This supports
mixing legacy codes that run with a 4-byte aligned stack with modern
codes that keep a 16-byte stack for SSE compatibility. The alternate
prologue and epilogue are slower and bigger than the regular ones, and
the alternate prologue requires a scratch register; this lowers the
number of registers available if used in conjunction with the
@code{regparm} attribute. The @code{force_align_arg_pointer}
attribute is incompatible with nested functions; this is considered a
hard error.
@item returns_twice
@cindex @code{returns_twice} attribute
The @code{returns_twice} attribute tells the compiler that a function may

View File

@ -537,6 +537,7 @@ Objective-C and Objective-C++ Dialects}.
-mthreads -mno-align-stringops -minline-all-stringops @gol
-mpush-args -maccumulate-outgoing-args -m128bit-long-double @gol
-m96bit-long-double -mregparm=@var{num} -msseregparm @gol
-mstackrealign @gol
-momit-leaf-frame-pointer -mno-red-zone -mno-tls-direct-seg-refs @gol
-mcmodel=@var{code-model} @gol
-m32 -m64 -mlarge-data-threshold=@var{num}}
@ -9464,6 +9465,21 @@ function by using the function attribute @samp{sseregparm}.
modules with the same value, including any libraries. This includes
the system libraries and startup modules.
@item -mstackrealign
@opindex mstackrealign
Realign the stack at entry. On the Intel x86, the
@option{-mstackrealign} option will generate an alternate prologue and
epilogue that realigns the runtime stack. This supports mixing legacy
codes that keep a 4-byte aligned stack with modern codes that keep a
16-byte stack for SSE compatibility. The alternate prologue and
epilogue are slower and bigger than the regular ones, and the
alternate prologue requires an extra scratch register; this lowers the
number of registers available if used in conjunction with the
@code{regparm} attribute. The @option{-mstackrealign} option is
incompatible with the nested function prologue; this is considered a
hard error. See also the attribute @code{force_align_arg_pointer},
applicable to individual functions.
@item -mpreferred-stack-boundary=@var{num}
@opindex mpreferred-stack-boundary
Attempt to keep the stack boundary aligned to a 2 raised to @var{num}

View File

@ -1,3 +1,10 @@
2006-05-12 Stuart Hastings <stuart@apple.com>
* testsuite/gcc.target/i386/20060512-1.c: New.
* testsuite/gcc.target/i386/20060512-2.c: New.
* testsuite/gcc.target/i386/20060512-3.c: New.
* testsuite/gcc.target/i386/20060512-4.c: New.
2006-05-17 Mark Mitchell <mark@codesourcery.com>
PR c++/26122

View File

@ -0,0 +1,28 @@
/* { dg-do run { target i?86-*-* } } */
/* { dg-options "-std=gnu99" } */
#include <emmintrin.h>
__m128i __attribute__ ((__noinline__))
vector_using_function ()
{
volatile __m128i vx; /* We want to force a vector-aligned store into the stack. */
vx = _mm_xor_si128 (vx, vx);
return vx;
}
int __attribute__ ((__noinline__, __force_align_arg_pointer__))
self_aligning_function (int x, int y)
{
__m128i ignored = vector_using_function ();
return (x + y);
}
int g_1 = 20;
int g_2 = 22;
int
main ()
{
int result;
asm ("pushl %esi"); /* Disalign runtime stack. */
result = self_aligning_function (g_1, g_2);
asm ("popl %esi");
if (result != 42)
abort ();
}

View File

@ -0,0 +1,12 @@
/* { dg-do compile { target i?86-*-* } } */
/* { dg-options "-std=gnu99" } */
int
outer_function (int x, int y)
{
int __attribute__ ((__noinline__, __force_align_arg_pointer__))
nested_function (int x, int y)
{ /* { dg-error "force_align_arg_pointer not supported for nested functions" } */
return (x + y);
}
return (3 + nested_function (x, y));
}

View File

@ -0,0 +1,28 @@
/* { dg-do run { target i?86-*-* } } */
/* { dg-options "-std=gnu99 -mstackrealign" } */
#include <emmintrin.h>
__m128i __attribute__ ((__noinline__))
vector_using_function ()
{
volatile __m128i vx; /* We want to force a vector-aligned store into the stack. */
vx = _mm_xor_si128 (vx, vx);
return vx;
}
int __attribute__ ((__noinline__))
self_aligning_function (int x, int y)
{
__m128i ignored = vector_using_function ();
return (x + y);
}
int g_1 = 20;
int g_2 = 22;
int
main ()
{
int result;
asm ("pushl %esi"); /* Disalign runtime stack. */
result = self_aligning_function (g_1, g_2);
asm ("popl %esi");
if (result != 42)
abort ();
}

View File

@ -0,0 +1,12 @@
/* { dg-do compile { target i?86-*-* } } */
/* { dg-options "-mstackrealign" } */
int
outer_function (int x, int y)
{
int __attribute__ ((__noinline__))
nested_function (int x, int y)
{ /* { dg-error "-mstackrealign ignored for nested functions" } */
return (x + y);
}
return (3 + nested_function (x, y));
}