[PATCH] Fix PR 95481: tail call fails with empty struct types
apinski@marvell.com
apinski@marvell.com
Mon May 31 06:30:25 GMT 2021
From: Andrew Pinski <apinski@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
More information about the Gcc-patches
mailing list