re PR target/38052 (genautomata segfaults when -O2 is enabled)

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.

From-SVN: r141926
This commit is contained in:
Richard Sandiford 2008-11-16 20:31:13 +00:00 committed by Richard Sandiford
parent 8d9d917290
commit 7cc003b5c2
2 changed files with 81 additions and 35 deletions

View File

@ -1,3 +1,12 @@
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

View File

@ -8433,48 +8433,85 @@ mips_global_pointer (void)
return GLOBAL_POINTER_REGNUM;
}
/* Return true if the current function should treat register REGNO
as call-saved. */
static bool
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)
{
/* Some functions should be treated as clobbering all call-saved
registers. */
if (crtl->saves_all_registers)
return true;
/* 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;
/* 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;
/* 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;
/* 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;
return false;
}
/* Return true if the current function must save register REGNO. */
static bool
mips_save_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)
return true;
if (mips_cfun_call_saved_reg_p (regno))
{
if (mips_cfun_might_clobber_call_saved_reg_p (regno))
return true;
/* Check call-saved registers. */
if ((crtl->saves_all_registers || df_regs_ever_live_p (regno))
&& !call_really_used_regs[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;
}
/* 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])
return true;
/* We need to save the old frame pointer before setting up a new one. */
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))
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 ()))
/* 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;