]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
RISC-V: Add Zalrsc amo-op patterns
authorPatrick O'Neill <patrick@rivosinc.com>
Thu, 8 Feb 2024 00:30:30 +0000 (16:30 -0800)
committerPatrick O'Neill <patrick@rivosinc.com>
Tue, 11 Jun 2024 17:05:17 +0000 (10:05 -0700)
All amo<op> patterns can be represented with lrsc sequences.
Add these patterns as a fallback when Zaamo is not enabled.

gcc/ChangeLog:

* config/riscv/sync.md (atomic_<atomic_optab><mode>): New expand pattern.
(amo_atomic_<atomic_optab><mode>): Rename amo pattern.
(atomic_fetch_<atomic_optab><mode>): New lrsc sequence pattern.
(lrsc_atomic_<atomic_optab><mode>): New expand pattern.
(amo_atomic_fetch_<atomic_optab><mode>): Rename amo pattern.
(lrsc_atomic_fetch_<atomic_optab><mode>): New lrsc sequence pattern.
(atomic_exchange<mode>): New expand pattern.
(amo_atomic_exchange<mode>): Rename amo pattern.
(lrsc_atomic_exchange<mode>): New lrsc sequence pattern.

gcc/testsuite/ChangeLog:

* gcc.target/riscv/amo-zaamo-preferred-over-zalrsc.c: New test.
* gcc.target/riscv/amo-zalrsc-amo-add-1.c: New test.
* gcc.target/riscv/amo-zalrsc-amo-add-2.c: New test.
* gcc.target/riscv/amo-zalrsc-amo-add-3.c: New test.
* gcc.target/riscv/amo-zalrsc-amo-add-4.c: New test.
* gcc.target/riscv/amo-zalrsc-amo-add-5.c: New test.

Signed-off-by: Patrick O'Neill <patrick@rivosinc.com>
gcc/config/riscv/sync.md
gcc/testsuite/gcc.target/riscv/amo-zaamo-preferred-over-zalrsc.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/amo-zalrsc-amo-add-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/amo-zalrsc-amo-add-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/amo-zalrsc-amo-add-3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/amo-zalrsc-amo-add-4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/amo-zalrsc-amo-add-5.c [new file with mode: 0644]

index c9544176ead5c22dac27ca6fd05568ebf4bb01d2..4df9d0b5a5ff4ef50376fa66a8d1cd12289d642f 100644 (file)
     DONE;
   })
 
-(define_insn "atomic_<atomic_optab><mode>"
+;; AMO ops
+
+(define_expand "atomic_<atomic_optab><mode>"
+  [(any_atomic:GPR (match_operand:GPR 0 "memory_operand")    ;; mem location
+                  (match_operand:GPR 1 "reg_or_0_operand")) ;; value for op
+   (match_operand:SI 2 "const_int_operand")]                ;; model
+  "TARGET_ZAAMO || TARGET_ZALRSC"
+{
+  if (TARGET_ZAAMO)
+    emit_insn (gen_amo_atomic_<atomic_optab><mode> (operands[0], operands[1],
+                                                   operands[2]));
+  else
+    emit_insn (gen_lrsc_atomic_<atomic_optab><mode> (operands[0], operands[1],
+                                                    operands[2]));
+  DONE;
+})
+
+(define_insn "amo_atomic_<atomic_optab><mode>"
   [(set (match_operand:GPR 0 "memory_operand" "+A")
        (unspec_volatile:GPR
          [(any_atomic:GPR (match_dup 0)
   [(set_attr "type" "atomic")
    (set (attr "length") (const_int 4))])
 
-(define_insn "atomic_fetch_<atomic_optab><mode>"
+(define_insn "lrsc_atomic_<atomic_optab><mode>"
+  [(set (match_operand:GPR 0 "memory_operand" "+A")
+       (unspec_volatile:GPR
+         [(any_atomic:GPR (match_dup 0)
+                    (match_operand:GPR 1 "reg_or_0_operand" "rJ"))
+          (match_operand:SI 2 "const_int_operand")] ;; model
+        UNSPEC_SYNC_OLD_OP))
+   (clobber (match_scratch:GPR 3 "=&r"))]           ;; tmp_1
+  "!TARGET_ZAAMO && TARGET_ZALRSC"
+  {
+    return "1:\;"
+          "lr.<amo>%I2\t%3, %0\;"
+          "<insn>\t%3, %3, %1\;"
+          "sc.<amo>%J2\t%3, %3, %0\;"
+          "bnez\t%3, 1b";
+  }
+  [(set_attr "type" "atomic")
+   (set (attr "length") (const_int 16))])
+
+;; AMO fetch ops
+
+(define_expand "atomic_fetch_<atomic_optab><mode>"
+  [(match_operand:GPR 0 "register_operand")                 ;; old value at mem
+   (any_atomic:GPR (match_operand:GPR 1 "memory_operand")    ;; mem location
+                  (match_operand:GPR 2 "reg_or_0_operand")) ;; value for op
+   (match_operand:SI 3 "const_int_operand")]                ;; model
+  "TARGET_ZAAMO || TARGET_ZALRSC"
+  {
+    if (TARGET_ZAAMO)
+      emit_insn (gen_amo_atomic_fetch_<atomic_optab><mode> (operands[0], operands[1],
+                                                           operands[2], operands[3]));
+    else
+      emit_insn (gen_lrsc_atomic_fetch_<atomic_optab><mode> (operands[0], operands[1],
+                                                            operands[2], operands[3]));
+    DONE;
+  })
+
+(define_insn "amo_atomic_fetch_<atomic_optab><mode>"
   [(set (match_operand:GPR 0 "register_operand" "=&r")
        (match_operand:GPR 1 "memory_operand" "+A"))
    (set (match_dup 1)
   [(set_attr "type" "atomic")
    (set (attr "length") (const_int 4))])
 
+(define_insn "lrsc_atomic_fetch_<atomic_optab><mode>"
+  [(set (match_operand:GPR 0 "register_operand" "=&r")
+       (match_operand:GPR 1 "memory_operand" "+A"))
+   (set (match_dup 1)
+       (unspec_volatile:GPR
+         [(any_atomic:GPR (match_dup 1)
+                    (match_operand:GPR 2 "reg_or_0_operand" "rJ"))
+          (match_operand:SI 3 "const_int_operand")] ;; model
+        UNSPEC_SYNC_OLD_OP))
+   (clobber (match_scratch:GPR 4 "=&r"))]        ;; tmp_1
+  "!TARGET_ZAAMO && TARGET_ZALRSC"
+  {
+    return "1:\;"
+          "lr.<amo>%I3\t%0, %1\;"
+          "<insn>\t%4, %0, %2\;"
+          "sc.<amo>%J3\t%4, %4, %1\;"
+          "bnez\t%4, 1b";
+  }
+  [(set_attr "type" "atomic")
+   (set (attr "length") (const_int 20))])
+
 (define_insn "subword_atomic_fetch_strong_<atomic_optab>"
   [(set (match_operand:SI 0 "register_operand" "=&r")             ;; old value at mem
        (match_operand:SI 1 "memory_operand" "+A"))                ;; mem location
   DONE;
 })
 
-(define_insn "atomic_exchange<mode>"
+(define_expand "atomic_exchange<mode>"
+  [(match_operand:GPR 0 "register_operand")  ;; old value at mem
+   (match_operand:GPR 1 "memory_operand")    ;; mem location
+   (match_operand:GPR 2 "register_operand")  ;; value for op
+   (match_operand:SI 3 "const_int_operand")] ;; model
+  "TARGET_ZAAMO || TARGET_ZALRSC"
+  {
+    if (TARGET_ZAAMO)
+      emit_insn (gen_amo_atomic_exchange<mode> (operands[0], operands[1],
+                                           operands[2], operands[3]));
+    else
+      emit_insn (gen_lrsc_atomic_exchange<mode> (operands[0], operands[1],
+                                            operands[2], operands[3]));
+    DONE;
+  })
+
+(define_insn "amo_atomic_exchange<mode>"
   [(set (match_operand:GPR 0 "register_operand" "=&r")
        (unspec_volatile:GPR
          [(match_operand:GPR 1 "memory_operand" "+A")
   [(set_attr "type" "atomic")
    (set (attr "length") (const_int 4))])
 
+(define_insn "lrsc_atomic_exchange<mode>"
+  [(set (match_operand:GPR 0 "register_operand" "=&r")
+       (unspec_volatile:GPR
+         [(match_operand:GPR 1 "memory_operand" "+A")
+          (match_operand:SI 3 "const_int_operand")] ;; model
+         UNSPEC_SYNC_EXCHANGE))
+   (set (match_dup 1)
+       (match_operand:GPR 2 "register_operand" "0"))
+   (clobber (match_scratch:GPR 4 "=&r"))]        ;; tmp_1
+  "!TARGET_ZAAMO && TARGET_ZALRSC"
+  {
+    return "1:\;"
+          "lr.<amo>%I3\t%4, %1\;"
+          "sc.<amo>%J3\t%0, %0, %1\;"
+          "bnez\t%0, 1b\;"
+          "mv\t%0, %4";
+  }
+  [(set_attr "type" "atomic")
+   (set (attr "length") (const_int 20))])
+
 (define_expand "atomic_exchange<mode>"
   [(match_operand:SHORT 0 "register_operand") ;; old value at mem
    (match_operand:SHORT 1 "memory_operand")   ;; mem location
   [(match_operand:QI 0 "register_operand" "")    ;; bool output
    (match_operand:QI 1 "memory_operand" "+A")    ;; memory
    (match_operand:SI 2 "const_int_operand" "")]  ;; model
-  "TARGET_ZALRSC"
+  "TARGET_ZAAMO || TARGET_ZALRSC"
 {
   /* We have no QImode atomics, so use the address LSBs to form a mask,
      then use an aligned SImode atomic.  */
   rtx shifted_set = gen_reg_rtx (SImode);
   riscv_lshift_subword (QImode, set, shift, &shifted_set);
 
-  emit_insn (gen_atomic_fetch_orsi (old, aligned_mem, shifted_set, model));
+  if (TARGET_ZAAMO)
+    emit_insn (gen_amo_atomic_fetch_orsi (old, aligned_mem, shifted_set, model));
+  else if (TARGET_ZALRSC)
+    emit_insn (gen_lrsc_atomic_fetch_orsi (old, aligned_mem, shifted_set, model));
 
   emit_move_insn (old, gen_rtx_ASHIFTRT (SImode, old,
                                         gen_lowpart (QImode, shift)));
diff --git a/gcc/testsuite/gcc.target/riscv/amo-zaamo-preferred-over-zalrsc.c b/gcc/testsuite/gcc.target/riscv/amo-zaamo-preferred-over-zalrsc.c
new file mode 100644 (file)
index 0000000..1c124c2
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* Ensure that AMO ops are emitted when both zalrsc and zaamo are enabled.  */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zalrsc } */
+/* { dg-add-options riscv_zaamo } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+** foo:
+**     amoadd\.w\tzero,a1,0\(a0\)
+**     ret
+*/
+void foo (int* bar, int* baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_RELAXED);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-zalrsc-amo-add-1.c b/gcc/testsuite/gcc.target/riscv/amo-zalrsc-amo-add-1.c
new file mode 100644 (file)
index 0000000..3fa7433
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* Verify that lrsc atomic op mappings match Table A.6's recommended mapping.  */
+/* { dg-options "-O3 -march=rv64id_zalrsc -mabi=lp64d" } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+** foo:
+**     1:
+**     lr.w\t[atx][0-9]+, 0\(a0\)
+**     add\t[atx][0-9]+, [atx][0-9]+, a1
+**     sc.w\t[atx][0-9]+, [atx][0-9]+, 0\(a0\)
+**      bnez\t[atx][0-9]+, 1b
+**     ret
+*/
+void foo (int* bar, int* baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_RELAXED);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-zalrsc-amo-add-2.c b/gcc/testsuite/gcc.target/riscv/amo-zalrsc-amo-add-2.c
new file mode 100644 (file)
index 0000000..af0a2d5
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* Verify that lrsc atomic op mappings match Table A.6's recommended mapping.  */
+/* { dg-options "-O3 -march=rv64id_zalrsc -mabi=lp64d" } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+** foo:
+**     1:
+**     lr.w.aq\t[atx][0-9]+, 0\(a0\)
+**     add\t[atx][0-9]+, [atx][0-9]+, a1
+**     sc.w\t[atx][0-9]+, [atx][0-9]+, 0\(a0\)
+**      bnez\t[atx][0-9]+, 1b
+**     ret
+*/
+void foo (int* bar, int* baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_ACQUIRE);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-zalrsc-amo-add-3.c b/gcc/testsuite/gcc.target/riscv/amo-zalrsc-amo-add-3.c
new file mode 100644 (file)
index 0000000..521869b
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* Verify that lrsc atomic op mappings match Table A.6's recommended mapping.  */
+/* { dg-options "-O3 -march=rv64id_zalrsc -mabi=lp64d" } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+** foo:
+**     1:
+**     lr.w\t[atx][0-9]+, 0\(a0\)
+**     add\t[atx][0-9]+, [atx][0-9]+, a1
+**     sc.w.rl\t[atx][0-9]+, [atx][0-9]+, 0\(a0\)
+**      bnez\t[atx][0-9]+, 1b
+**     ret
+*/
+void foo (int* bar, int* baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_RELEASE);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-zalrsc-amo-add-4.c b/gcc/testsuite/gcc.target/riscv/amo-zalrsc-amo-add-4.c
new file mode 100644 (file)
index 0000000..8b6e757
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* Verify that lrsc atomic op mappings match Table A.6's recommended mapping.  */
+/* { dg-options "-O3 -march=rv64id_zalrsc -mabi=lp64d" } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+** foo:
+**     1:
+**     lr.w.aq\t[atx][0-9]+, 0\(a0\)
+**     add\t[atx][0-9]+, [atx][0-9]+, a1
+**     sc.w.rl\t[atx][0-9]+, [atx][0-9]+, 0\(a0\)
+**      bnez\t[atx][0-9]+, 1b
+**     ret
+*/
+void foo (int* bar, int* baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_ACQ_REL);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-zalrsc-amo-add-5.c b/gcc/testsuite/gcc.target/riscv/amo-zalrsc-amo-add-5.c
new file mode 100644 (file)
index 0000000..0bdc47d
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* Verify that lrsc atomic op mappings match Table A.6's recommended mapping.  */
+/* { dg-options "-O3 -march=rv64id_zalrsc -mabi=lp64d" } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+** foo:
+**     1:
+**     lr.w.aqrl\t[atx][0-9]+, 0\(a0\)
+**     add\t[atx][0-9]+, [atx][0-9]+, a1
+**     sc.w.rl\t[atx][0-9]+, [atx][0-9]+, 0\(a0\)
+**      bnez\t[atx][0-9]+, 1b
+**     ret
+*/
+void foo (int* bar, int* baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_SEQ_CST);
+}