void qux (char *); int baz (void); int foo (void) { char buf[64]; qux (buf); return baz (); } int bar (void) { { char buf[64]; qux (buf); } return baz (); } While we must not tail call optimize the baz call in foo, because an address of a local variable escapes and it could be live during the tail call, in bar we don't tail call optimize it either, but we should. The IL difference in *.tailc between foo and bar is: char buf[64]; int _5; <bb 2> [local count: 1073741824]: qux (&buf); + buf ={v} {CLOBBER}; _5 = baz (); - buf ={v} {CLOBBER}; return _5; Right now, we just do: /* Make sure the tail invocation of this function does not indirectly refer to local variables. (Passing variables directly by value is OK.) */ FOR_EACH_LOCAL_DECL (cfun, idx, var) { if (TREE_CODE (var) != PARM_DECL && auto_var_in_fn_p (var, cfun->decl) && may_be_aliased (var) && (ref_maybe_used_by_stmt_p (call, var) || call_may_clobber_ref_p (call, var))) return; } Perhaps we could record all these variables in a bitmap and if there are any, perform a variable life analysis like cfgexpand.c does to determine variable conflicts or what has been discussed for PR86214, and if we can prove that those variables escaped, but are not live at the point of the tail call, we could still tail call optimize this.
This was previously reported as PR 87639, but this report has more analysis. Please close one or the other as a dup.
I suspect there is even older bug which reports this.
(In reply to Andrew Pinski from comment #2) > I suspect there is even older bug which reports this. PR 77938
And even PR 59813.
*** Bug 87639 has been marked as a duplicate of this bug. ***
. *** This bug has been marked as a duplicate of bug 59813 ***
Author: jakub Date: Wed May 8 17:06:46 2019 New Revision: 271013 URL: https://gcc.gnu.org/viewcvs?rev=271013&root=gcc&view=rev Log: PR c++/59813 PR tree-optimization/89060 * tree-ssa-live.h (live_vars_map): New typedef. (compute_live_vars, live_vars_at_stmt, destroy_live_vars): Declare. * tree-ssa-live.c: Include gimple-walk.h and cfganal.h. (struct compute_live_vars_data): New type. (compute_live_vars_visit, compute_live_vars_1, compute_live_vars, live_vars_at_stmt, destroy_live_vars): New functions. * tree-tailcall.c: Include tree-ssa-live.h. (live_vars, live_vars_vec): New global variables. (find_tail_calls): Perform variable life analysis before punting. (tree_optimize_tail_calls_1): Clean up live_vars and live_vars_vec. * tree-inline.h (struct copy_body_data): Add eh_landing_pad_dest member. * tree-inline.c (add_clobbers_to_eh_landing_pad): Remove BB argument. Perform variable life analysis to select variables that really need clobbers added. (copy_edges_for_bb): Don't call add_clobbers_to_eh_landing_pad here, instead set id->eh_landing_pad_dest and assert it is the same. (copy_cfg_body): Call it here if id->eh_landing_pad_dest is non-NULL. * gcc.dg/tree-ssa/pr89060.c: New test. Added: trunk/gcc/testsuite/gcc.dg/tree-ssa/pr89060.c Modified: trunk/gcc/ChangeLog trunk/gcc/testsuite/ChangeLog trunk/gcc/tree-inline.c trunk/gcc/tree-inline.h trunk/gcc/tree-ssa-live.c trunk/gcc/tree-ssa-live.h trunk/gcc/tree-tailcall.c
With the above commit, should this problem be fixed?