RISC-V: Add Zalrsc amo-op patterns

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>
This commit is contained in:
Patrick O'Neill 2024-02-07 16:30:30 -08:00
parent 0fea902b1b
commit 1588983be6
No known key found for this signature in database
GPG key ID: A021A255BA0CDD04
7 changed files with 231 additions and 5 deletions

View file

@ -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)));

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);
}