[MIPS] Update the ZC constraint for MIPSR6 and use it

Matthew Fortune Matthew.Fortune@imgtec.com
Tue Jan 6 12:42:00 GMT 2015


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



More information about the Gcc-patches mailing list