aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAndrew Pinski <apinski@marvell.com>2021-05-31 00:17:22 +0000
committerAndrew Pinski <apinski@marvell.com>2021-06-01 18:28:59 +0000
commitea418485c700494c3efdc282854c5f5a08702416 (patch)
tree769672eb702b47d8a88a80540d300e667ce47c6d /gcc
parent34aae6b561871d6d8b10c810f303cb6f18b5fdd0 (diff)
downloadgcc-ea418485c700494c3efdc282854c5f5a08702416.zip
gcc-ea418485c700494c3efdc282854c5f5a08702416.tar.gz
gcc-ea418485c700494c3efdc282854c5f5a08702416.tar.bz2
Fix PR 95481: tail call fails with empty struct types
The problem here is we don't have an assignment type any more for empty structs as they were removed during gimplifcation. This adds a special case where the assignment var does not exist and the return decl is empty typed. OK? Tested on aarch64-linux-gnu with no regressions. Thanks, Andrew Pinski changes since v1: v2: Use is_empty_type instead of zero-sized type. gcc/ChangeLog: PR tree-optimization/95481 * tree-tailcall.c (find_tail_calls): Handle empty typed return decls. gcc/testsuite/ChangeLog: PR tree-optimization/95481 * gcc.dg/tree-ssa/tailcall-10.c: New test. * gcc.dg/tree-ssa/tailcall-11.c: New test. * gcc.dg/tree-ssa/tailcall-12.c: New test. * gcc.dg/tree-ssa/tailcall-13.c: New test. * gcc.dg/tree-ssa/tailrecursion-8.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/tailcall-10.c12
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/tailcall-11.c12
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/tailcall-12.c12
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/tailcall-13.c15
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-8.c11
-rw-r--r--gcc/tree-tailcall.c6
6 files changed, 66 insertions, 2 deletions
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/tailcall-10.c b/gcc/testsuite/gcc.dg/tree-ssa/tailcall-10.c
new file mode 100644
index 0000000..484dcc1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/tailcall-10.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-tailc-details" } */
+
+struct A {};
+
+struct A goo(void);
+struct A foo(void)
+{
+ return goo();
+}
+
+/* { dg-final { scan-tree-dump-times "Found tail call" 1 "tailc"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/tailcall-11.c b/gcc/testsuite/gcc.dg/tree-ssa/tailcall-11.c
new file mode 100644
index 0000000..36e4417
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/tailcall-11.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-tailc-details" } */
+
+struct A {};
+
+void goo(void);
+struct A foo(void)
+{
+ goo();
+}
+
+/* { dg-final { scan-tree-dump-times "Found tail call" 1 "tailc"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/tailcall-12.c b/gcc/testsuite/gcc.dg/tree-ssa/tailcall-12.c
new file mode 100644
index 0000000..0eeb3ab
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/tailcall-12.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-tailc-details" } */
+
+struct A {};
+
+struct A goo(void);
+void foo(void)
+{
+ goo();
+}
+
+/* { dg-final { scan-tree-dump-times "Found tail call" 1 "tailc"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/tailcall-13.c b/gcc/testsuite/gcc.dg/tree-ssa/tailcall-13.c
new file mode 100644
index 0000000..855b3312
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/tailcall-13.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-tailc-details" } */
+
+struct A {};
+struct B{};
+
+struct B goo(void);
+struct A foo(void)
+{
+ struct A a;
+ goo();
+ return a;
+}
+
+/* { dg-final { scan-tree-dump-times "Found tail call" 1 "tailc"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-8.c b/gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-8.c
new file mode 100644
index 0000000..ecde499
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-8.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -foptimize-sibling-calls -fdump-tree-tailr1-details" } */
+
+struct A {};
+
+struct A foo()
+{
+ return foo();
+}
+
+/* { dg-final { scan-tree-dump-times "Eliminated tail recursion" 1 "tailr1"} } */
diff --git a/gcc/tree-tailcall.c b/gcc/tree-tailcall.c
index e866f72..a4d31c9 100644
--- a/gcc/tree-tailcall.c
+++ b/gcc/tree-tailcall.c
@@ -710,9 +710,11 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
ret_var = gimple_return_retval (as_a <greturn *> (stmt));
/* We may proceed if there either is no return value, or the return value
- is identical to the call's return. */
+ is identical to the call's return or if the return decl is an empty type
+ variable and the call's return was not assigned. */
if (ret_var
- && (ret_var != ass_var))
+ && (ret_var != ass_var
+ && !(is_empty_type (TREE_TYPE (ret_var)) && !ass_var)))
return;
/* If this is not a tail recursive call, we cannot handle addends or