[gcc r14-4286] __atomic_test_and_set: Fall back to library, not non-atomic code

Hans-Peter Nilsson hp@gcc.gnu.org
Tue Sep 26 21:40:15 GMT 2023


https://gcc.gnu.org/g:8e6757b30d0f3f13d47d0f842801a751ba6293c2

commit r14-4286-g8e6757b30d0f3f13d47d0f842801a751ba6293c2
Author: Hans-Peter Nilsson <hp@axis.com>
Date:   Sat Sep 23 05:06:52 2023 +0200

    __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) <case BUILT_IN_ATOMIC_TEST_AND_SET>:
            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:
---
 gcc/builtins.cc |  5 ++++-
 gcc/optabs.cc   | 22 +++++++---------------
 2 files changed, 11 insertions(+), 16 deletions(-)

diff --git a/gcc/builtins.cc b/gcc/builtins.cc
index 6e4274bb2a4..40dfd36a319 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 8b96f23aec0..e1898da2280 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;
 }


More information about the Gcc-cvs mailing list