re PR target/38052 (genautomata segfaults when -O2 is enabled)
authorRichard Sandiford <rdsandiford@googlemail.com>
Sun, 16 Nov 2008 20:31:13 +0000 (20:31 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Sun, 16 Nov 2008 20:31:13 +0000 (20:31 +0000)
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

gcc/ChangeLog
gcc/config/mips/mips.c

index ba593ae..ec60104 100644 (file)
@@ -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
index 4244a9f..5953e1a 100644 (file)
@@ -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;