===================================================================
@@ -7436,10 +7436,35 @@
return NULL_RTX;
}
+/* This function tries to emit an atomic test and set operation using
+ __atomic_test_and_set, if it is defined in the target. */
+
+static rtx
+maybe_emit_atomic_test_and_set (rtx target, rtx mem, enum memmodel model)
+{
#ifndef HAVE_atomic_test_and_set
-#define HAVE_atomic_test_and_set 0
-#define gen_atomic_test_and_set(x,y,z) (gcc_unreachable (), NULL_RTX)
+
+ return NULL_RTX;
+
+#else
+
+ /* Allow the target to use a different mode than mem for storing
+ the previous value in some target specific way, as in
+ compare_and_swap.
+ This allows test and set conditional operations to be combined
+ better with surrounding code. */
+ enum insn_code icode = CODE_FOR_atomic_test_and_set;
+ enum machine_mode imode = insn_data[icode].operand[0].mode;
+
+ if (target == NULL_RTX || GET_MODE (target) != imode)
+ target = gen_reg_rtx (imode);
+
+ emit_insn (gen_atomic_test_and_set (target, mem, GEN_INT (model)));
+
+ return target;
+
#endif
+}
/* This function expands the legacy _sync_lock test_and_set operation which is
generally an atomic exchange. Some limited targets only allow the
@@ -7464,11 +7489,8 @@
/* 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 (!ret && val == const1_rtx)
+ ret = maybe_emit_atomic_test_and_set (target, mem, MEMMODEL_ACQUIRE);
return ret;
}
@@ -7488,16 +7510,12 @@
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;
- }
+ ret = maybe_emit_atomic_test_and_set (target, mem, MEMMODEL_ACQUIRE);
/* 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)
+ ret = maybe_emit_atomic_exchange (target, mem, const1_rtx, model);
if (!ret)
ret = maybe_emit_compare_and_swap_exchange_loop (target, mem, const1_rtx);