From: Adrian Straetling Date: Tue, 7 Jun 2005 16:35:27 +0000 (+0000) Subject: s390.md: ("UNSPECV_MB", "UNSPECV_CAS"): New constants. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e0374221d9a8296937d7943791de7267a9d7dafa;p=gcc.git s390.md: ("UNSPECV_MB", "UNSPECV_CAS"): New constants. 2005-06-07 Adrian Straetling 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9e99ca669b7..6796d23fee1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2005-06-07 Adrian Straetling + + * 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 * sbitmap.h (sbitmap_iterator, sbitmap_iter_init, diff --git a/gcc/config/s390/2064.md b/gcc/config/s390/2064.md index 04564eb86f3..4c757acf1ef 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 05681c5b9dc..ca106c0f680 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 354f55e26fb..54661eddbc6 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 84d035357b7..f04f1387f48 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 93f805ed7f9..34ecc7ccd60 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, @@ -6691,6 +6695,86 @@ (set_attr "type" "jsr") (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" + [(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\t%0,%3,%S1" + [(set_attr "op_type" "RS") + (set_attr "type" "sem")]) + +(define_expand "sync_compare_and_swap_cc" + [(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" + [(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\t%0,%3,%S1" + [(set_attr "op_type" "RS") + (set_attr "type" "sem")]) + + ;; ;;- Miscellaneous instructions. ;; diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 3522320468d..37f3fc3a782 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,8 @@ +2005-06-07 Adrian Straetling + + * config/cpu/s390/atomicity.h: (__exchange_and_add, + __atomic_add): Use the builtins for atomic memory operations. + 2005-06-06 Paolo Carlini PR libstdc++/21770 (cont: __gnu_debug::string) diff --git a/libstdc++-v3/config/cpu/s390/atomicity.h b/libstdc++-v3/config/cpu/s390/atomicity.h index cf903b321f4..5a235940c8c 100644 --- a/libstdc++-v3/config/cpu/s390/atomicity.h +++ b/libstdc++-v3/config/cpu/s390/atomicity.h @@ -34,22 +34,10 @@ namespace __gnu_cxx _Atomic_word __attribute__ ((__unused__)) __exchange_and_add(volatile _Atomic_word* __mem, int __val) - { - register _Atomic_word __old_val, __new_val; - - __asm__ __volatile__ (" l %0,0(%3)\n" - "0: lr %1,%0\n" - " ar %1,%4\n" - " cs %0,%1,0(%3)\n" - " jl 0b" - : "=&d" (__old_val), "=&d" (__new_val), "=m" (*__mem) - : "a" (__mem), "d" (__val), "m" (*__mem) - : "cc", "memory"); - return __old_val; - } + { return __sync_fetch_and_add(__mem, __val); } void __attribute__ ((__unused__)) __atomic_add(volatile _Atomic_word* __mem, int __val) - { __exchange_and_add(__mem, __val); } + { __sync_fetch_and_add(__mem, __val); } } // namespace __gnu_cxx