diff options
author | Adrian Straetling <straetling@de.ibm.com> | 2005-06-07 16:35:27 +0000 |
---|---|---|
committer | Ulrich Weigand <uweigand@gcc.gnu.org> | 2005-06-07 16:35:27 +0000 |
commit | e0374221d9a8296937d7943791de7267a9d7dafa (patch) | |
tree | bb3a25e110cedc41afc38795fab064c14523fc41 /gcc | |
parent | b6e7e9af0465df9134110217990127a47bc5f5c5 (diff) | |
download | gcc-e0374221d9a8296937d7943791de7267a9d7dafa.zip gcc-e0374221d9a8296937d7943791de7267a9d7dafa.tar.gz gcc-e0374221d9a8296937d7943791de7267a9d7dafa.tar.bz2 |
s390.md: ("UNSPECV_MB", "UNSPECV_CAS"): New constants.
2005-06-07 Adrian Straetling <straetling@de.ibm.com>
gcc/ChangeLog:
* config/s390/s390.md: ("UNSPECV_MB", "UNSPECV_CAS"): New constants.
("type"): Add "sem" to 'type' attribute.
("memory_barrier", "*memory_barrier", "sync_compare_and_swapdi",
"sync_compare_and_swapsi", "sync_compare_and_swap_ccdi",
"sync_compare_and_swap_ccsi", "*sync_compare_and_swap_ccdi",
"*sync_compare_and_swap_ccsi"): New patterns.
* config/s390/2064.md: ("z_sem"): New insn_reservation.
* config/s390/2084.md: ("x_sem"): New insn_reservation.
* config/s390/s390.c: (s390_compare_emitted): New global variable.
(s390_emit_compare): Do not emit comparison again after cas.
* config/s390/s390.h (s390_compare_emitted): Declare.
libstdc++/ChangeLog:
* config/cpu/s390/atomicity.h: (__exchange_and_add,
__atomic_add): Use the builtins for atomic memory operations.
From-SVN: r100711
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/config/s390/2064.md | 5 | ||||
-rw-r--r-- | gcc/config/s390/2084.md | 5 | ||||
-rw-r--r-- | gcc/config/s390/s390.c | 21 | ||||
-rw-r--r-- | gcc/config/s390/s390.h | 2 | ||||
-rw-r--r-- | gcc/config/s390/s390.md | 86 |
6 files changed, 128 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9e99ca6..6796d23 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2005-06-07 Adrian Straetling <straetling@de.ibm.com> + + * config/s390/s390.md: ("UNSPECV_MB", "UNSPECV_CAS"): New constants. + ("type"): Add "sem" to 'type' attribute. + ("memory_barrier", "*memory_barrier", "sync_compare_and_swapdi", + "sync_compare_and_swapsi", "sync_compare_and_swap_ccdi", + "sync_compare_and_swap_ccsi", "*sync_compare_and_swap_ccdi", + "*sync_compare_and_swap_ccsi"): New patterns. + * config/s390/2064.md: ("z_sem"): New insn_reservation. + * config/s390/2084.md: ("x_sem"): New insn_reservation. + * config/s390/s390.c: (s390_compare_emitted): New global variable. + (s390_emit_compare): Do not emit comparison again after cas. + * config/s390/s390.h (s390_compare_emitted): Declare. + 2005-06-07 Kazu Hirata <kazu@codesourcery.com> * sbitmap.h (sbitmap_iterator, sbitmap_iter_init, diff --git a/gcc/config/s390/2064.md b/gcc/config/s390/2064.md index 04564eb..4c757ac 100644 --- a/gcc/config/s390/2064.md +++ b/gcc/config/s390/2064.md @@ -67,6 +67,11 @@ (eq_attr "type" "store")) "z_e1,z_wr") +(define_insn_reservation "z_sem" 2 + (and (eq_attr "cpu" "z900,g5,g6") + (eq_attr "type" "sem")) + "z_e1*2,z_wr") + (define_insn_reservation "z_call" 5 (and (eq_attr "cpu" "z900,g5,g6") (eq_attr "type" "jsr")) diff --git a/gcc/config/s390/2084.md b/gcc/config/s390/2084.md index 05681c5..ca106c0 100644 --- a/gcc/config/s390/2084.md +++ b/gcc/config/s390/2084.md @@ -123,6 +123,11 @@ (eq_attr "type" "idiv")) "x-e1-np*10,x-wr-np") +(define_insn_reservation "x_sem" 17 + (and (eq_attr "cpu" "z990") + (eq_attr "type" "sem")) + "x-e1-np+x-mem,x-e1-np*16,x-wr-st") + ;; ;; Multicycle insns ;; diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 354f55e..54661ed 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -163,6 +163,10 @@ static int s390_sr_alias_set = 0; emitted. */ rtx s390_compare_op0, s390_compare_op1; +/* Save the result of a compare_and_swap until the branch or scc is + emitted. */ +rtx s390_compare_emitted = NULL_RTX; + /* Structure used to hold the components of a S/390 memory address. A legitimate address on S/390 is of the general form @@ -609,10 +613,21 @@ rtx s390_emit_compare (enum rtx_code code, rtx op0, rtx op1) { enum machine_mode mode = s390_select_ccmode (code, op0, op1); - rtx cc = gen_rtx_REG (mode, CC_REGNUM); + rtx ret = NULL_RTX; - emit_insn (gen_rtx_SET (VOIDmode, cc, gen_rtx_COMPARE (mode, op0, op1))); - return gen_rtx_fmt_ee (code, VOIDmode, cc, const0_rtx); + /* Do not output a redundant compare instruction if a compare_and_swap + pattern already computed the result and the machine modes match. */ + if (s390_compare_emitted && GET_MODE (s390_compare_emitted) == mode) + ret = gen_rtx_fmt_ee (code, VOIDmode, s390_compare_emitted, const0_rtx); + else + { + rtx cc = gen_rtx_REG (mode, CC_REGNUM); + + emit_insn (gen_rtx_SET (VOIDmode, cc, gen_rtx_COMPARE (mode, op0, op1))); + ret = gen_rtx_fmt_ee (code, VOIDmode, cc, const0_rtx); + } + s390_compare_emitted = NULL_RTX; + return ret; } /* Emit a jump instruction to TARGET. If COND is NULL_RTX, emit an diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h index 84d0353..f04f138 100644 --- a/gcc/config/s390/s390.h +++ b/gcc/config/s390/s390.h @@ -799,7 +799,7 @@ do { \ /* Define the information needed to generate branch and scc insns. This is stored from the compare operation. Note that we can't use "rtx" here since it hasn't been defined! */ -extern struct rtx_def *s390_compare_op0, *s390_compare_op1; +extern struct rtx_def *s390_compare_op0, *s390_compare_op1, *s390_compare_emitted; /* Relative costs of operations. */ diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 93f805e..34ecc7c 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -146,6 +146,10 @@ ; TLS support (UNSPECV_SET_TP 500) + + ; Atomic Support + (UNSPECV_MB 700) + (UNSPECV_CAS 701) ]) ;; @@ -177,7 +181,7 @@ ;; Instruction type attribute used for scheduling. (define_attr "type" "none,integer,load,lr,la,larl,lm,stm, - cs,vs,store,idiv, + cs,vs,store,sem,idiv, imulhi,imulsi,imuldi, branch,jsr,fsimpdf,fsimpsf, floaddf,floadsf,fstoredf,fstoresf, @@ -6692,6 +6696,86 @@ (set_attr "atype" "agen")]) ;; +;;- Atomic operations +;; + +; +; memory barrier pattern. +; + +(define_expand "memory_barrier" + [(set (mem:BLK (match_dup 0)) + (unspec_volatile:BLK [(mem:BLK (match_dup 0))] UNSPECV_MB))] + "" +{ + operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (DImode)); + MEM_VOLATILE_P (operands[0]) = 1; +}) + +(define_insn "*memory_barrier" + [(set (match_operand:BLK 0 "" "") + (unspec_volatile:BLK [(match_operand:BLK 1 "" "")] UNSPECV_MB))] + "" + "bcr\t15,0" + [(set_attr "op_type" "RR")]) + +; +; compare and swap patterns. +; + +(define_insn "sync_compare_and_swap<mode>" + [(set (match_operand:GPR 0 "register_operand" "=r") + (match_operand:GPR 1 "memory_operand" "+Q")) + (set (match_dup 1) + (unspec_volatile:GPR + [(match_dup 1) + (match_operand:GPR 2 "register_operand" "0") + (match_operand:GPR 3 "register_operand" "r")] + UNSPECV_CAS)) + (clobber (reg:CC CC_REGNUM))] + "" + "cs<g>\t%0,%3,%S1" + [(set_attr "op_type" "RS<E>") + (set_attr "type" "sem")]) + +(define_expand "sync_compare_and_swap_cc<mode>" + [(parallel + [(set (match_operand:GPR 0 "register_operand" "") + (match_operand:GPR 1 "memory_operand" "")) + (set (match_dup 1) + (unspec_volatile:GPR + [(match_dup 1) + (match_operand:GPR 2 "register_operand" "") + (match_operand:GPR 3 "register_operand" "")] + UNSPECV_CAS)) + (set (match_dup 4) + (compare:CCZ (match_dup 1) (match_dup 2)))])] + "" +{ + operands[4] = gen_rtx_REG (CCZmode, CC_REGNUM); + s390_compare_op0 = operands[1]; + s390_compare_op1 = operands[2]; + s390_compare_emitted = operands[4]; +}) + +(define_insn "*sync_compare_and_swap_cc<mode>" + [(set (match_operand:GPR 0 "register_operand" "=r") + (match_operand:GPR 1 "memory_operand" "+Q")) + (set (match_dup 1) + (unspec_volatile:GPR + [(match_dup 1) + (match_operand:GPR 2 "register_operand" "0") + (match_operand:GPR 3 "register_operand" "r")] + UNSPECV_CAS)) + (set (reg:CCZ CC_REGNUM) + (compare:CCZ (match_dup 1) (match_dup 2)))] + "" + "cs<g>\t%0,%3,%S1" + [(set_attr "op_type" "RS<E>") + (set_attr "type" "sem")]) + + +;; ;;- Miscellaneous instructions. ;; |