diff options
author | krebbel <krebbel@138bc75d-0d04-0410-961f-82ee72b054a4> | 2017-04-25 07:37:50 +0000 |
---|---|---|
committer | krebbel <krebbel@138bc75d-0d04-0410-961f-82ee72b054a4> | 2017-04-25 07:37:50 +0000 |
commit | d90d26d883c38333e6780661d87c50d97e05c07f (patch) | |
tree | 28e95dc2ae7b20ece9816a634395a3f623677a51 /gcc/config/s390/s390.md | |
parent | 35f0c8ba25302315fd803f3ed1087750bdd4841a (diff) | |
download | gcc-d90d26d883c38333e6780661d87c50d97e05c07f.tar.gz |
S/390: PR80080: Optimize atomic patterns.
The attached patch optimizes the atomic_exchange and atomic_compare
patterns on s390 and s390x (mostly limited to SImode and DImode).
Among general optimizaation, the changes fix most of the problems
reported in PR 80080:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80080
gcc/ChangeLog:
2017-04-25 Dominik Vogt <vogt@linux.vnet.ibm.com>
PR target/80080
* s390-protos.h (s390_expand_cs_hqi): Removed.
(s390_expand_cs, s390_expand_atomic_exchange_tdsi): New prototypes.
* config/s390/s390.c (s390_emit_compare_and_swap): Handle all integer
modes as well as CCZ1mode and CCZmode.
(s390_expand_atomic_exchange_tdsi, s390_expand_atomic): Adapt to new
signature of s390_emit_compare_and_swap.
(s390_expand_cs_hqi): Likewise, make static.
(s390_expand_cs_tdsi): Generate an explicit compare before trying
compare-and-swap, in some cases.
(s390_expand_cs): Wrapper function.
(s390_expand_atomic_exchange_tdsi): New backend specific expander for
atomic_exchange.
(s390_match_ccmode_set): Allow CCZmode <-> CCZ1 mode.
* config/s390/s390.md ("atomic_compare_and_swap<mode>"): Merge the
patterns for small and large integers. Forbid symref memory operands.
Move expander to s390.c. Require cc register.
("atomic_compare_and_swap<DGPR:mode><CCZZ1:mode>_internal")
("*atomic_compare_and_swap<TDI:mode><CCZZ1:mode>_1")
("*atomic_compare_and_swapdi<CCZZ1:mode>_2")
("*atomic_compare_and_swapsi<CCZZ1:mode>_3"): Use s_operand to forbid
symref memory operands. Remove CC mode and call s390_match_ccmode
instead.
("atomic_exchange<mode>"): Allow and implement all integer modes.
gcc/testsuite/ChangeLog:
2017-04-25 Dominik Vogt <vogt@linux.vnet.ibm.com>
PR target/80080
* gcc.target/s390/md/atomic_compare_exchange-1.c: New test.
* gcc.target/s390/md/atomic_compare_exchange-1.inc: New test.
* gcc.target/s390/md/atomic_exchange-1.inc: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@247132 138bc75d-0d04-0410-961f-82ee72b054a4
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; }) |