@@ -5452,12 +5452,11 @@ fold_builtin_atomic_always_lock_free (tree arg)
of the pattern indicates support is present. */
size = INTVAL (expand_normal (arg)) * BITS_PER_UNIT;
mode = mode_for_size (size, MODE_INT, 0);
- icode = direct_optab_handler (sync_compare_and_swap_optab, mode);
- if (icode == CODE_FOR_nothing)
+ if (can_compare_and_swap_p (mode))
+ return integer_one_node;
+ else
return integer_zero_node;
-
- return integer_one_node;
}
/* Return true if the first argument to call EXP represents a size of
@@ -5190,8 +5190,7 @@ expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
itype = TREE_TYPE (TREE_TYPE (cmpxchg));
- if (direct_optab_handler (sync_compare_and_swap_optab, TYPE_MODE (itype))
- == CODE_FOR_nothing)
+ if (!can_compare_and_swap_p (TYPE_MODE (itype)))
return false;
/* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
@@ -6778,6 +6778,27 @@ expand_vec_cond_expr (tree vec_cond_type, tree op0, tree op1, tree op2,
}
+/* Return true if there is a compare_and_swap pattern. */
+
+bool
+can_compare_and_swap_p (enum machine_mode mode)
+{
+ enum insn_code icode;
+
+ /* Check for __sync_compare_and_swap. */
+ icode = direct_optab_handler (sync_compare_and_swap_optab, mode);
+ if (icode != CODE_FOR_nothing)
+ return true;
+
+ /* Check for __atomic_compare_and_swap. */
+ icode = direct_optab_handler (atomic_compare_and_swap_optab, mode);
+ if (icode != CODE_FOR_nothing)
+ return true;
+
+ /* No inline compare and swap. */
+ return false;
+}
+
/* This is an internal subroutine of the other compare_and_swap expanders.
MEM, OLD_VAL and NEW_VAL are as you'd expect for a compare-and-swap
operation. TARGET is an optional place to store the value result of
@@ -7014,8 +7035,7 @@ expand_atomic_exchange (rtx target, rtx mem, rtx val, enum memmodel model)
delete_insns_since (last_insn);
/* Otherwise, use a compare-and-swap loop for the exchange. */
- if (direct_optab_handler (sync_compare_and_swap_optab, mode)
- != CODE_FOR_nothing)
+ if (can_compare_and_swap_p (mode))
{
if (!target || !register_operand (target, mode))
target = gen_reg_rtx (mode);
@@ -7451,8 +7471,7 @@ expand_atomic_fetch_op (rtx target, rtx mem, rtx val, enum rtx_code code,
}
/* If nothing else has succeeded, default to a compare and swap loop. */
- if (direct_optab_handler (sync_compare_and_swap_optab, mode)
- != CODE_FOR_nothing)
+ if (can_compare_and_swap_p (mode))
{
rtx insn;
rtx t0 = gen_reg_rtx (mode), t1;
@@ -952,6 +952,9 @@ extern void expand_float (rtx, rtx, int);
/* Return the insn_code for a FLOAT_EXPR. */
enum insn_code can_float_p (enum machine_mode, enum machine_mode, int);
+/* Return true if there is an inline compare and swap pattern. */
+extern bool can_compare_and_swap_p (enum machine_mode);
+
/* Generate code for a FIX_EXPR. */
extern void expand_fix (rtx, rtx, int);