Commit 7d73a2ba by J"orn Rennecke Committed by Joern Rennecke

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
parent 7160c99d
2003-08-07 J"orn Rennecke <joern.rennecke@superh.com> 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.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 * sh.c (calc_live_regs): Use sh_pr_n_sets to determine if pr
needs saving on SHmedia. needs saving on SHmedia.
......
...@@ -4848,6 +4848,8 @@ calc_live_regs (live_regs_mask) ...@@ -4848,6 +4848,8 @@ calc_live_regs (live_regs_mask)
the initial value can become the PR_MEDIA_REG hard register, as seen for the initial value can become the PR_MEDIA_REG hard register, as seen for
execute/20010122-1.c:test9. */ execute/20010122-1.c:test9. */
if (TARGET_SHMEDIA) 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 (); pr_live = sh_pr_n_sets ();
else else
{ {
...@@ -4856,6 +4858,10 @@ calc_live_regs (live_regs_mask) ...@@ -4856,6 +4858,10 @@ calc_live_regs (live_regs_mask)
? (GET_CODE (pr_initial) != REG ? (GET_CODE (pr_initial) != REG
|| REGNO (pr_initial) != (PR_REG)) || REGNO (pr_initial) != (PR_REG))
: regs_ever_live[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 /* Force PR to be live if the prologue has to call the SHmedia
argument decoder or register saver. */ argument decoder or register saver. */
...@@ -5027,7 +5033,7 @@ sh5_schedule_saves (HARD_REG_SET *live_regs_mask, save_schedule *schedule, ...@@ -5027,7 +5033,7 @@ sh5_schedule_saves (HARD_REG_SET *live_regs_mask, save_schedule *schedule,
if (! current_function_interrupt) if (! current_function_interrupt)
for (i = FIRST_GENERAL_REG; tmpx < MAX_TEMPS && i <= LAST_GENERAL_REG; i++) 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) && ! FUNCTION_ARG_REGNO_P (i)
&& i != FIRST_RET_REG && i != FIRST_RET_REG
&& ! (current_function_needs_context && i == STATIC_CHAIN_REGNUM) && ! (current_function_needs_context && i == STATIC_CHAIN_REGNUM)
...@@ -5169,6 +5175,9 @@ sh_expand_prologue () ...@@ -5169,6 +5175,9 @@ sh_expand_prologue ()
rtx insn = emit_move_insn (gen_rtx_REG (DImode, tr), rtx insn = emit_move_insn (gen_rtx_REG (DImode, tr),
gen_rtx_REG (DImode, PR_MEDIA_REG)); 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 /* If this function only exits with sibcalls, this copy
will be flagged as dead. */ will be flagged as dead. */
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD,
...@@ -5552,7 +5561,7 @@ sh_expand_epilogue () ...@@ -5552,7 +5561,7 @@ sh_expand_epilogue ()
save_schedule schedule; save_schedule schedule;
save_entry *entry; save_entry *entry;
int *tmp_pnt; int *tmp_pnt;
entry = sh5_schedule_saves (&live_regs_mask, &schedule, d_rounding); entry = sh5_schedule_saves (&live_regs_mask, &schedule, d_rounding);
offset_base = -entry[1].offset + d_rounding; offset_base = -entry[1].offset + d_rounding;
tmp_pnt = schedule.temps; tmp_pnt = schedule.temps;
...@@ -5660,8 +5669,11 @@ sh_expand_epilogue () ...@@ -5660,8 +5669,11 @@ sh_expand_epilogue ()
} }
insn = emit_move_insn (reg_rtx, mem_rtx); insn = emit_move_insn (reg_rtx, mem_rtx);
if (reg == PR_MEDIA_REG && sh_media_register_for_return () >= 0)
offset += GET_MODE_SIZE (mode); /* 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) if (entry->offset + offset_base != d + d_rounding)
...@@ -8835,17 +8847,29 @@ scavenge_reg (HARD_REG_SET *s) ...@@ -8835,17 +8847,29 @@ scavenge_reg (HARD_REG_SET *s)
rtx rtx
sh_get_pr_initial_val (void) sh_get_pr_initial_val (void)
{ {
rtx val;
/* ??? Unfortunately, get_hard_reg_initial_val doesn't always work for the /* ??? Unfortunately, get_hard_reg_initial_val doesn't always work for the
PR register on SHcompact, because it might be clobbered by the prologue. 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 if (TARGET_SHCOMPACT
&& (rtx_equal_function_value_matters && ((current_function_args_info.call_cookie
|| (current_function_args_info.call_cookie & ~ CALL_COOKIE_RET_TRAMP (1))
& ~ CALL_COOKIE_RET_TRAMP (1))
|| current_function_has_nonlocal_label)) || current_function_has_nonlocal_label))
return gen_rtx_MEM (SImode, return_address_pointer_rtx); 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" #include "gt-sh.h"
...@@ -142,6 +142,7 @@ ...@@ -142,6 +142,7 @@
(UNSPEC_DTPOFF 23) (UNSPEC_DTPOFF 23)
(UNSPEC_GOTTPOFF 24) (UNSPEC_GOTTPOFF 24)
(UNSPEC_TPOFF 25) (UNSPEC_TPOFF 25)
(UNSPEC_RA 26)
;; These are used with unspec_volatile. ;; These are used with unspec_volatile.
(UNSPECV_BLOCKAGE 0) (UNSPECV_BLOCKAGE 0)
...@@ -3471,16 +3472,18 @@ ...@@ -3471,16 +3472,18 @@
fake %1,%0" fake %1,%0"
[(set_attr "type" "pcload,move,load,move,prget,move,store,pcload")]) [(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" "") [(set (match_operand:SI 0 "general_movdst_operand" "")
(mem:SI (reg:SI RAP_REG)))] (unspec:SI [(match_operand 1 "register_operand" "")] UNSPEC_RA))]
"TARGET_SHCOMPACT "TARGET_SHCOMPACT"
&& ! rtx_equal_function_value_matters "#"
&& ! ((current_function_args_info.call_cookie "&& ! rtx_equal_function_value_matters"
& ~ CALL_COOKIE_RET_TRAMP (1))
|| current_function_has_nonlocal_label)"
[(set (match_dup 0) (match_dup 1))] [(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" (define_insn "*movsi_media"
[(set (match_operand:SI 0 "general_movdst_operand" [(set (match_operand:SI 0 "general_movdst_operand"
...@@ -6174,6 +6177,7 @@ ...@@ -6174,6 +6177,7 @@
(define_insn "sibcall_media" (define_insn "sibcall_media"
[(call (mem:DI (match_operand:DI 0 "target_reg_operand" "k")) [(call (mem:DI (match_operand:DI 0 "target_reg_operand" "k"))
(match_operand 1 "" "")) (match_operand 1 "" ""))
(use (reg:SI PR_MEDIA_REG))
(return)] (return)]
"TARGET_SHMEDIA" "TARGET_SHMEDIA"
"blink %0, r63" "blink %0, r63"
......
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