diff mbox

-fuse-caller-save - Enable for MIPS

Message ID 535A5A8F.30901@mentor.com
State New
Headers show

Commit Message

Tom de Vries April 25, 2014, 12:52 p.m. UTC
On 22-04-14 17:05, Tom de Vries wrote:
> I've updated the fuse-caller-save patch series to model non-callee call clobbers
> in CALL_INSN_FUNCTION_USAGE.
>

Richard,

this patch enables the fuse-caller-save optimization for MIPS.

It adds the $6 clobber in CALL_INSN_FUNCTION_USAGE when required, and sets 
TARGET_CALL_FUSAGE_CONTAINS_NON_CALLEE_CLOBBERS to true.

I've done a minimal rebuild for mips, ran the fuse-caller-save testcase and 
checked with -dP that I can find $6 in the C_I_F_U.

ok for trunk if a full MIPS build and test cycle succeeds?

Thanks,
- Tom

2014-01-12  Radovan Obradovic  <robradovic@mips.com>
             Tom de Vries  <tom@codesourcery.com>

	* config/mips/mips.h (POST_CALL_TMP_REG): Define.
	* config/mips/mips.c (mips_split_call): Use POST_CALL_TMP_REG.
	(TARGET_CALL_FUSAGE_CONTAINS_NON_CALLEE_CLOBBERS): Redefine to true.
	(mips_expand_call): Add POST_CALL_TMP_REG clobber.
	* config/mips/mips.md (define_expand "untyped_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.

Comments

Richard Sandiford April 25, 2014, 1:22 p.m. UTC | #1
Tom de Vries <Tom_deVries@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.

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.

> 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).

> +/* 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.

Thanks,
Richard
diff mbox

Patch

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);
+
       gcc_assert (!lazy_p && type == MIPS_CALL_NORMAL);
       return insn;
     }
@@ -7087,7 +7093,13 @@  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))
+    clobber_reg (&CALL_INSN_FUNCTION_USAGE (insn), post_call_tmp_reg);
+
+  return insn;
 }
 
 /* Split call instruction INSN into a $gp-clobbering call and
@@ -7099,10 +7111,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 +19144,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..8c5498a 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -2212,6 +2212,11 @@  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, 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)
+
 /* 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..e333c42 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -6787,8 +6787,15 @@ 
   ""
 {
   int i;
+  rtx insn;
+  rtx post_call_tmp_reg = gen_rtx_REG (word_mode, POST_CALL_TMP_REG);
 
-  emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
+  insn = emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
+
+  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);
 
   for (i = 0; i < XVECLEN (operands[2], 0); i++)
     {
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" } } */
+/* 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" } } */
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"
 }