2014-01-12 Radovan Obradovic <robradovic@mips.com>
Tom de Vries <tom@codesourcery.com>
* config/mips/mips.c (POST_CALL_TMP_REG): Define.
(mips_split_call): Use POST_CALL_TMP_REG.
(mips_fn_other_hard_reg_usage): New function.
(TARGET_FN_OTHER_HARD_REG_USAGE): Define targhook using new function.
(mips_expand_call): Add POST_CALL_TMP_REG clobber.
* gcc.target/mips/mips.exp: Add use-caller-save to -ffoo/-fno-foo
options.
* gcc.target/mips/fuse-caller-save.c: New test.
---
gcc/config/mips/mips.c | 41 +++++++++++++++++++++---
gcc/testsuite/gcc.target/mips/fuse-caller-save.c | 30 +++++++++++++++++
gcc/testsuite/gcc.target/mips/mips.exp | 1 +
3 files changed, 67 insertions(+), 5 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/mips/fuse-caller-save.c
@@ -175,6 +175,11 @@ along with GCC; see the file COPYING3. If not see
/* Return the usual opcode for a nop. */
#define MIPS_NOP 0
+/* Temporary register that is used after a call, and suitable for both
+ MIPS16 and non-MIPS16 code. $4 and $5 are used for returning complex double
+ values in soft-float code, so $6 is the first suitable candidate. */
+#define POST_CALL_TMP_REG (GP_ARG_FIRST + 2)
+
/* Classifies an address.
ADDRESS_REG
@@ -6906,11 +6911,19 @@ mips_expand_call (enum mips_call_type type, rtx result, rtx addr,
{
rtx orig_addr, pattern, insn;
int fp_code;
+ rtx post_call_tmp_reg = gen_rtx_REG (word_mode, POST_CALL_TMP_REG);
fp_code = aux == 0 ? 0 : (int) GET_MODE (aux);
insn = mips16_build_call_stub (result, &addr, args_size, fp_code);
if (insn)
{
+ if (TARGET_EXPLICIT_RELOCS
+ && TARGET_CALL_CLOBBERED_GP
+ && !find_reg_note (insn, REG_NORETURN, 0))
+ CALL_INSN_FUNCTION_USAGE (insn)
+ = gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_CLOBBER (VOIDmode, post_call_tmp_reg),
+ CALL_INSN_FUNCTION_USAGE (insn));
gcc_assert (!lazy_p && type == MIPS_CALL_NORMAL);
return insn;
}
@@ -6966,7 +6979,16 @@ mips_expand_call (enum mips_call_type type, rtx result, rtx addr,
pattern = fn (result, addr, args_size);
}
- return mips_emit_call_insn (pattern, orig_addr, addr, lazy_p);
+ insn = mips_emit_call_insn (pattern, orig_addr, addr, lazy_p);
+ if (TARGET_EXPLICIT_RELOCS
+ && TARGET_CALL_CLOBBERED_GP
+ && !find_reg_note (insn, REG_NORETURN, 0))
+ CALL_INSN_FUNCTION_USAGE (insn)
+ = gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_CLOBBER (VOIDmode, post_call_tmp_reg),
+ CALL_INSN_FUNCTION_USAGE (insn));
+
+ return insn;
}
/* Split call instruction INSN into a $gp-clobbering call and
@@ -6978,10 +7000,8 @@ mips_split_call (rtx insn, rtx call_pattern)
{
emit_call_insn (call_pattern);
if (!find_reg_note (insn, REG_NORETURN, 0))
- /* Pick a temporary register that is suitable for both MIPS16 and
- non-MIPS16 code. $4 and $5 are used for returning complex double
- values in soft-float code, so $6 is the first suitable candidate. */
- mips_restore_gp_from_cprestore_slot (gen_rtx_REG (Pmode, GP_ARG_FIRST + 2));
+ mips_restore_gp_from_cprestore_slot (gen_rtx_REG (Pmode,
+ POST_CALL_TMP_REG));
}
/* Return true if a call to DECL may need to use JALX. */
@@ -18687,6 +18707,14 @@ mips_case_values_threshold (void)
else
return default_case_values_threshold ();
}
+
+/* Implement TARGET_FN_OTHER_HARD_REG_USAGE. */
+
+static bool
+mips_fn_other_hard_reg_usage (struct hard_reg_set_container *fn_used_regs)
+{
+ return true;
+}
/* Initialize the GCC target structure. */
#undef TARGET_ASM_ALIGNED_HI_OP
@@ -18921,6 +18949,9 @@ mips_case_values_threshold (void)
#undef TARGET_CASE_VALUES_THRESHOLD
#define TARGET_CASE_VALUES_THRESHOLD mips_case_values_threshold
+#undef TARGET_FN_OTHER_HARD_REG_USAGE
+#define TARGET_FN_OTHER_HARD_REG_USAGE mips_fn_other_hard_reg_usage
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-mips.h"
new file mode 100644
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-fuse-caller-save" } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-Os" } } */
+/* Testing -fuse-caller-save optimization option. */
+
+static int __attribute__((noinline)) NOCOMPRESSION
+bar (int x)
+{
+ return x + 3;
+}
+
+int __attribute__((noinline)) NOCOMPRESSION
+foo (int y)
+{
+ return y + bar (y);
+}
+
+int NOCOMPRESSION
+main (void)
+{
+ return !(foo (5) == 13);
+}
+
+/* Check that there are only 2 stack-saves: r31 in main and foo. */
+
+/* Check that there only 2 sw/sd. */
+/* { dg-final { scan-assembler-times "(?n)s\[wd\]\t\\\$.*,.*\\(\\\$sp\\)" 2 } } */
+
+/* Check that the first caller-save register is unused. */
+/* { dg-final { scan-assembler-not "\\\$16" } } */
@@ -305,6 +305,7 @@ foreach option {
tree-vectorize
unroll-all-loops
unroll-loops
+ use-caller-save
} {
lappend mips_option_groups $option "-f(no-|)$option"
}
--
1.8.3.2