diff options
author | Richard Sandiford <rdsandiford@googlemail.com> | 2008-11-16 20:31:13 +0000 |
---|---|---|
committer | Richard Sandiford <rdsandiford@googlemail.com> | 2008-11-16 20:31:13 +0000 |
commit | 8443086a40bf244188e51bd3f9a36cae8a6ed5f3 (patch) | |
tree | bdc35ba9036ef04b4c9475e0971bd8161b85eaf8 | |
parent | 3b7fe2b798e5dc85e58e526f19009a2183e7686f (diff) |
gcc/
PR target/38052
* config/mips/mips.c (mips_cfun_call_saved_reg_p)
(mips_cfun_might_clobber_call_saved_reg_p): New functions,
split out from...
(mips_save_reg_p): ...here. Always consult TARGET_CALL_SAVED_GP
rather than call_really_used_regs when handling $gp.
git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@141926 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/config/mips/mips.c | 93 |
2 files changed, 74 insertions, 28 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ba593aec95e..ec60104c1f7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,6 +1,15 @@ 2008-11-16 Richard Sandiford <rdsandiford@googlemail.com> PR target/38052 + * config/mips/mips.c (mips_cfun_call_saved_reg_p) + (mips_cfun_might_clobber_call_saved_reg_p): New functions, + split out from... + (mips_save_reg_p): ...here. Always consult TARGET_CALL_SAVED_GP + rather than call_really_used_regs when handling $gp. + +2008-11-16 Richard Sandiford <rdsandiford@googlemail.com> + + PR target/38052 * config/mips/mips.c (machine_function): Update the comment above global_pointer. (mips_global_pointer): Use INVALID_REGNUM rather than 0 to indicate diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 4244a9f6848..5953e1a680c 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -8433,48 +8433,85 @@ mips_global_pointer (void) return GLOBAL_POINTER_REGNUM; } -/* Return true if the current function must save register REGNO. */ +/* Return true if the current function should treat register REGNO + as call-saved. */ static bool -mips_save_reg_p (unsigned int regno) +mips_cfun_call_saved_reg_p (unsigned int regno) +{ + /* call_insns preserve $28 unless they explicitly say otherwise, + so call_really_used_regs[] treats $28 as call-saved. However, + we want the ABI property rather than the default call_insn + property here. */ + return (regno == GLOBAL_POINTER_REGNUM + ? TARGET_CALL_SAVED_GP + : !call_really_used_regs[regno]); +} + +/* Return true if the function body might clobber register REGNO. + We know that REGNO is call-saved. */ + +static bool +mips_cfun_might_clobber_call_saved_reg_p (unsigned int regno) { - /* We need to save $gp if TARGET_CALL_SAVED_GP and if we have not - chosen a call-clobbered substitute. */ - if (TARGET_CALL_SAVED_GP - && regno == GLOBAL_POINTER_REGNUM - && cfun->machine->global_pointer == regno) + /* Some functions should be treated as clobbering all call-saved + registers. */ + if (crtl->saves_all_registers) return true; - /* Check call-saved registers. */ - if ((crtl->saves_all_registers || df_regs_ever_live_p (regno)) - && !call_really_used_regs[regno]) + /* DF handles cases where a register is explicitly referenced in + the rtl. Incoming values are passed in call-clobbered registers, + so we can assume that any live call-saved register is set within + the function. */ + if (df_regs_ever_live_p (regno)) return true; - /* Save both registers in an FPR pair if either one is used. This is - needed for the case when MIN_FPRS_PER_FMT == 1, which allows the odd - register to be used without the even register. */ - if (FP_REG_P (regno) - && MAX_FPRS_PER_FMT == 2 - && df_regs_ever_live_p (regno + 1) - && !call_really_used_regs[regno + 1]) + /* Check for registers that are clobbered by FUNCTION_PROFILER. + These clobbers are not explicit in the rtl. */ + if (crtl->profile && MIPS_SAVE_REG_FOR_PROFILING_P (regno)) return true; - /* We need to save the old frame pointer before setting up a new one. */ + /* If we're using a call-saved global pointer, the function's + prologue will need to set it up. */ + if (cfun->machine->global_pointer == regno) + return true; + + /* The function's prologue will need to set the frame pointer if + frame_pointer_needed. */ if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed) return true; - /* Check for registers that must be saved for FUNCTION_PROFILER. */ - if (crtl->profile && MIPS_SAVE_REG_FOR_PROFILING_P (regno)) + /* If a MIPS16 function returns a value in FPRs, its epilogue + will need to call an external libgcc routine. This yet-to-be + generated call_insn will clobber $31. */ + if (regno == GP_REG_FIRST + 31 && mips16_cfun_returns_in_fpr_p ()) return true; - /* We need to save the incoming return address if it is ever clobbered - within the function, if __builtin_eh_return is being used to set a - different return address, or if a stub is being used to return a - value in FPRs. */ - if (regno == GP_REG_FIRST + 31 - && (df_regs_ever_live_p (regno) - || crtl->calls_eh_return - || mips16_cfun_returns_in_fpr_p ())) + return false; +} + +/* Return true if the current function must save register REGNO. */ + +static bool +mips_save_reg_p (unsigned int regno) +{ + if (mips_cfun_call_saved_reg_p (regno)) + { + if (mips_cfun_might_clobber_call_saved_reg_p (regno)) + return true; + + /* Save both registers in an FPR pair if either one is used. This is + needed for the case when MIN_FPRS_PER_FMT == 1, which allows the odd + register to be used without the even register. */ + if (FP_REG_P (regno) + && MAX_FPRS_PER_FMT == 2 + && mips_cfun_might_clobber_call_saved_reg_p (regno + 1)) + return true; + } + + /* We need to save the incoming return address if __builtin_eh_return + is being used to set a different return address. */ + if (regno == GP_REG_FIRST + 31 && crtl->calls_eh_return) return true; return false; |