Bug 89060

Summary: Improve tail call optimization
Product: gcc Reporter: Jakub Jelinek <jakub>
Component: tree-optimizationAssignee: Not yet assigned to anyone <unassigned>
Severity: normal CC: amonakov, bugdal
Priority: P3 Keywords: missed-optimization
Version: 9.0   
Target Milestone: ---   
URL: http://gcc.gnu.org/ml/gcc-patches/2019-02/msg00424.html
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed:

Description Jakub Jelinek 2019-01-25 11:33:28 UTC
void qux (char *);
int baz (void);

foo (void)
  char buf[64];
  qux (buf);
  return baz ();

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)))

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.
Comment 1 Alexander Monakov 2019-01-25 13:10:42 UTC
This was previously reported as PR 87639, but this report has more analysis. Please close one or the other as a dup.
Comment 2 Andrew Pinski 2019-01-25 14:41:55 UTC
I suspect there is even older bug which reports this.
Comment 3 Andrew Pinski 2019-01-25 14:44:56 UTC
(In reply to Andrew Pinski from comment #2)
> I suspect there is even older bug which reports this.

PR 77938
Comment 4 Andrew Pinski 2019-01-25 14:47:04 UTC
And even PR 59813.
Comment 5 Jakub Jelinek 2019-01-25 15:49:15 UTC
*** Bug 87639 has been marked as a duplicate of this bug. ***
Comment 6 Jakub Jelinek 2019-01-25 15:51:42 UTC

*** This bug has been marked as a duplicate of bug 59813 ***
Comment 7 Jakub Jelinek 2019-05-08 17:07:18 UTC
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
	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
	* 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.

Comment 8 Rich Felker 2019-05-08 20:54:38 UTC
With the above commit, should this problem be fixed?