This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[IA-64] Fix dynamic allocation in leaf functions
- From: Eric Botcazou <ebotcazou at adacore dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 19 Nov 2012 23:12:14 +0100
- Subject: [IA-64] Fix dynamic allocation in leaf functions
Hi,
the IA-64 has a red zone of 16 bytes at the bottom of the stack:
/* IA64 has a 16 byte scratch area that is at the bottom of the stack. */
#define STACK_POINTER_OFFSET 16
but doesn't maintain it for leaf functions:
/* We always use the 16-byte scratch area provided by the caller, but
if we are a leaf function, there's no one to which we need to provide
a scratch area. */
if (crtl->is_leaf)
total_size = MAX (0, total_size - 16);
Things go wrong when a dynamic allocation is made in a leaf function, because
STACK_DYNAMIC_OFFSET comprises STACK_POINTER_OFFSET and thus thinks that the
red zone is present. This has probably been there since day #1 but was hidden
by the double alignment that used to be made by allocate_dynamic_stack_space
up to 4.5 and that was cleaned up by RTH in 4.6 and up.
Fix attached, bootstrapped/regtested on ia64-suse-linux. It eliminates:
-FAIL: gcc.c-torture/execute/20040811-1.c execution, -O0
-FAIL: gcc.c-torture/execute/pr43220.c execution, -O0
-FAIL: gcc.c-torture/execute/vla-dealloc-1.c execution, -O0
-WARNING: program timed out.
-WARNING: program timed out.
-WARNING: program timed out.
on the mainline. I think that we need to put this on mainline and 4.7 branch
at least; not clear for the 4.6 branch at this point. OK for which ones?
2012-11-19 Eric Botcazou <ebotcazou@adacore.com>
* config/ia64/ia64.c (ia64_compute_frame_size): Allocate the scratch
area if the function allocates dynamic stack space.
(ia64_initial_elimination_offset): Adjust offsets to above change.
--
Eric Botcazou
Index: config/ia64/ia64.c
===================================================================
--- config/ia64/ia64.c (revision 193596)
+++ config/ia64/ia64.c (working copy)
@@ -2885,8 +2885,10 @@ ia64_compute_frame_size (HOST_WIDE_INT s
/* We always use the 16-byte scratch area provided by the caller, but
if we are a leaf function, there's no one to which we need to provide
- a scratch area. */
- if (crtl->is_leaf)
+ a scratch area. However, if the function allocates dynamic stack space,
+ the dynamic offset is computed early and contains STACK_POINTER_OFFSET,
+ so we need to cope. */
+ if (crtl->is_leaf && !cfun->calls_alloca)
total_size = MAX (0, total_size - 16);
current_frame_info.total_size = total_size;
@@ -2920,18 +2922,15 @@ ia64_initial_elimination_offset (int fro
switch (to)
{
case HARD_FRAME_POINTER_REGNUM:
- if (crtl->is_leaf)
- offset = -current_frame_info.total_size;
- else
- offset = -(current_frame_info.total_size
- - crtl->outgoing_args_size - 16);
+ offset = -current_frame_info.total_size;
+ if (!crtl->is_leaf || cfun->calls_alloca)
+ offset += 16 + crtl->outgoing_args_size;
break;
case STACK_POINTER_REGNUM:
- if (crtl->is_leaf)
- offset = 0;
- else
- offset = 16 + crtl->outgoing_args_size;
+ offset = 0;
+ if (!crtl->is_leaf || cfun->calls_alloca)
+ offset += 16 + crtl->outgoing_args_size;
break;
default: