]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
fnsplit: Set musttail call during function splitting if there are musttail calls...
authorJakub Jelinek <jakub@redhat.com>
Fri, 21 Mar 2025 11:17:45 +0000 (12:17 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 21 Mar 2025 11:17:45 +0000 (12:17 +0100)
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  <jakub@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.

gcc/ipa-split.cc
gcc/testsuite/g++.dg/opt/musttail1.C [new file with mode: 0644]

index ff562e2a636f4f712e07ccc5f35744def3106999..729fb79af52c40747da517df620805db112ccab6 100644 (file)
@@ -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 (file)
index 0000000..5fe8ab6
--- /dev/null
@@ -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;
+}