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]

S/390: Minor reorg of s390_frame_info


Hello,

this is a minor cleanup to the logic around determining frame size and
saved/restored registers.  The main purpose is to remove some duplicated
logic between s390_frame_info, s390_arg_frame_offset, s390_emit_prologue,
and s390_optimize_prolog.

The result of this patch is to make s390_frame_info a utility routine
that can be called multiple times and from multiple locations by moving
all changes to global state out to s390_emit_prologue (its sole current
caller).  Once this is done, the other routines mentioned above are able 
to just call s390_frame_info instead of duplicating part of its logic.

This should have zero effect on generated code.

Bootstrapped/regtested on s390-ibm-linux and s390x-ibm-linux,
applied to mainline.

Bye,
Ulrich


ChangeLog:

	* config/s390/s390.c (struct machine_function):  New member
	last_restore_gpr.
	(s390_frame_info): Add BASE_USED and RETURN_ADDR_USED parameters.
	Do not modify machine->save_return_addr_p or regs_ever_live.
	Fill in machine->last_restore_gpr.
	(s390_optimize_prolog): Use s390_frame_info to compute registers
	to save/restore, remove duplicated code.
	(s390_arg_frame_offset): Use s390_frame_info to compute frame
	size, remove duplicated code.
	(s390_emit_prologue): Adapt s390_frame_info call.  Update
	machine->save_return_addr_p and regs_ever_live.
	(s390_emit_epilogue): Use machine->last_restore_gpr instead of
	machine->last_save_gpr.


Index: gcc/config/s390/s390.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390.c,v
retrieving revision 1.148
diff -c -p -r1.148 s390.c
*** gcc/config/s390/s390.c	14 Jun 2004 12:11:06 -0000	1.148
--- gcc/config/s390/s390.c	16 Jun 2004 19:53:35 -0000
*************** struct machine_function GTY(())
*** 213,218 ****
--- 213,219 ----
    int first_save_gpr;
    int first_restore_gpr;
    int last_save_gpr;
+   int last_restore_gpr;
  
    /* Size of stack frame.  */
    HOST_WIDE_INT frame_size;
*************** static rtx find_ltrel_base (rtx);
*** 242,248 ****
  static void replace_ltrel_base (rtx *, rtx);
  static void s390_optimize_prolog (bool);
  static int find_unused_clobbered_reg (void);
! static void s390_frame_info (void);
  static rtx save_fpr (rtx, int, int);
  static rtx restore_fpr (rtx, int, int);
  static rtx save_gprs (rtx, int, int, int);
--- 243,249 ----
  static void replace_ltrel_base (rtx *, rtx);
  static void s390_optimize_prolog (bool);
  static int find_unused_clobbered_reg (void);
! static void s390_frame_info (int, int);
  static rtx save_fpr (rtx, int, int);
  static rtx restore_fpr (rtx, int, int);
  static rtx save_gprs (rtx, int, int, int);
*************** s390_output_pool_entry (rtx exp, enum ma
*** 4942,5005 ****
  static void
  s390_optimize_prolog (bool base_used)
  {
-   int save_first, save_last, restore_first, restore_last;
-   int i, j;
    rtx insn, new_insn, next_insn;
  
!   /* Recompute regs_ever_live data for special registers.  */
    regs_ever_live[BASE_REGISTER] = base_used;
    regs_ever_live[RETURN_REGNUM] = cfun->machine->save_return_addr_p;
    regs_ever_live[STACK_POINTER_REGNUM] = cfun->machine->frame_size > 0;
  
- 
-   /* Find first and last gpr to be saved.  */
- 
-   for (i = 6; i < 16; i++)
-     if (regs_ever_live[i])
-       if (!global_regs[i]
- 	  || i == STACK_POINTER_REGNUM
-           || i == RETURN_REGNUM
-           || i == BASE_REGISTER
-           || (flag_pic && i == (int)PIC_OFFSET_TABLE_REGNUM))
- 	break;
- 
-   for (j = 15; j > i; j--)
-     if (regs_ever_live[j])
-       if (!global_regs[j]
- 	  || j == STACK_POINTER_REGNUM
-           || j == RETURN_REGNUM
-           || j == BASE_REGISTER
-           || (flag_pic && j == (int)PIC_OFFSET_TABLE_REGNUM))
- 	break;
- 
-   if (i == 16)
-     {
-       /* Nothing to save/restore.  */
-       save_first = restore_first = -1;
-       save_last = restore_last = -1;
-     }
-   else
-     {
-       /* Save/restore from i to j.  */
-       save_first = restore_first = i;
-       save_last = restore_last = j;
-     }
- 
-   /* Varargs functions need to save gprs 2 to 6.  */
-   if (current_function_stdarg)
-     {
-       save_first = 2;
-       if (save_last < 6)
-         save_last = 6;
-     }
- 
- 
    /* If all special registers are in fact used, there's nothing we
       can do, so no point in walking the insn list.  */
-   if (i <= BASE_REGISTER && j >= BASE_REGISTER
-       && (TARGET_CPU_ZARCH || (i <= RETURN_REGNUM && j >= RETURN_REGNUM)))
-     return;
  
  
    /* Search for prolog/epilog insns and replace them.  */
  
--- 4943,4966 ----
  static void
  s390_optimize_prolog (bool base_used)
  {
    rtx insn, new_insn, next_insn;
  
!   /* Do a final recompute of the frame-related data.  */
! 
!   s390_frame_info (base_used, cfun->machine->save_return_addr_p);
    regs_ever_live[BASE_REGISTER] = base_used;
    regs_ever_live[RETURN_REGNUM] = cfun->machine->save_return_addr_p;
    regs_ever_live[STACK_POINTER_REGNUM] = cfun->machine->frame_size > 0;
  
    /* If all special registers are in fact used, there's nothing we
       can do, so no point in walking the insn list.  */
  
+   if (cfun->machine->first_save_gpr <= BASE_REGISTER 
+       && cfun->machine->last_save_gpr >= BASE_REGISTER
+       && (TARGET_CPU_ZARCH 
+           || (cfun->machine->first_save_gpr <= RETURN_REGNUM 
+               && cfun->machine->last_save_gpr >= RETURN_REGNUM)))
+     return;
  
    /* Search for prolog/epilog insns and replace them.  */
  
*************** s390_optimize_prolog (bool base_used)
*** 5028,5036 ****
  	  if (first > BASE_REGISTER || last < BASE_REGISTER)
  	    continue;
  
! 	  if (save_first != -1)
  	    {
! 	      new_insn = save_gprs (base, off, save_first, save_last);
  	      new_insn = emit_insn_before (new_insn, insn);
  	      INSN_ADDRESSES_NEW (new_insn, -1);
  	    }
--- 4989,4998 ----
  	  if (first > BASE_REGISTER || last < BASE_REGISTER)
  	    continue;
  
! 	  if (cfun->machine->first_save_gpr != -1)
  	    {
! 	      new_insn = save_gprs (base, off, cfun->machine->first_save_gpr,
! 				    cfun->machine->last_save_gpr);
  	      new_insn = emit_insn_before (new_insn, insn);
  	      INSN_ADDRESSES_NEW (new_insn, -1);
  	    }
*************** s390_optimize_prolog (bool base_used)
*** 5052,5060 ****
  	  if (GET_CODE (base) != REG || off < 0)
  	    continue;
  
! 	  if (save_first != -1)
  	    {
! 	      new_insn = save_gprs (base, off, save_first, save_last);
  	      new_insn = emit_insn_before (new_insn, insn);
  	      INSN_ADDRESSES_NEW (new_insn, -1);
  	    }
--- 5014,5023 ----
  	  if (GET_CODE (base) != REG || off < 0)
  	    continue;
  
! 	  if (cfun->machine->first_save_gpr != -1)
  	    {
! 	      new_insn = save_gprs (base, off, cfun->machine->first_save_gpr,
! 				    cfun->machine->last_save_gpr);
  	      new_insn = emit_insn_before (new_insn, insn);
  	      INSN_ADDRESSES_NEW (new_insn, -1);
  	    }
*************** s390_optimize_prolog (bool base_used)
*** 5078,5086 ****
  	  if (first > BASE_REGISTER || last < BASE_REGISTER)
  	    continue;
  
! 	  if (restore_first != -1)
  	    {
! 	      new_insn = restore_gprs (base, off, restore_first, restore_last);
  	      new_insn = emit_insn_before (new_insn, insn);
  	      INSN_ADDRESSES_NEW (new_insn, -1);
  	    }
--- 5041,5050 ----
  	  if (first > BASE_REGISTER || last < BASE_REGISTER)
  	    continue;
  
! 	  if (cfun->machine->first_restore_gpr != -1)
  	    {
! 	      new_insn = restore_gprs (base, off, cfun->machine->first_restore_gpr,
! 				       cfun->machine->last_restore_gpr);
  	      new_insn = emit_insn_before (new_insn, insn);
  	      INSN_ADDRESSES_NEW (new_insn, -1);
  	    }
*************** s390_optimize_prolog (bool base_used)
*** 5102,5110 ****
  	  if (GET_CODE (base) != REG || off < 0)
  	    continue;
  
! 	  if (restore_first != -1)
  	    {
! 	      new_insn = restore_gprs (base, off, restore_first, restore_last);
  	      new_insn = emit_insn_before (new_insn, insn);
  	      INSN_ADDRESSES_NEW (new_insn, -1);
  	    }
--- 5066,5075 ----
  	  if (GET_CODE (base) != REG || off < 0)
  	    continue;
  
! 	  if (cfun->machine->first_restore_gpr != -1)
  	    {
! 	      new_insn = restore_gprs (base, off, cfun->machine->first_restore_gpr,
! 				       cfun->machine->last_restore_gpr);
  	      new_insn = emit_insn_before (new_insn, insn);
  	      INSN_ADDRESSES_NEW (new_insn, -1);
  	    }
*************** find_unused_clobbered_reg (void)
*** 5258,5268 ****
    return 0;
  }
  
! /* Fill FRAME with info about frame of current function.  */
  
  static void
! s390_frame_info (void)
  {
    int i, j;
    HOST_WIDE_INT fsize = get_frame_size ();
  
--- 5223,5236 ----
    return 0;
  }
  
! /* Fill cfun->machine with info about frame of current function.  
!    BASE_USED and RETURN_ADDR_USED specify whether we assume the
!    base and return address register will need to be saved.  */
  
  static void
! s390_frame_info (int base_used, int return_addr_used)
  {
+   int live_regs[16];
    int i, j;
    HOST_WIDE_INT fsize = get_frame_size ();
  
*************** s390_frame_info (void)
*** 5283,5341 ****
  
    /* Does function need to setup frame and save area.  */
  
!   if (! current_function_is_leaf
        || TARGET_TPF_PROFILING
        || cfun->machine->frame_size > 0
        || current_function_calls_alloca
        || current_function_stdarg)
      cfun->machine->frame_size += STARTING_FRAME_OFFSET;
  
!   /* If we use the return register, we'll need to make sure
!      it is going to be saved/restored.  */
  
!   if (!current_function_is_leaf
!       || TARGET_TPF_PROFILING
!       || regs_ever_live[RETURN_REGNUM])
!     cfun->machine->save_return_addr_p = 1;
  
!   /* Find first and last gpr to be saved.  Note that at this point,
!      we assume the base register and -on S/390- the return register
!      always need to be saved.  This is done because the usage of these
!      register might change even after the prolog was emitted.
!      If it turns out later that we really don't need them, the
!      prolog/epilog code is modified again.  */
  
!   regs_ever_live[BASE_REGISTER] = 1;
!   if (!TARGET_CPU_ZARCH || cfun->machine->save_return_addr_p)
!     regs_ever_live[RETURN_REGNUM] = 1;
!   regs_ever_live[STACK_POINTER_REGNUM] = cfun->machine->frame_size > 0;
  
!   for (i = 6; i < 16; i++)
!     if (regs_ever_live[i])
!       if (!global_regs[i]
! 	  || i == STACK_POINTER_REGNUM
!           || i == RETURN_REGNUM
!           || i == BASE_REGISTER
!           || (flag_pic && i == (int)PIC_OFFSET_TABLE_REGNUM))
! 	break;
  
    for (j = 15; j > i; j--)
!     if (regs_ever_live[j])
!       if (!global_regs[j]
! 	  || j == STACK_POINTER_REGNUM
!           || j == RETURN_REGNUM
!           || j == BASE_REGISTER
!           || (flag_pic && j == (int)PIC_OFFSET_TABLE_REGNUM))
! 	break;
  
!   /* Save / Restore from gpr i to j.  */
!   cfun->machine->first_save_gpr = i;
!   cfun->machine->first_restore_gpr = i;
!   cfun->machine->last_save_gpr  = j;
  
    /* Varargs functions need to save gprs 2 to 6.  */
    if (current_function_stdarg)
!     cfun->machine->first_save_gpr = 2;
  }
  
  /* Return offset between argument pointer and frame pointer
--- 5251,5315 ----
  
    /* Does function need to setup frame and save area.  */
  
!   if (!current_function_is_leaf
        || TARGET_TPF_PROFILING
        || cfun->machine->frame_size > 0
        || current_function_calls_alloca
        || current_function_stdarg)
      cfun->machine->frame_size += STARTING_FRAME_OFFSET;
  
!   /* Find first and last gpr to be saved.  We trust regs_ever_live
!      data, except that we don't save and restore global registers.
  
!      Also, all registers with special meaning to the compiler need
!      to be handled extra.  */
  
!   for (i = 0; i < 16; i++)
!     live_regs[i] = regs_ever_live[i] && !global_regs[i];
  
!   if (flag_pic)
!     live_regs[PIC_OFFSET_TABLE_REGNUM] = 
!     regs_ever_live[PIC_OFFSET_TABLE_REGNUM];
  
!   live_regs[BASE_REGISTER] = base_used;
!   live_regs[RETURN_REGNUM] = return_addr_used;
!   live_regs[STACK_POINTER_REGNUM] = cfun->machine->frame_size > 0;
  
+   for (i = 6; i < 16; i++)
+     if (live_regs[i])
+       break;
    for (j = 15; j > i; j--)
!     if (live_regs[j])
!       break;
  
!   if (i == 16)
!     {
!       /* Nothing to save/restore.  */
!       cfun->machine->first_save_gpr = -1;
!       cfun->machine->first_restore_gpr = -1;
!       cfun->machine->last_save_gpr = -1;
!       cfun->machine->last_restore_gpr = -1;
!     }
!   else
!     {
!       /* Save / Restore from gpr i to j.  */
!       cfun->machine->first_save_gpr = i;
!       cfun->machine->first_restore_gpr = i;
!       cfun->machine->last_save_gpr = j;
!       cfun->machine->last_restore_gpr = j;
!     }
  
    /* Varargs functions need to save gprs 2 to 6.  */
    if (current_function_stdarg)
!     {
!       if (cfun->machine->first_save_gpr == -1
!           || cfun->machine->first_save_gpr > 2)
!         cfun->machine->first_save_gpr = 2;
! 
!       if (cfun->machine->last_save_gpr == -1
!           || cfun->machine->last_save_gpr < 6)
!         cfun->machine->last_save_gpr = 6;
!     }
  }
  
  /* Return offset between argument pointer and frame pointer
*************** s390_frame_info (void)
*** 5344,5373 ****
  HOST_WIDE_INT
  s390_arg_frame_offset (void)
  {
!   HOST_WIDE_INT fsize = get_frame_size ();
!   int save_fprs_p, i;
  
!   /* fprs 8 - 15 are caller saved for 64 Bit ABI.  */
!   save_fprs_p = 0;
!   if (TARGET_64BIT)
!     for (i = 24; i < 32; i++)
!       if (regs_ever_live[i] && !global_regs[i])
! 	{
!           save_fprs_p = 1;
! 	  break;
! 	}
! 
!   fsize = fsize + save_fprs_p * 64;
! 
!   /* Does function need to setup frame and save area.  */
! 
!   if (! current_function_is_leaf
!       || TARGET_TPF_PROFILING
!       || fsize > 0
!       || current_function_calls_alloca
!       || current_function_stdarg)
!     fsize += STARTING_FRAME_OFFSET;
!   return fsize + STACK_POINTER_OFFSET;
  }
  
  /* Emit insn to save fpr REGNUM at offset OFFSET relative
--- 5318,5332 ----
  HOST_WIDE_INT
  s390_arg_frame_offset (void)
  {
!   /* See the comment in s390_emit_prologue about the assumptions we make
!      whether or not the base and return address register need to be saved.  */
!   int return_addr_used = !current_function_is_leaf
! 			 || TARGET_TPF_PROFILING
! 			 || regs_ever_live[RETURN_REGNUM]
! 			 || cfun->machine->save_return_addr_p;
  
!   s390_frame_info (1, !TARGET_CPU_ZARCH || return_addr_used);
!   return cfun->machine->frame_size + STACK_POINTER_OFFSET;
  }
  
  /* Emit insn to save fpr REGNUM at offset OFFSET relative
*************** s390_emit_prologue (void)
*** 5556,5564 ****
    rtx temp_reg;
    int i;
  
!   /* Compute frame_info.  */
  
!   s390_frame_info ();
  
    /* Choose best register to use for temp use within prologue.
       See below for why TPF must use the register 1.  */
--- 5515,5543 ----
    rtx temp_reg;
    int i;
  
!   /* At this point, we decide whether we'll need to save/restore the
!      return address register.  This decision is final on zSeries machines;
!      on S/390 it can still be overridden in s390_split_branches.  */
! 
!   if (!current_function_is_leaf
!       || TARGET_TPF_PROFILING
!       || regs_ever_live[RETURN_REGNUM])
!     cfun->machine->save_return_addr_p = 1;
! 
!   /* Compute frame info.  Note that at this point, we assume the base 
!      register and -on S/390- the return register always need to be saved.
!      This is done because the usage of these registers might change even 
!      after the prolog was emitted.  If it turns out later that we really 
!      don't need them, the prolog/epilog code is modified again.  */
  
!   s390_frame_info (1, !TARGET_CPU_ZARCH || cfun->machine->save_return_addr_p);
! 
!   /* We need to update regs_ever_live to avoid data-flow problems.  */
! 
!   regs_ever_live[BASE_REGISTER] = 1;
!   regs_ever_live[RETURN_REGNUM] = !TARGET_CPU_ZARCH 
! 				  || cfun->machine->save_return_addr_p;
!   regs_ever_live[STACK_POINTER_REGNUM] = cfun->machine->frame_size > 0;
  
    /* Choose best register to use for temp use within prologue.
       See below for why TPF must use the register 1.  */
*************** s390_emit_epilogue (bool sibcall)
*** 5736,5742 ****
    if (cfun->machine->first_restore_gpr != -1)
      {
        area_bottom = cfun->machine->first_restore_gpr * UNITS_PER_WORD;
!       area_top = (cfun->machine->last_save_gpr + 1) * UNITS_PER_WORD;
      }
    else
      {
--- 5715,5721 ----
    if (cfun->machine->first_restore_gpr != -1)
      {
        area_bottom = cfun->machine->first_restore_gpr * UNITS_PER_WORD;
!       area_top = (cfun->machine->last_restore_gpr + 1) * UNITS_PER_WORD;
      }
    else
      {
*************** s390_emit_epilogue (bool sibcall)
*** 5834,5840 ****
  	 to stack location from where they get restored.  */
  
        for (i = cfun->machine->first_restore_gpr;
! 	   i <= cfun->machine->last_save_gpr;
  	   i++)
  	{
  	  /* These registers are special and need to be
--- 5813,5819 ----
  	 to stack location from where they get restored.  */
  
        for (i = cfun->machine->first_restore_gpr;
! 	   i <= cfun->machine->last_restore_gpr;
  	   i++)
  	{
  	  /* These registers are special and need to be
*************** s390_emit_epilogue (bool sibcall)
*** 5862,5868 ****
  
  	  if (cfun->machine->save_return_addr_p
  	      || (cfun->machine->first_restore_gpr < BASE_REGISTER
! 		  && cfun->machine->last_save_gpr > RETURN_REGNUM))
  	    {
  	      int return_regnum = find_unused_clobbered_reg();
  	      if (!return_regnum)
--- 5841,5847 ----
  
  	  if (cfun->machine->save_return_addr_p
  	      || (cfun->machine->first_restore_gpr < BASE_REGISTER
! 		  && cfun->machine->last_restore_gpr > RETURN_REGNUM))
  	    {
  	      int return_regnum = find_unused_clobbered_reg();
  	      if (!return_regnum)
*************** s390_emit_epilogue (bool sibcall)
*** 5885,5891 ****
  
        insn = restore_gprs (frame_pointer, offset,
  			   cfun->machine->first_restore_gpr,
! 			   cfun->machine->last_save_gpr);
        emit_insn (insn);
      }
  
--- 5864,5870 ----
  
        insn = restore_gprs (frame_pointer, offset,
  			   cfun->machine->first_restore_gpr,
! 			   cfun->machine->last_restore_gpr);
        emit_insn (insn);
      }
  
-- 
  Dr. Ulrich Weigand
  weigand@informatik.uni-erlangen.de


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