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]

[PATCH] S/390: Better return address reg usage


Hi,

the attached patch optimizes the use of r14 (return address reg) for
leaf functions calling __builtin_return_address. Without that patch 
the back end saved r14 if it was ever used - by a read or a write access.
The patch adds a small helper function to determine whether a register 
was ever clobbered anywhere in the current function.
The value of __builtin_return_address(0) is now given by
get_hard_reg_initial_val instead of the stack location. This optimization
is only valid for the z/Architecture otherwise r14 maybe used as a temp
register in the branch splitting code.

Bootstrapped on s390 and s390x. No testsuite regressions.

Ok for mainline?

Bye,

-Andreas-


2005-05-03  Andreas Krebbel  <krebbel1@de.ibm.com>

	* config/s390/s390.c (s390_return_addr_rtx): Use
	get_hard_reg_initial_val for z/Architectures.
	(s390_reg_clobbered_rtx, s390_regs_ever_clobbered): New functions.
	(s390_init_frame_layout): Use s390_regs_ever_clobbered instead
	of regs_ever_live.
	(s390_emit_prologue): Don't use r14 as temporary if
	get_hard_reg_initial_val was called for it.


Index: gcc/config/s390/s390.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390.c,v
retrieving revision 1.223
diff -p -c -r1.223 s390.c
*** gcc/config/s390/s390.c	23 Apr 2005 21:28:35 -0000	1.223
--- gcc/config/s390/s390.c	3 May 2005 11:03:24 -0000
*************** s390_return_addr_rtx (int count, rtx fra
*** 5918,5925 ****
  
    if (count == 0)
      {
!       cfun_frame_layout.save_return_addr_p = true;
!       return gen_rtx_MEM (Pmode, return_address_pointer_rtx);
      }
  
    if (TARGET_PACKED_STACK)
--- 5918,5931 ----
  
    if (count == 0)
      {
!       /* On non-z architectures branch splitting could overwrite r14.  */
!       if (TARGET_CPU_ZARCH)
! 	return get_hard_reg_initial_val (Pmode, RETURN_REGNUM);
!       else
! 	{
! 	  cfun_frame_layout.save_return_addr_p = true;
! 	  return gen_rtx_MEM (Pmode, return_address_pointer_rtx);
! 	}
      }
  
    if (TARGET_PACKED_STACK)
*************** s390_frame_info (void)
*** 6211,6216 ****
--- 6217,6276 ----
      }
  }
  
+ /* Helper function for s390_regs_ever_clobbered. Sets the fields in DATA for all 
+    clobbered hard regs in SETREG.  */
+ 
+ static void
+ s390_reg_clobbered_rtx (rtx setreg, rtx set_insn ATTRIBUTE_UNUSED, void *data)
+ {
+   int *regs_ever_clobbered = (int*)data;
+   unsigned int i;
+ 
+   while (GET_CODE (setreg) == SUBREG)
+     setreg = SUBREG_REG (setreg);
+ 
+   if (GENERAL_REG_P (setreg))
+     {
+       for (i = REGNO (setreg); 
+ 	   i < REGNO (setreg) + HARD_REGNO_NREGS (REGNO (setreg), 
+ 						  GET_MODE (setreg));
+ 	   i++)
+ 	regs_ever_clobbered[i] = 1;
+     }
+ }
+ 
+ /* Walks through all basic blocks of the current function looking
+    for clobbered hard regs using s390_reg_clobbered_rtx. The fields
+    of the passed integer array REGS_EVER_CLOBBERED are set to one for
+    each those regs.  */
+ 
+ static void
+ s390_regs_ever_clobbered (int *regs_ever_clobbered)
+ {
+   basic_block cur_bb;
+   rtx cur_insn;
+   int i;
+ 
+   memset (regs_ever_clobbered, 0, 16 * sizeof (int));
+ 
+   if (!current_function_is_leaf)
+     {
+       for (i = 0; i < 16; i++)
+ 	regs_ever_clobbered[i] = call_really_used_regs[i];
+     }
+ 
+   FOR_EACH_BB(cur_bb)
+     {
+       FOR_BB_INSNS (cur_bb, cur_insn)
+ 	{
+ 	  if (INSN_P (cur_insn))
+ 	    note_stores (PATTERN (cur_insn),
+ 			 s390_reg_clobbered_rtx, 
+ 			 regs_ever_clobbered);
+ 	}
+     }
+ }
+ 
  /* Generate frame layout.  Fills in register and frame data for the current
     function in cfun->machine.  This routine can be called multiple times;
     it will re-do the complete frame layout every time.  */
*************** s390_init_frame_layout (void)
*** 6221,6229 ****
    HOST_WIDE_INT frame_size;
    int base_used;
    int live_regs[16];
  
    /* If return address register is explicitly used, we need to save it.  */
!   if (regs_ever_live[RETURN_REGNUM]
        || !current_function_is_leaf
        || TARGET_TPF_PROFILING
        || current_function_stdarg
--- 6281,6292 ----
    HOST_WIDE_INT frame_size;
    int base_used;
    int live_regs[16];
+   int clobbered_regs[16];
+ 
+   s390_regs_ever_clobbered (clobbered_regs);
  
    /* If return address register is explicitly used, we need to save it.  */
!   if (clobbered_regs[RETURN_REGNUM]
        || !current_function_is_leaf
        || TARGET_TPF_PROFILING
        || current_function_stdarg
*************** s390_emit_prologue (void)
*** 6547,6553 ****
    /* Choose best register to use for temp use within prologue.
       See below for why TPF must use the register 1.  */
  
!   if (!current_function_is_leaf && !TARGET_TPF_PROFILING)
      temp_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
    else
      temp_reg = gen_rtx_REG (Pmode, 1);
--- 6610,6618 ----
    /* Choose best register to use for temp use within prologue.
       See below for why TPF must use the register 1.  */
  
!   if (!has_hard_reg_initial_val (Pmode, RETURN_REGNUM) 
!       && !current_function_is_leaf 
!       && !TARGET_TPF_PROFILING)
      temp_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
    else
      temp_reg = gen_rtx_REG (Pmode, 1);


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