This moves an #ifdef block of code from calls.c to targetm.function_ok_for_sibcall. Only two targets, x86 and rs6000, define REG_PARM_STACK_SPACE or OUTGOING_REG_PARM_STACK_SPACE macros that might vary depending on the called function. Macros like UNITS_PER_WORD don't change over a function boundary, nor does the MIPS ABI, nor does TARGET_64BIT on PA-RISC. Other targets are even more trivially seen to not need the calls.c code.
Besides cleaning up a small piece of #ifdef code, the motivation for this patch is to allow tail calls on PowerPC for functions that require less reg_parm_stack_space than their caller. The original code in calls.c only permitted tail calls when exactly equal. Bootstrapped and regression tested powerpc64le-linux and x86_64-linux. OK for master? PR middle-end/97267 * calls.h (maybe_complain_about_tail_call): Declare. * calls.c (maybe_complain_about_tail_call): Make global. (can_implement_as_sibling_call_p): Move REG_PARM_STACK_SPACE check to.. * config/i386/i386.c (ix86_function_ok_for_sibcall): ..here, and.. * config/rs6000/rs6000-logue.c (rs6000_function_ok_for_sibcall): .. here. Modify to allow reg_parm_stack_space less or equal to caller, and delete redundant OUTGOING_REG_PARM_STACK_SPACE test. * testsuite/gcc.target/powerpc/pr97267.c: New test. diff --git a/gcc/calls.c b/gcc/calls.c index ed4363811c8..df7324f9343 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -1873,7 +1873,7 @@ maybe_warn_nonstring_arg (tree fndecl, tree exp) /* Issue an error if CALL_EXPR was flagged as requiring tall-call optimization. */ -static void +void maybe_complain_about_tail_call (tree call_expr, const char *reason) { gcc_assert (TREE_CODE (call_expr) == CALL_EXPR); @@ -3501,20 +3501,6 @@ can_implement_as_sibling_call_p (tree exp, return false; } -#ifdef REG_PARM_STACK_SPACE - /* If outgoing reg parm stack space changes, we cannot do sibcall. */ - if (OUTGOING_REG_PARM_STACK_SPACE (funtype) - != OUTGOING_REG_PARM_STACK_SPACE (TREE_TYPE (current_function_decl)) - || (reg_parm_stack_space != REG_PARM_STACK_SPACE (current_function_decl))) - { - maybe_complain_about_tail_call (exp, - "inconsistent size of stack space" - " allocated for arguments which are" - " passed in registers"); - return false; - } -#endif - /* Check whether the target is able to optimize the call into a sibcall. */ if (!targetm.function_ok_for_sibcall (fndecl, exp)) diff --git a/gcc/calls.h b/gcc/calls.h index dfb951ca45b..6d4feb59dd0 100644 --- a/gcc/calls.h +++ b/gcc/calls.h @@ -133,6 +133,7 @@ extern bool reference_callee_copied (CUMULATIVE_ARGS *, extern void maybe_warn_alloc_args_overflow (tree, tree, tree[2], int[2]); extern tree get_attr_nonstring_decl (tree, tree * = NULL); extern bool maybe_warn_nonstring_arg (tree, tree); +extern void maybe_complain_about_tail_call (tree, const char *); extern bool get_size_range (tree, tree[2], bool = false); extern rtx rtx_for_static_chain (const_tree, bool); extern bool cxx17_empty_base_field_p (const_tree); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index f684954af81..58fc5280935 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -939,6 +939,19 @@ ix86_function_ok_for_sibcall (tree decl, tree exp) decl_or_type = type; } + /* If outgoing reg parm stack space changes, we cannot do sibcall. */ + if (OUTGOING_REG_PARM_STACK_SPACE (type) + != OUTGOING_REG_PARM_STACK_SPACE (TREE_TYPE (current_function_decl)) + || (REG_PARM_STACK_SPACE (decl_or_type) + != REG_PARM_STACK_SPACE (current_function_decl))) + { + maybe_complain_about_tail_call (exp, + "inconsistent size of stack space" + " allocated for arguments which are" + " passed in registers"); + return false; + } + /* Check that the return value locations are the same. Like if we are returning floats on the 80387 register stack, we cannot make a sibcall from a function that doesn't return a float to a diff --git a/gcc/config/rs6000/rs6000-logue.c b/gcc/config/rs6000/rs6000-logue.c index d90cd5736e1..814b549e4ca 100644 --- a/gcc/config/rs6000/rs6000-logue.c +++ b/gcc/config/rs6000/rs6000-logue.c @@ -30,6 +30,7 @@ #include "df.h" #include "tm_p.h" #include "ira.h" +#include "calls.h" #include "print-tree.h" #include "varasm.h" #include "explow.h" @@ -1133,6 +1134,17 @@ rs6000_function_ok_for_sibcall (tree decl, tree exp) else fntype = TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (exp))); + /* If reg parm stack space increases, we cannot sibcall. */ + if (REG_PARM_STACK_SPACE (decl ? decl : fntype) + > REG_PARM_STACK_SPACE (current_function_decl)) + { + maybe_complain_about_tail_call (exp, + "inconsistent size of stack space" + " allocated for arguments which are" + " passed in registers"); + return false; + } + /* We can't do it if the called function has more vector parameters than the current function; there's nowhere to put the VRsave code. */ if (TARGET_ALTIVEC_ABI diff --git a/gcc/testsuite/gcc.target/powerpc/pr97267.c b/gcc/testsuite/gcc.target/powerpc/pr97267.c new file mode 100644 index 00000000000..cab46245fc9 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr97267.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +static int __attribute__ ((__noclone__, __noinline__)) +reg_args (int j1, int j2, int j3, int j4, int j5, int j6, int j7, int j8) +{ + return j1 + j2 + j3 + j4 + j5 + j6 + j7 + j8; +} + +int __attribute__ ((__noclone__, __noinline__)) +stack_args (int j1, int j2, int j3, int j4, int j5, int j6, int j7, int j8, + int j9) +{ + if (j9 == 0) + return 0; + return reg_args (j1, j2, j3, j4, j5, j6, j7, j8); +} + +/* { dg-final { scan-assembler-not {(?n)^\s+bl\s} } } */ -- Alan Modra Australia Development Lab, IBM