aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2025-03-21 12:18:35 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2025-03-21 12:18:35 +0100
commit28caa267dc757d80ffe37d638d981d3572c164ae (patch)
tree4a29c7b8a8f4b45332958b2288d0234584eed923 /gcc
parent589c94da22ec71fe8518878e801e88b05deffe18 (diff)
downloadgcc-28caa267dc757d80ffe37d638d981d3572c164ae.zip
gcc-28caa267dc757d80ffe37d638d981d3572c164ae.tar.gz
gcc-28caa267dc757d80ffe37d638d981d3572c164ae.tar.bz2
icf: Punt for musttail call flag differences in ICF [PR119376]
The following testcase shows we were ignoring musttail flags on calls when deciding if two functions are the same. That can result in problems in both directions, either we silently lose musttail attribute because there is a similar function without it earlier and then we e.g. don't diagnose if it can't be tail called or don't try harder to do a tail call, or we get it even in functions which didn't have it before. The following patch for now just punts if it differs. Perhaps we could just merge it and get musttail flag if any of the merged functions had one in such position, but it feels to me that it is now too late in GCC 15 cycle to play with this. 2025-03-21 Jakub Jelinek <jakub@redhat.com> PR ipa/119376 * ipa-icf-gimple.cc (func_checker::compare_gimple_call): Return false for gimple_call_must_tail_p mismatches. * c-c++-common/musttail27.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ipa-icf-gimple.cc3
-rw-r--r--gcc/testsuite/c-c++-common/musttail27.c31
2 files changed, 33 insertions, 1 deletions
diff --git a/gcc/ipa-icf-gimple.cc b/gcc/ipa-icf-gimple.cc
index 51ca8a3..ac16986 100644
--- a/gcc/ipa-icf-gimple.cc
+++ b/gcc/ipa-icf-gimple.cc
@@ -708,7 +708,8 @@ func_checker::compare_gimple_call (gcall *s1, gcall *s2)
|| gimple_call_from_thunk_p (s1) != gimple_call_from_thunk_p (s2)
|| gimple_call_from_new_or_delete (s1) != gimple_call_from_new_or_delete (s2)
|| gimple_call_va_arg_pack_p (s1) != gimple_call_va_arg_pack_p (s2)
- || gimple_call_alloca_for_var_p (s1) != gimple_call_alloca_for_var_p (s2))
+ || gimple_call_alloca_for_var_p (s1) != gimple_call_alloca_for_var_p (s2)
+ || gimple_call_must_tail_p (s1) != gimple_call_must_tail_p (s2))
return false;
unsigned check_arg_types_from = 0;
diff --git a/gcc/testsuite/c-c++-common/musttail27.c b/gcc/testsuite/c-c++-common/musttail27.c
new file mode 100644
index 0000000..2a92bcb
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/musttail27.c
@@ -0,0 +1,31 @@
+/* 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\\\]" 4 "optimized" } } */
+
+int foo (int);
+
+int
+bar (int x)
+{
+ [[gnu::musttail]] return foo (x + 1);
+}
+
+int
+baz (int x)
+{
+ return foo (x + 1);
+}
+
+int
+qux (int x)
+{
+ return foo (x + 2);
+}
+
+int
+corge (int x)
+{
+ [[gnu::musttail]] return foo (x + 2);
+}