aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRobert Suchanek <robert.suchanek@imgtec.com>2015-08-18 12:42:12 +0000
committerRobert Suchanek <rts@gcc.gnu.org>2015-08-18 12:42:12 +0000
commitec8a2131b6a1384c71a69eb0ca24b234621437b6 (patch)
tree086a2c0a88767149b195b4a2fb6395acd370962c /gcc
parent7b008bbc0c4050da71786bb51de743964807aa44 (diff)
downloadgcc-ec8a2131b6a1384c71a69eb0ca24b234621437b6.zip
gcc-ec8a2131b6a1384c71a69eb0ca24b234621437b6.tar.gz
gcc-ec8a2131b6a1384c71a69eb0ca24b234621437b6.tar.bz2
[MIPS] Fix register renaming in the interrupt handlers.
gcc/ * config/mips/mips-protos.h (mips_hard_regno_rename_ok): New prototype. * config/mips/mips.c (mips_hard_regno_rename_ok): New function. (mips_hard_regno_scratch_ok): Likewise. (TARGET_HARD_REGNO_SCRATCH_OK): Define macro. * config/mips/mips.h (HARD_REGNO_RENAME_OK): New. gcc/testsuite/ * gcc.target/mips/interrupt_handler-bug-1.c: New test. From-SVN: r226968
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/config/mips/mips-protos.h1
-rw-r--r--gcc/config/mips/mips.c30
-rw-r--r--gcc/config/mips/mips.h3
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.target/mips/interrupt_handler-bug-1.c11
6 files changed, 57 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3bbbec6..dcd5d47 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2015-08-18 Robert Suchanek <robert.suchanek@imgtec.com>
+
+ * config/mips/mips-protos.h (mips_hard_regno_rename_ok): New prototype.
+ * config/mips/mips.c (mips_hard_regno_rename_ok): New function.
+ (mips_hard_regno_scratch_ok): Likewise.
+ (TARGET_HARD_REGNO_SCRATCH_OK): Define macro.
+ * config/mips/mips.h (HARD_REGNO_RENAME_OK): New.
+
2015-08-18 Bin Cheng <bin.cheng@arm.com>
* tree-ssa-loop-niter.c (refine_value_range_using_guard): New.
diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h
index 244eb8d..d9ad910 100644
--- a/gcc/config/mips/mips-protos.h
+++ b/gcc/config/mips/mips-protos.h
@@ -303,6 +303,7 @@ extern const char *mips_output_sync_loop (rtx_insn *, rtx *);
extern unsigned int mips_sync_loop_insns (rtx_insn *, rtx *);
extern const char *mips_output_division (const char *, rtx *);
extern const char *mips_output_probe_stack_range (rtx, rtx);
+extern bool mips_hard_regno_rename_ok (unsigned int, unsigned int);
extern unsigned int mips_hard_regno_nregs (int, machine_mode);
extern bool mips_linked_madd_p (rtx_insn *, rtx_insn *);
extern bool mips_store_data_bypass_p (rtx_insn *, rtx_insn *);
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 238b9b0..401d73b 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -12281,6 +12281,33 @@ mips_hard_regno_mode_ok_p (unsigned int regno, machine_mode mode)
return false;
}
+/* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
+
+bool
+mips_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
+ unsigned int new_reg)
+{
+ /* Interrupt functions can only use registers that have already been
+ saved by the prologue, even if they would normally be call-clobbered. */
+ if (cfun->machine->interrupt_handler_p && !df_regs_ever_live_p (new_reg))
+ return false;
+
+ return true;
+}
+
+/* Return nonzero if register REGNO can be used as a scratch register
+ in peephole2. */
+
+bool
+mips_hard_regno_scratch_ok (unsigned int regno)
+{
+ /* See mips_hard_regno_rename_ok. */
+ if (cfun->machine->interrupt_handler_p && !df_regs_ever_live_p (regno))
+ return false;
+
+ return true;
+}
+
/* Implement HARD_REGNO_NREGS. */
unsigned int
@@ -19827,6 +19854,9 @@ mips_ira_change_pseudo_allocno_class (int regno, reg_class_t allocno_class)
#undef TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS
#define TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS mips_ira_change_pseudo_allocno_class
+#undef TARGET_HARD_REGNO_SCRATCH_OK
+#define TARGET_HARD_REGNO_SCRATCH_OK mips_hard_regno_scratch_ok
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-mips.h"
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index 6e262d6..da1de01 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -1876,6 +1876,9 @@ FP_ASM_SPEC "\
#define HARD_REGNO_MODE_OK(REGNO, MODE) \
mips_hard_regno_mode_ok[ (int)(MODE) ][ (REGNO) ]
+#define HARD_REGNO_RENAME_OK(OLD_REG, NEW_REG) \
+ mips_hard_regno_rename_ok (OLD_REG, NEW_REG)
+
/* Select a register mode required for caller save of hard regno REGNO. */
#define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE) \
mips_hard_regno_caller_save_mode (REGNO, NREGS, MODE)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c414191..aff223c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2015-08-18 Robert Suchanek <robert.suchanek@imgtec.com>
+
+ * gcc.target/mips/interrupt_handler-bug-1.c: New test.
+
2015-08-18 Bin Cheng <bin.cheng@arm.com>
* gcc.dg/tree-ssa/loop-bound-1.c: New test.
diff --git a/gcc/testsuite/gcc.target/mips/interrupt_handler-bug-1.c b/gcc/testsuite/gcc.target/mips/interrupt_handler-bug-1.c
new file mode 100644
index 0000000..2784705
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/interrupt_handler-bug-1.c
@@ -0,0 +1,11 @@
+/* { dg-options "-funroll-loops" } */
+int foo;
+int bar;
+
+void __attribute__ ((interrupt))
+isr (void)
+{
+ if (!foo)
+ while (bar & 0xFF30);
+}
+/* { dg-final { scan-assembler-not "^isr:.*\\\$8.*isr" } } */