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
>

Reply via email to