commit:     25603f8e2ac7815ea0d33bb3bb67add54eec017a
Author:     Sam James <sam <AT> gentoo <DOT> org>
AuthorDate: Sat Apr  5 15:33:23 2025 +0000
Commit:     Sam James <sam <AT> gentoo <DOT> org>
CommitDate: Sat Apr  5 15:33:23 2025 +0000
URL:        https://gitweb.gentoo.org/proj/gcc-patches.git/commit/?id=25603f8e

15.0.0: add another tailcall patch

Bug: https://gcc.gnu.org/PR119614
Signed-off-by: Sam James <sam <AT> gentoo.org>

 15.0.0/gentoo/88_all_PR119614.patch | 134 ++++++++++++++++++++++++++++++++++++
 1 file changed, 134 insertions(+)

diff --git a/15.0.0/gentoo/88_all_PR119614.patch 
b/15.0.0/gentoo/88_all_PR119614.patch
new file mode 100644
index 0000000..e577f8f
--- /dev/null
+++ b/15.0.0/gentoo/88_all_PR119614.patch
@@ -0,0 +1,134 @@
+https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119614#c12
+
+2025-04-05  Jakub Jelinek  <[email protected]>
+
+       PR tree-optimization/119614
+       * tree-tailcall.cc (find_tail_calls): Remember edges which have been
+       walked through if !ass_var.  Perform IPA-VRP workaround even when
+       ret_var is not TREE_CONSTANT, in that case check in a loop if it is
+       a PHI result and in that case look at the PHI argument from
+       corresponding edge in the edge vector.
+
+       * g++.dg/opt/pr119613.C: Change { c || c++11 } in obviously C++ only
+       test to just c++11.
+       * g++.dg/opt/pr119614.C: New test.
+
+--- a/gcc/tree-tailcall.cc     2025-04-04 20:52:34.450015821 +0200
++++ b/gcc/tree-tailcall.cc     2025-04-05 14:50:50.106693562 +0200
+@@ -920,6 +920,7 @@ find_tail_calls (basic_block bb, struct
+   auto_bitmap to_move_defs;
+   auto_vec<gimple *> to_move_stmts;
+   bool is_noreturn = gimple_call_noreturn_p (call);
++  auto_vec<edge> edges;
+ 
+   abb = bb;
+   agsi = gsi;
+@@ -933,6 +934,8 @@ find_tail_calls (basic_block bb, struct
+       {
+         edge e = single_non_eh_succ_edge (abb);
+         ass_var = propagate_through_phis (ass_var, e);
++        if (!ass_var)
++          edges.safe_push (e);
+         abb = e->dest;
+         agsi = gsi_start_bb (abb);
+       }
+@@ -1040,9 +1043,7 @@ find_tail_calls (basic_block bb, struct
+       /* If IPA-VRP proves called function always returns a singleton range,
+        the return value is replaced by the only value in that range.
+        For tail call purposes, pretend such replacement didn't happen.  */
+-      if (ass_var == NULL_TREE
+-        && !tail_recursion
+-        && TREE_CONSTANT (ret_var))
++      if (ass_var == NULL_TREE && !tail_recursion)
+       if (tree type = gimple_range_type (call))
+         if (tree callee = gimple_call_fndecl (call))
+           if ((INTEGRAL_TYPE_P (type)
+@@ -1052,9 +1053,43 @@ find_tail_calls (basic_block bb, struct
+                                             type)
+               && useless_type_conversion_p (TREE_TYPE (ret_var), type)
+               && ipa_return_value_range (val, callee)
+-              && val.singleton_p (&valr)
+-              && operand_equal_p (ret_var, valr, 0))
+-            ok = true;
++              && val.singleton_p (&valr))
++            {
++              tree rv = ret_var;
++              unsigned int i = edges.length ();
++              /* If ret_var is equal to valr, we can tail optimize.  */
++              if (operand_equal_p (ret_var, valr, 0))
++                ok = true;
++              else
++                /* Otherwise, if ret_var is a PHI result, try to find out
++                   if valr isn't propagated through PHIs on the path from
++                   call's bb to SSA_NAME_DEF_STMT (ret_var)'s bb.  */
++                while (TREE_CODE (rv) == SSA_NAME
++                       && gimple_code (SSA_NAME_DEF_STMT (rv)) == GIMPLE_PHI)
++                  {
++                    tree nrv = NULL_TREE;
++                    gimple *g = SSA_NAME_DEF_STMT (rv);
++                    for (; i; --i)
++                      {
++                        if (edges[i - 1]->dest == gimple_bb (g))
++                          {
++                            nrv
++                              = gimple_phi_arg_def_from_edge (g,
++                                                              edges[i - 1]);
++                            --i;
++                            break;
++                          }
++                      }
++                    if (nrv == NULL_TREE)
++                      break;
++                    if (operand_equal_p (nrv, valr, 0))
++                      {
++                        ok = true;
++                        break;
++                      }
++                    rv = nrv;
++                  }
++            }
+       if (!ok)
+       {
+         maybe_error_musttail (call,
+--- a/gcc/testsuite/g++.dg/opt/pr119613.C      2025-04-04 20:51:42.482706589 
+0200
++++ b/gcc/testsuite/g++.dg/opt/pr119613.C      2025-04-05 14:57:31.157353618 
+0200
+@@ -1,5 +1,5 @@
+ // PR middle-end/119613
+-// { dg-do compile { target { musttail && { c || c++11 } } } }
++// { dg-do compile { target { musttail && c++11 } } }
+ // { dg-options "-O0" }
+ 
+ struct S { S () {} };
+--- a/gcc/testsuite/g++.dg/opt/pr119614.C      2025-04-05 14:57:16.276551780 
+0200
++++ b/gcc/testsuite/g++.dg/opt/pr119614.C      2025-04-05 14:56:46.020954674 
+0200
+@@ -0,0 +1,30 @@
++// PR tree-optimization/119614
++// { dg-do compile { target musttail } }
++// { dg-options "-O2" }
++
++struct S {} b;
++char *foo ();
++int e, g;
++void bar ();
++void corge (S);
++
++[[gnu::noinline]] char *
++baz ()
++{
++  bar ();
++  return 0;
++}
++
++const char *
++qux ()
++{
++  if (e)
++    {
++      S a = b;
++      corge (a);
++      if (g)
++        return 0;
++      [[gnu::musttail]] return baz ();
++    }
++  return foo ();
++}

Reply via email to