Atomic instructions require zero-offset memory addresses.
If we allow all addresses, the nonzero-offset addresses will
be prepared in an extra register in an extra instruction before
the actual atomic instruction.
This patch introduces the predicate "riscv_sync_memory_operand",
which restricts the memory operand to be suitable for atomic
instructions.
gcc/
PR 100266
* config/riscv/sync.md (riscv_sync_memory_operand): New.
* config/riscv/sync.md (riscv_load_reserved): Use new predicate.
* config/riscv/sync.md (riscv_store_conditional): Likewise.
* config/riscv/sync.md (atomic_<atomic_optab>): Likewise.
* config/riscv/sync.md (atomic_fetch_<atomic_optab>): Likewise.
* config/riscv/sync.md (atomic_exchange): Likewise.
* config/riscv/sync.md (atomic_compare_and_swap): Likewise.
---
gcc/config/riscv/sync.md | 34 +++++++++++++++++++---------------
1 file changed, 19 insertions(+), 15 deletions(-)
diff --git a/gcc/config/riscv/sync.md b/gcc/config/riscv/sync.md
index 66548bf891b..8f184d8bbb4 100644
--- a/gcc/config/riscv/sync.md
+++ b/gcc/config/riscv/sync.md
@@ -30,6 +30,10 @@ (define_c_enum "unspec" [
UNSPEC_STORE_CONDITIONAL
])
+(define_predicate "riscv_sync_memory_operand"
+ (and (match_operand 0 "memory_operand")
+ (match_code "reg" "0")))
+
(define_code_iterator any_atomic [plus ior xor and])
(define_code_attr atomic_optab
[(plus "add") (ior "or") (xor "xor") (and "and")])
@@ -118,7 +122,7 @@ (define_expand "atomic_store<mode>"
(define_insn "@riscv_load_reserved<mode>"
[(set (match_operand:GPR 0 "register_operand" "=r")
(unspec_volatile:GPR
- [(match_operand:GPR 1 "memory_operand" "A")
+ [(match_operand:GPR 1 "riscv_sync_memory_operand" "A")
(match_operand:SI 2 "const_int_operand")] ;; model
UNSPEC_LOAD_RESERVED))]
"TARGET_ATOMIC"
@@ -133,7 +137,7 @@ (define_insn "riscv_load_reserved"
[(set (match_operand:DI 0 "register_operand" "=r")
(sign_extend:DI
(unspec_volatile:SI
- [(match_operand:SI 1 "memory_operand" "A")
+ [(match_operand:SI 1 "riscv_sync_memory_operand" "A")
(match_operand:SI 2 "const_int_operand")] ;; model
UNSPEC_LOAD_RESERVED)))]
"TARGET_ATOMIC && TARGET_64BIT"
@@ -143,7 +147,7 @@ (define_insn "riscv_load_reserved"
(define_insn "@riscv_store_conditional<mode>"
[(set (match_operand:GPR 0 "register_operand" "=&r")
(unspec_volatile:GPR [(const_int 0)] UNSPEC_STORE_CONDITIONAL))
- (set (match_operand:GPR 1 "memory_operand" "=A")
+ (set (match_operand:GPR 1 "riscv_sync_memory_operand" "=A")
(unspec_volatile:GPR
[(match_operand:GPR 2 "reg_or_0_operand" "rJ")
(match_operand:SI 3 "const_int_operand")] ;; model
@@ -162,7 +166,7 @@ (define_insn "riscv_store_conditional"
[(set (match_operand:DI 0 "register_operand" "=&r")
(sign_extend:DI
(unspec_volatile:SI [(const_int 0)] UNSPEC_STORE_CONDITIONAL)))
- (set (match_operand:SI 1 "memory_operand" "=A")
+ (set (match_operand:SI 1 "riscv_sync_memory_operand" "=A")
(unspec_volatile:SI
[(match_operand:SI 2 "reg_or_0_operand" "rJ")
(match_operand:SI 3 "const_int_operand")] ;; model
@@ -172,7 +176,7 @@ (define_insn "riscv_store_conditional"
)
(define_insn "atomic_<atomic_optab><mode>"
- [(set (match_operand:GPR 0 "memory_operand" "+A")
+ [(set (match_operand:GPR 0 "riscv_sync_memory_operand" "+A")
(unspec_volatile:GPR
[(any_atomic:GPR (match_dup 0)
(match_operand:GPR 1 "reg_or_0_operand" "rJ"))
@@ -184,7 +188,7 @@ (define_insn "atomic_<atomic_optab><mode>"
(define_insn "atomic_fetch_<atomic_optab><mode>"
[(set (match_operand:GPR 0 "register_operand" "=&r")
- (match_operand:GPR 1 "memory_operand" "+A"))
+ (match_operand:GPR 1 "riscv_sync_memory_operand" "+A"))
(set (match_dup 1)
(unspec_volatile:GPR
[(any_atomic:GPR (match_dup 1)
@@ -198,7 +202,7 @@ (define_insn "atomic_fetch_<atomic_optab><mode>"
(define_insn "atomic_exchange<mode>"
[(set (match_operand:GPR 0 "register_operand" "=&r")
(unspec_volatile:GPR
- [(match_operand:GPR 1 "memory_operand" "+A")
+ [(match_operand:GPR 1 "riscv_sync_memory_operand" "+A")
(match_operand:SI 3 "const_int_operand")] ;; model
UNSPEC_SYNC_EXCHANGE))
(set (match_dup 1)
@@ -222,14 +226,14 @@ (define_insn "atomic_cas_value_strong<mode>"
[(set (attr "length") (const_int 20))])
(define_expand "atomic_compare_and_swap<mode>"
- [(match_operand:SI 0 "register_operand" "") ;; bool output
- (match_operand:GPR 1 "register_operand" "") ;; val output
- (match_operand:GPR 2 "memory_operand" "") ;; memory
- (match_operand:GPR 3 "reg_or_0_operand" "") ;; expected value
- (match_operand:GPR 4 "reg_or_0_operand" "") ;; desired value
- (match_operand:SI 5 "const_int_operand" "") ;; is_weak
- (match_operand:SI 6 "const_int_operand" "") ;; mod_s
- (match_operand:SI 7 "const_int_operand" "")] ;; mod_f
+ [(match_operand:SI 0 "register_operand" "") ;; bool output
+ (match_operand:GPR 1 "register_operand" "") ;; val output
+ (match_operand:GPR 2 "riscv_sync_memory_operand" "") ;; memory
+ (match_operand:GPR 3 "reg_or_0_operand" "") ;; expected value
+ (match_operand:GPR 4 "reg_or_0_operand" "") ;; desired value
+ (match_operand:SI 5 "const_int_operand" "") ;; is_weak
+ (match_operand:SI 6 "const_int_operand" "") ;; mod_s
+ (match_operand:SI 7 "const_int_operand" "")] ;; mod_f
"TARGET_ATOMIC"
{
emit_insn (gen_atomic_cas_value_strong<mode> (operands[1], operands[2],
--
2.35.3