[2/7] v7: Handle frame pointer for stack alignment

H.J. Lu hjl.tools@gmail.com
Sat Jun 28 18:11:00 GMT 2008


Frame pointer register is used by stack alignment to save and restore
stack pointer. So we have to eliminate frame pointer when stack is
aligned.  We also can only set if frame pointer is needed in one place.
This patch moved frame_pointer_needed initialization to compute_regsets
which is called before init_elim_table. Tested on Linux/ia32,
Linux/x86-64 and Linux/ia64.  Ian, Ricard, is this OK for trunk?

Thanks.

H.J.
---
2008-06-28  Joey Ye  <joey.ye@intel.com>
	    H.J. Lu  <hongjiu.lu@intel.com>

	* reload1.c (init_elim_table): Move frame_pointer_needed
	initialization to ...
	* global.c (compute_regsets): Here. Set frame_pointer_needed
	when stack is realigned.

	* global.c (compute_regsets): Eliminate frame pointer when
	stack is realigned.
	* reload1.c (init_elim_table): Likwise.

--- ../../gcc/gcc/global.c	2008-06-27 08:52:44.000000000 -0700
+++ gcc/gcc/global.c	2008-06-28 08:59:50.000000000 -0700
@@ -206,7 +206,9 @@ static void build_insn_chain (void);
 
    This will normally be called with ELIM_SET as the file static
    variable eliminable_regset, and NO_GLOBAL_SET as the file static
-   variable NO_GLOBAL_ALLOC_REGS.  */
+   variable NO_GLOBAL_ALLOC_REGS.
+
+   It also initializes frame_pointer_needed.  */
 
 static void
 compute_regsets (HARD_REG_SET *elim_set, 
@@ -222,10 +224,19 @@ compute_regsets (HARD_REG_SET *elim_set,
   static const struct {const int from, to; } eliminables[] = ELIMINABLE_REGS;
   size_t i;
 #endif
+
+  /* FIXME: If EXIT_IGNORE_STACK is set, we will not save and restore
+     sp for alloca.  So we can't eliminate the frame pointer in that
+     case.  At some point, we should improve this by emitting the
+     sp-adjusting insns for this case.  */
   int need_fp
     = (! flag_omit_frame_pointer
        || (cfun->calls_alloca && EXIT_IGNORE_STACK)
-       || FRAME_POINTER_REQUIRED);
+       || FRAME_POINTER_REQUIRED
+       || crtl->accesses_prior_frames
+       || crtl->stack_realign_needed);
+
+  frame_pointer_needed = need_fp;
 
   max_regno = max_reg_num ();
   compact_blocks ();
@@ -246,7 +257,10 @@ compute_regsets (HARD_REG_SET *elim_set,
     {
       bool cannot_elim
 	= (! CAN_ELIMINATE (eliminables[i].from, eliminables[i].to)
-	   || (eliminables[i].to == STACK_POINTER_REGNUM && need_fp));
+	   || (eliminables[i].to == STACK_POINTER_REGNUM
+	       && need_fp 
+	       && (! SUPPORTS_STACK_ALIGNMENT
+		   || ! stack_realign_fp)));
 
       if (!regs_asm_clobbered[eliminables[i].from])
 	{
--- ../../gcc/gcc/reload1.c	2008-06-27 08:52:44.000000000 -0700
+++ gcc/gcc/reload1.c	2008-06-27 10:00:33.000000000 -0700
@@ -3663,8 +3663,11 @@ update_eliminables (HARD_REG_SET *pset)
   frame_pointer_needed = 1;
   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
     {
-      if (ep->can_eliminate && ep->from == FRAME_POINTER_REGNUM
-	  && ep->to != HARD_FRAME_POINTER_REGNUM)
+      if (ep->can_eliminate
+	  && ep->from == FRAME_POINTER_REGNUM
+	  && ep->to != HARD_FRAME_POINTER_REGNUM
+	  && (! SUPPORTS_STACK_ALIGNMENT
+	      || ! crtl->stack_realign_needed))
 	frame_pointer_needed = 0;
 
       if (! ep->can_eliminate && ep->can_eliminate_previous)
@@ -3695,7 +3698,9 @@ elimination_target_reg_p (rtx x)
   return false;
 }
 
-/* Initialize the table of registers to eliminate.  */
+/* Initialize the table of registers to eliminate.
+   Pre-condition: global flag frame_pointer_needed has been set before
+   calling this function.  */
 
 static void
 init_elim_table (void)
@@ -3708,19 +3713,6 @@ init_elim_table (void)
   if (!reg_eliminate)
     reg_eliminate = XCNEWVEC (struct elim_table, NUM_ELIMINABLE_REGS);
 
-  /* Does this function require a frame pointer?  */
-
-  frame_pointer_needed = (! flag_omit_frame_pointer
-			  /* ?? If EXIT_IGNORE_STACK is set, we will not save
-			     and restore sp for alloca.  So we can't eliminate
-			     the frame pointer in that case.  At some point,
-			     we should improve this by emitting the
-			     sp-adjusting insns for this case.  */
-			  || (cfun->calls_alloca
-			      && EXIT_IGNORE_STACK)
-			  || crtl->accesses_prior_frames
-			  || FRAME_POINTER_REQUIRED);
-
   num_eliminable = 0;
 
 #ifdef ELIMINABLE_REGS
@@ -3731,7 +3723,10 @@ init_elim_table (void)
       ep->to = ep1->to;
       ep->can_eliminate = ep->can_eliminate_previous
 	= (CAN_ELIMINATE (ep->from, ep->to)
-	   && ! (ep->to == STACK_POINTER_REGNUM && frame_pointer_needed));
+	   && ! (ep->to == STACK_POINTER_REGNUM
+		 && frame_pointer_needed 
+		 && (! SUPPORTS_STACK_ALIGNMENT
+		     || ! stack_realign_fp)));
     }
 #else
   reg_eliminate[0].from = reg_eliminate_1[0].from;



More information about the Gcc-patches mailing list