From: Hans-Peter Nilsson Date: Sat, 23 Sep 2023 03:06:52 +0000 (+0200) Subject: __atomic_test_and_set: Fall back to library, not non-atomic code X-Git-Tag: basepoints/gcc-15~5853 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8e6757b30d0f3f13d47d0f842801a751ba6293c2;p=thirdparty%2Fgcc.git __atomic_test_and_set: Fall back to library, not non-atomic code Make __atomic_test_and_set consistent with other __atomic_ and __sync_ builtins: call a matching library function instead of emitting non-atomic code when the target has no direct insn support. There's special-case code handling targetm.atomic_test_and_set_trueval != 1 trying a modified maybe_emit_sync_lock_test_and_set. Previously, if that worked but its matching emit_store_flag_force returned NULL, we'd segfault later on. Now that the caller handles NULL, gcc_assert here instead. While the referenced PR:s are ARM-specific, the issue is general. PR target/107567 PR target/109166 * builtins.cc (expand_builtin) : Handle failure from expand_builtin_atomic_test_and_set. * optabs.cc (expand_atomic_test_and_set): When all attempts fail to generate atomic code through target support, return NULL instead of emitting non-atomic code. Also, for code handling targetm.atomic_test_and_set_trueval != 1, gcc_assert result from calling emit_store_flag_force instead of returning NULL. --- diff --git a/gcc/builtins.cc b/gcc/builtins.cc index 6e4274bb2a4e..40dfd36a3197 100644 --- a/gcc/builtins.cc +++ b/gcc/builtins.cc @@ -8387,7 +8387,10 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode, break; case BUILT_IN_ATOMIC_TEST_AND_SET: - return expand_builtin_atomic_test_and_set (exp, target); + target = expand_builtin_atomic_test_and_set (exp, target); + if (target) + return target; + break; case BUILT_IN_ATOMIC_CLEAR: return expand_builtin_atomic_clear (exp); diff --git a/gcc/optabs.cc b/gcc/optabs.cc index 8b96f23aec05..e1898da22808 100644 --- a/gcc/optabs.cc +++ b/gcc/optabs.cc @@ -7080,25 +7080,17 @@ expand_atomic_test_and_set (rtx target, rtx mem, enum memmodel model) /* Recall that the legacy lock_test_and_set optab was allowed to do magic things with the value 1. Thus we try again without trueval. */ if (!ret && targetm.atomic_test_and_set_trueval != 1) - ret = maybe_emit_sync_lock_test_and_set (subtarget, mem, const1_rtx, model); - - /* Failing all else, assume a single threaded environment and simply - perform the operation. */ - if (!ret) { - /* If the result is ignored skip the move to target. */ - if (subtarget != const0_rtx) - emit_move_insn (subtarget, mem); + ret = maybe_emit_sync_lock_test_and_set (subtarget, mem, const1_rtx, model); - emit_move_insn (mem, trueval); - ret = subtarget; + if (ret) + { + /* Rectify the not-one trueval. */ + ret = emit_store_flag_force (target, NE, ret, const0_rtx, mode, 0, 1); + gcc_assert (ret); + } } - /* Recall that have to return a boolean value; rectify if trueval - is not exactly one. */ - if (targetm.atomic_test_and_set_trueval != 1) - ret = emit_store_flag_force (target, NE, ret, const0_rtx, mode, 0, 1); - return ret; }