On 25-04-14 15:22, Richard Sandiford wrote:
Tom de Vries <[email protected]> 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 <[email protected]> Tom de Vries <[email protected]> * 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
