diff options
author | Dominik Vogt <vogt@linux.vnet.ibm.com> | 2016-07-18 13:10:27 +0000 |
---|---|---|
committer | Andreas Krebbel <krebbel@gcc.gnu.org> | 2016-07-18 13:10:27 +0000 |
commit | 7072df0aae0c59ae437e5cc28e4e5e5777e930ba (patch) | |
tree | eae0f0bf4792f63f3083251ebd6cbec79241a3cb /gcc/cfgexpand.c | |
parent | 54158a1aa94f7b75f59d6ca8d6ca7ebfc11e1673 (diff) | |
download | gcc-7072df0aae0c59ae437e5cc28e4e5e5777e930ba.zip gcc-7072df0aae0c59ae437e5cc28e4e5e5777e930ba.tar.gz gcc-7072df0aae0c59ae437e5cc28e4e5e5777e930ba.tar.bz2 |
Allocate constant size dynamic stack space in the prologue
The attached patch fixes a warning during Linux kernel compilation
on S/390 due to -mwarn-dynamicstack and runtime alignment of stack
variables with constant size causing cfun->calls_alloca to be set
(even if alloca is not used at all). The patched code places
constant size runtime aligned variables in the "virtual stack
vars" area instead of creating a "virtual stack dynamic" area.
This behaviour is activated by defining
#define ALLOCATE_DYNAMIC_STACK_SPACE_IN_PROLOGUE 1
in the backend; otherwise the old logic is used.
The kernel uses runtime alignment for the page structure (aligned
to 16 bytes), and apart from triggereing the alloca warning
(-mwarn-dynamicstack), the current Gcc also generates inefficient
code like
aghi %r15,-160 # prologue: create stack frame
lgr %r11,%r15 # prologue: generate frame pointer
aghi %r15,-32 # space for dynamic stack
which could be simplified to
aghi %r15,-192
(if later optimization passes are able to get rid of the frame
pointer). Is there a specific reason why the patched behaviour
shouldn't be used for all platforms?
--
As the placement of runtime aligned stack variables with constant
size is done completely in the middleend, I don't see a way to fix
this in the backend.
gcc/ChangeLog:
2016-07-18 Dominik Vogt <vogt@linux.vnet.ibm.com>
* cfgexpand.c (expand_stack_vars): Implement synamic stack space
allocation in the prologue.
* explow.c (get_dynamic_stack_base): New function to return an address
expression for the dynamic stack base.
(get_dynamic_stack_size): New function to do the required dynamic stack
space size calculations.
(allocate_dynamic_stack_space): Use new functions.
(align_dynamic_address): Move some code from
allocate_dynamic_stack_space to new function.
* explow.h (get_dynamic_stack_base, get_dynamic_stack_size): Export.
gcc/testsuite/ChangeLog:
2016-07-18 Dominik Vogt <vogt@linux.vnet.ibm.com>
* gcc.target/s390/warn-dynamicstack-1.c: New test.
* gcc.dg/stack-usage-2.c (foo3): Adapt expected warning.
stack-layout-dynamic-1.c: New test.
From-SVN: r238432
Diffstat (limited to 'gcc/cfgexpand.c')
-rw-r--r-- | gcc/cfgexpand.c | 22 |
1 files changed, 17 insertions, 5 deletions
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 984ac4a..9a2837b 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -1053,6 +1053,7 @@ expand_stack_vars (bool (*pred) (size_t), struct stack_vars_data *data) HOST_WIDE_INT large_size = 0, large_alloc = 0; rtx large_base = NULL; unsigned large_align = 0; + bool large_allocation_done = false; tree decl; /* Determine if there are any variables requiring "large" alignment. @@ -1096,11 +1097,6 @@ expand_stack_vars (bool (*pred) (size_t), struct stack_vars_data *data) large_size &= -(HOST_WIDE_INT)alignb; large_size += stack_vars[i].size; } - - /* If there were any, allocate space. */ - if (large_size > 0) - large_base = allocate_dynamic_stack_space (GEN_INT (large_size), 0, - large_align, true); } for (si = 0; si < n; ++si) @@ -1186,6 +1182,22 @@ expand_stack_vars (bool (*pred) (size_t), struct stack_vars_data *data) /* Large alignment is only processed in the last pass. */ if (pred) continue; + + /* If there were any variables requiring "large" alignment, allocate + space. */ + if (large_size > 0 && ! large_allocation_done) + { + HOST_WIDE_INT loffset; + rtx large_allocsize; + + large_allocsize = GEN_INT (large_size); + get_dynamic_stack_size (&large_allocsize, 0, large_align, NULL); + loffset = alloc_stack_frame_space + (INTVAL (large_allocsize), + PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT); + large_base = get_dynamic_stack_base (loffset, large_align); + large_allocation_done = true; + } gcc_assert (large_base != NULL); large_alloc += alignb - 1; |