From 806973409adc48c8ca701d55fdbad897b0e31c78 Mon Sep 17 00:00:00 2001
From: Dominik Vogt <vogt@linux.vnet.ibm.com>
Date: Fri, 11 Dec 2015 11:33:23 +0100
Subject: [PATCH] S/390: Allow to use r1 to r4 as literal pool base
pointer.
The old code only considered r5 and r13.
---
gcc/config/s390/s390.c | 61 +++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 48 insertions(+), 13 deletions(-)
@@ -9506,6 +9506,26 @@ s390_frame_info (void)
& ~(STACK_BOUNDARY / BITS_PER_UNIT - 1));
}
+/* Returns the register number that is used as a temp register in the prologue.
+ */
+static int
+s390_get_prologue_temp_regno (void)
+{
+ if (!has_hard_reg_initial_val (Pmode, RETURN_REGNUM)
+ && !crtl->is_leaf
+ && !TARGET_TPF_PROFILING)
+ return RETURN_REGNUM;
+ if (cfun_save_high_fprs_p)
+ /* Needs an address register. */
+ return 1;
+ else if (TARGET_BACKCHAIN)
+ /* Does not need an address register. */
+ return 0;
+
+ /* No temp register needed. */
+ return -1;
+}
+
/* 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. */
@@ -9543,10 +9563,24 @@ s390_init_frame_layout (void)
as base register to avoid save/restore overhead. */
if (!base_used)
cfun->machine->base_reg = NULL_RTX;
- else if (crtl->is_leaf && !df_regs_ever_live_p (5))
- cfun->machine->base_reg = gen_rtx_REG (Pmode, 5);
else
- cfun->machine->base_reg = gen_rtx_REG (Pmode, BASE_REGNUM);
+ {
+ int br = 0;
+
+ if (crtl->is_leaf)
+ {
+ int temp_regno;
+
+ temp_regno = s390_get_prologue_temp_regno ();
+ /* Prefer r5 (most likely to be free). */
+ for (br = 5;
+ br >= 1 && (br == temp_regno || df_regs_ever_live_p (br));
+ br--)
+ ;
+ }
+ cfun->machine->base_reg =
+ gen_rtx_REG (Pmode, (br > 0) ? br : BASE_REGNUM);
+ }
s390_register_info ();
s390_frame_info ();
@@ -10385,19 +10419,16 @@ s390_emit_prologue (void)
{
rtx insn, addr;
rtx temp_reg;
+ int temp_regno;
int i;
int offset;
int next_fpr = 0;
- /* 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)
- && !crtl->is_leaf
- && !TARGET_TPF_PROFILING)
- temp_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
- else
- temp_reg = gen_rtx_REG (Pmode, 1);
+ /* If new uses of temp_reg are introduced into the prologue, be sure to
+ update the conditions in s390_get_prologue_temp_regno(). Otherwise the
+ prologue might overwrite the literal pool pointer in r1. */
+ temp_regno = s390_get_prologue_temp_regno ();
+ temp_reg = (temp_regno >= 0) ? gen_rtx_REG (Pmode, temp_regno) : NULL_RTX;
s390_save_gprs_to_fprs ();
@@ -10551,7 +10582,10 @@ s390_emit_prologue (void)
/* Save incoming stack pointer into temp reg. */
if (TARGET_BACKCHAIN || next_fpr)
- insn = emit_insn (gen_move_insn (temp_reg, stack_pointer_rtx));
+ {
+ gcc_assert (temp_regno >= 0);
+ insn = emit_insn (gen_move_insn (temp_reg, stack_pointer_rtx));
+ }
/* Subtract frame size from stack pointer. */
@@ -10606,6 +10640,7 @@ s390_emit_prologue (void)
if (cfun_save_high_fprs_p && next_fpr)
{
+ gcc_assert (temp_regno >= 1);
/* If the stack might be accessed through a different register
we have to make sure that the stack pointer decrement is not
moved below the use of the stack slots. */
--
2.3.0