aboutsummaryrefslogtreecommitdiff
path: root/gcc/cfgexpand.c
diff options
context:
space:
mode:
authorDominik Vogt <vogt@linux.vnet.ibm.com>2016-07-18 13:10:27 +0000
committerAndreas Krebbel <krebbel@gcc.gnu.org>2016-07-18 13:10:27 +0000
commit7072df0aae0c59ae437e5cc28e4e5e5777e930ba (patch)
treeeae0f0bf4792f63f3083251ebd6cbec79241a3cb /gcc/cfgexpand.c
parent54158a1aa94f7b75f59d6ca8d6ca7ebfc11e1673 (diff)
downloadgcc-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.c22
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;