On Mon, May 31, 2021 at 8:36 AM apinski--- via Gcc-patches <gcc-patches@gcc.gnu.org> wrote: > > 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;
I wonder if is_empty_type () would work here, it should be slightly more powerful plus it avoids adding a function that feels like it should be already present ;) Thanks, Richard, > > /* If this is not a tail recursive call, we cannot handle addends or > -- > 2.17.1 >