summaryrefslogtreecommitdiff
path: root/gcc/config/s390/s390.md
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/s390/s390.md')
-rw-r--r--gcc/config/s390/s390.md110
1 files changed, 47 insertions, 63 deletions
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 9baafccdf5a..8a700edab94 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -10230,83 +10230,56 @@
(define_expand "atomic_compare_and_swap<mode>"
[(match_operand:SI 0 "register_operand") ;; bool success output
- (match_operand:DGPR 1 "nonimmediate_operand");; oldval output
- (match_operand:DGPR 2 "memory_operand") ;; memory
- (match_operand:DGPR 3 "register_operand") ;; expected intput
- (match_operand:DGPR 4 "register_operand") ;; newval intput
+ (match_operand:DINT 1 "nonimmediate_operand");; oldval output
+ (match_operand:DINT 2 "s_operand") ;; memory
+ (match_operand:DINT 3 "general_operand") ;; expected intput
+ (match_operand:DINT 4 "general_operand") ;; newval intput
(match_operand:SI 5 "const_int_operand") ;; is_weak
(match_operand:SI 6 "const_int_operand") ;; success model
(match_operand:SI 7 "const_int_operand")] ;; failure model
""
{
- rtx cc, cmp, output = operands[1];
-
- if (!register_operand (output, <MODE>mode))
- output = gen_reg_rtx (<MODE>mode);
-
- if (MEM_ALIGN (operands[2]) < GET_MODE_BITSIZE (GET_MODE (operands[2])))
+ if (GET_MODE_BITSIZE (<MODE>mode) >= 16
+ && GET_MODE_BITSIZE (<MODE>mode) > MEM_ALIGN (operands[2]))
FAIL;
- emit_insn (gen_atomic_compare_and_swap<mode>_internal
- (output, operands[2], operands[3], operands[4]));
-
- /* We deliberately accept non-register operands in the predicate
- to ensure the write back to the output operand happens *before*
- the store-flags code below. This makes it easier for combine
- to merge the store-flags code with a potential test-and-branch
- pattern following (immediately!) afterwards. */
- if (output != operands[1])
- emit_move_insn (operands[1], output);
-
- cc = gen_rtx_REG (CCZ1mode, CC_REGNUM);
- cmp = gen_rtx_EQ (SImode, cc, const0_rtx);
- emit_insn (gen_cstorecc4 (operands[0], cmp, cc, const0_rtx));
- DONE;
-})
-
-(define_expand "atomic_compare_and_swap<mode>"
- [(match_operand:SI 0 "register_operand") ;; bool success output
- (match_operand:HQI 1 "nonimmediate_operand") ;; oldval output
- (match_operand:HQI 2 "memory_operand") ;; memory
- (match_operand:HQI 3 "general_operand") ;; expected intput
- (match_operand:HQI 4 "general_operand") ;; newval intput
- (match_operand:SI 5 "const_int_operand") ;; is_weak
- (match_operand:SI 6 "const_int_operand") ;; success model
- (match_operand:SI 7 "const_int_operand")] ;; failure model
- ""
-{
- s390_expand_cs_hqi (<MODE>mode, operands[0], operands[1], operands[2],
- operands[3], operands[4], INTVAL (operands[5]));
- DONE;
-})
+ s390_expand_cs (<MODE>mode, operands[0], operands[1], operands[2],
+ operands[3], operands[4], INTVAL (operands[5]));
+ DONE;})
(define_expand "atomic_compare_and_swap<mode>_internal"
[(parallel
[(set (match_operand:DGPR 0 "register_operand")
- (match_operand:DGPR 1 "memory_operand"))
+ (match_operand:DGPR 1 "s_operand"))
(set (match_dup 1)
(unspec_volatile:DGPR
[(match_dup 1)
(match_operand:DGPR 2 "register_operand")
(match_operand:DGPR 3 "register_operand")]
UNSPECV_CAS))
- (set (reg:CCZ1 CC_REGNUM)
- (compare:CCZ1 (match_dup 1) (match_dup 2)))])]
- "")
+ (set (match_operand 4 "cc_reg_operand")
+ (match_dup 5))])]
+ "GET_MODE (operands[4]) == CCZmode
+ || GET_MODE (operands[4]) == CCZ1mode"
+{
+ operands[5]
+ = gen_rtx_COMPARE (GET_MODE (operands[4]), operands[1], operands[2]);
+})
; cdsg, csg
(define_insn "*atomic_compare_and_swap<mode>_1"
[(set (match_operand:TDI 0 "register_operand" "=r")
- (match_operand:TDI 1 "memory_operand" "+S"))
+ (match_operand:TDI 1 "s_operand" "+S"))
(set (match_dup 1)
(unspec_volatile:TDI
[(match_dup 1)
(match_operand:TDI 2 "register_operand" "0")
(match_operand:TDI 3 "register_operand" "r")]
UNSPECV_CAS))
- (set (reg:CCZ1 CC_REGNUM)
- (compare:CCZ1 (match_dup 1) (match_dup 2)))]
- "TARGET_ZARCH"
+ (set (reg CC_REGNUM)
+ (compare (match_dup 1) (match_dup 2)))]
+ "TARGET_ZARCH
+ && s390_match_ccmode (insn, CCZ1mode)"
"c<td>sg\t%0,%3,%S1"
[(set_attr "op_type" "RSY")
(set_attr "type" "sem")])
@@ -10314,16 +10287,17 @@
; cds, cdsy
(define_insn "*atomic_compare_and_swapdi_2"
[(set (match_operand:DI 0 "register_operand" "=r,r")
- (match_operand:DI 1 "memory_operand" "+Q,S"))
+ (match_operand:DI 1 "s_operand" "+Q,S"))
(set (match_dup 1)
(unspec_volatile:DI
[(match_dup 1)
(match_operand:DI 2 "register_operand" "0,0")
(match_operand:DI 3 "register_operand" "r,r")]
UNSPECV_CAS))
- (set (reg:CCZ1 CC_REGNUM)
- (compare:CCZ1 (match_dup 1) (match_dup 2)))]
- "!TARGET_ZARCH"
+ (set (reg CC_REGNUM)
+ (compare (match_dup 1) (match_dup 2)))]
+ "!TARGET_ZARCH
+ && s390_match_ccmode (insn, CCZ1mode)"
"@
cds\t%0,%3,%S1
cdsy\t%0,%3,%S1"
@@ -10334,16 +10308,16 @@
; cs, csy
(define_insn "*atomic_compare_and_swapsi_3"
[(set (match_operand:SI 0 "register_operand" "=r,r")
- (match_operand:SI 1 "memory_operand" "+Q,S"))
+ (match_operand:SI 1 "s_operand" "+Q,S"))
(set (match_dup 1)
(unspec_volatile:SI
[(match_dup 1)
(match_operand:SI 2 "register_operand" "0,0")
(match_operand:SI 3 "register_operand" "r,r")]
UNSPECV_CAS))
- (set (reg:CCZ1 CC_REGNUM)
- (compare:CCZ1 (match_dup 1) (match_dup 2)))]
- ""
+ (set (reg CC_REGNUM)
+ (compare (match_dup 1) (match_dup 2)))]
+ "s390_match_ccmode (insn, CCZ1mode)"
"@
cs\t%0,%3,%S1
csy\t%0,%3,%S1"
@@ -10430,15 +10404,25 @@
DONE;
})
+;; Pattern to implement atomic_exchange with a compare-and-swap loop. The code
+;; generated by the middleend is not good.
(define_expand "atomic_exchange<mode>"
- [(match_operand:HQI 0 "register_operand") ;; val out
- (match_operand:HQI 1 "memory_operand") ;; memory
- (match_operand:HQI 2 "general_operand") ;; val in
+ [(match_operand:DINT 0 "register_operand") ;; val out
+ (match_operand:DINT 1 "s_operand") ;; memory
+ (match_operand:DINT 2 "general_operand") ;; val in
(match_operand:SI 3 "const_int_operand")] ;; model
""
{
- s390_expand_atomic (<MODE>mode, SET, operands[0], operands[1],
- operands[2], false);
+ if (<MODE>mode != QImode
+ && MEM_ALIGN (operands[1]) < GET_MODE_BITSIZE (<MODE>mode))
+ FAIL;
+ if (<MODE>mode == HImode || <MODE>mode == QImode)
+ s390_expand_atomic (<MODE>mode, SET, operands[0], operands[1], operands[2],
+ false);
+ else if (<MODE>mode == SImode || TARGET_ZARCH)
+ s390_expand_atomic_exchange_tdsi (operands[0], operands[1], operands[2]);
+ else
+ FAIL;
DONE;
})