A recent commit introduced a mechanism to emit proper fences for RISC-V. Additionally, we already have emit_move_insn (). Let's reuse this code and provide atomic_load<mode> and atomic_store<mode> for RISC-V (as defined in section "Code Porting and Mapping Guidelines" of the unpriv spec). Note, that this works also for sub-word atomics.
gcc/ PR 100265 * config/riscv/sync.md (atomic_load<mode>): New. * config/riscv/sync.md (atomic_store<mode>): New. --- gcc/config/riscv/sync.md | 41 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/gcc/config/riscv/sync.md b/gcc/config/riscv/sync.md index ae80f94f2e0..9eb0dde9086 100644 --- a/gcc/config/riscv/sync.md +++ b/gcc/config/riscv/sync.md @@ -23,6 +23,7 @@ (define_c_enum "unspec" [ UNSPEC_COMPARE_AND_SWAP UNSPEC_SYNC_OLD_OP UNSPEC_SYNC_EXCHANGE + UNSPEC_ATOMIC_LOAD UNSPEC_ATOMIC_STORE UNSPEC_MEMORY_BARRIER ]) @@ -72,6 +73,46 @@ (define_insn "*mem_fence" ;; Atomic memory operations. +(define_expand "atomic_load<mode>" + [(set (match_operand:ANYI 0 "register_operand" "=r") + (unspec_volatile:ANYI + [(match_operand:ANYI 1 "memory_operand" "A") + (match_operand:SI 2 "const_int_operand")] ;; model + UNSPEC_ATOMIC_LOAD))] + "" + { + rtx target = operands[0]; + rtx mem = operands[1]; + enum memmodel model = memmodel_from_int (INTVAL (operands[2])); + + if (is_mm_seq_cst (model)) + emit_insn (gen_mem_fence (GEN_INT (MEMMODEL_SEQ_CST))); + emit_move_insn (target, mem); + if (is_mm_acquire (model) || is_mm_seq_cst (model)) + emit_insn (gen_mem_fence (GEN_INT (MEMMODEL_ACQUIRE))); + + DONE; +}) + +(define_expand "atomic_store<mode>" + [(set (match_operand:ANYI 0 "memory_operand" "=A") + (unspec_volatile:ANYI + [(match_operand:ANYI 1 "reg_or_0_operand" "rJ") + (match_operand:SI 2 "const_int_operand")] ;; model + UNSPEC_ATOMIC_STORE))] + "" + { + rtx mem = operands[0]; + rtx val = operands[1]; + enum memmodel model = memmodel_from_int (INTVAL (operands[2])); + + if (is_mm_release (model) || is_mm_seq_cst (model)) + emit_insn (gen_mem_fence (GEN_INT (MEMMODEL_RELEASE))); + emit_move_insn (mem, val); + + DONE; +}) + (define_insn "atomic_<atomic_optab><mode>" [(set (match_operand:GPR 0 "memory_operand" "+A") (unspec_volatile:GPR -- 2.35.3