This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
S/390: Minor reorg of s390_frame_info
- From: Ulrich Weigand <weigand at i1 dot informatik dot uni-erlangen dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 17 Jun 2004 01:43:48 +0200 (CEST)
- Subject: 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