Commit b767fc11 by Ulrich Weigand Committed by Ulrich Weigand

s390.c (struct machine_function): New member last_restore_gpr.

	* 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.

From-SVN: r83275
parent 16865eaa
2004-06-16 Ulrich Weigand <uweigand@de.ibm.com>
* 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.
2004-06-16 Richard Henderson <rth@redhat.com> 2004-06-16 Richard Henderson <rth@redhat.com>
* c-parse.in (if_stmt_locus): Remove. * c-parse.in (if_stmt_locus): Remove.
......
...@@ -213,6 +213,7 @@ struct machine_function GTY(()) ...@@ -213,6 +213,7 @@ struct machine_function GTY(())
int first_save_gpr; int first_save_gpr;
int first_restore_gpr; int first_restore_gpr;
int last_save_gpr; int last_save_gpr;
int last_restore_gpr;
/* Size of stack frame. */ /* Size of stack frame. */
HOST_WIDE_INT frame_size; HOST_WIDE_INT frame_size;
...@@ -242,7 +243,7 @@ static rtx find_ltrel_base (rtx); ...@@ -242,7 +243,7 @@ static rtx find_ltrel_base (rtx);
static void replace_ltrel_base (rtx *, rtx); static void replace_ltrel_base (rtx *, rtx);
static void s390_optimize_prolog (bool); static void s390_optimize_prolog (bool);
static int find_unused_clobbered_reg (void); static int find_unused_clobbered_reg (void);
static void s390_frame_info (void); static void s390_frame_info (int, int);
static rtx save_fpr (rtx, int, int); static rtx save_fpr (rtx, int, int);
static rtx restore_fpr (rtx, int, int); static rtx restore_fpr (rtx, int, int);
static rtx save_gprs (rtx, int, int, int); static rtx save_gprs (rtx, int, int, int);
...@@ -4942,64 +4943,24 @@ s390_output_pool_entry (rtx exp, enum machine_mode mode, unsigned int align) ...@@ -4942,64 +4943,24 @@ s390_output_pool_entry (rtx exp, enum machine_mode mode, unsigned int align)
static void static void
s390_optimize_prolog (bool base_used) s390_optimize_prolog (bool base_used)
{ {
int save_first, save_last, restore_first, restore_last;
int i, j;
rtx insn, new_insn, next_insn; rtx insn, new_insn, next_insn;
/* Recompute regs_ever_live data for special registers. */ /* 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[BASE_REGISTER] = base_used;
regs_ever_live[RETURN_REGNUM] = cfun->machine->save_return_addr_p; regs_ever_live[RETURN_REGNUM] = cfun->machine->save_return_addr_p;
regs_ever_live[STACK_POINTER_REGNUM] = cfun->machine->frame_size > 0; 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 /* If all special registers are in fact used, there's nothing we
can do, so no point in walking the insn list. */ 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;
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. */ /* Search for prolog/epilog insns and replace them. */
...@@ -5028,9 +4989,10 @@ s390_optimize_prolog (bool base_used) ...@@ -5028,9 +4989,10 @@ s390_optimize_prolog (bool base_used)
if (first > BASE_REGISTER || last < BASE_REGISTER) if (first > BASE_REGISTER || last < BASE_REGISTER)
continue; continue;
if (save_first != -1) if (cfun->machine->first_save_gpr != -1)
{ {
new_insn = save_gprs (base, off, save_first, save_last); new_insn = save_gprs (base, off, cfun->machine->first_save_gpr,
cfun->machine->last_save_gpr);
new_insn = emit_insn_before (new_insn, insn); new_insn = emit_insn_before (new_insn, insn);
INSN_ADDRESSES_NEW (new_insn, -1); INSN_ADDRESSES_NEW (new_insn, -1);
} }
...@@ -5052,9 +5014,10 @@ s390_optimize_prolog (bool base_used) ...@@ -5052,9 +5014,10 @@ s390_optimize_prolog (bool base_used)
if (GET_CODE (base) != REG || off < 0) if (GET_CODE (base) != REG || off < 0)
continue; continue;
if (save_first != -1) if (cfun->machine->first_save_gpr != -1)
{ {
new_insn = save_gprs (base, off, save_first, save_last); new_insn = save_gprs (base, off, cfun->machine->first_save_gpr,
cfun->machine->last_save_gpr);
new_insn = emit_insn_before (new_insn, insn); new_insn = emit_insn_before (new_insn, insn);
INSN_ADDRESSES_NEW (new_insn, -1); INSN_ADDRESSES_NEW (new_insn, -1);
} }
...@@ -5078,9 +5041,10 @@ s390_optimize_prolog (bool base_used) ...@@ -5078,9 +5041,10 @@ s390_optimize_prolog (bool base_used)
if (first > BASE_REGISTER || last < BASE_REGISTER) if (first > BASE_REGISTER || last < BASE_REGISTER)
continue; continue;
if (restore_first != -1) if (cfun->machine->first_restore_gpr != -1)
{ {
new_insn = restore_gprs (base, off, restore_first, restore_last); new_insn = restore_gprs (base, off, cfun->machine->first_restore_gpr,
cfun->machine->last_restore_gpr);
new_insn = emit_insn_before (new_insn, insn); new_insn = emit_insn_before (new_insn, insn);
INSN_ADDRESSES_NEW (new_insn, -1); INSN_ADDRESSES_NEW (new_insn, -1);
} }
...@@ -5102,9 +5066,10 @@ s390_optimize_prolog (bool base_used) ...@@ -5102,9 +5066,10 @@ s390_optimize_prolog (bool base_used)
if (GET_CODE (base) != REG || off < 0) if (GET_CODE (base) != REG || off < 0)
continue; continue;
if (restore_first != -1) if (cfun->machine->first_restore_gpr != -1)
{ {
new_insn = restore_gprs (base, off, restore_first, restore_last); new_insn = restore_gprs (base, off, cfun->machine->first_restore_gpr,
cfun->machine->last_restore_gpr);
new_insn = emit_insn_before (new_insn, insn); new_insn = emit_insn_before (new_insn, insn);
INSN_ADDRESSES_NEW (new_insn, -1); INSN_ADDRESSES_NEW (new_insn, -1);
} }
...@@ -5258,11 +5223,14 @@ find_unused_clobbered_reg (void) ...@@ -5258,11 +5223,14 @@ find_unused_clobbered_reg (void)
return 0; return 0;
} }
/* Fill FRAME with info about frame of current function. */ /* 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 static void
s390_frame_info (void) s390_frame_info (int base_used, int return_addr_used)
{ {
int live_regs[16];
int i, j; int i, j;
HOST_WIDE_INT fsize = get_frame_size (); HOST_WIDE_INT fsize = get_frame_size ();
...@@ -5283,59 +5251,65 @@ s390_frame_info (void) ...@@ -5283,59 +5251,65 @@ s390_frame_info (void)
/* Does function need to setup frame and save area. */ /* Does function need to setup frame and save area. */
if (! current_function_is_leaf if (!current_function_is_leaf
|| TARGET_TPF_PROFILING || TARGET_TPF_PROFILING
|| cfun->machine->frame_size > 0 || cfun->machine->frame_size > 0
|| current_function_calls_alloca || current_function_calls_alloca
|| current_function_stdarg) || current_function_stdarg)
cfun->machine->frame_size += STARTING_FRAME_OFFSET; cfun->machine->frame_size += STARTING_FRAME_OFFSET;
/* If we use the return register, we'll need to make sure /* Find first and last gpr to be saved. We trust regs_ever_live
it is going to be saved/restored. */ data, except that we don't save and restore global registers.
if (!current_function_is_leaf Also, all registers with special meaning to the compiler need
|| TARGET_TPF_PROFILING to be handled extra. */
|| 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, for (i = 0; i < 16; i++)
we assume the base register and -on S/390- the return register live_regs[i] = regs_ever_live[i] && !global_regs[i];
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 (flag_pic)
if (!TARGET_CPU_ZARCH || cfun->machine->save_return_addr_p) live_regs[PIC_OFFSET_TABLE_REGNUM] =
regs_ever_live[RETURN_REGNUM] = 1; regs_ever_live[PIC_OFFSET_TABLE_REGNUM];
regs_ever_live[STACK_POINTER_REGNUM] = cfun->machine->frame_size > 0;
for (i = 6; i < 16; i++) live_regs[BASE_REGISTER] = base_used;
if (regs_ever_live[i]) live_regs[RETURN_REGNUM] = return_addr_used;
if (!global_regs[i] live_regs[STACK_POINTER_REGNUM] = cfun->machine->frame_size > 0;
|| i == STACK_POINTER_REGNUM
|| i == RETURN_REGNUM
|| i == BASE_REGISTER
|| (flag_pic && i == (int)PIC_OFFSET_TABLE_REGNUM))
break;
for (i = 6; i < 16; i++)
if (live_regs[i])
break;
for (j = 15; j > i; j--) for (j = 15; j > i; j--)
if (regs_ever_live[j]) if (live_regs[j])
if (!global_regs[j] break;
|| 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. */ if (i == 16)
cfun->machine->first_save_gpr = i; {
cfun->machine->first_restore_gpr = i; /* Nothing to save/restore. */
cfun->machine->last_save_gpr = j; 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. */ /* Varargs functions need to save gprs 2 to 6. */
if (current_function_stdarg) if (current_function_stdarg)
cfun->machine->first_save_gpr = 2; {
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 /* Return offset between argument pointer and frame pointer
...@@ -5344,30 +5318,15 @@ s390_frame_info (void) ...@@ -5344,30 +5318,15 @@ s390_frame_info (void)
HOST_WIDE_INT HOST_WIDE_INT
s390_arg_frame_offset (void) s390_arg_frame_offset (void)
{ {
HOST_WIDE_INT fsize = get_frame_size (); /* See the comment in s390_emit_prologue about the assumptions we make
int save_fprs_p, i; 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;
/* fprs 8 - 15 are caller saved for 64 Bit ABI. */ s390_frame_info (1, !TARGET_CPU_ZARCH || return_addr_used);
save_fprs_p = 0; return cfun->machine->frame_size + STACK_POINTER_OFFSET;
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 /* Emit insn to save fpr REGNUM at offset OFFSET relative
...@@ -5556,9 +5515,29 @@ s390_emit_prologue (void) ...@@ -5556,9 +5515,29 @@ s390_emit_prologue (void)
rtx temp_reg; rtx temp_reg;
int i; int i;
/* Compute frame_info. */ /* 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 (); 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. /* Choose best register to use for temp use within prologue.
See below for why TPF must use the register 1. */ See below for why TPF must use the register 1. */
...@@ -5736,7 +5715,7 @@ s390_emit_epilogue (bool sibcall) ...@@ -5736,7 +5715,7 @@ s390_emit_epilogue (bool sibcall)
if (cfun->machine->first_restore_gpr != -1) if (cfun->machine->first_restore_gpr != -1)
{ {
area_bottom = cfun->machine->first_restore_gpr * UNITS_PER_WORD; area_bottom = cfun->machine->first_restore_gpr * UNITS_PER_WORD;
area_top = (cfun->machine->last_save_gpr + 1) * UNITS_PER_WORD; area_top = (cfun->machine->last_restore_gpr + 1) * UNITS_PER_WORD;
} }
else else
{ {
...@@ -5834,7 +5813,7 @@ s390_emit_epilogue (bool sibcall) ...@@ -5834,7 +5813,7 @@ s390_emit_epilogue (bool sibcall)
to stack location from where they get restored. */ to stack location from where they get restored. */
for (i = cfun->machine->first_restore_gpr; for (i = cfun->machine->first_restore_gpr;
i <= cfun->machine->last_save_gpr; i <= cfun->machine->last_restore_gpr;
i++) i++)
{ {
/* These registers are special and need to be /* These registers are special and need to be
...@@ -5862,7 +5841,7 @@ s390_emit_epilogue (bool sibcall) ...@@ -5862,7 +5841,7 @@ s390_emit_epilogue (bool sibcall)
if (cfun->machine->save_return_addr_p if (cfun->machine->save_return_addr_p
|| (cfun->machine->first_restore_gpr < BASE_REGISTER || (cfun->machine->first_restore_gpr < BASE_REGISTER
&& cfun->machine->last_save_gpr > RETURN_REGNUM)) && cfun->machine->last_restore_gpr > RETURN_REGNUM))
{ {
int return_regnum = find_unused_clobbered_reg(); int return_regnum = find_unused_clobbered_reg();
if (!return_regnum) if (!return_regnum)
...@@ -5885,7 +5864,7 @@ s390_emit_epilogue (bool sibcall) ...@@ -5885,7 +5864,7 @@ s390_emit_epilogue (bool sibcall)
insn = restore_gprs (frame_pointer, offset, insn = restore_gprs (frame_pointer, offset,
cfun->machine->first_restore_gpr, cfun->machine->first_restore_gpr,
cfun->machine->last_save_gpr); cfun->machine->last_restore_gpr);
emit_insn (insn); emit_insn (insn);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment