@@ -86,7 +86,24 @@
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)
@@ -98,7 +115,44 @@
[(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)
@@ -112,6 +166,27 @@
[(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
@@ -248,7 +323,23 @@
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")
@@ -261,6 +352,26 @@
[(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
@@ -516,7 +627,7 @@
[(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. */
@@ -537,7 +648,10 @@
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)));
new file mode 100644
@@ -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);
+}
new file mode 100644
@@ -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);
+}
new file mode 100644
@@ -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);
+}
new file mode 100644
@@ -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);
+}
new file mode 100644
@@ -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);
+}
new file mode 100644
@@ -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);
+}
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> --- Changes from v3: Added -mabi=lp64d to testcases. --- gcc/config/riscv/sync.md | 124 +++++++++++++++++- .../riscv/amo-zaamo-preferred-over-zalrsc.c | 17 +++ .../gcc.target/riscv/amo-zalrsc-amo-add-1.c | 19 +++ .../gcc.target/riscv/amo-zalrsc-amo-add-2.c | 19 +++ .../gcc.target/riscv/amo-zalrsc-amo-add-3.c | 19 +++ .../gcc.target/riscv/amo-zalrsc-amo-add-4.c | 19 +++ .../gcc.target/riscv/amo-zalrsc-amo-add-5.c | 19 +++ 7 files changed, 231 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/gcc.target/riscv/amo-zaamo-preferred-over-zalrsc.c create mode 100644 gcc/testsuite/gcc.target/riscv/amo-zalrsc-amo-add-1.c create mode 100644 gcc/testsuite/gcc.target/riscv/amo-zalrsc-amo-add-2.c create mode 100644 gcc/testsuite/gcc.target/riscv/amo-zalrsc-amo-add-3.c create mode 100644 gcc/testsuite/gcc.target/riscv/amo-zalrsc-amo-add-4.c create mode 100644 gcc/testsuite/gcc.target/riscv/amo-zalrsc-amo-add-5.c