This change brings atomic fences in line with table A.6 of the ISA
manual.

Relax mem_thread_fence according to the memmodel given.

2022-03-31 Patrick O'Neill <patr...@rivosinc.com>

        * riscv.cc: Expose helper functions to sync.md.
        * riscv-protos.h: Likewise.
        * sync.md (mem_thread_fence_1): Change fence depending on
        aquire/release requirements.
        * amo-thread-fence-1: New test.
        * amo-thread-fence-2: Likewise.
        * amo-thread-fence-3: Likewise.
        * amo-thread-fence-4: Likewise.
        * amo-thread-fence-5: Likewise.

Signed-off-by: Patrick O'Neill <patr...@rivosinc.com>
---
 gcc/config/riscv/riscv-protos.h                  |  2 ++
 gcc/config/riscv/riscv.cc                        |  4 ++--
 gcc/config/riscv/sync.md                         | 16 +++++++++++++---
 .../gcc.target/riscv/amo-thread-fence-1.c        |  6 ++++++
 .../gcc.target/riscv/amo-thread-fence-2.c        |  6 ++++++
 .../gcc.target/riscv/amo-thread-fence-3.c        |  6 ++++++
 .../gcc.target/riscv/amo-thread-fence-4.c        |  6 ++++++
 .../gcc.target/riscv/amo-thread-fence-5.c        |  6 ++++++
 8 files changed, 47 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/amo-thread-fence-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/amo-thread-fence-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/amo-thread-fence-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/amo-thread-fence-4.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/amo-thread-fence-5.c

diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index e32ea86a530..4390ede84f5 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -76,6 +76,8 @@ extern bool riscv_expand_block_move (rtx, rtx, rtx);
 extern bool riscv_store_data_bypass_p (rtx_insn *, rtx_insn *);
 extern rtx riscv_gen_gpr_save_insn (struct riscv_frame_info *);
 extern bool riscv_gpr_save_operation_p (rtx);
+extern bool riscv_memmodel_needs_amo_acquire (enum memmodel);
+extern bool riscv_memmodel_needs_amo_release (enum memmodel);
 extern enum memmodel riscv_parent_memmodel (enum memmodel, enum memmodel);
 extern enum memmodel riscv_simplify_memmodel (enum memmodel);
 
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 48d18a83f06..3ee910261a2 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -3619,7 +3619,7 @@ riscv_simplify_memmodel(enum memmodel model) {
 /* Return true if the .AQ suffix should be added to an AMO to implement the
    acquire portion of memory model MODEL.  */
 
-static bool
+bool
 riscv_memmodel_needs_amo_acquire (enum memmodel model)
 {
   switch (model)
@@ -3645,7 +3645,7 @@ riscv_memmodel_needs_amo_acquire (enum memmodel model)
 /* Return true if the .RL suffix should be added to an AMO to implement the
    release portion of memory model MODEL.  */
 
-static bool
+bool
 riscv_memmodel_needs_amo_release (enum memmodel model)
 {
   switch (model)
diff --git a/gcc/config/riscv/sync.md b/gcc/config/riscv/sync.md
index 1cc3731da38..a7a040180f5 100644
--- a/gcc/config/riscv/sync.md
+++ b/gcc/config/riscv/sync.md
@@ -46,14 +46,24 @@
   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"
   [(set (match_operand:BLK 0 "" "")
        (unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))
    (match_operand:SI 1 "const_int_operand" "")] ;; model
   ""
-  "fence\tiorw,iorw")
+  {
+    enum memmodel model = (enum memmodel) INTVAL (operands[1]);
+    if (model == MEMMODEL_ACQ_REL)
+       return "fence.tso";
+    else if (riscv_memmodel_needs_amo_acquire (model) &&
+            riscv_memmodel_needs_amo_release (model))
+       return "fence\trw,rw";
+    else if (riscv_memmodel_needs_amo_acquire (model))
+       return "fence\tr,rw";
+    else if (riscv_memmodel_needs_amo_release (model))
+       return "fence\trw,w";
+  }
+  [(set (attr "length") (const_int 4))])
 
 ;; Atomic memory operations.
 
diff --git a/gcc/testsuite/gcc.target/riscv/amo-thread-fence-1.c 
b/gcc/testsuite/gcc.target/riscv/amo-thread-fence-1.c
new file mode 100644
index 00000000000..833629bf2f2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-thread-fence-1.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-final { scan-assembler-not "fence\t" } } */
+
+int main() {
+  __atomic_thread_fence(__ATOMIC_RELAXED);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-thread-fence-2.c 
b/gcc/testsuite/gcc.target/riscv/amo-thread-fence-2.c
new file mode 100644
index 00000000000..3395ee41dbb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-thread-fence-2.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-final { scan-assembler "fence\tr,rw" } } */
+
+int main() {
+  __atomic_thread_fence(__ATOMIC_ACQUIRE);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-thread-fence-3.c 
b/gcc/testsuite/gcc.target/riscv/amo-thread-fence-3.c
new file mode 100644
index 00000000000..59cc4e5d394
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-thread-fence-3.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-final { scan-assembler "fence\trw,w" } } */
+
+int main() {
+  __atomic_thread_fence(__ATOMIC_RELEASE);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-thread-fence-4.c 
b/gcc/testsuite/gcc.target/riscv/amo-thread-fence-4.c
new file mode 100644
index 00000000000..2afed9a9e38
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-thread-fence-4.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-final { scan-assembler "fence.tso" } } */
+
+int main() {
+  __atomic_thread_fence(__ATOMIC_ACQ_REL);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-thread-fence-5.c 
b/gcc/testsuite/gcc.target/riscv/amo-thread-fence-5.c
new file mode 100644
index 00000000000..b8d56c0f066
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-thread-fence-5.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-final { scan-assembler "fence\trw,rw" } } */
+
+int main() {
+  __atomic_thread_fence(__ATOMIC_SEQ_CST);
+}
-- 
2.25.1

Reply via email to