mem_thread_fence gets the desired memory model as operand. Let's emit fences according to this value (as defined in section "Code Porting and Mapping Guidelines" of the unpriv spec).
gcc/ PR 100265 * config/riscv/sync.md (mem_thread_fence): Emit fences according to given operand. * config/riscv/sync.md (mem_fence): Add INSNs for different fence flavours. * config/riscv/sync.md (mem_thread_fence_1): Remove. --- gcc/config/riscv/sync.md | 41 +++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/gcc/config/riscv/sync.md b/gcc/config/riscv/sync.md index 86f4cef6af9..ae80f94f2e0 100644 --- a/gcc/config/riscv/sync.md +++ b/gcc/config/riscv/sync.md @@ -34,26 +34,41 @@ (define_code_attr atomic_optab ;; Memory barriers. (define_expand "mem_thread_fence" - [(match_operand:SI 0 "const_int_operand" "")] ;; model + [(match_operand:SI 0 "const_int_operand")] ;; model "" { - if (INTVAL (operands[0]) != MEMMODEL_RELAXED) - { - rtx mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode)); - MEM_VOLATILE_P (mem) = 1; - emit_insn (gen_mem_thread_fence_1 (mem, operands[0])); - } + enum memmodel model = memmodel_from_int (INTVAL (operands[0])); + if (!(is_mm_relaxed (model))) + emit_insn (gen_mem_fence (operands[0])); DONE; }) -;; Until the RISC-V memory model (hence its mapping from C++) is finalized, -;; conservatively emit a full FENCE. -(define_insn "mem_thread_fence_1" +(define_expand "mem_fence" + [(set (match_dup 1) + (unspec:BLK [(match_dup 1) (match_operand:SI 0 "const_int_operand")] + UNSPEC_MEMORY_BARRIER))] + "" +{ + operands[1] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode)); + MEM_VOLATILE_P (operands[1]) = 1; +}) + +(define_insn "*mem_fence" [(set (match_operand:BLK 0 "" "") - (unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER)) - (match_operand:SI 1 "const_int_operand" "")] ;; model + (unspec:BLK [(match_dup 0) (match_operand:SI 1 "const_int_operand")] + UNSPEC_MEMORY_BARRIER))] "" - "fence\tiorw,iorw") +{ + enum memmodel model = memmodel_from_int (INTVAL (operands[1])); + if (is_mm_consume (model) || is_mm_acquire (model)) + return "fence\tr, rw"; + else if (is_mm_release (model)) + return "fence\trw, w"; + else if (is_mm_acq_rel (model)) + return "fence.tso"; + else + return "fence\trw, rw"; +}) ;; Atomic memory operations. -- 2.35.3