On Tue, 1 Apr 2025, Jakub Jelinek wrote:

> Hi!
> 
> While working on the previous tailc patch, I've noticed the following
> problem.
> The testcase below fails, because we decide to tail recursion optimize
> the call, but tail recursion (as documented in tree-tailcall.cc) needs to
> add some result multiplication and/or addition if any tail recursion uses
> accumulator, which is added right before the return.
> So, if there are musttail non-recurive calls in the function, successful
> tail recursion optimization will mean we'll later error on the musttail
> calls.  musttail recursive calls are ok, those would be tail recursion
> optimized.
> 
> So, the following patch punts on all tail recursion optimizations if it
> needs accumulators (add and/or mult) if there is at least one non-recursive
> musttail call.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK.

Do we update cfun->has_musttail at some point for optimized away
musttail calls with respect to inlining/DCE?  I do wonder whether
tree-tailcall.cc itself could "quickly" determine whether we have
any musttail calls that we can handle and will not diagnose?

Thanks,
Richard.

> 2025-04-01  Jakub Jelinek  <ja...@redhat.com>
> 
>       PR tree-optimization/119493
>       * tree-tailcall.cc (tree_optimize_tail_calls_1): Ignore tail recursion
>       candidates which need accumulators if there is at least one musttail
>       non-recursive call.
> 
>       * gcc.dg/pr119493-2.c: New test.
> 
> --- gcc/tree-tailcall.cc.jj   2025-03-31 13:00:58.288725496 +0200
> +++ gcc/tree-tailcall.cc      2025-03-31 14:34:31.285106333 +0200
> @@ -1373,6 +1373,38 @@ tree_optimize_tail_calls_1 (bool opt_tai
>        live_vars = NULL;
>      }
>  
> +  if (cfun->has_musttail)
> +    {
> +      /* We can't mix non-recursive must tail calls with tail recursive
> +      calls which require accumulators, because in that case we have to
> +      emit code in between the musttail calls and return, which prevent
> +      calling them as tail calls.  So, in that case give up on the
> +      tail recursion.  */
> +      for (act = tailcalls; act; act = act->next)
> +     if (!act->tail_recursion)
> +       {
> +         gcall *call = as_a <gcall *> (gsi_stmt (act->call_gsi));
> +         if (gimple_call_must_tail_p (call))
> +           break;
> +       }
> +      if (act)
> +     for (struct tailcall **p = &tailcalls; *p; )
> +       {
> +         if ((*p)->tail_recursion && ((*p)->add || (*p)->mult))
> +           {
> +             struct tailcall *a = *p;
> +             *p = (*p)->next;
> +             gcall *call = as_a <gcall *> (gsi_stmt (a->call_gsi));
> +             maybe_error_musttail (call,
> +                                   _("tail recursion with accumulation "
> +                                     "mixed with musttail "
> +                                     "non-recursive call"), diag_musttail);
> +             free (a);
> +           }
> +         else
> +           p = &(*p)->next;
> +       }
> +    }
>    /* Construct the phi nodes and accumulators if necessary.  */
>    a_acc = m_acc = NULL_TREE;
>    for (act = tailcalls; act; act = act->next)
> --- gcc/testsuite/gcc.dg/pr119493-2.c.jj      2025-03-31 14:41:18.977464154 
> +0200
> +++ gcc/testsuite/gcc.dg/pr119493-2.c 2025-03-31 14:45:24.327068682 +0200
> @@ -0,0 +1,22 @@
> +/* PR tree-optimization/119493 */
> +/* { dg-do compile { target musttail } } */
> +/* { dg-options "-O2 -fdump-tree-tailr1-details" } */
> +/* { dg-final { scan-tree-dump-times "tail recursion with accumulation mixed 
> with musttail non-recursive call" 2 "tailr1" } } */
> +
> +[[gnu::noipa]] int
> +bar (int x, int y)
> +{
> +  return x + y;
> +}
> +
> +[[gnu::noinline, gnu::noclone]] int
> +foo (int x, int y)
> +{
> +  if (x < 10)
> +    [[gnu::musttail]] return bar (x, y);
> +  if (y & 2)
> +    return foo (x - 1, y) * 2;
> +  if (y & 1)
> +    [[gnu::musttail]] return foo (x - 1, y);
> +  return foo (x - 1, y) * 3;
> +}
> 
>       Jakub
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)

Reply via email to