]> git.ipfire.org Git - thirdparty/gcc.git/commit
tailc: Deal with trivially useless EH cleanups [PR119491]
authorJakub Jelinek <jakub@redhat.com>
Wed, 2 Apr 2025 18:02:34 +0000 (20:02 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 2 Apr 2025 18:02:34 +0000 (20:02 +0200)
commit8ea537988f718f026d94b558e09479c3b5fe088a
treedc3a8c42e7c63884cc23466563620cc0ac5c4533
parent29bc904cb827615ed9f36bc3742ccc4ac77515ec
tailc: Deal with trivially useless EH cleanups [PR119491]

The following testcases FAIL, because EH cleanup is performed only before
IPA and then right before musttail pass.
At -O2 etc. (except for -O0/-Og) we handle musttail calls in the tailc
pass though, and we can fail at that point because the calls might appear
to throw internal exceptions which just don't do anything interesting
(perhaps have debug statements or clobber statements in them) before they
continue with resume of the exception (i.e. throw it externally).

As Richi said in the PR (and I agree) that moving passes is risky at this
point, the following patch instead teaches the tail{r,c} and musttail
passes to deal with such extra EDGE_EH edges.

It is fairly simple thing, if we see an EDGE_EH edge from the call we
just look up where it lands and if there are no
non-debug/non-clobber/non-label statements before resx which throws
externally, such edge can be ignored for tail call optimization or
tail recursion.  At other spots I just need to avoid using
single_succ/single_succ_edge because the bb might have another edge -
EDGE_EH.

To make this less risky, this is done solely for the musttail calls for now.

2025-04-02  Jakub Jelinek  <jakub@redhat.com>

PR tree-optimization/119491
* tree-tailcall.cc (single_non_eh_succ_edge): New function.
(independent_of_stmt_p): Use single_non_eh_succ_edge (bb)->dest
instead of single_succ (bb).
(empty_eh_cleanup): New function.
(find_tail_calls): Diagnose throwing of exceptions which do not
propagate only if there are no EDGE_EH successor edges.  If there are
and the call is musttail, use empty_eh_cleanup to find if the cleanup
is not empty.  If not or the call is not musttail, use different
diagnostics.  Set is_noreturn even if there are successor edges.  Use
single_non_eh_succ_edge (abb) instead of single_succ_edge (abb).  Punt
on internal noreturn calls.
(decrease_profile): Don't assert 0 or 1 successor edges.
(eliminate_tail_call): Use
single_non_eh_succ_edge (gsi_bb (t->call_gsi)) instead of
single_succ_edge (gsi_bb (t->call_gsi)).
(tree_optimize_tail_calls_1): Also look into basic blocks with
single succ edge which is EDGE_EH for noreturn musttail calls.

* g++.dg/opt/musttail3.C: New test.
* g++.dg/opt/musttail4.C: New test.
* g++.dg/opt/musttail5.C: New test.
gcc/testsuite/g++.dg/opt/musttail3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/opt/musttail4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/opt/musttail5.C [new file with mode: 0644]
gcc/tree-tailcall.cc