From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2153) id BC87D3858C30; Thu, 2 Feb 2023 09:55:39 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org BC87D3858C30 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1675331739; bh=RsXaFvVm3jlyBc/hwdpMR3yp4y2QqqHpYn0xxIuL+Ww=; h=From:To:Subject:Date:From; b=soP243ugwtPHWOJcJEXfcHf4AY0degjweiI7Qn291cpdVqzWcEDu2f5fJ9rLLIlZg fvtOnvGNDnom4sX67oYNFYwcFKEn/vmev304NUxsTupZf63fZL479B6A3LAoBEU//k EwmiSOG9iIrz/TohZCUhzOFaWswCBWtuBDF2sqz0= MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Jakub Jelinek To: gcc-cvs@gcc.gnu.org Subject: [gcc r13-5645] Replace IFN_TRAP with BUILT_IN_UNREACHABLE_TRAP [PR107300] X-Act-Checkin: gcc X-Git-Author: Jakub Jelinek X-Git-Refname: refs/heads/master X-Git-Oldrev: 209f02b0a9e9adc0bf0247cb5eef04e0f175d64e X-Git-Newrev: d2423144eb36a68fd0da9224857ce807714874a7 Message-Id: <20230202095539.BC87D3858C30@sourceware.org> Date: Thu, 2 Feb 2023 09:55:39 +0000 (GMT) List-Id: https://gcc.gnu.org/g:d2423144eb36a68fd0da9224857ce807714874a7 commit r13-5645-gd2423144eb36a68fd0da9224857ce807714874a7 Author: Jakub Jelinek Date: Thu Feb 2 10:54:54 2023 +0100 Replace IFN_TRAP with BUILT_IN_UNREACHABLE_TRAP [PR107300] For PR106099 I've added IFN_TRAP as an alternative to __builtin_trap meant for __builtin_unreachable purposes (e.g. with -funreachable-traps or some sanitizers) which doesn't need vops because __builtin_unreachable doesn't need them either. This works in various cases, but unfortunately IPA likes to decide on the redirection to unreachable just by tweaking the cgraph edge to point to a different FUNCTION_DECL. As internal functions don't have a decl, this causes problems like in the following testcase. The following patch fixes it by removing IFN_TRAP again and replacing it with user inaccessible BUILT_IN_UNREACHABLE_TRAP, so that e.g. builtin_decl_unreachable can return it directly and we don't need to tweak it later in wherever we actually replace the call stmt. 2023-02-02 Jakub Jelinek PR ipa/107300 * builtins.def (BUILT_IN_UNREACHABLE_TRAP): New builtin. * internal-fn.def (TRAP): Remove. * internal-fn.cc (expand_TRAP): Remove. * tree.cc (build_common_builtin_nodes): Define BUILT_IN_UNREACHABLE_TRAP if not yet defined. (builtin_decl_unreachable): Use BUILT_IN_UNREACHABLE_TRAP instead of BUILT_IN_TRAP. * gimple.cc (gimple_build_builtin_unreachable): Remove emitting internal function for BUILT_IN_TRAP. * asan.cc (maybe_instrument_call): Handle BUILT_IN_UNREACHABLE_TRAP. * cgraph.cc (cgraph_edge::verify_corresponds_to_fndecl): Handle BUILT_IN_UNREACHABLE_TRAP instead of BUILT_IN_TRAP. * ipa-devirt.cc (possible_polymorphic_call_target_p): Handle BUILT_IN_UNREACHABLE_TRAP. * builtins.cc (expand_builtin, is_inexpensive_builtin): Likewise. * tree-cfg.cc (verify_gimple_call, pass_warn_function_return::execute): Likewise. * attribs.cc (decl_attributes): Don't report exclusions on BUILT_IN_UNREACHABLE_TRAP either. * gcc.dg/pr107300.c: New test. Diff: --- gcc/asan.cc | 1 + gcc/attribs.cc | 1 + gcc/builtins.cc | 2 ++ gcc/builtins.def | 1 + gcc/cgraph.cc | 4 ++-- gcc/gimple.cc | 11 +---------- gcc/internal-fn.cc | 6 ------ gcc/internal-fn.def | 5 ----- gcc/ipa-devirt.cc | 6 ++++-- gcc/testsuite/gcc.dg/pr107300.c | 19 +++++++++++++++++++ gcc/tree-cfg.cc | 3 +++ gcc/tree.cc | 9 ++++++++- 12 files changed, 42 insertions(+), 26 deletions(-) diff --git a/gcc/asan.cc b/gcc/asan.cc index d833f89cc4f..57834b70dba 100644 --- a/gcc/asan.cc +++ b/gcc/asan.cc @@ -2951,6 +2951,7 @@ maybe_instrument_call (gimple_stmt_iterator *iter) switch (DECL_FUNCTION_CODE (callee)) { case BUILT_IN_UNREACHABLE: + case BUILT_IN_UNREACHABLE_TRAP: case BUILT_IN_TRAP: /* Don't instrument these. */ return false; diff --git a/gcc/attribs.cc b/gcc/attribs.cc index 7db730cf831..b1300018d1e 100644 --- a/gcc/attribs.cc +++ b/gcc/attribs.cc @@ -846,6 +846,7 @@ decl_attributes (tree *node, tree attributes, int flags, || !DECL_P (*anode) || DECL_BUILT_IN_CLASS (*anode) != BUILT_IN_NORMAL || (DECL_FUNCTION_CODE (*anode) != BUILT_IN_UNREACHABLE + && DECL_FUNCTION_CODE (*anode) != BUILT_IN_UNREACHABLE_TRAP && (DECL_FUNCTION_CODE (*anode) != BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE))) { diff --git a/gcc/builtins.cc b/gcc/builtins.cc index af45829875e..8327bcb2c3a 100644 --- a/gcc/builtins.cc +++ b/gcc/builtins.cc @@ -7844,6 +7844,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode, break; case BUILT_IN_TRAP: + case BUILT_IN_UNREACHABLE_TRAP: expand_builtin_trap (); return const0_rtx; @@ -11310,6 +11311,7 @@ is_inexpensive_builtin (tree decl) case BUILT_IN_VA_ARG_PACK_LEN: case BUILT_IN_VA_COPY: case BUILT_IN_TRAP: + case BUILT_IN_UNREACHABLE_TRAP: case BUILT_IN_SAVEREGS: case BUILT_IN_POPCOUNTL: case BUILT_IN_POPCOUNTLL: diff --git a/gcc/builtins.def b/gcc/builtins.def index 0afa4c55ad9..4ad95a12f83 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -1048,6 +1048,7 @@ DEF_GCC_BUILTIN (BUILT_IN_SETJMP, "setjmp", BT_FN_INT_PTR, ATTR_RT_NOTHRO DEF_EXT_LIB_BUILTIN (BUILT_IN_STRFMON, "strfmon", BT_FN_SSIZE_STRING_SIZE_CONST_STRING_VAR, ATTR_FORMAT_STRFMON_NOTHROW_3_4) DEF_LIB_BUILTIN (BUILT_IN_STRFTIME, "strftime", BT_FN_SIZE_STRING_SIZE_CONST_STRING_CONST_TM_PTR, ATTR_FORMAT_STRFTIME_NOTHROW_3_0) DEF_GCC_BUILTIN (BUILT_IN_TRAP, "trap", BT_FN_VOID, ATTR_NORETURN_NOTHROW_LEAF_COLD_LIST) +DEF_GCC_BUILTIN (BUILT_IN_UNREACHABLE_TRAP, "unreachable trap", BT_FN_VOID, ATTR_CONST_NORETURN_NOTHROW_LEAF_COLD_LIST) DEF_GCC_BUILTIN (BUILT_IN_UNREACHABLE, "unreachable", BT_FN_VOID, ATTR_CONST_NORETURN_NOTHROW_LEAF_COLD_LIST) DEF_GCC_BUILTIN (BUILT_IN_UNWIND_INIT, "unwind_init", BT_FN_VOID, ATTR_NULL) DEF_GCC_BUILTIN (BUILT_IN_UPDATE_SETJMP_BUF, "update_setjmp_buf", BT_FN_VOID_PTR, ATTR_NULL) diff --git a/gcc/cgraph.cc b/gcc/cgraph.cc index 06bc980fa52..f0d06bfe36b 100644 --- a/gcc/cgraph.cc +++ b/gcc/cgraph.cc @@ -3248,11 +3248,11 @@ cgraph_edge::verify_corresponds_to_fndecl (tree decl) node = node->ultimate_alias_target (); /* Optimizers can redirect unreachable calls or calls triggering undefined - behavior to __builtin_unreachable or __builtin_trap. */ + behavior to __builtin_unreachable or __builtin_unreachable trap. */ if (fndecl_built_in_p (callee->decl, BUILT_IN_NORMAL) && (DECL_FUNCTION_CODE (callee->decl) == BUILT_IN_UNREACHABLE - || DECL_FUNCTION_CODE (callee->decl) == BUILT_IN_TRAP)) + || DECL_FUNCTION_CODE (callee->decl) == BUILT_IN_UNREACHABLE_TRAP)) return false; if (callee->former_clone_of != node->decl diff --git a/gcc/gimple.cc b/gcc/gimple.cc index b97fbd54da2..5e4eda417fb 100644 --- a/gcc/gimple.cc +++ b/gcc/gimple.cc @@ -430,16 +430,7 @@ gimple_build_builtin_unreachable (location_t loc) { tree data = NULL_TREE; tree fn = sanitize_unreachable_fn (&data, loc); - gcall *g; - if (DECL_FUNCTION_CODE (fn) != BUILT_IN_TRAP) - g = gimple_build_call (fn, data != NULL_TREE, data); - else - { - /* Instead of __builtin_trap use .TRAP, so that it doesn't - need vops. */ - gcc_checking_assert (data == NULL_TREE); - g = gimple_build_call_internal (IFN_TRAP, 0); - } + gcall *g = gimple_build_call (fn, data != NULL_TREE, data); gimple_call_set_ctrl_altering (g, true); gimple_set_location (g, loc); return g; diff --git a/gcc/internal-fn.cc b/gcc/internal-fn.cc index 54ce04c6830..a7936ff37ef 100644 --- a/gcc/internal-fn.cc +++ b/gcc/internal-fn.cc @@ -4517,12 +4517,6 @@ expand_SPACESHIP (internal_fn, gcall *stmt) emit_move_insn (target, ops[0].value); } -void -expand_TRAP (internal_fn, gcall *) -{ - expand_builtin_trap (); -} - void expand_ASSUME (internal_fn, gcall *) { diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def index 1389c1137d6..22b4a2d9296 100644 --- a/gcc/internal-fn.def +++ b/gcc/internal-fn.def @@ -457,11 +457,6 @@ DEF_INTERNAL_FN (SHUFFLEVECTOR, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL) /* <=> optimization. */ DEF_INTERNAL_FN (SPACESHIP, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL) -/* __builtin_trap created from/for __builtin_unreachable. */ -DEF_INTERNAL_FN (TRAP, ECF_CONST | ECF_LEAF | ECF_NORETURN - | ECF_NOTHROW | ECF_COLD | ECF_LOOPING_CONST_OR_PURE, - NULL) - /* [[assume (cond)]]. */ DEF_INTERNAL_FN (ASSUME, ECF_CONST | ECF_LEAF | ECF_NOTHROW | ECF_LOOPING_CONST_OR_PURE, NULL) diff --git a/gcc/ipa-devirt.cc b/gcc/ipa-devirt.cc index e26266e9426..14cf132c767 100644 --- a/gcc/ipa-devirt.cc +++ b/gcc/ipa-devirt.cc @@ -3471,8 +3471,10 @@ possible_polymorphic_call_target_p (tree otr_type, unsigned int i; bool final; - if (fndecl_built_in_p (n->decl, BUILT_IN_UNREACHABLE) - || fndecl_built_in_p (n->decl, BUILT_IN_TRAP)) + if (fndecl_built_in_p (n->decl, BUILT_IN_NORMAL) + && (DECL_FUNCTION_CODE (n->decl) == BUILT_IN_UNREACHABLE + || DECL_FUNCTION_CODE (n->decl) == BUILT_IN_TRAP + || DECL_FUNCTION_CODE (n->decl) == BUILT_IN_UNREACHABLE_TRAP)) return true; if (is_cxa_pure_virtual_p (n->decl)) diff --git a/gcc/testsuite/gcc.dg/pr107300.c b/gcc/testsuite/gcc.dg/pr107300.c new file mode 100644 index 00000000000..836908ee9dd --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr107300.c @@ -0,0 +1,19 @@ +/* PR ipa/107300 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fipa-cp-clone -funreachable-traps -fno-inline" } */ + +void +bar (int x, int y) +{ + if (x) + __builtin_unreachable (); + + if (y) + __builtin_abort (); +} + +void +foo (void) +{ + bar (0, 0); +} diff --git a/gcc/tree-cfg.cc b/gcc/tree-cfg.cc index 9ecf138cbfd..a9fcc7fd050 100644 --- a/gcc/tree-cfg.cc +++ b/gcc/tree-cfg.cc @@ -3503,6 +3503,7 @@ verify_gimple_call (gcall *stmt) switch (DECL_FUNCTION_CODE (fndecl)) { case BUILT_IN_UNREACHABLE: + case BUILT_IN_UNREACHABLE_TRAP: case BUILT_IN_TRAP: if (gimple_call_num_args (stmt) > 0) { @@ -9681,6 +9682,8 @@ pass_warn_function_return::execute (function *fun) && ((LOCATION_LOCUS (gimple_location (last)) == BUILTINS_LOCATION && (gimple_call_builtin_p (last, BUILT_IN_UNREACHABLE) + || gimple_call_builtin_p (last, + BUILT_IN_UNREACHABLE_TRAP) || gimple_call_builtin_p (last, BUILT_IN_TRAP))) || gimple_call_builtin_p (last, ubsan_missing_ret))) { diff --git a/gcc/tree.cc b/gcc/tree.cc index 80c09676754..41ccbf3b3cb 100644 --- a/gcc/tree.cc +++ b/gcc/tree.cc @@ -9758,6 +9758,7 @@ build_common_builtin_nodes (void) if (!builtin_decl_explicit_p (BUILT_IN_UNREACHABLE) || !builtin_decl_explicit_p (BUILT_IN_TRAP) + || !builtin_decl_explicit_p (BUILT_IN_UNREACHABLE_TRAP) || !builtin_decl_explicit_p (BUILT_IN_ABORT)) { ftype = build_function_type (void_type_node, void_list_node); @@ -9767,6 +9768,12 @@ build_common_builtin_nodes (void) "__builtin_unreachable", ECF_NOTHROW | ECF_LEAF | ECF_NORETURN | ECF_CONST | ECF_COLD); + if (!builtin_decl_explicit_p (BUILT_IN_UNREACHABLE_TRAP)) + local_define_builtin ("__builtin_unreachable trap", ftype, + BUILT_IN_UNREACHABLE_TRAP, + "__builtin_unreachable trap", + ECF_NOTHROW | ECF_LEAF | ECF_NORETURN + | ECF_CONST | ECF_COLD); if (!builtin_decl_explicit_p (BUILT_IN_ABORT)) local_define_builtin ("__builtin_abort", ftype, BUILT_IN_ABORT, "abort", @@ -10908,7 +10915,7 @@ builtin_decl_unreachable () if (sanitize_flags_p (SANITIZE_UNREACHABLE) ? (flag_sanitize_trap & SANITIZE_UNREACHABLE) : flag_unreachable_traps) - fncode = BUILT_IN_TRAP; + fncode = BUILT_IN_UNREACHABLE_TRAP; /* For non-trapping sanitize, we will rewrite __builtin_unreachable () later, in the sanopt pass. */