Fix PR 95481: tail call fails with empty struct types

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

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

Thanks,
Andrew Pinski

changes since v1:
v2: Use is_empty_type instead of zero-sized type.

gcc/ChangeLog:
	PR tree-optimization/95481
	* tree-tailcall.c (find_tail_calls): Handle empty typed
	return decls.

gcc/testsuite/ChangeLog:

	PR tree-optimization/95481
	* 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.
This commit is contained in:
Andrew Pinski 2021-05-31 00:17:22 +00:00
parent 34aae6b561
commit ea418485c7
6 changed files with 66 additions and 2 deletions

View file

@ -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"} } */

View file

@ -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"} } */

View file

@ -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"} } */

View file

@ -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"} } */

View file

@ -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"} } */

View file

@ -710,9 +710,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 an empty type
variable and the call's return was not assigned. */
if (ret_var
&& (ret_var != ass_var))
&& (ret_var != ass_var
&& !(is_empty_type (TREE_TYPE (ret_var)) && !ass_var)))
return;
/* If this is not a tail recursive call, we cannot handle addends or