Update the ZC constraint for MIPSR6 to allow it to be used as the memory operand for implementations of atomic operations. Also switch the internal implementation of atomic operations to use ZC instead of ZR.
This fix accurately describes the memory constraints for the LL and SC instructions. An offset can therefore be used to access a data item (ie. %lo (<var>)) rather than always having to load the address into a register. Tested for mips32r2, mips32r6 and micromips. gcc/ * config/mips/constraints.md (ZC): Add support for R6 LL/SC offsets. (ZD): Update to use ISA_HAS_PREF_LL_SC_9BIT. * config/mips/mips.h (ISA_HAS_PREFETCH_9BIT): Rename to... (ISA_HAS_PREF_LL_SC_9BIT): ... this. New macro. * config/mips/sync.md (sync_compare_and_swap<mode>): Use ZC instead of ZR for the memory operand of LL/SC. (compare_and_swap_12, sync_add<mode>): Likewise. (sync_<optab>_12, sync_old_<optab>_12): Likewise. (sync_new_<optab>_12, sync_nand_12): Likewise. (sync_old_nand_12, sync_new_nand_12): Likewise. (sync_sub<mode>, sync_old_add<mode>): Likewise. (sync_old_sub<mode>, sync_new_add<mode>): Likewise. (sync_new_sub<mode>, sync_<optab><mode>): Likewise. (sync_old_<optab><mode>, sync_new_<optab><mode>"): Likewise. (sync_nand<mode>, sync_old_nand<mode>): Likewise. (sync_new_nand<mode>, sync_lock_test_and_set<mode>): Likewise. (test_and_set_12, atomic_compare_and_swap<mode>): Likewise. (atomic_exchange<mode>_llsc, atomic_fetch_add<mode>_llsc): Likewise. * doc/md.texi (ZC): Update description. OK to commit? Thanks, Matthew --- gcc/config/mips/constraints.md | 14 ++++++------ gcc/config/mips/mips.h | 4 ++-- gcc/config/mips/sync.md | 50 +++++++++++++++++++++--------------------- gcc/doc/md.texi | 8 +++---- 4 files changed, 37 insertions(+), 39 deletions(-) diff --git a/gcc/config/mips/constraints.md b/gcc/config/mips/constraints.md index 816880c..f5f257d 100644 --- a/gcc/config/mips/constraints.md +++ b/gcc/config/mips/constraints.md @@ -309,23 +309,23 @@ (define_constraint "Yx" (match_operand 0 "low_bitmask_operand")) (define_memory_constraint "ZC" - "When compiling microMIPS code, this constraint matches a memory operand - whose address is formed from a base register and a 12-bit offset. These - operands can be used for microMIPS instructions such as @code{ll} and - @code{sc}. When not compiling for microMIPS code, @code{ZC} is - equivalent to @code{R}." + "A memory operand whose address is formed by a base register and offset + that is suitable for use in instructions with the same addressing mode + as @code{ll} and @code{sc}." (and (match_code "mem") (if_then_else (match_test "TARGET_MICROMIPS") (match_test "umips_12bit_offset_address_p (XEXP (op, 0), mode)") - (match_test "mips_address_insns (XEXP (op, 0), mode, false)")))) + (if_then_else (match_test "ISA_HAS_PREF_LL_SC_9BIT") + (match_test "mips_9bit_offset_address_p (XEXP (op, 0), mode)") + (match_test "mips_address_insns (XEXP (op, 0), mode, false)"))))) (define_address_constraint "ZD" "An address suitable for a @code{prefetch} instruction, or for any other instruction with the same addressing mode as @code{prefetch}." (if_then_else (match_test "TARGET_MICROMIPS") (match_test "umips_12bit_offset_address_p (op, mode)") - (if_then_else (match_test "ISA_HAS_PREFETCH_9BIT") + (if_then_else (match_test "ISA_HAS_PREF_LL_SC_9BIT") (match_test "mips_9bit_offset_address_p (op, mode)") (match_test "mips_address_insns (op, mode, false)")))) diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index 9dad480..b608b17 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -1089,8 +1089,8 @@ struct mips_cpu_info { || mips_isa_rev >= 1) \ && !TARGET_MIPS16) -/* ISA has data prefetch with limited 9-bit displacement. */ -#define ISA_HAS_PREFETCH_9BIT (mips_isa_rev >= 6) +/* ISA has data prefetch, LL and SC with limited 9-bit displacement. */ +#define ISA_HAS_PREF_LL_SC_9BIT (mips_isa_rev >= 6) /* ISA has data indexed prefetch instructions. This controls use of 'prefx', along with TARGET_HARD_FLOAT and TARGET_DOUBLE_FLOAT. diff --git a/gcc/config/mips/sync.md b/gcc/config/mips/sync.md index cf6c05b..72d2fe4 100644 --- a/gcc/config/mips/sync.md +++ b/gcc/config/mips/sync.md @@ -59,7 +59,7 @@ (define_insn "*memory_barrier" ;; Can be removed in favor of atomic_compare_and_swap below. (define_insn "sync_compare_and_swap<mode>" [(set (match_operand:GPR 0 "register_operand" "=&d,&d") - (match_operand:GPR 1 "memory_operand" "+ZR,ZR")) + (match_operand:GPR 1 "memory_operand" "+ZC,ZC")) (set (match_dup 1) (unspec_volatile:GPR [(match_operand:GPR 2 "reg_or_0_operand" "dJ,dJ") (match_operand:GPR 3 "arith_operand" "I,d")] @@ -89,7 +89,7 @@ (define_expand "sync_compare_and_swap<mode>" ;; Helper insn for mips_expand_atomic_qihi. (define_insn "compare_and_swap_12" [(set (match_operand:SI 0 "register_operand" "=&d,&d") - (match_operand:SI 1 "memory_operand" "+ZR,ZR")) + (match_operand:SI 1 "memory_operand" "+ZC,ZC")) (set (match_dup 1) (unspec_volatile:SI [(match_operand:SI 2 "register_operand" "d,d") (match_operand:SI 3 "register_operand" "d,d") @@ -106,7 +106,7 @@ (define_insn "compare_and_swap_12" (set_attr "sync_insn1_op2" "5")]) (define_insn "sync_add<mode>" - [(set (match_operand:GPR 0 "memory_operand" "+ZR,ZR") + [(set (match_operand:GPR 0 "memory_operand" "+ZC,ZC") (unspec_volatile:GPR [(plus:GPR (match_dup 0) (match_operand:GPR 1 "arith_operand" "I,d"))] @@ -134,7 +134,7 @@ (define_expand "sync_<optab><mode>" ;; Helper insn for sync_<optab><mode> (define_insn "sync_<optab>_12" - [(set (match_operand:SI 0 "memory_operand" "+ZR") + [(set (match_operand:SI 0 "memory_operand" "+ZC") (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d") @@ -174,7 +174,7 @@ (define_expand "sync_old_<optab><mode>" ;; Helper insn for sync_old_<optab><mode> (define_insn "sync_old_<optab>_12" [(set (match_operand:SI 0 "register_operand" "=&d") - (match_operand:SI 1 "memory_operand" "+ZR")) + (match_operand:SI 1 "memory_operand" "+ZC")) (set (match_dup 1) (unspec_volatile:SI [(match_operand:SI 2 "register_operand" "d") @@ -217,7 +217,7 @@ (define_expand "sync_new_<optab><mode>" (define_insn "sync_new_<optab>_12" [(set (match_operand:SI 0 "register_operand" "=&d") (unspec_volatile:SI - [(match_operand:SI 1 "memory_operand" "+ZR") + [(match_operand:SI 1 "memory_operand" "+ZC") (match_operand:SI 2 "register_operand" "d") (match_operand:SI 3 "register_operand" "d") (atomic_hiqi_op:SI (match_dup 0) @@ -257,7 +257,7 @@ (define_expand "sync_nand<mode>" ;; Helper insn for sync_nand<mode> (define_insn "sync_nand_12" - [(set (match_operand:SI 0 "memory_operand" "+ZR") + [(set (match_operand:SI 0 "memory_operand" "+ZC") (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d") @@ -296,7 +296,7 @@ (define_expand "sync_old_nand<mode>" ;; Helper insn for sync_old_nand<mode> (define_insn "sync_old_nand_12" [(set (match_operand:SI 0 "register_operand" "=&d") - (match_operand:SI 1 "memory_operand" "+ZR")) + (match_operand:SI 1 "memory_operand" "+ZC")) (set (match_dup 1) (unspec_volatile:SI [(match_operand:SI 2 "register_operand" "d") @@ -337,7 +337,7 @@ (define_expand "sync_new_nand<mode>" (define_insn "sync_new_nand_12" [(set (match_operand:SI 0 "register_operand" "=&d") (unspec_volatile:SI - [(match_operand:SI 1 "memory_operand" "+ZR") + [(match_operand:SI 1 "memory_operand" "+ZC") (match_operand:SI 2 "register_operand" "d") (match_operand:SI 3 "register_operand" "d") (match_operand:SI 4 "reg_or_0_operand" "dJ")] @@ -360,7 +360,7 @@ (define_insn "sync_new_nand_12" (set_attr "sync_insn1_op2" "4")]) (define_insn "sync_sub<mode>" - [(set (match_operand:GPR 0 "memory_operand" "+ZR") + [(set (match_operand:GPR 0 "memory_operand" "+ZC") (unspec_volatile:GPR [(minus:GPR (match_dup 0) (match_operand:GPR 1 "register_operand" "d"))] @@ -374,7 +374,7 @@ (define_insn "sync_sub<mode>" ;; Can be removed in favor of atomic_fetch_add below. (define_insn "sync_old_add<mode>" [(set (match_operand:GPR 0 "register_operand" "=&d,&d") - (match_operand:GPR 1 "memory_operand" "+ZR,ZR")) + (match_operand:GPR 1 "memory_operand" "+ZC,ZC")) (set (match_dup 1) (unspec_volatile:GPR [(plus:GPR (match_dup 1) @@ -389,7 +389,7 @@ (define_insn "sync_old_add<mode>" (define_insn "sync_old_sub<mode>" [(set (match_operand:GPR 0 "register_operand" "=&d") - (match_operand:GPR 1 "memory_operand" "+ZR")) + (match_operand:GPR 1 "memory_operand" "+ZC")) (set (match_dup 1) (unspec_volatile:GPR [(minus:GPR (match_dup 1) @@ -404,7 +404,7 @@ (define_insn "sync_old_sub<mode>" (define_insn "sync_new_add<mode>" [(set (match_operand:GPR 0 "register_operand" "=&d,&d") - (plus:GPR (match_operand:GPR 1 "memory_operand" "+ZR,ZR") + (plus:GPR (match_operand:GPR 1 "memory_operand" "+ZC,ZC") (match_operand:GPR 2 "arith_operand" "I,d"))) (set (match_dup 1) (unspec_volatile:GPR @@ -420,7 +420,7 @@ (define_insn "sync_new_add<mode>" (define_insn "sync_new_sub<mode>" [(set (match_operand:GPR 0 "register_operand" "=&d") - (minus:GPR (match_operand:GPR 1 "memory_operand" "+ZR") + (minus:GPR (match_operand:GPR 1 "memory_operand" "+ZC") (match_operand:GPR 2 "register_operand" "d"))) (set (match_dup 1) (unspec_volatile:GPR @@ -435,7 +435,7 @@ (define_insn "sync_new_sub<mode>" (set_attr "sync_insn1_op2" "2")]) (define_insn "sync_<optab><mode>" - [(set (match_operand:GPR 0 "memory_operand" "+ZR,ZR") + [(set (match_operand:GPR 0 "memory_operand" "+ZC,ZC") (unspec_volatile:GPR [(fetchop_bit:GPR (match_operand:GPR 1 "uns_arith_operand" "K,d") (match_dup 0))] @@ -448,7 +448,7 @@ (define_insn "sync_<optab><mode>" (define_insn "sync_old_<optab><mode>" [(set (match_operand:GPR 0 "register_operand" "=&d,&d") - (match_operand:GPR 1 "memory_operand" "+ZR,ZR")) + (match_operand:GPR 1 "memory_operand" "+ZC,ZC")) (set (match_dup 1) (unspec_volatile:GPR [(fetchop_bit:GPR (match_operand:GPR 2 "uns_arith_operand" "K,d") @@ -463,7 +463,7 @@ (define_insn "sync_old_<optab><mode>" (define_insn "sync_new_<optab><mode>" [(set (match_operand:GPR 0 "register_operand" "=&d,&d") - (match_operand:GPR 1 "memory_operand" "+ZR,ZR")) + (match_operand:GPR 1 "memory_operand" "+ZC,ZC")) (set (match_dup 1) (unspec_volatile:GPR [(fetchop_bit:GPR (match_operand:GPR 2 "uns_arith_operand" "K,d") @@ -478,7 +478,7 @@ (define_insn "sync_new_<optab><mode>" (set_attr "sync_insn1_op2" "2")]) (define_insn "sync_nand<mode>" - [(set (match_operand:GPR 0 "memory_operand" "+ZR,ZR") + [(set (match_operand:GPR 0 "memory_operand" "+ZC,ZC") (unspec_volatile:GPR [(match_operand:GPR 1 "uns_arith_operand" "K,d")] UNSPEC_SYNC_OLD_OP))] "GENERATE_LL_SC" @@ -490,7 +490,7 @@ (define_insn "sync_nand<mode>" (define_insn "sync_old_nand<mode>" [(set (match_operand:GPR 0 "register_operand" "=&d,&d") - (match_operand:GPR 1 "memory_operand" "+ZR,ZR")) + (match_operand:GPR 1 "memory_operand" "+ZC,ZC")) (set (match_dup 1) (unspec_volatile:GPR [(match_operand:GPR 2 "uns_arith_operand" "K,d")] UNSPEC_SYNC_OLD_OP))] @@ -504,7 +504,7 @@ (define_insn "sync_old_nand<mode>" (define_insn "sync_new_nand<mode>" [(set (match_operand:GPR 0 "register_operand" "=&d,&d") - (match_operand:GPR 1 "memory_operand" "+ZR,ZR")) + (match_operand:GPR 1 "memory_operand" "+ZC,ZC")) (set (match_dup 1) (unspec_volatile:GPR [(match_operand:GPR 2 "uns_arith_operand" "K,d")] UNSPEC_SYNC_NEW_OP))] @@ -519,7 +519,7 @@ (define_insn "sync_new_nand<mode>" (define_insn "sync_lock_test_and_set<mode>" [(set (match_operand:GPR 0 "register_operand" "=&d,&d") - (match_operand:GPR 1 "memory_operand" "+ZR,ZR")) + (match_operand:GPR 1 "memory_operand" "+ZC,ZC")) (set (match_dup 1) (unspec_volatile:GPR [(match_operand:GPR 2 "arith_operand" "I,d")] UNSPEC_SYNC_EXCHANGE))] @@ -546,7 +546,7 @@ (define_expand "sync_lock_test_and_set<mode>" (define_insn "test_and_set_12" [(set (match_operand:SI 0 "register_operand" "=&d") - (match_operand:SI 1 "memory_operand" "+ZR")) + (match_operand:SI 1 "memory_operand" "+ZC")) (set (match_dup 1) (unspec_volatile:SI [(match_operand:SI 2 "register_operand" "d") (match_operand:SI 3 "register_operand" "d") @@ -576,7 +576,7 @@ (define_insn "atomic_compare_and_swap<mode>" ;; TODO: the obscuring unspec can be relaxed for permissive memory ;; models. ;; Same applies to other atomic_* patterns. - (unspec_volatile:GPR [(match_operand:GPR 2 "memory_operand" "+ZR,ZR") + (unspec_volatile:GPR [(match_operand:GPR 2 "memory_operand" "+ZC,ZC") (match_operand:GPR 3 "reg_or_0_operand" "dJ,dJ")] UNSPEC_ATOMIC_COMPARE_AND_SWAP)) (set (match_operand:GPR 1 "register_operand" "=&d,&d") @@ -629,7 +629,7 @@ (define_expand "atomic_exchange<mode>" (define_insn "atomic_exchange<mode>_llsc" [(set (match_operand:GPR 0 "register_operand" "=&d,&d") - (unspec_volatile:GPR [(match_operand:GPR 1 "memory_operand" "+ZR,ZR")] + (unspec_volatile:GPR [(match_operand:GPR 1 "memory_operand" "+ZC,ZC")] UNSPEC_ATOMIC_EXCHANGE)) (set (match_dup 1) (unspec_volatile:GPR [(match_operand:GPR 2 "arith_operand" "I,d")] @@ -684,7 +684,7 @@ (define_expand "atomic_fetch_add<mode>" (define_insn "atomic_fetch_add<mode>_llsc" [(set (match_operand:GPR 0 "register_operand" "=&d,&d") - (unspec_volatile:GPR [(match_operand:GPR 1 "memory_operand" "+ZR,ZR")] + (unspec_volatile:GPR [(match_operand:GPR 1 "memory_operand" "+ZC,ZC")] UNSPEC_ATOMIC_FETCH_OP)) (set (match_dup 1) (unspec_volatile:GPR diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 7f0426c..1ea39e2 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -2987,11 +2987,9 @@ Floating-point zero. An address that can be used in a non-macro load or store. @item ZC -When compiling microMIPS code, this constraint matches a memory operand -whose address is formed from a base register and a 12-bit offset. These -operands can be used for microMIPS instructions such as @code{ll} and -@code{sc}. When not compiling for microMIPS code, @code{ZC} is -equivalent to @code{R}. +A memory operand whose address is formed by a base register and offset +that is suitable for use in instructions with the same addressing mode +as @code{ll} and @code{sc}. @item ZD An address suitable for a @code{prefetch} instruction, or for any other -- 2.2.1