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:
parent
34aae6b561
commit
ea418485c7
6 changed files with 66 additions and 2 deletions
12
gcc/testsuite/gcc.dg/tree-ssa/tailcall-10.c
Normal file
12
gcc/testsuite/gcc.dg/tree-ssa/tailcall-10.c
Normal 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"} } */
|
12
gcc/testsuite/gcc.dg/tree-ssa/tailcall-11.c
Normal file
12
gcc/testsuite/gcc.dg/tree-ssa/tailcall-11.c
Normal 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"} } */
|
12
gcc/testsuite/gcc.dg/tree-ssa/tailcall-12.c
Normal file
12
gcc/testsuite/gcc.dg/tree-ssa/tailcall-12.c
Normal 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"} } */
|
15
gcc/testsuite/gcc.dg/tree-ssa/tailcall-13.c
Normal file
15
gcc/testsuite/gcc.dg/tree-ssa/tailcall-13.c
Normal 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"} } */
|
11
gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-8.c
Normal file
11
gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-8.c
Normal 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"} } */
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue