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)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id 9E0A415800A for ; Wed, 02 Apr 2025 04:59:52 +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 7F2A6335CC2 for ; Wed, 02 Apr 2025 04:59:52 +0000 (UTC) Received: from bobolink.gentoo.org (localhost [127.0.0.1]) by bobolink.gentoo.org (Postfix) with ESMTP id 6AA7F110105; Wed, 02 Apr 2025 04:59:51 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [IPv6:2001:470:ea4a:1:5054:ff:fec7:86e4]) (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 5E467110105 for ; Wed, 02 Apr 2025 04:59:51 +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 EF724335CC2 for ; Wed, 02 Apr 2025 04:59:50 +0000 (UTC) Received: from localhost.localdomain (localhost [IPv6:::1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id 538A4181E for ; Wed, 02 Apr 2025 04:59:49 +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: <1743569985.6f8b1c816299484f66a6184635b6202eb5ec72b0.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 15.0.0/gentoo/README.history X-VCS-Directories: 15.0.0/gentoo/ X-VCS-Committer: sam X-VCS-Committer-Name: Sam James X-VCS-Revision: 6f8b1c816299484f66a6184635b6202eb5ec72b0 X-VCS-Branch: master Date: Wed, 02 Apr 2025 04:59:49 +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: eaea736d-07f3-4c98-ba74-bf51a44009de X-Archives-Hash: 61b9c71c13e3a9752f0f912d854facb2 commit: 6f8b1c816299484f66a6184635b6202eb5ec72b0 Author: Sam James gentoo org> AuthorDate: Wed Apr 2 04:59:09 2025 +0000 Commit: Sam James gentoo org> CommitDate: Wed Apr 2 04:59:45 2025 +0000 URL: https://gitweb.gentoo.org/proj/gcc-patches.git/commit/?id=6f8b1c81 15.0.0: add another tailcall patch (for eh this time) This should fix protobuf. Bug: https://gcc.gnu.org/PR119491 Signed-off-by: Sam James gentoo.org> 15.0.0/gentoo/83_all_PR119491-tailcall-eh.patch | 323 ++++++++++++++++++++++++ 15.0.0/gentoo/README.history | 1 + 2 files changed, 324 insertions(+) diff --git a/15.0.0/gentoo/83_all_PR119491-tailcall-eh.patch b/15.0.0/gentoo/83_all_PR119491-tailcall-eh.patch new file mode 100644 index 0000000..339ba64 --- /dev/null +++ b/15.0.0/gentoo/83_all_PR119491-tailcall-eh.patch @@ -0,0 +1,323 @@ +https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119491#c4 + +2025-04-01 Jakub Jelinek + + PR tree-optimization/119491 + * tree-tailcall.cc (independent_of_stmt_p): Use + find_fallthru_edge (bb->succs)->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 + find_fallthru_edge (abb->succs) instead of single_succ_edge (abb). + (decrease_profile): Don't assert 0 or 1 successor edges. + (eliminate_tail_call): Use + find_fallthru_edge (gsi_bb (t->call_gsi)->succs) 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. +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 e71341bfb2bc..b910dce7acbd 100644 +--- a/gcc/tree-tailcall.cc ++++ b/gcc/tree-tailcall.cc +@@ -245,7 +245,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)); +- for (bb = call_bb; bb != at_bb; bb = single_succ (bb)) ++ for (bb = call_bb; bb != at_bb; bb = find_fallthru_edge (bb->succs)->dest) + bb->aux = &bb->aux; + bb->aux = &bb->aux; + +@@ -289,7 +289,7 @@ independent_of_stmt_p (tree expr, gimple *at, gimple_stmt_iterator gsi, + } + + /* Unmark the blocks. */ +- for (bb = call_bb; bb != at_bb; bb = single_succ (bb)) ++ for (bb = call_bb; bb != at_bb; bb = find_fallthru_edge (bb->succs)->dest) + bb->aux = NULL; + bb->aux = NULL; + +@@ -462,6 +462,33 @@ maybe_error_musttail (gcall *call, const char *err, bool diag_musttail) + } + } + ++/* Return true if there is no real work performed in the exception ++ path starting at BB and it will in the end result in external exception. ++ Search at most CNT basic blocks (so that we don't need to do trivial ++ loop discovery). */ ++static bool ++empty_eh_cleanup (basic_block bb, int cnt) ++{ ++ if (EDGE_COUNT (bb->succs) > 1) ++ return false; ++ ++ for (gimple_stmt_iterator gsi = gsi_after_labels (bb); !gsi_end_p (gsi); ++ gsi_next (&gsi)) ++ { ++ gimple *g = gsi_stmt (gsi); ++ if (is_gimple_debug (g) || gimple_clobber_p (g)) ++ continue; ++ if (is_gimple_resx (g) && stmt_can_throw_external (cfun, g)) ++ return true; ++ return false; ++ } ++ if (!single_succ_p (bb)) ++ return false; ++ if (cnt == 1) ++ return false; ++ return empty_eh_cleanup (single_succ (bb), cnt - 1); ++} ++ + /* 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 +639,35 @@ 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) + { +- if (stmt == last_stmt) +- maybe_error_musttail (call, +- _("call may throw exception that does not " +- "propagate"), diag_musttail); +- else +- maybe_error_musttail (call, _("code between call and return"), +- diag_musttail); +- return; ++ if (stmt != last_stmt) ++ { ++ maybe_error_musttail (call, _("code between call and return"), ++ diag_musttail); ++ return; ++ } ++ ++ edge e; ++ edge_iterator ei; ++ FOR_EACH_EDGE (e, ei, bb->succs) ++ if (e->flags & EDGE_EH) ++ break; ++ ++ if (!e) ++ { ++ maybe_error_musttail (call, ++ _("call may throw exception that does not " ++ "propagate"), diag_musttail); ++ return; ++ } ++ ++ if (!gimple_call_must_tail_p (call) ++ || !empty_eh_cleanup (e->dest, 20)) ++ { ++ maybe_error_musttail (call, ++ _("call may throw exception caught locally " ++ "or perform cleanups"), diag_musttail); ++ return; ++ } + } + + /* If the function returns a value, then at present, the tail call +@@ -763,8 +811,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; +- bool is_noreturn +- = EDGE_COUNT (bb->succs) == 0 && gimple_call_noreturn_p (call); ++ bool is_noreturn = gimple_call_noreturn_p (call); + + abb = bb; + agsi = gsi; +@@ -776,8 +823,9 @@ find_tail_calls (basic_block bb, struct tailcall **ret, bool only_musttail, + + while (gsi_end_p (agsi)) + { +- ass_var = propagate_through_phis (ass_var, single_succ_edge (abb)); +- abb = single_succ (abb); ++ edge e = find_fallthru_edge (abb->succs); ++ ass_var = propagate_through_phis (ass_var, e); ++ abb = e->dest; + agsi = gsi_start_bb (abb); + } + +@@ -1112,11 +1160,6 @@ static void + decrease_profile (basic_block bb, profile_count count) + { + bb->count = bb->count - count; +- if (!single_succ_p (bb)) +- { +- gcc_assert (!EDGE_COUNT (bb->succs)); +- return; +- } + } + + /* Eliminates tail call described by T. TMP_VARS is a list of +@@ -1181,7 +1224,7 @@ eliminate_tail_call (struct tailcall *t, class loop *&new_loop) + else + { + /* Number of executions of function has reduced by the tailcall. */ +- e = single_succ_edge (gsi_bb (t->call_gsi)); ++ e = find_fallthru_edge (gsi_bb (t->call_gsi)->succs); + + profile_count count = e->count (); + +@@ -1196,8 +1239,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. */ +- e = redirect_edge_and_branch (single_succ_edge (gsi_bb (t->call_gsi)), +- first); ++ e = redirect_edge_and_branch (e, first); + } + gcc_assert (e); + PENDING_STMT (e) = NULL; +@@ -1362,7 +1404,9 @@ tree_optimize_tail_calls_1 (bool opt_tailcalls, bool only_musttail, + { + basic_block bb; + FOR_EACH_BB_FN (bb, cfun) +- if (EDGE_COUNT (bb->succs) == 0) ++ if (EDGE_COUNT (bb->succs) == 0 ++ || (single_succ_p (bb) ++ && (single_succ_edge (bb)->flags & EDGE_EH))) + if (gimple *c = last_nondebug_stmt (bb)) + if (is_gimple_call (c) + && gimple_call_must_tail_p (as_a (c)) diff --git a/15.0.0/gentoo/README.history b/15.0.0/gentoo/README.history index 7e0990c..b497164 100644 --- a/15.0.0/gentoo/README.history +++ b/15.0.0/gentoo/README.history @@ -1,6 +1,7 @@ 51 ???? + 82_all_PR119318-ipa-cp.patch + + 83_all_PR119491-tailcall-eh.patch 50 31 March 2025