From 7d73a2bae9ca5a839059e88058686d36c8b094a7 Mon Sep 17 00:00:00 2001 From: "J\"orn Rennecke" Date: Thu, 7 Aug 2003 22:40:07 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 15 +++++++++++++++ gcc/config/sh/sh.c | 44 ++++++++++++++++++++++++++++++++++---------- gcc/config/sh/sh.md | 20 ++++++++++++-------- 3 files changed, 61 insertions(+), 18 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9568cca24d5..4eb8d9ca898 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,20 @@ 2003-08-07 J"orn Rennecke + * 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. diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index d64d919fbbc..d1b203b943c 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -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" diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index d4dd5d1287d..2c8462ffc58 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -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" -- 2.30.2