From: Andrew Pinski <apin...@marvell.com>

The problem here is we don't have an assignment type any more
for zero-length structs as they were removed during gimplifcation.
This adds a special case where the assignment var does not exist
and the return decl is zero-length.

OK? Tested on aarch64-linux-gnu with no regressions.

Thanks,
Andrew Pinski

gcc/ChangeLog:
        * tree-tailcall.c (zero_sized_decl): New function.
        (find_tail_calls): Handle zero sized return decls.

gcc/testsuite/ChangeLog:

        * 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   | 12 ++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/tailcall-11.c   | 12 ++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/tailcall-12.c   | 12 ++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/tailcall-13.c   | 15 +++++++++++++
 .../gcc.dg/tree-ssa/tailrecursion-8.c         | 11 ++++++++++
 gcc/tree-tailcall.c                           | 22 +++++++++++++++++--
 6 files changed, 82 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/tailcall-10.c
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/tailcall-11.c
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/tailcall-12.c
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/tailcall-13.c
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-8.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
index 00000000000..484dcc125fc
--- /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 00000000000..36e441775ff
--- /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 00000000000..0eeb3ab2794
--- /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 00000000000..855b3312ef4
--- /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 00000000000..ecde499a06b
--- /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 e866f7272ed..ebb42f7aa9b 100644
--- a/gcc/tree-tailcall.c
+++ b/gcc/tree-tailcall.c
@@ -410,6 +410,22 @@ propagate_through_phis (tree var, edge e)
 static live_vars_map *live_vars;
 static vec<bitmap_head> live_vars_vec;
 
+/* Return true if decl is zero sized.  */
+
+static bool
+zero_sized_decl (const_tree decl)
+{
+  if (!decl)
+    return true;
+
+  tree type = TREE_TYPE (decl);
+  if (AGGREGATE_TYPE_P (type) && TYPE_SIZE (type)
+      && integer_zerop (TYPE_SIZE (type)))
+    return true;
+  return false;
+}
+
+
 /* Finds tailcalls falling into basic block BB. The list of found tailcalls is
    added to the start of RET.  */
 
@@ -710,9 +726,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 a zero sized
+     variable and the call's return was not assigned. */
   if (ret_var
-      && (ret_var != ass_var))
+      && (ret_var != ass_var
+         && !(zero_sized_decl (ret_var) && !ass_var)))
     return;
 
   /* If this is not a tail recursive call, we cannot handle addends or
-- 
2.17.1

Reply via email to