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