From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp.gentoo.org (woodpecker.gentoo.org [140.211.166.183]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id 3B3BD1581EE for ; Wed, 02 Apr 2025 16:14:23 +0000 (UTC) Received: from lists.gentoo.org (bobolink.gentoo.org [140.211.166.189]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: relay-lists.gentoo.org@gentoo.org) by smtp.gentoo.org (Postfix) with ESMTPSA id 22BD6343249 for ; Wed, 02 Apr 2025 16:14:23 +0000 (UTC) Received: from bobolink.gentoo.org (localhost [127.0.0.1]) by bobolink.gentoo.org (Postfix) with ESMTP id 19690110276; Wed, 02 Apr 2025 16:14:22 +0000 (UTC) Received: from smtp.gentoo.org (woodpecker.gentoo.org [140.211.166.183]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by bobolink.gentoo.org (Postfix) with ESMTPS id 0EBF7110276 for ; Wed, 02 Apr 2025 16:14:22 +0000 (UTC) Received: from oystercatcher.gentoo.org (oystercatcher.gentoo.org [148.251.78.52]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id 9D83934309E for ; Wed, 02 Apr 2025 16:14:21 +0000 (UTC) Received: from localhost.localdomain (localhost [IPv6:::1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id D36E21DF6 for ; Wed, 02 Apr 2025 16:14:19 +0000 (UTC) From: "Sam James" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Sam James" Message-ID: <1743610451.e4168bed2ceeb5eb7240f82a0135a61dcf777da8.sam@gentoo> Subject: [gentoo-commits] proj/gcc-patches:master commit in: 15.0.0/gentoo/ X-VCS-Repository: proj/gcc-patches X-VCS-Files: 15.0.0/gentoo/83_all_PR119491-tailcall-eh.patch X-VCS-Directories: 15.0.0/gentoo/ X-VCS-Committer: sam X-VCS-Committer-Name: Sam James X-VCS-Revision: e4168bed2ceeb5eb7240f82a0135a61dcf777da8 X-VCS-Branch: master Date: Wed, 02 Apr 2025 16:14:19 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-Archives-Salt: 54987cf2-221b-47e8-95e0-05f7988bd014 X-Archives-Hash: cb2ac00a0df76a8b04eae50b08d86217 commit: e4168bed2ceeb5eb7240f82a0135a61dcf777da8 Author: Sam James gentoo org> AuthorDate: Wed Apr 2 16:14:11 2025 +0000 Commit: Sam James gentoo org> CommitDate: Wed Apr 2 16:14:11 2025 +0000 URL: https://gitweb.gentoo.org/proj/gcc-patches.git/commit/?id=e4168bed 15.0.0: refresh 83_all_PR119491-tailcall-eh.patch Signed-off-by: Sam James gentoo.org> 15.0.0/gentoo/83_all_PR119491-tailcall-eh.patch | 341 ++++++++++++++---------- 1 file changed, 199 insertions(+), 142 deletions(-) diff --git a/15.0.0/gentoo/83_all_PR119491-tailcall-eh.patch b/15.0.0/gentoo/83_all_PR119491-tailcall-eh.patch index 1873a71..040d2f8 100644 --- a/15.0.0/gentoo/83_all_PR119491-tailcall-eh.patch +++ b/15.0.0/gentoo/83_all_PR119491-tailcall-eh.patch @@ -1,6 +1,38 @@ -https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119491#c5 +https://inbox.sourceware.org/gcc-patches/Z+1hCrznhv68Sv4J@tucnak/ -2025-04-01 Jakub Jelinek +From e561af4c75ca62ae9363700531e60cc5793a88b3 Mon Sep 17 00:00:00 2001 +Message-ID: +From: Jakub Jelinek +Date: Wed, 2 Apr 2025 18:08:42 +0200 +Subject: [PATCH] tailc: Deal with trivially useless EH cleanups [PR119491] + +Hi! + +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. + +Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? + +2025-04-02 Jakub Jelinek PR tree-optimization/119491 * tree-tailcall.cc (single_non_eh_succ_edge): New function. @@ -24,10 +56,156 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119491#c5 * 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 | 41 ++++++++++ + gcc/testsuite/g++.dg/opt/musttail4.C | 35 +++++++++ + gcc/testsuite/g++.dg/opt/musttail5.C | 41 ++++++++++ + gcc/tree-tailcall.cc | 113 +++++++++++++++++++++------ + 4 files changed, 207 insertions(+), 23 deletions(-) + create mode 100644 gcc/testsuite/g++.dg/opt/musttail3.C + create mode 100644 gcc/testsuite/g++.dg/opt/musttail4.C + create mode 100644 gcc/testsuite/g++.dg/opt/musttail5.C ---- a/gcc/tree-tailcall.cc 2025-04-01 16:47:30.373502796 +0200 -+++ b/gcc/tree-tailcall.cc 2025-04-02 09:02:35.572760732 +0200 -@@ -219,6 +219,23 @@ suitable_for_tail_call_opt_p (gcall *cal +diff --git a/gcc/testsuite/g++.dg/opt/musttail3.C b/gcc/testsuite/g++.dg/opt/musttail3.C +new file mode 100644 +index 000000000000..1c4e54952b1e +--- /dev/null ++++ b/gcc/testsuite/g++.dg/opt/musttail3.C +@@ -0,0 +1,41 @@ ++// PR tree-optimization/119491 ++// { dg-do compile { target { external_musttail && c++11 } } } ++// { dg-options "-O2" } ++ ++struct A { ++ struct B {}; ++ A () {} ++}; ++void qux (); ++unsigned char v; ++A w; ++void foo (A); ++ ++template ++[[gnu::always_inline]] static inline void ++bar (int &) ++{ ++} ++ ++[[gnu::always_inline]] static inline void ++baz (int *) ++{ ++ int r = 0; ++ bar (r); ++} ++ ++[[gnu::always_inline]] inline void ++corge (A) ++{ ++ if (v) ++ qux (); ++ [[gnu::musttail]] return foo (w); ++} ++ ++void ++freddy (A) ++{ ++ int t; ++ baz (&t); ++ [[gnu::musttail]] return corge (A{}); ++} +diff --git a/gcc/testsuite/g++.dg/opt/musttail4.C b/gcc/testsuite/g++.dg/opt/musttail4.C +new file mode 100644 +index 000000000000..ede2959f7d74 +--- /dev/null ++++ b/gcc/testsuite/g++.dg/opt/musttail4.C +@@ -0,0 +1,35 @@ ++// { dg-do compile { target { external_musttail && c++11 } } } ++// { dg-options "-O2 -fexceptions" } ++ ++struct S { ~S (); }; ++volatile int v; ++struct T { ~T () { v = v + 1; } }; ++struct U { ~U () {} }; ++int foo (); ++ ++int ++bar () noexcept ++{ ++ [[gnu::musttail]] return foo (); // { dg-error "cannot tail-call: call may throw exception that does not propagate" } ++} ++ ++int ++baz () ++{ ++ S s; ++ [[gnu::musttail]] return foo (); // { dg-error "cannot tail-call: other reasons" } ++} ++ ++int ++qux () ++{ ++ T t; ++ [[gnu::musttail]] return foo (); // { dg-error "cannot tail-call: other reasons" } ++} ++ ++int ++corge () ++{ ++ U u; ++ [[gnu::musttail]] return foo (); ++} +diff --git a/gcc/testsuite/g++.dg/opt/musttail5.C b/gcc/testsuite/g++.dg/opt/musttail5.C +new file mode 100644 +index 000000000000..604dd6907aa9 +--- /dev/null ++++ b/gcc/testsuite/g++.dg/opt/musttail5.C +@@ -0,0 +1,41 @@ ++// PR tree-optimization/119491 ++// { dg-do compile { target { external_musttail && c++11 } } } ++// { dg-options "-O2" } ++ ++struct A { ++ struct B {}; ++ A () {} ++}; ++void qux (); ++unsigned char v; ++A w; ++[[noreturn]] void foo (A); ++ ++template ++[[gnu::always_inline]] static inline void ++bar (int &) ++{ ++} ++ ++[[gnu::always_inline]] static inline void ++baz (int *) ++{ ++ int r = 0; ++ bar (r); ++} ++ ++[[gnu::always_inline]] inline void ++corge (A) ++{ ++ if (v) ++ qux (); ++ [[gnu::musttail]] return foo (w); ++} ++ ++void ++freddy (A) ++{ ++ int t; ++ baz (&t); ++ [[gnu::musttail]] return corge (A{}); ++} +diff --git a/gcc/tree-tailcall.cc b/gcc/tree-tailcall.cc +index 374be2ae6a75..477729ca2137 100644 +--- a/gcc/tree-tailcall.cc ++++ b/gcc/tree-tailcall.cc +@@ -253,6 +253,23 @@ suitable_for_tail_call_opt_p (gcall *call, bool diag_musttail) return true; } @@ -51,7 +229,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119491#c5 /* Checks whether the expression EXPR in stmt AT is independent of the statement pointed to by GSI (in a sense that we already know EXPR's value at GSI). We use the fact that we are only called from the chain of -@@ -245,7 +262,7 @@ independent_of_stmt_p (tree expr, gimple +@@ -279,7 +296,7 @@ independent_of_stmt_p (tree expr, gimple *at, gimple_stmt_iterator gsi, /* Mark the blocks in the chain leading to the end. */ at_bb = gimple_bb (at); call_bb = gimple_bb (gsi_stmt (gsi)); @@ -60,7 +238,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119491#c5 bb->aux = &bb->aux; bb->aux = &bb->aux; -@@ -289,7 +306,7 @@ independent_of_stmt_p (tree expr, gimple +@@ -323,7 +340,7 @@ independent_of_stmt_p (tree expr, gimple *at, gimple_stmt_iterator gsi, } /* Unmark the blocks. */ @@ -69,7 +247,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119491#c5 bb->aux = NULL; bb->aux = NULL; -@@ -462,6 +479,33 @@ maybe_error_musttail (gcall *call, const +@@ -496,6 +513,33 @@ maybe_error_musttail (gcall *call, const char *err, bool diag_musttail) } } @@ -103,7 +281,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119491#c5 /* Argument for compute_live_vars/live_vars_at_stmt and what compute_live_vars returns. Computed lazily, but just once for the function. */ static live_vars_map *live_vars; -@@ -612,14 +656,36 @@ find_tail_calls (basic_block bb, struct +@@ -646,14 +690,36 @@ find_tail_calls (basic_block bb, struct tailcall **ret, bool only_musttail, if ((stmt_could_throw_p (cfun, stmt) && !stmt_can_throw_external (cfun, stmt)) || EDGE_COUNT (bb->succs) > 1) { @@ -148,7 +326,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119491#c5 } /* If the function returns a value, then at present, the tail call -@@ -763,8 +829,7 @@ find_tail_calls (basic_block bb, struct +@@ -844,8 +910,7 @@ find_tail_calls (basic_block bb, struct tailcall **ret, bool only_musttail, a = NULL_TREE; auto_bitmap to_move_defs; auto_vec to_move_stmts; @@ -158,7 +336,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119491#c5 abb = bb; agsi = gsi; -@@ -776,8 +841,9 @@ find_tail_calls (basic_block bb, struct +@@ -857,8 +922,9 @@ find_tail_calls (basic_block bb, struct tailcall **ret, bool only_musttail, while (gsi_end_p (agsi)) { @@ -170,7 +348,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119491#c5 agsi = gsi_start_bb (abb); } -@@ -851,6 +917,11 @@ find_tail_calls (basic_block bb, struct +@@ -932,6 +998,11 @@ find_tail_calls (basic_block bb, struct tailcall **ret, bool only_musttail, /* See if this is a tail call we can handle. */ if (is_noreturn) { @@ -182,7 +360,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119491#c5 tree rettype = TREE_TYPE (TREE_TYPE (current_function_decl)); tree calltype = TREE_TYPE (gimple_call_fntype (call)); if (!VOID_TYPE_P (rettype) -@@ -1112,11 +1183,6 @@ static void +@@ -1193,11 +1264,6 @@ static void decrease_profile (basic_block bb, profile_count count) { bb->count = bb->count - count; @@ -194,7 +372,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119491#c5 } /* Eliminates tail call described by T. TMP_VARS is a list of -@@ -1181,7 +1247,7 @@ eliminate_tail_call (struct tailcall *t, +@@ -1262,7 +1328,7 @@ eliminate_tail_call (struct tailcall *t, class loop *&new_loop) else { /* Number of executions of function has reduced by the tailcall. */ @@ -203,7 +381,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119491#c5 profile_count count = e->count (); -@@ -1196,8 +1262,7 @@ eliminate_tail_call (struct tailcall *t, +@@ -1277,8 +1343,7 @@ eliminate_tail_call (struct tailcall *t, class loop *&new_loop) decrease_profile (e->dest, count); /* Replace the call by a jump to the start of function. */ @@ -213,7 +391,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119491#c5 } gcc_assert (e); PENDING_STMT (e) = NULL; -@@ -1362,7 +1427,9 @@ tree_optimize_tail_calls_1 (bool opt_tai +@@ -1443,7 +1508,9 @@ tree_optimize_tail_calls_1 (bool opt_tailcalls, bool only_musttail, { basic_block bb; FOR_EACH_BB_FN (bb, cfun) @@ -224,129 +402,8 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119491#c5 if (gimple *c = last_nondebug_stmt (bb)) if (is_gimple_call (c) && gimple_call_must_tail_p (as_a (c)) ---- a/gcc/testsuite/g++.dg/opt/musttail3.C 2025-04-01 18:47:10.474945080 +0200 -+++ b/gcc/testsuite/g++.dg/opt/musttail3.C 2025-04-01 18:49:27.063068029 +0200 -@@ -0,0 +1,41 @@ -+// PR tree-optimization/119491 -+// { dg-do compile { target { external_musttail && c++11 } } } -+// { dg-options "-O2" } -+ -+struct A { -+ struct B {}; -+ A () {} -+}; -+void qux (); -+unsigned char v; -+A w; -+void foo (A); -+ -+template -+[[gnu::always_inline]] static inline void -+bar (int &) -+{ -+} -+ -+[[gnu::always_inline]] static inline void -+baz (int *) -+{ -+ int r = 0; -+ bar (r); -+} -+ -+[[gnu::always_inline]] inline void -+corge (A) -+{ -+ if (v) -+ qux (); -+ [[gnu::musttail]] return foo (w); -+} -+ -+void -+freddy (A) -+{ -+ int t; -+ baz (&t); -+ [[gnu::musttail]] return corge (A{}); -+} ---- a/gcc/testsuite/g++.dg/opt/musttail4.C 2025-04-01 19:10:56.389350911 +0200 -+++ b/gcc/testsuite/g++.dg/opt/musttail4.C 2025-04-01 19:28:18.285020409 +0200 -@@ -0,0 +1,35 @@ -+// { dg-do compile { target { external_musttail && c++11 } } } -+// { dg-options "-O2 -fexceptions" } -+ -+struct S { ~S (); }; -+volatile int v; -+struct T { ~T () { v = v + 1; } }; -+struct U { ~U () {} }; -+int foo (); -+ -+int -+bar () noexcept -+{ -+ [[gnu::musttail]] return foo (); // { dg-error "cannot tail-call: call may throw exception that does not propagate" } -+} -+ -+int -+baz () -+{ -+ S s; -+ [[gnu::musttail]] return foo (); // { dg-error "cannot tail-call: other reasons" } -+} -+ -+int -+qux () -+{ -+ T t; -+ [[gnu::musttail]] return foo (); // { dg-error "cannot tail-call: other reasons" } -+} -+ -+int -+corge () -+{ -+ U u; -+ [[gnu::musttail]] return foo (); -+} ---- a/gcc/testsuite/g++.dg/opt/musttail5.C 2025-04-01 19:14:50.981127712 +0200 -+++ b/gcc/testsuite/g++.dg/opt/musttail5.C 2025-04-01 19:11:25.249954382 +0200 -@@ -0,0 +1,41 @@ -+// PR tree-optimization/119491 -+// { dg-do compile { target { external_musttail && c++11 } } } -+// { dg-options "-O2" } -+ -+struct A { -+ struct B {}; -+ A () {} -+}; -+void qux (); -+unsigned char v; -+A w; -+[[noreturn]] void foo (A); -+ -+template -+[[gnu::always_inline]] static inline void -+bar (int &) -+{ -+} -+ -+[[gnu::always_inline]] static inline void -+baz (int *) -+{ -+ int r = 0; -+ bar (r); -+} -+ -+[[gnu::always_inline]] inline void -+corge (A) -+{ -+ if (v) -+ qux (); -+ [[gnu::musttail]] return foo (w); -+} -+ -+void -+freddy (A) -+{ -+ int t; -+ baz (&t); -+ [[gnu::musttail]] return corge (A{}); -+} + +base-commit: aca8155c09001f269a20d6df438fa0e749dd5388 +-- +2.49.0 +