This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] S/390: Better return address reg usage
- From: Andreas Krebbel <krebbel1 at de dot ibm dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 3 May 2005 16:08:22 +0200
- Subject: [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);