aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Sandiford <rdsandiford@googlemail.com>2008-11-16 20:31:13 +0000
committerRichard Sandiford <rdsandiford@googlemail.com>2008-11-16 20:31:13 +0000
commit8443086a40bf244188e51bd3f9a36cae8a6ed5f3 (patch)
treebdc35ba9036ef04b4c9475e0971bd8161b85eaf8
parent3b7fe2b798e5dc85e58e526f19009a2183e7686f (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/ChangeLog9
-rw-r--r--gcc/config/mips/mips.c93
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;