Commit 77f33f44 by Richard Henderson Committed by Richard Henderson

aarch64: Simplify LSE cas generation

The cas insn is a single insn, and if expanded properly need not
be split after reload.  Use the proper inputs for the insn.

	* config/aarch64/aarch64.c (aarch64_expand_compare_and_swap):
	Force oldval into the rval register for TARGET_LSE; emit the compare
	during initial expansion so that it may be deleted if unused.
	(aarch64_gen_atomic_cas): Remove.
	* config/aarch64/atomics.md (@aarch64_compare_and_swap<SHORT>_lse):
	Change =&r to +r for operand 0; use match_dup for operand 2;
	remove is_weak and mod_f operands as unused.  Drop the split
	and merge with...
	(@aarch64_atomic_cas<SHORT>): ... this pattern's output; remove.
	(@aarch64_compare_and_swap<GPI>_lse): Similarly.
	(@aarch64_atomic_cas<GPI>): Similarly.

From-SVN: r265656
parent 187cea94
2018-10-31 Richard Henderson <richard.henderson@linaro.org>
* config/aarch64/aarch64.c (aarch64_expand_compare_and_swap):
Force oldval into the rval register for TARGET_LSE; emit the compare
during initial expansion so that it may be deleted if unused.
(aarch64_gen_atomic_cas): Remove.
* config/aarch64/atomics.md (@aarch64_compare_and_swap<SHORT>_lse):
Change =&r to +r for operand 0; use match_dup for operand 2;
remove is_weak and mod_f operands as unused. Drop the split
and merge with...
(@aarch64_atomic_cas<SHORT>): ... this pattern's output; remove.
(@aarch64_compare_and_swap<GPI>_lse): Similarly.
(@aarch64_atomic_cas<GPI>): Similarly.
2018-10-31 Richard Biener <rguenther@suse.de>
* tree-eh.c (replace_trapping_overflow): Simplify ABS_EXPR case
......@@ -563,7 +563,6 @@ rtx aarch64_load_tp (rtx);
void aarch64_expand_compare_and_swap (rtx op[]);
void aarch64_split_compare_and_swap (rtx op[]);
void aarch64_gen_atomic_cas (rtx, rtx, rtx, rtx, rtx);
bool aarch64_atomic_ldop_supported_p (enum rtx_code);
void aarch64_gen_atomic_ldop (enum rtx_code, rtx, rtx, rtx, rtx, rtx);
......
......@@ -14620,16 +14620,27 @@ aarch64_expand_compare_and_swap (rtx operands[])
}
if (TARGET_LSE)
emit_insn (gen_aarch64_compare_and_swap_lse (mode, rval, mem, oldval,
newval, is_weak, mod_s,
mod_f));
{
/* The CAS insn requires oldval and rval overlap, but we need to
have a copy of oldval saved across the operation to tell if
the operation is successful. */
if (mode == QImode || mode == HImode)
rval = copy_to_mode_reg (SImode, gen_lowpart (SImode, oldval));
else if (reg_overlap_mentioned_p (rval, oldval))
rval = copy_to_mode_reg (mode, oldval);
else
emit_move_insn (rval, oldval);
emit_insn (gen_aarch64_compare_and_swap_lse (mode, rval, mem,
newval, mod_s));
aarch64_gen_compare_reg (EQ, rval, oldval);
}
else
emit_insn (gen_aarch64_compare_and_swap (mode, rval, mem, oldval, newval,
is_weak, mod_s, mod_f));
if (mode == QImode || mode == HImode)
emit_move_insn (operands[1], gen_lowpart (mode, rval));
rval = gen_lowpart (mode, rval);
emit_move_insn (operands[1], rval);
x = gen_rtx_REG (CCmode, CC_REGNUM);
x = gen_rtx_EQ (SImode, x, const0_rtx);
......@@ -14679,31 +14690,6 @@ aarch64_emit_post_barrier (enum memmodel model)
}
}
/* Emit an atomic compare-and-swap operation. RVAL is the destination register
for the data in memory. EXPECTED is the value expected to be in memory.
DESIRED is the value to store to memory. MEM is the memory location. MODEL
is the memory ordering to use. */
void
aarch64_gen_atomic_cas (rtx rval, rtx mem,
rtx expected, rtx desired,
rtx model)
{
machine_mode mode;
mode = GET_MODE (mem);
/* Move the expected value into the CAS destination register. */
emit_insn (gen_rtx_SET (rval, expected));
/* Emit the CAS. */
emit_insn (gen_aarch64_atomic_cas (mode, rval, mem, desired, model));
/* Compare the expected value with the value loaded by the CAS, to establish
whether the swap was made. */
aarch64_gen_compare_reg (EQ, rval, expected);
}
/* Split a compare and swap pattern. */
void
......
......@@ -85,56 +85,50 @@
}
)
(define_insn_and_split "@aarch64_compare_and_swap<mode>_lse"
[(set (reg:CC CC_REGNUM) ;; bool out
(unspec_volatile:CC [(const_int 0)] UNSPECV_ATOMIC_CMPSW))
(set (match_operand:SI 0 "register_operand" "=&r") ;; val out
(define_insn "@aarch64_compare_and_swap<mode>_lse"
[(set (match_operand:SI 0 "register_operand" "+r") ;; val out
(zero_extend:SI
(match_operand:SHORT 1 "aarch64_sync_memory_operand" "+Q"))) ;; memory
(match_operand:SHORT 1 "aarch64_sync_memory_operand" "+Q"))) ;; memory
(set (match_dup 1)
(unspec_volatile:SHORT
[(match_operand:SI 2 "aarch64_plus_operand" "rI") ;; expected
(match_operand:SHORT 3 "aarch64_reg_or_zero" "rZ") ;; desired
(match_operand:SI 4 "const_int_operand") ;; is_weak
(match_operand:SI 5 "const_int_operand") ;; mod_s
(match_operand:SI 6 "const_int_operand")] ;; mod_f
[(match_dup 0) ;; expected
(match_operand:SHORT 2 "aarch64_reg_or_zero" "rZ") ;; desired
(match_operand:SI 3 "const_int_operand")] ;; mod_s
UNSPECV_ATOMIC_CMPSW))]
"TARGET_LSE"
"#"
"&& reload_completed"
[(const_int 0)]
{
aarch64_gen_atomic_cas (operands[0], operands[1],
operands[2], operands[3],
operands[5]);
DONE;
}
)
{
enum memmodel model = memmodel_from_int (INTVAL (operands[3]));
if (is_mm_relaxed (model))
return "cas<atomic_sfx>\t%<w>0, %<w>2, %1";
else if (is_mm_acquire (model) || is_mm_consume (model))
return "casa<atomic_sfx>\t%<w>0, %<w>2, %1";
else if (is_mm_release (model))
return "casl<atomic_sfx>\t%<w>0, %<w>2, %1";
else
return "casal<atomic_sfx>\t%<w>0, %<w>2, %1";
})
(define_insn_and_split "@aarch64_compare_and_swap<mode>_lse"
[(set (reg:CC CC_REGNUM) ;; bool out
(unspec_volatile:CC [(const_int 0)] UNSPECV_ATOMIC_CMPSW))
(set (match_operand:GPI 0 "register_operand" "=&r") ;; val out
(define_insn "@aarch64_compare_and_swap<mode>_lse"
[(set (match_operand:GPI 0 "register_operand" "+r") ;; val out
(match_operand:GPI 1 "aarch64_sync_memory_operand" "+Q")) ;; memory
(set (match_dup 1)
(unspec_volatile:GPI
[(match_operand:GPI 2 "aarch64_plus_operand" "rI") ;; expect
(match_operand:GPI 3 "aarch64_reg_or_zero" "rZ") ;; desired
(match_operand:SI 4 "const_int_operand") ;; is_weak
(match_operand:SI 5 "const_int_operand") ;; mod_s
(match_operand:SI 6 "const_int_operand")] ;; mod_f
[(match_dup 0) ;; expected
(match_operand:GPI 2 "aarch64_reg_or_zero" "rZ") ;; desired
(match_operand:SI 3 "const_int_operand")] ;; mod_s
UNSPECV_ATOMIC_CMPSW))]
"TARGET_LSE"
"#"
"&& reload_completed"
[(const_int 0)]
{
aarch64_gen_atomic_cas (operands[0], operands[1],
operands[2], operands[3],
operands[5]);
DONE;
}
)
{
enum memmodel model = memmodel_from_int (INTVAL (operands[3]));
if (is_mm_relaxed (model))
return "cas<atomic_sfx>\t%<w>0, %<w>2, %1";
else if (is_mm_acquire (model) || is_mm_consume (model))
return "casa<atomic_sfx>\t%<w>0, %<w>2, %1";
else if (is_mm_release (model))
return "casl<atomic_sfx>\t%<w>0, %<w>2, %1";
else
return "casal<atomic_sfx>\t%<w>0, %<w>2, %1";
})
(define_expand "atomic_exchange<mode>"
[(match_operand:ALLI 0 "register_operand" "")
......@@ -610,55 +604,6 @@
return "swpal<atomic_sfx>\t%<w>2, %<w>0, %1";
})
;; Atomic compare-and-swap: HI and smaller modes.
(define_insn "@aarch64_atomic_cas<mode>"
[(set (match_operand:SI 0 "register_operand" "+&r") ;; out
(zero_extend:SI
(match_operand:SHORT 1 "aarch64_sync_memory_operand" "+Q"))) ;; memory.
(set (match_dup 1)
(unspec_volatile:SHORT
[(match_dup 0)
(match_operand:SHORT 2 "aarch64_reg_or_zero" "rZ") ;; value.
(match_operand:SI 3 "const_int_operand" "")] ;; model.
UNSPECV_ATOMIC_CAS))]
"TARGET_LSE && reload_completed"
{
enum memmodel model = memmodel_from_int (INTVAL (operands[3]));
if (is_mm_relaxed (model))
return "cas<atomic_sfx>\t%<w>0, %<w>2, %1";
else if (is_mm_acquire (model) || is_mm_consume (model))
return "casa<atomic_sfx>\t%<w>0, %<w>2, %1";
else if (is_mm_release (model))
return "casl<atomic_sfx>\t%<w>0, %<w>2, %1";
else
return "casal<atomic_sfx>\t%<w>0, %<w>2, %1";
})
;; Atomic compare-and-swap: SI and larger modes.
(define_insn "@aarch64_atomic_cas<mode>"
[(set (match_operand:GPI 0 "register_operand" "+&r") ;; out
(match_operand:GPI 1 "aarch64_sync_memory_operand" "+Q")) ;; memory.
(set (match_dup 1)
(unspec_volatile:GPI
[(match_dup 0)
(match_operand:GPI 2 "aarch64_reg_or_zero" "rZ") ;; value.
(match_operand:SI 3 "const_int_operand" "")] ;; model.
UNSPECV_ATOMIC_CAS))]
"TARGET_LSE && reload_completed"
{
enum memmodel model = memmodel_from_int (INTVAL (operands[3]));
if (is_mm_relaxed (model))
return "cas<atomic_sfx>\t%<w>0, %<w>2, %1";
else if (is_mm_acquire (model) || is_mm_consume (model))
return "casa<atomic_sfx>\t%<w>0, %<w>2, %1";
else if (is_mm_release (model))
return "casl<atomic_sfx>\t%<w>0, %<w>2, %1";
else
return "casal<atomic_sfx>\t%<w>0, %<w>2, %1";
})
;; Atomic load-op: Load data, operate, store result, keep data.
(define_insn "@aarch64_atomic_load<atomic_ldop><mode>"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment