This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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:

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]