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 <ja...@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; +} Jakub