diff options
author | Kito Cheng <kito.cheng@sifive.com> | 2024-02-28 16:01:52 +0800 |
---|---|---|
committer | Kito Cheng <kito.cheng@sifive.com> | 2024-02-29 11:05:21 +0800 |
commit | fd07a29e39f5347d6cef3e7042a32306f97a1719 (patch) | |
tree | 9d8de21d93e2ce4157969f8e10885e83fbb870e1 | |
parent | 5ff49272bf4eb6a030739cc24ba001f206305e08 (diff) | |
download | gcc-fd07a29e39f5347d6cef3e7042a32306f97a1719.zip gcc-fd07a29e39f5347d6cef3e7042a32306f97a1719.tar.gz gcc-fd07a29e39f5347d6cef3e7042a32306f97a1719.tar.bz2 |
RISC-V: Fix __atomic_compare_exchange with 32 bit value on RV64
atomic_compare_and_swapsi will use lr.w to do obtain the original value,
which sign extends to DI. RV64 only has DI comparisons, so we also need
to sign extend the expected value to DI as otherwise the comparison will
fail when the expected value has the 32nd bit set.
gcc/ChangeLog:
PR target/114130
* config/riscv/sync.md (atomic_compare_and_swap<mode>): Sign
extend the expected value if needed.
gcc/testsuite/ChangeLog:
* gcc.target/riscv/pr114130.c: New.
Reviewed-by: Palmer Dabbelt <palmer@rivosinc.com>
-rw-r--r-- | gcc/config/riscv/sync.md | 9 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/riscv/pr114130.c | 12 |
2 files changed, 21 insertions, 0 deletions
diff --git a/gcc/config/riscv/sync.md b/gcc/config/riscv/sync.md index 54bb0a6..6f0b5aa 100644 --- a/gcc/config/riscv/sync.md +++ b/gcc/config/riscv/sync.md @@ -353,6 +353,15 @@ (match_operand:SI 7 "const_int_operand" "")] ;; mod_f "TARGET_ATOMIC" { + if (word_mode != <MODE>mode && operands[3] != const0_rtx) + { + /* We don't have SI mode compare on RV64, so we need to make sure expected + value is sign-extended. */ + rtx tmp0 = gen_reg_rtx (word_mode); + emit_insn (gen_extend_insn (tmp0, operands[3], word_mode, <MODE>mode, 0)); + operands[3] = simplify_gen_subreg (<MODE>mode, tmp0, word_mode, 0); + } + emit_insn (gen_atomic_cas_value_strong<mode> (operands[1], operands[2], operands[3], operands[4], operands[6], operands[7])); diff --git a/gcc/testsuite/gcc.target/riscv/pr114130.c b/gcc/testsuite/gcc.target/riscv/pr114130.c new file mode 100644 index 0000000..647e27d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/pr114130.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc -mabi=lp64" } */ +#include <stdint-gcc.h> + +void foo(uint32_t *p) { + uintptr_t x = *(uintptr_t *)p; + uint32_t e = !p ? 0 : (uintptr_t)p >> 1; + uint32_t d = (uintptr_t)x; + __atomic_compare_exchange(p, &e, &d, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED); +} + +/* { dg-final { scan-assembler-bound {sext.w\t} >= 1 } } */ |