]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Fix PR 95481: tail call fails with empty struct types
authorAndrew Pinski <apinski@marvell.com>
Mon, 31 May 2021 00:17:22 +0000 (00:17 +0000)
committerAndrew Pinski <apinski@marvell.com>
Tue, 1 Jun 2021 18:28:59 +0000 (18:28 +0000)
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.

gcc/testsuite/gcc.dg/tree-ssa/tailcall-10.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/tailcall-11.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/tailcall-12.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/tailcall-13.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-8.c [new file with mode: 0644]
gcc/tree-tailcall.c

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 (file)
index 0000000..484dcc1
--- /dev/null
@@ -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 (file)
index 0000000..36e4417
--- /dev/null
@@ -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 (file)
index 0000000..0eeb3ab
--- /dev/null
@@ -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 (file)
index 0000000..855b331
--- /dev/null
@@ -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 (file)
index 0000000..ecde499
--- /dev/null
@@ -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"} } */
index e866f7272ed88a70bb339afbec4026f483cc9227..a4d31c90c49539921cbf7fc3088a7b2fbbf21425 100644 (file)
@@ -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