diff --git a/gcc/ChangeLog b/gcc/ChangeLog index de4cedee343..59dc4abbab5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2016-01-15 Richard Sandiford + + PR middle-end/69246 + * calls.c (emit_call_1): Force n_popped to zero for sibcalls. + 2016-01-15 Ilya Enkovich * config/i386/i386.c (scalar_chain::compute_convert_gain): Fix typo. diff --git a/gcc/calls.c b/gcc/calls.c index a1549348b52..8f573b83430 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -272,12 +272,19 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU rtx rounded_stack_size_rtx = GEN_INT (rounded_stack_size); rtx call, funmem, pat; int already_popped = 0; - HOST_WIDE_INT n_popped - = targetm.calls.return_pops_args (fndecl, funtype, stack_size); + HOST_WIDE_INT n_popped = 0; + + /* Sibling call patterns never pop arguments (no sibcall(_value)_pop + patterns exist). Any popping that the callee does on return will + be from our caller's frame rather than ours. */ + if (!(ecf_flags & ECF_SIBCALL)) + { + n_popped += targetm.calls.return_pops_args (fndecl, funtype, stack_size); #ifdef CALL_POPS_ARGS - n_popped += CALL_POPS_ARGS (*get_cumulative_args (args_so_far)); + n_popped += CALL_POPS_ARGS (*get_cumulative_args (args_so_far)); #endif + } /* Ensure address is valid. SYMBOL_REF is already valid, so no need, and we don't want to load it into a register as an optimization, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index fb098b56763..2c08f8d7f0d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2016-01-15 Richard Sandiford + + PR middle-end/69246 + * gcc.target/i386/pr69246.c: New test. + 2016-01-15 Dominik Vogt * gfortran.dg/bind_c_array_params_2.f90: Fix test patterns for diff --git a/gcc/testsuite/gcc.target/i386/pr69246.c b/gcc/testsuite/gcc.target/i386/pr69246.c new file mode 100644 index 00000000000..e56e691c444 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr69246.c @@ -0,0 +1,18 @@ +/* { dg-do compile { target ia32 } } */ +/* { dg-options "-O2" } */ + +void (__attribute__ ((stdcall)) *a) (int); + +void __attribute__ ((stdcall)) +foo (int x) +{ + a (x); +} + +int (__attribute__ ((stdcall)) *b) (int); + +int __attribute__ ((stdcall)) +bar (int x) +{ + return b (x); +}