https://gcc.gnu.org/g:589c94da22ec71fe8518878e801e88b05deffe18

commit r15-8493-g589c94da22ec71fe8518878e801e88b05deffe18
Author: Jakub Jelinek <ja...@redhat.com>
Date:   Fri Mar 21 12:17:45 2025 +0100

    fnsplit: Set musttail call during function splitting if there are musttail 
calls [PR119376]
    
    The just posted inliner patch can regress musttail calls if we perform
    function splitting and then inline the outlined body back into the original
    (or inline both the small function and outlined large body into something
    else).
    If there are any musttail calls, I think we need to call the outlined
    body using a musttail call, so that the inliner will preserve musttail
    attributes in the body.
    
    2025-03-21  Jakub Jelinek  <ja...@redhat.com>
    
            PR ipa/119376
            * ipa-split.cc (split_function): Call gimple_call_set_must_tail
            on the call to outlined partition if has_musttail and
            !add_tsan_func_exit.
    
            * g++.dg/opt/musttail1.C: New test.

Diff:
---
 gcc/ipa-split.cc                     |  2 ++
 gcc/testsuite/g++.dg/opt/musttail1.C | 35 +++++++++++++++++++++++++++++++++++
 2 files changed, 37 insertions(+)

diff --git a/gcc/ipa-split.cc b/gcc/ipa-split.cc
index ff562e2a636f..729fb79af52c 100644
--- a/gcc/ipa-split.cc
+++ b/gcc/ipa-split.cc
@@ -1473,6 +1473,8 @@ split_function (basic_block return_bb, class split_point 
*split_point,
        args_to_pass[i] = arg;
       }
   call = gimple_build_call_vec (node->decl, args_to_pass);
+  if (cur_node->get_fun ()->has_musttail && !add_tsan_func_exit)
+    gimple_call_set_must_tail (call, true);
   gimple_set_block (call, DECL_INITIAL (current_function_decl));
   args_to_pass.release ();
 
diff --git a/gcc/testsuite/g++.dg/opt/musttail1.C 
b/gcc/testsuite/g++.dg/opt/musttail1.C
new file mode 100644
index 000000000000..5fe8ab6bd392
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/musttail1.C
@@ -0,0 +1,35 @@
+// PR ipa/119376
+// { dg-do compile { target musttail } }
+// { dg-options "-O2 -fdump-tree-optimized" }
+// { dg-final { scan-tree-dump-times "  \[^\n\r]* = foo \\\(\[^\n\r]*\\\); 
\\\[tail call\\\] \\\[must tail call\\\]" 2 "optimized" } }
+// { dg-final { scan-tree-dump-times "  \[^\n\r]* = foo \\\(\[^\n\r]*\\\); 
\\\[tail call\\\]" 3 "optimized" } }
+
+int foo (int x);
+typedef int (*F) (int);
+int v;
+
+inline int
+bar (int x)
+{
+  if (__builtin_expect (x == 42, 1))
+    return 1;
+  [[gnu::musttail]] return foo (x + v * (x | v) * (x & v) * (x - v) * (x + v * 
v));
+}
+
+int
+baz (int x)
+{
+  [[gnu::musttail]] return bar (x);
+}
+
+int
+qux (int x)
+{
+  return bar (x + 1);
+}
+
+F
+corge ()
+{
+  return &bar;
+}

Reply via email to