diff options
Diffstat (limited to 'gcc/config/s390/s390.md')
-rw-r--r-- | gcc/config/s390/s390.md | 110 |
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; }) |