diff options
author | Andrew Pinski <apinski@marvell.com> | 2021-05-31 00:17:22 +0000 |
---|---|---|
committer | Andrew Pinski <apinski@marvell.com> | 2021-06-01 18:28:59 +0000 |
commit | ea418485c700494c3efdc282854c5f5a08702416 (patch) | |
tree | 769672eb702b47d8a88a80540d300e667ce47c6d /gcc | |
parent | 34aae6b561871d6d8b10c810f303cb6f18b5fdd0 (diff) | |
download | gcc-ea418485c700494c3efdc282854c5f5a08702416.zip gcc-ea418485c700494c3efdc282854c5f5a08702416.tar.gz gcc-ea418485c700494c3efdc282854c5f5a08702416.tar.bz2 |
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.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/tailcall-10.c | 12 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/tailcall-11.c | 12 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/tailcall-12.c | 12 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/tailcall-13.c | 15 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-8.c | 11 | ||||
-rw-r--r-- | gcc/tree-tailcall.c | 6 |
6 files changed, 66 insertions, 2 deletions
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 0000000..484dcc1 --- /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 0000000..36e4417 --- /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 0000000..0eeb3ab --- /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 0000000..855b3312 --- /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 0000000..ecde499 --- /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 e866f72..a4d31c9 100644 --- a/gcc/tree-tailcall.c +++ b/gcc/tree-tailcall.c @@ -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 |