On 25-04-14 15:22, Richard Sandiford wrote:
Tom de Vries <tom_devr...@mentor.com> writes:
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 45256e9..b61cd44 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -7027,11 +7027,17 @@ 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))
+ clobber_reg (&CALL_INSN_FUNCTION_USAGE (insn), post_call_tmp_reg);
+
I think this condition should go in mips_emit_call_insn instead,
so that we don't have 4 instances of it. untyped_call could then
use mips_expand_call as well.
Richard,
Done.
Until now there was no real downside to using $6 for non-MIPS16 code.
Now that there is, it would probably be worth making it:
+#define POST_CALL_TMP_REG \
(TARGET_MIPS16 ? GP_ARG_FIRST + 2 : PIC_OFFSET_TABLE_REGNUM)
and only adding the clobber for MIPS16.
Done.
diff --git a/gcc/testsuite/gcc.target/mips/fuse-caller-save.c
b/gcc/testsuite/gcc.target/mips/fuse-caller-save.c
new file mode 100644
index 0000000..1fd6c7d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/fuse-caller-save.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-fuse-caller-save" } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-Os" } } */
I might have asked this before, sorry, but why this skip? Please add a brief
comment (in the string, if short enough).
I've reduced the amount of skips a bit, and added a comment why they are
skipped.
+/* 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" } } */
It'd be good to avoid NOCOMPRESSION because the only case that really
needs the temporary register is MIPS16. Please try putting the test
in a header file and reusing it for three tests, one each of MIPS16,
microMIPS and uncompressed.
Done, I think, I'm not 100% sure I understood what you wanted me to do here.
build and reg-tested on MIPS.
OK for trunk?
Thanks,
- Tom
2014-01-12 Radovan Obradovic <robrado...@mips.com>
Tom de Vries <t...@codesourcery.com>
* config/mips/mips-protos.h (mips_emit_call_insn): Declare.
* config/mips/mips.h (POST_CALL_TMP_REG): Define.
* config/mips/mips.c (mips_emit_call_insn): Remove static. Use
last_call_insn. Add POST_CALL_TMP_REG clobber
(mips_split_call): Use POST_CALL_TMP_REG.
(TARGET_CALL_FUSAGE_CONTAINS_NON_CALLEE_CLOBBERS): Redefine to true.
* config/mips/mips.md (define_expand "untyped_call"): Use
mips_emit_call_insn.
* gcc.target/mips/mips.exp: Add use-caller-save to -ffoo/-fno-foo
options.
* gcc.target/mips/fuse-caller-save.h: New include file.
* gcc.target/mips/fuse-caller-save.c: New test.
* gcc.target/mips/fuse-caller-save-mips16.c: Same.
* gcc.target/mips/fuse-caller-save-micromips.c: Same.
---
gcc/config/mips/mips-protos.h | 1 +
gcc/config/mips/mips.c | 24 ++++++++++++++++------
gcc/config/mips/mips.h | 7 +++++++
gcc/config/mips/mips.md | 4 +++-
.../gcc.target/mips/fuse-caller-save-micromips.c | 17 +++++++++++++++
.../gcc.target/mips/fuse-caller-save-mip16.c | 17 +++++++++++++++
gcc/testsuite/gcc.target/mips/fuse-caller-save.c | 17 +++++++++++++++
gcc/testsuite/gcc.target/mips/fuse-caller-save.h | 17 +++++++++++++++
gcc/testsuite/gcc.target/mips/mips.exp | 1 +
9 files changed, 98 insertions(+), 7 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/mips/fuse-caller-save-micromips.c
create mode 100644 gcc/testsuite/gcc.target/mips/fuse-caller-save-mip16.c
create mode 100644 gcc/testsuite/gcc.target/mips/fuse-caller-save.c
create mode 100644 gcc/testsuite/gcc.target/mips/fuse-caller-save.h
diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h
index 3d59b7b..19ea919 100644
--- a/gcc/config/mips/mips-protos.h
+++ b/gcc/config/mips/mips-protos.h
@@ -232,6 +232,7 @@ extern bool mips_use_pic_fn_addr_reg_p (const_rtx);
extern rtx mips_expand_call (enum mips_call_type, rtx, rtx, rtx, rtx, bool);
extern void mips_split_call (rtx, rtx);
extern bool mips_get_pic_call_symbol (rtx *, int);
+extern rtx mips_emit_call_insn (rtx, rtx, rtx, bool);
extern void mips_expand_fcc_reload (rtx, rtx, rtx);
extern void mips_set_return_address (rtx, rtx);
extern bool mips_move_by_pieces_p (unsigned HOST_WIDE_INT, unsigned int);
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 45256e9..5b7dd3f 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -2814,12 +2814,13 @@ mips_force_temporary (rtx dest, rtx value)
ADDR is the legitimized form, and LAZY_P is true if the call
address is lazily-bound. */
-static rtx
+rtx
mips_emit_call_insn (rtx pattern, rtx orig_addr, rtx addr, bool lazy_p)
{
rtx insn, reg;
- insn = emit_call_insn (pattern);
+ emit_call_insn (pattern);
+ insn = last_call_insn ();
if (TARGET_MIPS16 && mips_use_pic_fn_addr_reg_p (orig_addr))
{
@@ -2843,6 +2844,16 @@ mips_emit_call_insn (rtx pattern, rtx orig_addr, rtx addr, bool lazy_p)
gen_rtx_REG (Pmode, GOT_VERSION_REGNUM));
emit_insn (gen_update_got_version ());
}
+
+ if (TARGET_MIPS16
+ && TARGET_EXPLICIT_RELOCS
+ && TARGET_CALL_CLOBBERED_GP
+ && !find_reg_note (insn, REG_NORETURN, 0))
+ {
+ rtx post_call_tmp_reg = gen_rtx_REG (word_mode, POST_CALL_TMP_REG);
+ clobber_reg (&CALL_INSN_FUNCTION_USAGE (insn), post_call_tmp_reg);
+ }
+
return insn;
}
@@ -7099,10 +7110,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. */
@@ -19134,6 +19143,9 @@ mips_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update)
#undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV
#define TARGET_ATOMIC_ASSIGN_EXPAND_FENV mips_atomic_assign_expand_fenv
+#undef TARGET_CALL_FUSAGE_CONTAINS_NON_CALLEE_CLOBBERS
+#define TARGET_CALL_FUSAGE_CONTAINS_NON_CALLEE_CLOBBERS true
+
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 b25865b..2a1cfff 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -2212,6 +2212,13 @@ enum reg_class
#define FP_ARG_FIRST (FP_REG_FIRST + 12)
#define FP_ARG_LAST (FP_ARG_FIRST + MAX_ARGS_IN_REGISTERS - 1)
+/* Temporary register that is used after a call. $4 and $5 are used for
+ returning complex double values in soft-float code, so $6 is the first
+ suitable candidate for !TARGET_MIPS16. For TARGET_MIPS16, we use
+ PIC_OFFSET_TABLE_REGNUM instead. */
+#define POST_CALL_TMP_REG \
+ (TARGET_MIPS16 ? GP_ARG_FIRST + 2 : PIC_OFFSET_TABLE_REGNUM)
+
/* 1 if N is a possible register number for function argument passing.
We have no FP argument registers when soft-float. When FP registers
are 32 bits, we can't directly reference the odd numbered ones. */
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index f914ab6..6254376 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -6787,8 +6787,10 @@
""
{
int i;
+ rtx insn, call;
- emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
+ call = GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx);
+ insn = mips_emit_call_insn (call, operands[0], operands[0], false);
for (i = 0; i < XVECLEN (operands[2], 0); i++)
{
diff --git a/gcc/testsuite/gcc.target/mips/fuse-caller-save-micromips.c b/gcc/testsuite/gcc.target/mips/fuse-caller-save-micromips.c
new file mode 100644
index 0000000..9fbd8a4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/fuse-caller-save-micromips.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-fuse-caller-save (-mmicromips)" } */
+/* The scan of the sp-relative saves will fail for -O0 and -O1.
+ For -flto, scans will fail because there's no code in the .s file. */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-flto"} } */
+/* Testing -fuse-caller-save optimization option. */
+
+#define ATTRIBUTE MICROMIPS
+#include "fuse-caller-save.h"
+
+/* 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" } } */
diff --git a/gcc/testsuite/gcc.target/mips/fuse-caller-save-mip16.c b/gcc/testsuite/gcc.target/mips/fuse-caller-save-mip16.c
new file mode 100644
index 0000000..d083394
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/fuse-caller-save-mip16.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-fuse-caller-save (-mips16)" } */
+/* The scan of the sp-relative saves will fail for -O0 and -O1.
+ For -flto, scans will fail because there's no code in the .s file. */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-flto"} } */
+/* Testing -fuse-caller-save optimization option. */
+
+#define ATTRIBUTE MIPS16
+#include "fuse-caller-save.h"
+
+/* 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" } } */
diff --git a/gcc/testsuite/gcc.target/mips/fuse-caller-save.c b/gcc/testsuite/gcc.target/mips/fuse-caller-save.c
new file mode 100644
index 0000000..1ad0023
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/fuse-caller-save.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-fuse-caller-save" } */
+/* The scan of the sp-relative saves will fail for -O0 and -O1.
+ For -flto, scans will fail because there's no code in the .s file. */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-flto"} } */
+/* Testing -fuse-caller-save optimization option. */
+
+#define ATTRIBUTE NOCOMPRESSION
+#include "fuse-caller-save.h"
+
+/* 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" } } */
diff --git a/gcc/testsuite/gcc.target/mips/fuse-caller-save.h b/gcc/testsuite/gcc.target/mips/fuse-caller-save.h
new file mode 100644
index 0000000..edf6039
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/fuse-caller-save.h
@@ -0,0 +1,17 @@
+static int __attribute__((noinline)) ATTRIBUTE
+bar (int x)
+{
+ return x + 3;
+}
+
+int __attribute__((noinline)) ATTRIBUTE
+foo (int y)
+{
+ return y + bar (y);
+}
+
+int ATTRIBUTE
+main (void)
+{
+ return !(foo (5) == 13);
+}
diff --git a/gcc/testsuite/gcc.target/mips/mips.exp b/gcc/testsuite/gcc.target/mips/mips.exp
index 8c72cff..6ad8160 100644
--- a/gcc/testsuite/gcc.target/mips/mips.exp
+++ b/gcc/testsuite/gcc.target/mips/mips.exp
@@ -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