sh.c (calc_live_regs): If the return address pointer is live, force pr live.
* sh.c (calc_live_regs): If the return address pointer is live, force pr live. (sh5_schedule_saves): Exclude PR_MEDIA_REG from being a temp register for saves / restores. (sh_expand_epilogue): If sh_media_register_for_return returns a register number, flag the instructions that restores PR_MEDIA_REG as possibly dead. Remove dead update of offset. (sh_get_pr_initial_val): Use UNSPEC_RA if we don't know yet if we can use the result of get_hard_reg_initial_val. * sh.md (UNSPEC_RA): New constant. (movsi_i_lowpart+1): Changed into a define_insn_and_split, named: (load_ra). Handle UNSPEC_RA. (sibcall_media): Use PR_MEDIA_REG. From-SVN: r70234
This commit is contained in:
parent
7160c99da0
commit
7d73a2bae9
3 changed files with 61 additions and 18 deletions
|
@ -1,5 +1,20 @@
|
|||
2003-08-07 J"orn Rennecke <joern.rennecke@superh.com>
|
||||
|
||||
* sh.c (calc_live_regs): If the return address pointer is live,
|
||||
force pr live.
|
||||
(sh5_schedule_saves): Exclude PR_MEDIA_REG from being a temp register
|
||||
for saves / restores.
|
||||
(sh_expand_epilogue): If sh_media_register_for_return returns a
|
||||
register number, flag the instructions that restores PR_MEDIA_REG
|
||||
as possibly dead.
|
||||
Remove dead update of offset.
|
||||
(sh_get_pr_initial_val): Use UNSPEC_RA if we don't know yet if
|
||||
we can use the result of get_hard_reg_initial_val.
|
||||
* sh.md (UNSPEC_RA): New constant.
|
||||
(movsi_i_lowpart+1): Changed into a define_insn_and_split, named:
|
||||
(load_ra). Handle UNSPEC_RA.
|
||||
(sibcall_media): Use PR_MEDIA_REG.
|
||||
|
||||
* sh.h (CALL_USED_REGISTERS): Include PR_REG and PR_MEDIA_REG.
|
||||
* sh.c (calc_live_regs): Use sh_pr_n_sets to determine if pr
|
||||
needs saving on SHmedia.
|
||||
|
|
|
@ -4848,6 +4848,8 @@ calc_live_regs (live_regs_mask)
|
|||
the initial value can become the PR_MEDIA_REG hard register, as seen for
|
||||
execute/20010122-1.c:test9. */
|
||||
if (TARGET_SHMEDIA)
|
||||
/* ??? this function is called from initial_elimination_offset, hence we
|
||||
can't use the result of sh_media_register_for_return here. */
|
||||
pr_live = sh_pr_n_sets ();
|
||||
else
|
||||
{
|
||||
|
@ -4856,6 +4858,10 @@ calc_live_regs (live_regs_mask)
|
|||
? (GET_CODE (pr_initial) != REG
|
||||
|| REGNO (pr_initial) != (PR_REG))
|
||||
: regs_ever_live[PR_REG]);
|
||||
/* For Shcompact, if not optimizing, we end up with a memory reference
|
||||
using the return address pointer for __builtin_return_address even
|
||||
though there is no actual need to put the PR register on the stack. */
|
||||
pr_live |= regs_ever_live[RETURN_ADDRESS_POINTER_REGNUM];
|
||||
}
|
||||
/* Force PR to be live if the prologue has to call the SHmedia
|
||||
argument decoder or register saver. */
|
||||
|
@ -5027,7 +5033,7 @@ sh5_schedule_saves (HARD_REG_SET *live_regs_mask, save_schedule *schedule,
|
|||
|
||||
if (! current_function_interrupt)
|
||||
for (i = FIRST_GENERAL_REG; tmpx < MAX_TEMPS && i <= LAST_GENERAL_REG; i++)
|
||||
if (call_used_regs[i] && ! fixed_regs[i]
|
||||
if (call_used_regs[i] && ! fixed_regs[i] && i != PR_MEDIA_REG
|
||||
&& ! FUNCTION_ARG_REGNO_P (i)
|
||||
&& i != FIRST_RET_REG
|
||||
&& ! (current_function_needs_context && i == STATIC_CHAIN_REGNUM)
|
||||
|
@ -5169,6 +5175,9 @@ sh_expand_prologue ()
|
|||
rtx insn = emit_move_insn (gen_rtx_REG (DImode, tr),
|
||||
gen_rtx_REG (DImode, PR_MEDIA_REG));
|
||||
|
||||
/* ??? We should suppress saving pr when we don't need it, but this
|
||||
is tricky because of builtin_return_address. */
|
||||
|
||||
/* If this function only exits with sibcalls, this copy
|
||||
will be flagged as dead. */
|
||||
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD,
|
||||
|
@ -5552,7 +5561,7 @@ sh_expand_epilogue ()
|
|||
save_schedule schedule;
|
||||
save_entry *entry;
|
||||
int *tmp_pnt;
|
||||
|
||||
|
||||
entry = sh5_schedule_saves (&live_regs_mask, &schedule, d_rounding);
|
||||
offset_base = -entry[1].offset + d_rounding;
|
||||
tmp_pnt = schedule.temps;
|
||||
|
@ -5660,8 +5669,11 @@ sh_expand_epilogue ()
|
|||
}
|
||||
|
||||
insn = emit_move_insn (reg_rtx, mem_rtx);
|
||||
|
||||
offset += GET_MODE_SIZE (mode);
|
||||
if (reg == PR_MEDIA_REG && sh_media_register_for_return () >= 0)
|
||||
/* This is dead, unless we return with a sibcall. */
|
||||
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD,
|
||||
const0_rtx,
|
||||
REG_NOTES (insn));
|
||||
}
|
||||
|
||||
if (entry->offset + offset_base != d + d_rounding)
|
||||
|
@ -8835,17 +8847,29 @@ scavenge_reg (HARD_REG_SET *s)
|
|||
rtx
|
||||
sh_get_pr_initial_val (void)
|
||||
{
|
||||
rtx val;
|
||||
|
||||
/* ??? Unfortunately, get_hard_reg_initial_val doesn't always work for the
|
||||
PR register on SHcompact, because it might be clobbered by the prologue.
|
||||
We don't know if that's the case before rtl generation is finished. */
|
||||
We check first if that is known to be the case. */
|
||||
if (TARGET_SHCOMPACT
|
||||
&& (rtx_equal_function_value_matters
|
||||
|| (current_function_args_info.call_cookie
|
||||
& ~ CALL_COOKIE_RET_TRAMP (1))
|
||||
&& ((current_function_args_info.call_cookie
|
||||
& ~ CALL_COOKIE_RET_TRAMP (1))
|
||||
|| current_function_has_nonlocal_label))
|
||||
return gen_rtx_MEM (SImode, return_address_pointer_rtx);
|
||||
return
|
||||
get_hard_reg_initial_val (Pmode, TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG);
|
||||
|
||||
/* If we haven't finished rtl generation, there might be a nonlocal label
|
||||
that we haven't seen yet.
|
||||
??? get_hard_reg_initial_val fails if it is called while no_new_pseudos
|
||||
is set, unless it has been called before for the same register. And even
|
||||
then, we end in trouble if we didn't use the register in the same
|
||||
basic block before. So call get_hard_reg_initial_val now and wrap it
|
||||
in an unspec if we might need to replace it. */
|
||||
val
|
||||
= get_hard_reg_initial_val (Pmode, TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG);
|
||||
if (TARGET_SHCOMPACT && rtx_equal_function_value_matters)
|
||||
return gen_rtx_UNSPEC (SImode, gen_rtvec (1, val), UNSPEC_RA);
|
||||
return val;
|
||||
}
|
||||
|
||||
#include "gt-sh.h"
|
||||
|
|
|
@ -142,6 +142,7 @@
|
|||
(UNSPEC_DTPOFF 23)
|
||||
(UNSPEC_GOTTPOFF 24)
|
||||
(UNSPEC_TPOFF 25)
|
||||
(UNSPEC_RA 26)
|
||||
|
||||
;; These are used with unspec_volatile.
|
||||
(UNSPECV_BLOCKAGE 0)
|
||||
|
@ -3471,16 +3472,18 @@
|
|||
fake %1,%0"
|
||||
[(set_attr "type" "pcload,move,load,move,prget,move,store,pcload")])
|
||||
|
||||
(define_split
|
||||
(define_insn_and_split "load_ra"
|
||||
[(set (match_operand:SI 0 "general_movdst_operand" "")
|
||||
(mem:SI (reg:SI RAP_REG)))]
|
||||
"TARGET_SHCOMPACT
|
||||
&& ! rtx_equal_function_value_matters
|
||||
&& ! ((current_function_args_info.call_cookie
|
||||
& ~ CALL_COOKIE_RET_TRAMP (1))
|
||||
|| current_function_has_nonlocal_label)"
|
||||
(unspec:SI [(match_operand 1 "register_operand" "")] UNSPEC_RA))]
|
||||
"TARGET_SHCOMPACT"
|
||||
"#"
|
||||
"&& ! rtx_equal_function_value_matters"
|
||||
[(set (match_dup 0) (match_dup 1))]
|
||||
"operands[1] = sh_get_pr_initial_val ();")
|
||||
"
|
||||
{
|
||||
if (current_function_has_nonlocal_label)
|
||||
operands[1] = gen_rtx_MEM (SImode, return_address_pointer_rtx);
|
||||
}")
|
||||
|
||||
(define_insn "*movsi_media"
|
||||
[(set (match_operand:SI 0 "general_movdst_operand"
|
||||
|
@ -6174,6 +6177,7 @@
|
|||
(define_insn "sibcall_media"
|
||||
[(call (mem:DI (match_operand:DI 0 "target_reg_operand" "k"))
|
||||
(match_operand 1 "" ""))
|
||||
(use (reg:SI PR_MEDIA_REG))
|
||||
(return)]
|
||||
"TARGET_SHMEDIA"
|
||||
"blink %0, r63"
|
||||
|
|
Loading…
Add table
Reference in a new issue