http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40718 http://bugs.gentoo.org/show_bug.cgi?id=282189 svn diff -r151029:151030 > pr151030.patch Index: gcc/testsuite/gcc.target/i386/pr40718.c =================================================================== --- gcc/testsuite/gcc.target/i386/pr40718.c (revision 0) +++ gcc/testsuite/gcc.target/i386/pr40718.c (revision 151030) @@ -0,0 +1,36 @@ +/* { dg-do run } */ +/* { dg-require-effective-target ilp32 } */ +/* { dg-options "-O1 -foptimize-sibling-calls" } */ + +void abort (void); + +struct S +{ + void (__attribute__((__stdcall__)) *f) (struct S *); + int i; +}; + +void __attribute__((__stdcall__)) +foo (struct S *s) +{ + s->i++; +} + +void __attribute__((__stdcall__)) +bar (struct S *s) +{ + foo(s); + s->f(s); +} + +int main (void) +{ + struct S s = { foo, 0 }; + + bar (&s); + if (s.i != 2) + abort (); + + return 0; +} + Index: gcc/config/i386/i386.md =================================================================== --- gcc/config/i386/i386.md (revision 151029) +++ gcc/config/i386/i386.md (revision 151030) @@ -14973,22 +14973,25 @@ (match_operand:SI 1 "" "")) (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_operand:SI 2 "immediate_operand" "i")))] - "!TARGET_64BIT" + "!SIBLING_CALL_P (insn) && !TARGET_64BIT" { if (constant_call_address_operand (operands[0], Pmode)) - { - if (SIBLING_CALL_P (insn)) - return "jmp\t%P0"; - else - return "call\t%P0"; - } - if (SIBLING_CALL_P (insn)) - return "jmp\t%A0"; - else - return "call\t%A0"; + return "call\t%P0"; + return "call\t%A0"; } [(set_attr "type" "call")]) +(define_insn "*sibcall_pop_1" + [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "s,U")) + (match_operand:SI 1 "" "")) + (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) + (match_operand:SI 2 "immediate_operand" "i,i")))] + "SIBLING_CALL_P (insn) && !TARGET_64BIT" + "@ + jmp\t%P0 + jmp\t%A0" + [(set_attr "type" "call")]) + (define_expand "call" [(call (match_operand:QI 0 "" "") (match_operand 1 "" "")) @@ -21469,22 +21472,26 @@ (match_operand:SI 2 "" ""))) (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_operand:SI 3 "immediate_operand" "i")))] - "!TARGET_64BIT" + "!SIBLING_CALL_P (insn) && !TARGET_64BIT" { if (constant_call_address_operand (operands[1], Pmode)) - { - if (SIBLING_CALL_P (insn)) - return "jmp\t%P1"; - else - return "call\t%P1"; - } - if (SIBLING_CALL_P (insn)) - return "jmp\t%A1"; - else - return "call\t%A1"; + return "call\t%P1"; + return "call\t%A1"; } [(set_attr "type" "callv")]) +(define_insn "*sibcall_value_pop_1" + [(set (match_operand 0 "" "") + (call (mem:QI (match_operand:SI 1 "call_insn_operand" "s,U")) + (match_operand:SI 2 "" ""))) + (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) + (match_operand:SI 3 "immediate_operand" "i,i")))] + "SIBLING_CALL_P (insn) && !TARGET_64BIT" + "@ + jmp\t%P1 + jmp\t%A1" + [(set_attr "type" "callv")]) + (define_insn "*call_value_0" [(set (match_operand 0 "" "") (call (mem:QI (match_operand:SI 1 "constant_call_address_operand" ""))