diff mbox

Fix finding reg-sets of call insn in collect_fn_hard_reg_usage

Message ID 53ABFC43.6050002@mentor.com
State New
Headers show

Commit Message

Tom de Vries June 26, 2014, 10:56 a.m. UTC
On 19-06-14 18:47, Richard Henderson wrote:
> And I forgot to mention it might be worth while to notice simple recursion.
> Avoid the early exit path if caller == callee, despite the caller-save info not
> being valid.
>
>

Richard,

attached patch enables handling of self-recursive functions in the 
fuse-caller-save optimization, and adds a test-case.

I've done an x86_64 build and ran the i386.exp testsuite.

OK for trunk if full bootstrap and reg-test succeeds?

Thanks,
- Tom

Comments

Jeff Law June 30, 2014, 8:42 p.m. UTC | #1
On 06/26/14 04:56, Tom de Vries wrote:
> On 19-06-14 18:47, Richard Henderson wrote:
>> And I forgot to mention it might be worth while to notice simple
>> recursion.
>> Avoid the early exit path if caller == callee, despite the caller-save
>> info not
>> being valid.
>>
>>
>
> Richard,
>
> attached patch enables handling of self-recursive functions in the
> fuse-caller-save optimization, and adds a test-case.
>
> I've done an x86_64 build and ran the i386.exp testsuite.
>
> OK for trunk if full bootstrap and reg-test succeeds?
Yes.

Thanks,
Jeff
diff mbox

Patch

2014-06-26  Tom de Vries  <tom@codesourcery.com>

	* final.c (get_call_fndecl): Declare.
	(self_recursive_call_p): New function.
	(collect_fn_hard_reg_usage): Handle self-recursive function calls.

	* gcc.target/i386/fuse-caller-save-rec.c: New test.

diff --git a/gcc/final.c b/gcc/final.c
index 9525efc..ed0ba0b 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -225,6 +225,7 @@  static int final_addr_vec_align (rtx);
 #endif
 static int align_fuzz (rtx, rtx, int, unsigned);
 static void collect_fn_hard_reg_usage (void);
+static tree get_call_fndecl (rtx);
 
 /* Initialize data in final at the beginning of a compilation.  */
 
@@ -4750,6 +4751,16 @@  make_pass_clean_state (gcc::context *ctxt)
   return new pass_clean_state (ctxt);
 }
 
+/* Return true if INSN is a call to the the current function.  */
+
+static bool
+self_recursive_call_p (rtx insn)
+{
+  tree fndecl = get_call_fndecl (insn);
+  return (fndecl == current_function_decl
+	  && decl_binds_to_current_def_p (fndecl));
+}
+
 /* Collect hard register usage for the current function.  */
 
 static void
@@ -4775,7 +4786,8 @@  collect_fn_hard_reg_usage (void)
       if (!NONDEBUG_INSN_P (insn))
 	continue;
 
-      if (CALL_P (insn))
+      if (CALL_P (insn)
+	  && !self_recursive_call_p (insn))
 	{
 	  if (!get_call_reg_set_usage (insn, &insn_used_regs,
 				       call_used_reg_set))
diff --git a/gcc/testsuite/gcc.target/i386/fuse-caller-save-rec.c b/gcc/testsuite/gcc.target/i386/fuse-caller-save-rec.c
new file mode 100644
index 0000000..b30a0b4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fuse-caller-save-rec.c
@@ -0,0 +1,32 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fuse-caller-save -fomit-frame-pointer -fno-optimize-sibling-calls" } */
+/* { dg-additional-options "-mregparm=1" { target ia32 } } */
+
+/* Test -fuse-caller-save optimization on self-recursive function.  */
+
+static int __attribute__((noinline))
+bar (int x)
+{
+  if (x > 4)
+    return bar (x - 3);
+  return 0;
+}
+
+int __attribute__((noinline))
+foo (int y)
+{
+  return y + bar (y);
+}
+
+int
+main (void)
+{
+  return !(foo (5) == 13);
+}
+
+/* Verify that no registers where saved on stack.  */
+/* { dg-final { scan-assembler-not "\.cfi_offset"  } } */
+
+/* Verify that bar is self-recursive.  */
+/* { dg-final { scan-assembler-times "call\tbar" 2 } } */
+
-- 
1.9.1