Commit 31d68947 by Alan Modra Committed by Jeff Law

pa.c (hppa_expand_prologue): Simplify code storing return pointer.

 	* pa.c (hppa_expand_prologue): Simplify code storing return
 	pointer.  For large (>=8k) frames with a post_store, adjust stack
 	pointer by 8k-64 first rather than by 64.  When testing with
 	VAL_14_BITS_P, always use the actual value rather than the value
 	negated.  Add blockage to prevent scheduling of spills before
 	stack frame has been created.
	(hppa_expand_epilogue): Simplify code loading return pointer.
 	Allow a slightly larger range for merge_sp_adjust_with_load case.
 	When testing with VAL_14_BITS_P, always use the actual value.

From-SVN: r39826
parent 4096479e
2001-02-18 Alan Modra <alan@linuxcare.com.au> 2001-02-18 Alan Modra <alan@linuxcare.com.au>
* pa.c (hppa_expand_prologue): Simplify code storing return
pointer. For large (>=8k) frames with a post_store, adjust stack
pointer by 8k-64 first rather than by 64. When testing with
VAL_14_BITS_P, always use the actual value rather than the value
negated. Add blockage to prevent scheduling of spills before
stack frame has been created.
(hppa_expand_epilogue): Simplify code loading return pointer.
Allow a slightly larger range for merge_sp_adjust_with_load case.
When testing with VAL_14_BITS_P, always use the actual value.
* pa.c (pa_adjust_insn_length): Check that block move * pa.c (pa_adjust_insn_length): Check that block move
pattern is a set before looking at operands. pattern is a set before looking at operands.
......
...@@ -2989,14 +2989,11 @@ hppa_expand_prologue() ...@@ -2989,14 +2989,11 @@ hppa_expand_prologue()
/* Save RP first. The calling conventions manual states RP will /* Save RP first. The calling conventions manual states RP will
always be stored into the caller's frame at sp-20 or sp - 16 always be stored into the caller's frame at sp-20 or sp - 16
depending on which ABI is in use. */ depending on which ABI is in use. */
if ((regs_ever_live[2] || profile_flag) && TARGET_64BIT) if (regs_ever_live[2] || profile_flag)
store_reg (2, -16, STACK_POINTER_REGNUM); store_reg (2, TARGET_64BIT ? -16 : -20, STACK_POINTER_REGNUM);
if ((regs_ever_live[2] || profile_flag) && ! TARGET_64BIT)
store_reg (2, -20, STACK_POINTER_REGNUM);
/* Allocate the local frame and set up the frame pointer if needed. */ /* Allocate the local frame and set up the frame pointer if needed. */
if (actual_fsize) if (actual_fsize != 0)
{ {
if (frame_pointer_needed) if (frame_pointer_needed)
{ {
...@@ -3004,7 +3001,7 @@ hppa_expand_prologue() ...@@ -3004,7 +3001,7 @@ hppa_expand_prologue()
new stack pointer, then store away the saved old frame pointer new stack pointer, then store away the saved old frame pointer
into the stack at sp+actual_fsize and at the same time update into the stack at sp+actual_fsize and at the same time update
the stack pointer by actual_fsize bytes. Two versions, first the stack pointer by actual_fsize bytes. Two versions, first
handles small (<8k) frames. The second handles large (>8k) handles small (<8k) frames. The second handles large (>=8k)
frames. */ frames. */
emit_move_insn (tmpreg, frame_pointer_rtx); emit_move_insn (tmpreg, frame_pointer_rtx);
emit_move_insn (frame_pointer_rtx, stack_pointer_rtx); emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
...@@ -3018,12 +3015,19 @@ hppa_expand_prologue() ...@@ -3018,12 +3015,19 @@ hppa_expand_prologue()
So instead use stwm to store at *sp and post-increment the So instead use stwm to store at *sp and post-increment the
stack pointer as an atomic operation. Then increment sp to stack pointer as an atomic operation. Then increment sp to
finish allocating the new frame. */ finish allocating the new frame. */
emit_insn (gen_post_store (stack_pointer_rtx, tmpreg, int adjust1 = 8192 - 64;
GEN_INT (64))); int adjust2 = actual_fsize - adjust1;
rtx delta = GEN_INT (adjust1);
emit_insn (gen_post_store (stack_pointer_rtx, tmpreg, delta));
set_reg_plus_d (STACK_POINTER_REGNUM, set_reg_plus_d (STACK_POINTER_REGNUM,
STACK_POINTER_REGNUM, STACK_POINTER_REGNUM,
actual_fsize - 64); adjust2);
} }
/* Prevent register spills from being scheduled before the
stack pointer is raised. Necessary as we will be storing
registers using the frame pointer as a base register, and
we happen to set fp before raising sp. */
emit_insn (gen_blockage ());
} }
/* no frame pointer needed. */ /* no frame pointer needed. */
else else
...@@ -3032,27 +3036,28 @@ hppa_expand_prologue() ...@@ -3032,27 +3036,28 @@ hppa_expand_prologue()
and allocating the stack frame at the same time. If so, just and allocating the stack frame at the same time. If so, just
make a note of it and defer allocating the frame until saving make a note of it and defer allocating the frame until saving
the callee registers. */ the callee registers. */
if (VAL_14_BITS_P (-actual_fsize) if (VAL_14_BITS_P (actual_fsize)
&& local_fsize == 0 && local_fsize == 0
&& ! profile_flag && ! profile_flag
&& ! flag_pic) && ! flag_pic)
merge_sp_adjust_with_store = 1; merge_sp_adjust_with_store = 1;
/* Can not optimize. Adjust the stack frame by actual_fsize bytes. */ /* Can not optimize. Adjust the stack frame by actual_fsize
else if (actual_fsize != 0) bytes. */
else
set_reg_plus_d (STACK_POINTER_REGNUM, set_reg_plus_d (STACK_POINTER_REGNUM,
STACK_POINTER_REGNUM, STACK_POINTER_REGNUM,
actual_fsize); actual_fsize);
} }
}
/* The hppa calling conventions say that %r19, the pic offset /* The hppa calling conventions say that %r19, the pic offset
register, is saved at sp - 32 (in this function's frame) when register, is saved at sp - 32 (in this function's frame)
generating PIC code. FIXME: What is the correct thing to do when generating PIC code. FIXME: What is the correct thing
for functions which make no calls and allocate no frame? Do to do for functions which make no calls and allocate no
we need to allocate a frame, or can we just omit the save? For frame? Do we need to allocate a frame, or can we just omit
now we'll just omit the save. */ the save? For now we'll just omit the save. */
if (actual_fsize != 0 && flag_pic && !TARGET_64BIT) if (flag_pic && !TARGET_64BIT)
store_reg (PIC_OFFSET_TABLE_REGNUM, -32, STACK_POINTER_REGNUM); store_reg (PIC_OFFSET_TABLE_REGNUM, -32, STACK_POINTER_REGNUM);
}
/* Profiling code. /* Profiling code.
...@@ -3226,8 +3231,9 @@ void ...@@ -3226,8 +3231,9 @@ void
hppa_expand_epilogue () hppa_expand_epilogue ()
{ {
rtx tmpreg; rtx tmpreg;
int offset,i; int offset, i;
int merge_sp_adjust_with_load = 0; int merge_sp_adjust_with_load = 0;
int ret_off = 0;
/* We will use this often. */ /* We will use this often. */
tmpreg = gen_rtx_REG (word_mode, 1); tmpreg = gen_rtx_REG (word_mode, 1);
...@@ -3235,23 +3241,24 @@ hppa_expand_epilogue () ...@@ -3235,23 +3241,24 @@ hppa_expand_epilogue ()
/* Try to restore RP early to avoid load/use interlocks when /* Try to restore RP early to avoid load/use interlocks when
RP gets used in the return (bv) instruction. This appears to still RP gets used in the return (bv) instruction. This appears to still
be necessary even when we schedule the prologue and epilogue. */ be necessary even when we schedule the prologue and epilogue. */
if (frame_pointer_needed if (regs_ever_live [2] || profile_flag)
&& !TARGET_64BIT {
&& (regs_ever_live [2] || profile_flag)) ret_off = TARGET_64BIT ? -16 : -20;
load_reg (2, -20, FRAME_POINTER_REGNUM); if (frame_pointer_needed)
else if (TARGET_64BIT && frame_pointer_needed {
&& (regs_ever_live[2] || profile_flag)) load_reg (2, ret_off, FRAME_POINTER_REGNUM);
load_reg (2, -16, FRAME_POINTER_REGNUM); ret_off = 0;
else if (TARGET_64BIT }
&& ! frame_pointer_needed else
&& (regs_ever_live[2] || profile_flag) {
&& VAL_14_BITS_P (actual_fsize + 20))
load_reg (2, - (actual_fsize + 16), STACK_POINTER_REGNUM);
/* No frame pointer, and stack is smaller than 8k. */ /* No frame pointer, and stack is smaller than 8k. */
else if (! frame_pointer_needed if (VAL_14_BITS_P (ret_off - actual_fsize))
&& VAL_14_BITS_P (actual_fsize + 20) {
&& (regs_ever_live[2] || profile_flag)) load_reg (2, ret_off - actual_fsize, STACK_POINTER_REGNUM);
load_reg (2, - (actual_fsize + 20), STACK_POINTER_REGNUM); ret_off = 0;
}
}
}
/* General register restores. */ /* General register restores. */
if (frame_pointer_needed) if (frame_pointer_needed)
...@@ -3272,9 +3279,9 @@ hppa_expand_epilogue () ...@@ -3272,9 +3279,9 @@ hppa_expand_epilogue ()
/* Only for the first load. /* Only for the first load.
merge_sp_adjust_with_load holds the register load merge_sp_adjust_with_load holds the register load
with which we will merge the sp adjustment. */ with which we will merge the sp adjustment. */
if (VAL_14_BITS_P (actual_fsize + 20) if (merge_sp_adjust_with_load == 0
&& local_fsize == 0 && local_fsize == 0
&& ! merge_sp_adjust_with_load) && VAL_14_BITS_P (-actual_fsize))
merge_sp_adjust_with_load = i; merge_sp_adjust_with_load = i;
else else
load_reg (i, offset, STACK_POINTER_REGNUM); load_reg (i, offset, STACK_POINTER_REGNUM);
...@@ -3314,47 +3321,10 @@ hppa_expand_epilogue () ...@@ -3314,47 +3321,10 @@ hppa_expand_epilogue ()
This is necessary as we must not cut the stack back before all the This is necessary as we must not cut the stack back before all the
restores are finished. */ restores are finished. */
emit_insn (gen_blockage ()); emit_insn (gen_blockage ());
/* No frame pointer, but we have a stack greater than 8k. We restore
%r2 very late in this case. (All other cases are restored as early
as possible.) */
if (! frame_pointer_needed
&& ! VAL_14_BITS_P (actual_fsize + 20)
&& ! TARGET_64BIT
&& (regs_ever_live[2] || profile_flag))
{
set_reg_plus_d (STACK_POINTER_REGNUM,
STACK_POINTER_REGNUM,
- actual_fsize);
/* This used to try and be clever by not depending on the value in
%r30 and instead use the value held in %r1 (so that the 2nd insn
which sets %r30 could be put in the delay slot of the return insn).
That won't work since if the stack is exactly 8k set_reg_plus_d
doesn't set %r1, just %r30. */
load_reg (2, - 20, STACK_POINTER_REGNUM);
}
else if (! frame_pointer_needed
&& ! VAL_14_BITS_P (actual_fsize + 20)
&& TARGET_64BIT
&& (regs_ever_live[2] || profile_flag))
{
set_reg_plus_d (STACK_POINTER_REGNUM,
STACK_POINTER_REGNUM,
- actual_fsize);
/* This used to try and be clever by not depending on the value in
%r30 and instead use the value held in %r1 (so that the 2nd insn
which sets %r30 could be put in the delay slot of the return insn).
That won't work since if the stack is exactly 8k set_reg_plus_d
doesn't set %r1, just %r30. */
load_reg (2, - 16, STACK_POINTER_REGNUM);
}
/* Reset stack pointer (and possibly frame pointer). The stack /* Reset stack pointer (and possibly frame pointer). The stack
pointer is initially set to fp + 64 to avoid a race condition. */ pointer is initially set to fp + 64 to avoid a race condition. */
else if (frame_pointer_needed) if (frame_pointer_needed)
{ {
set_reg_plus_d (STACK_POINTER_REGNUM, FRAME_POINTER_REGNUM, 64); set_reg_plus_d (STACK_POINTER_REGNUM, FRAME_POINTER_REGNUM, 64);
emit_insn (gen_pre_load (frame_pointer_rtx, emit_insn (gen_pre_load (frame_pointer_rtx,
...@@ -3362,14 +3332,25 @@ hppa_expand_epilogue () ...@@ -3362,14 +3332,25 @@ hppa_expand_epilogue ()
GEN_INT (-64))); GEN_INT (-64)));
} }
/* If we were deferring a callee register restore, do it now. */ /* If we were deferring a callee register restore, do it now. */
else if (! frame_pointer_needed && merge_sp_adjust_with_load) else if (merge_sp_adjust_with_load)
emit_insn (gen_pre_load (gen_rtx_REG (word_mode, merge_sp_adjust_with_load), {
rtx delta = GEN_INT (-actual_fsize);
emit_insn (gen_pre_load (gen_rtx_REG (word_mode,
merge_sp_adjust_with_load),
stack_pointer_rtx, stack_pointer_rtx,
GEN_INT (- actual_fsize))); delta));
}
else if (actual_fsize != 0) else if (actual_fsize != 0)
{
set_reg_plus_d (STACK_POINTER_REGNUM, set_reg_plus_d (STACK_POINTER_REGNUM,
STACK_POINTER_REGNUM, STACK_POINTER_REGNUM,
- actual_fsize); - actual_fsize);
}
/* If we haven't restored %r2 yet (no frame pointer, and a stack
frame greater than 8k), do so now. */
if (ret_off != 0)
load_reg (2, ret_off, STACK_POINTER_REGNUM);
} }
/* Set up a callee saved register for the pic offset table register. */ /* Set up a callee saved register for the pic offset table register. */
......
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