aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/config/mips/mips.c32
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.target/mips/save-restore-5.c16
4 files changed, 49 insertions, 12 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b36c380..240d5e7 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2007-07-06 Richard Sandiford <richard@codesourcery.com>
+
+ * config/mips/mips.c (mips16e_save_restore_pattern_p): Check that
+ the topmost argument register is not also included in the save mask.
+ (mips16e_collect_argument_save_p): Take a pointer to the argument
+ register, rather than a pointer to the number of arguments.
+ (mips16e_collect_argument_saves): Only include argument saves
+ that aren't in the register mask.
+
2007-07-06 Uros Bizjak <ubizjak@gmail.com>
PR rtl_optimization/32450
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 783ff03..8c7b70c 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -7334,6 +7334,12 @@ mips16e_save_restore_pattern_p (rtx pattern, HOST_WIDE_INT adjust,
if (extra != 0)
return false;
+ /* Make sure that the topmost argument register is not saved twice.
+ The checks above ensure that the same is then true for the other
+ argument registers. */
+ if (nargs > 0 && BITSET_P (mask, GP_ARG_FIRST + nargs - 1))
+ return false;
+
/* Pass back information, if requested. */
if (info)
{
@@ -7458,14 +7464,13 @@ mips16e_collect_propagate_value (rtx x, rtx *reg_values)
}
/* Return true if (set DEST SRC) stores an argument register into its
- caller-allocated save slot. If the register is not included in
- [GP_ARG_FIRST, GP_ARG_LAST + *NARGS_PTR), destructively modify
- *NARGS_PTR such that this condition holds. REG_VALUES is as for
+ caller-allocated save slot, storing the number of that argument
+ register in *REGNO_PTR if so. REG_VALUES is as for
mips16e_collect_propagate_value. */
static bool
-mips16e_collect_argument_save (rtx dest, rtx src, rtx *reg_values,
- unsigned int *nargs_ptr)
+mips16e_collect_argument_save_p (rtx dest, rtx src, rtx *reg_values,
+ unsigned int *regno_ptr)
{
unsigned int argno, regno;
HOST_WIDE_INT offset, required_offset;
@@ -7495,10 +7500,7 @@ mips16e_collect_argument_save (rtx dest, rtx src, rtx *reg_values,
if (offset != required_offset)
return false;
- /* Make sure that *NARGS_PTR is big enough. */
- if (*nargs_ptr <= argno)
- *nargs_ptr = argno + 1;
-
+ *regno_ptr = regno;
return true;
}
@@ -7514,7 +7516,7 @@ mips16e_collect_argument_saves (void)
{
rtx reg_values[FIRST_PSEUDO_REGISTER];
rtx insn, next, set, dest, src;
- unsigned int nargs;
+ unsigned int nargs, regno;
push_topmost_sequence ();
nargs = 0;
@@ -7534,8 +7536,14 @@ mips16e_collect_argument_saves (void)
dest = SET_DEST (set);
src = SET_SRC (set);
- if (mips16e_collect_argument_save (dest, src, reg_values, &nargs))
- delete_insn (insn);
+ if (mips16e_collect_argument_save_p (dest, src, reg_values, &regno))
+ {
+ if (!BITSET_P (cfun->machine->frame.mask, regno))
+ {
+ delete_insn (insn);
+ nargs = MAX (nargs, (regno - GP_ARG_FIRST) + 1);
+ }
+ }
else if (REG_P (dest) && GET_MODE (dest) == word_mode)
reg_values[REGNO (dest)]
= mips16e_collect_propagate_value (src, reg_values);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 3772aff..a630290 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2007-07-06 Richard Sandiford <richard@codesourcery.com>
+
+ * gcc.target/mips/save-restore-5.c: New test.
+
2007-07-06 Uros Bizjak <ubizjak@gmail.com>
PR rtl_optimization/32450
diff --git a/gcc/testsuite/gcc.target/mips/save-restore-5.c b/gcc/testsuite/gcc.target/mips/save-restore-5.c
new file mode 100644
index 0000000..6c2f37c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/save-restore-5.c
@@ -0,0 +1,16 @@
+/* Check that we don't try to save the same register twice. */
+/* { dg-mips-options "-mips32r2 -mgp32 -mips16 -O2" } */
+/* { dg-do assemble } */
+
+int bar (int, int, int, int);
+void frob (void);
+
+void
+foo (int a1, int a2, int a3, int a4)
+{
+ asm volatile ("" ::: "$2", "$3", "$4", "$5", "$6", "$7", "$8",
+ "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$16",
+ "$18", "$19", "$20", "$21", "$22", "$23", "$24",
+ "$25", "$30", "$31", "memory");
+ __builtin_eh_return (bar (a1, a2, a3, a4), frob);
+}