OSDN Git Service

* optabs.c (expand_atomic_test_and_set): Honor
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 4 Mar 2012 02:34:55 +0000 (02:34 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 4 Mar 2012 02:34:55 +0000 (02:34 +0000)
atomic_test_and_set_trueval even when atomic_test_and_set
optab is not in use.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_7-branch@184878 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/optabs.c

index 29e57cc..11cecf6 100644 (file)
@@ -1,3 +1,9 @@
+2012-03-02  Richard Henderson  <rth@redhat.com>
+
+       * optabs.c (expand_atomic_test_and_set): Honor
+       atomic_test_and_set_trueval even when atomic_test_and_set
+       optab is not in use.
+
 2012-03-02  Peter Bergner  <bergner@vnet.ibm.com>
 
        Backport from mainline
index b0ecdf0..fd353d7 100644 (file)
@@ -7384,34 +7384,57 @@ rtx
 expand_atomic_test_and_set (rtx target, rtx mem, enum memmodel model)
 {
   enum machine_mode mode = GET_MODE (mem);
-  rtx ret;
+  rtx ret, trueval, subtarget;
 
   ret = maybe_emit_atomic_test_and_set (target, mem, model);
   if (ret)
     return ret;
 
-  if (target == NULL_RTX)
-    target = gen_reg_rtx (mode);
+  /* Be binary compatible with non-default settings of trueval, and different
+     cpu revisions.  E.g. one revision may have atomic-test-and-set, but
+     another only has atomic-exchange.  */
+  if (targetm.atomic_test_and_set_trueval == 1)
+    {
+      trueval = const1_rtx;
+      subtarget = target ? target : gen_reg_rtx (mode);
+    }
+  else
+    {
+      trueval = gen_int_mode (targetm.atomic_test_and_set_trueval, mode);
+      subtarget = gen_reg_rtx (mode);
+    }
 
-  /* 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;
+  /* Try the atomic-exchange optab...  */
+  ret = maybe_emit_atomic_exchange (subtarget, mem, trueval, model);
 
-  ret = maybe_emit_compare_and_swap_exchange_loop (target, mem, const1_rtx);
-  if (ret)
-    return ret;
+  /* ... then an atomic-compare-and-swap loop ... */
+  if (!ret)
+    ret = maybe_emit_compare_and_swap_exchange_loop (subtarget, mem, trueval);
 
-  ret = maybe_emit_sync_lock_test_and_set (target, mem, const1_rtx, model);
-  if (ret)
-    return ret;
+  /* ... before trying the vaguely defined legacy lock_test_and_set. */
+  if (!ret)
+    ret = maybe_emit_sync_lock_test_and_set (subtarget, mem, trueval, model);
 
-  /* Failing all else, assume a single threaded environment and simply perform
-     the operation.  */
-  emit_move_insn (target, mem);
-  emit_move_insn (mem, const1_rtx);
-  return target;
+  /* 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)
+    {
+      emit_move_insn (subtarget, mem);
+      emit_move_insn (mem, trueval);
+      ret = subtarget;
+    }
+
+  /* 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;
 }
 
 /* This function expands the atomic exchange operation: