OSDN Git Service

atomic: Create and use maybe_emit_atomic_test_and_set.
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 24 Jan 2012 17:55:29 +0000 (17:55 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 24 Jan 2012 17:55:29 +0000 (17:55 +0000)
* optabs.c (CODE_FOR_atomic_test_and_set): Provide default.
(maybe_emit_atomic_test_and_set): New.
(expand_sync_lock_test_and_set): Use it.
(expand_atomic_test_and_set): Likewise.
* doc/extend.texi (__atomic_test_and_set): Adjust the docs to match
the implementation; clarify implementation defined details.
* doc/md.texi (atomic_test_and_set): Document.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@183483 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/doc/extend.texi
gcc/doc/md.texi
gcc/optabs.c

index c06613e..9616c2b 100644 (file)
@@ -1,5 +1,15 @@
 2012-01-25  Richard Henderson  <rth@redhat.com>
 
+       * optabs.c (CODE_FOR_atomic_test_and_set): Provide default.
+       (maybe_emit_atomic_test_and_set): New.
+       (expand_sync_lock_test_and_set): Use it.
+       (expand_atomic_test_and_set): Likewise.
+       * doc/extend.texi (__atomic_test_and_set): Adjust the docs to match
+       the implementation; clarify implementation defined details.
+       * doc/md.texi (atomic_test_and_set): Document.
+
+2012-01-25  Richard Henderson  <rth@redhat.com>
+
        * config/sparc/predicates.md (zero_or_v7_operand): Use match_code.
 
 2012-01-25  Richard Henderson  <rth@redhat.com>
index 229e87c..e159736 100644 (file)
@@ -7202,11 +7202,12 @@ All memory models are valid.
 
 @end deftypefn
 
-@deftypefn {Built-in Function} bool __atomic_test_and_set (bool *ptr, int memmodel)
+@deftypefn {Built-in Function} bool __atomic_test_and_set (void *ptr, int memmodel)
 
 This built-in function performs an atomic test-and-set operation on
-@code{*@var{ptr}}.  @code{*@var{ptr}} is set to the value 1 and
-the previous contents are returned.
+the byte at @code{*@var{ptr}}.  The byte is set to some implementation
+defined non-zero "set" value and the return value is @code{true} if and only
+if the previous contents were "set".
 
 All memory models are valid.
 
index bcfd420..afdc3e3 100644 (file)
@@ -5893,6 +5893,19 @@ the operation followed by the arithmetic operation required to produce the
 result.  If none of these are available a compare-and-swap loop will be
 used.
 
+@cindex @code{atomic_test_and_set} instruction pattern
+@item @samp{atomic_test_and_set}
+
+This pattern emits code for @code{__builtin_atomic_test_and_set}.
+Operand 0 is an output operand which is set to true if the previous
+previous contents of the byte was "set", and false otherwise.  Operand 1
+is the @code{QImode} memory to be modified.  Operand 2 is the memory
+model to be used.
+
+The specific value that defines "set" is implementation defined, and
+is normally based on what is performed by the native atomic test and set
+instruction.
+
 @cindex @code{mem_thread_fence@var{mode}} instruction pattern
 @item @samp{mem_thread_fence@var{mode}}
 This pattern emits code required to implement a thread fence with
index a532ba3..0f6d763 100644 (file)
@@ -7304,11 +7304,41 @@ maybe_emit_compare_and_swap_exchange_loop (rtx target, rtx mem, rtx val)
   return NULL_RTX;
 }
 
+/* This function tries to implement an atomic test-and-set operation
+   using the atomic_test_and_set instruction pattern.  A boolean value
+   is returned from the operation, using TARGET if possible.  */
+
 #ifndef HAVE_atomic_test_and_set
 #define HAVE_atomic_test_and_set 0
+#define CODE_FOR_atomic_test_and_set CODE_FOR_nothing
 #define gen_atomic_test_and_set(x,y,z)  (gcc_unreachable (), NULL_RTX)
 #endif
 
+static rtx
+maybe_emit_atomic_test_and_set (rtx target, rtx mem, enum memmodel model)
+{
+  enum machine_mode pat_bool_mode;
+  const struct insn_data_d *id;
+
+  if (!HAVE_atomic_test_and_set)
+    return NULL_RTX;
+
+  id = &insn_data[CODE_FOR_atomic_test_and_set];
+  pat_bool_mode = id->operand[0].mode;
+
+  /* ??? We only support test-and-set on single bytes at the moment.
+     We'd have to change the builtin to allow wider memories.  */
+  gcc_checking_assert (id->operand[1].mode == QImode);
+  gcc_checking_assert (GET_MODE (mem) == QImode);
+
+  if (target == NULL || GET_MODE (target) != pat_bool_mode)
+    target = gen_reg_rtx (pat_bool_mode);
+
+  emit_insn (gen_atomic_test_and_set (target, mem, GEN_INT (model)));
+
+  return target;
+}
+
 /* This function expands the legacy _sync_lock test_and_set operation which is
    generally an atomic exchange.  Some limited targets only allow the
    constant 1 to be stored.  This is an ACQUIRE operation. 
@@ -7323,20 +7353,21 @@ expand_sync_lock_test_and_set (rtx target, rtx mem, rtx val)
 
   /* Try an atomic_exchange first.  */
   ret = maybe_emit_atomic_exchange (target, mem, val, MEMMODEL_ACQUIRE);
+  if (ret)
+    return ret;
 
-  if (!ret)
-    ret = maybe_emit_sync_lock_test_and_set (target, mem, val,
-                                            MEMMODEL_ACQUIRE);
-  if (!ret)
-    ret = maybe_emit_compare_and_swap_exchange_loop (target, mem, val);
+  ret = maybe_emit_sync_lock_test_and_set (target, mem, val, MEMMODEL_ACQUIRE);
+  if (ret)
+    return ret;
+
+  ret = maybe_emit_compare_and_swap_exchange_loop (target, mem, val);
+  if (ret)
+    return ret;
 
   /* If there are no other options, try atomic_test_and_set if the value
      being stored is 1.  */
-  if (!ret && val == const1_rtx && HAVE_atomic_test_and_set)
-    {
-      ret = gen_atomic_test_and_set (target, mem, GEN_INT (MEMMODEL_ACQUIRE));
-      emit_insn (ret);
-    }
+  if (val == const1_rtx)
+    ret = maybe_emit_atomic_test_and_set (target, mem, MEMMODEL_ACQUIRE);
 
   return ret;
 }
@@ -7351,28 +7382,26 @@ rtx
 expand_atomic_test_and_set (rtx target, rtx mem, enum memmodel model)
 {
   enum machine_mode mode = GET_MODE (mem);
-  rtx ret = NULL_RTX;
+  rtx ret;
+
+  ret = maybe_emit_atomic_test_and_set (target, mem, model);
+  if (ret)
+    return ret;
 
   if (target == NULL_RTX)
     target = gen_reg_rtx (mode);
 
-  if (HAVE_atomic_test_and_set)
-    {
-      ret = gen_atomic_test_and_set (target, mem, GEN_INT (MEMMODEL_ACQUIRE));
-      emit_insn (ret);
-      return ret;
-    }
-
   /* If there is no test and set, try exchange, then a compare_and_swap loop,
      then __sync_test_and_set.  */
   ret = maybe_emit_atomic_exchange (target, mem, const1_rtx, model);
+  if (ret)
+    return ret;
 
-  if (!ret)
-    ret = maybe_emit_compare_and_swap_exchange_loop (target, mem, const1_rtx);
-
-  if (!ret)
-    ret = maybe_emit_sync_lock_test_and_set (target, mem, const1_rtx, model);
+  ret = maybe_emit_compare_and_swap_exchange_loop (target, mem, const1_rtx);
+  if (ret)
+    return ret;
 
+  ret = maybe_emit_sync_lock_test_and_set (target, mem, const1_rtx, model);
   if (ret)
     return ret;