diff mbox

Treat tail calls as scheduling barriers (PR rtl-optimization/48721)

Message ID 20111130175422.GL27242@tyan-ft48-01.lab.bos.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Nov. 30, 2011, 5:54 p.m. UTC
Hi!

As discussed in the PR, I think tail calls are best handled as full
scheduling barriers, scheduling tail calls before other insns effectively
means we remove those other insns, but isn't dead insn removal the job
of other passes instead?
In any case, tail calls need to come up after all restoration of
call saved register, on this testcase GCC wanted to schedule a tail
call before r12 restoring insn.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2011-11-30  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/48721
	* sched-deps.c (sched_analyze_insn): For SIBLING_CALL_P set
	reg_pending_barrier to TRUE_BARRIER.

	* gcc.target/i386/pr48721.c: New test.


	Jakub

Comments

Vladimir Makarov Nov. 30, 2011, 6:18 p.m. UTC | #1
On 11/30/2011 12:54 PM, Jakub Jelinek wrote:
> Hi!
>
> As discussed in the PR, I think tail calls are best handled as full
> scheduling barriers, scheduling tail calls before other insns effectively
> means we remove those other insns, but isn't dead insn removal the job
> of other passes instead?
> In any case, tail calls need to come up after all restoration of
> call saved register, on this testcase GCC wanted to schedule a tail
> call before r12 restoring insn.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>
> 2011-11-30  Jakub Jelinek<jakub@redhat.com>
>
> 	PR rtl-optimization/48721
> 	* sched-deps.c (sched_analyze_insn): For SIBLING_CALL_P set
> 	reg_pending_barrier to TRUE_BARRIER.
>
> 	* gcc.target/i386/pr48721.c: New test.
>
> --- gcc/sched-deps.c.jj	2011-11-28 17:58:04.000000000 +0100
> +++ gcc/sched-deps.c	2011-11-30 14:10:55.117267854 +0100
> @@ -2873,7 +2873,11 @@ sched_analyze_insn (struct deps_desc *de
>   	  else
>   	    sched_analyze_2 (deps, XEXP (link, 0), insn);
>   	}
> -      if (find_reg_note (insn, REG_SETJMP, NULL))
> +      /* Don't schedule anything after a tail call, tail call needs
> +	 to use at least all call-saved registers.  */
> +      if (SIBLING_CALL_P (insn))
> +	reg_pending_barrier = TRUE_BARRIER;
> +      else if (find_reg_note (insn, REG_SETJMP, NULL))
>   	reg_pending_barrier = MOVE_BARRIER;
>       }
>
> --- gcc/testsuite/gcc.target/i386/pr48721.c.jj	2011-11-30 14:14:26.290628842 +0100
> +++ gcc/testsuite/gcc.target/i386/pr48721.c	2011-11-30 12:24:06.000000000 +0100
> @@ -0,0 +1,51 @@
> +/* PR rtl-optimization/48721 */
> +/* { dg-do compile } */
> +/* { dg-options "-O -foptimize-sibling-calls -fsched2-use-superblocks -fschedule-insns2 -mtune=core2" } */
> +
> +extern unsigned char a[];
> +extern int b[], d[], e[], f[], g[], *h[], m[], *n[], o[];
> +extern char c[];
> +
> +struct S
> +{
> +  unsigned char s1;
> +  int s2, s3, s4, s5, s6, s7, s8;
> +};
> +
> +__attribute__((noinline, noclone)) int
> +foo (int x)
> +{
> +  return 0;
> +}
> +
> +int
> +bar (int x, struct S *y)
> +{
> +  int z;
> +  switch (x)
> +    {
> +    case 1:
> +    case 2:
> +      {
> +	int t2, t4, t5, t6, t7, t8;
> +	z = o[y->s8 * 6];
> +	t8 = *n[m[x] * 5];
> +	t4 = *h[y->s7];
> +	t7 = z;
> +	z = g[f[x] + y->s6];
> +	t6 = e[y->s5];
> +	t5 = d[c[x] + y->s3 * 17];
> +	if (z)
> +	  t2 = b[z];
> +	if (a[z] != y->s1)
> +	  return foo (x);
> +	y->s8 = t8;
> +	y->s4 = t4;
> +	y->s7 = t7;
> +	y->s6 = t6;
> +	y->s5 = t5;
> +	y->s2 = t2;
> +      }
> +    }
> +  return 0;
> +}
>
Ok, thanks.
diff mbox

Patch

--- gcc/sched-deps.c.jj	2011-11-28 17:58:04.000000000 +0100
+++ gcc/sched-deps.c	2011-11-30 14:10:55.117267854 +0100
@@ -2873,7 +2873,11 @@  sched_analyze_insn (struct deps_desc *de
 	  else
 	    sched_analyze_2 (deps, XEXP (link, 0), insn);
 	}
-      if (find_reg_note (insn, REG_SETJMP, NULL))
+      /* Don't schedule anything after a tail call, tail call needs
+	 to use at least all call-saved registers.  */
+      if (SIBLING_CALL_P (insn))
+	reg_pending_barrier = TRUE_BARRIER;
+      else if (find_reg_note (insn, REG_SETJMP, NULL))
 	reg_pending_barrier = MOVE_BARRIER;
     }
 
--- gcc/testsuite/gcc.target/i386/pr48721.c.jj	2011-11-30 14:14:26.290628842 +0100
+++ gcc/testsuite/gcc.target/i386/pr48721.c	2011-11-30 12:24:06.000000000 +0100
@@ -0,0 +1,51 @@ 
+/* PR rtl-optimization/48721 */
+/* { dg-do compile } */
+/* { dg-options "-O -foptimize-sibling-calls -fsched2-use-superblocks -fschedule-insns2 -mtune=core2" } */
+
+extern unsigned char a[];
+extern int b[], d[], e[], f[], g[], *h[], m[], *n[], o[];
+extern char c[];
+
+struct S
+{
+  unsigned char s1;
+  int s2, s3, s4, s5, s6, s7, s8;
+};
+
+__attribute__((noinline, noclone)) int
+foo (int x)
+{
+  return 0;
+}
+
+int
+bar (int x, struct S *y)
+{
+  int z;
+  switch (x)
+    {
+    case 1:
+    case 2:
+      {
+	int t2, t4, t5, t6, t7, t8;
+	z = o[y->s8 * 6];
+	t8 = *n[m[x] * 5];
+	t4 = *h[y->s7];
+	t7 = z;
+	z = g[f[x] + y->s6];
+	t6 = e[y->s5];
+	t5 = d[c[x] + y->s3 * 17];
+	if (z)
+	  t2 = b[z];
+	if (a[z] != y->s1)
+	  return foo (x);
+	y->s8 = t8;
+	y->s4 = t4;
+	y->s7 = t7;
+	y->s6 = t6;
+	y->s5 = t5;
+	y->s2 = t2;
+      }
+    }
+  return 0;
+}