Commit e0374221 by Adrian Straetling Committed by Ulrich Weigand

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
parent b6e7e9af
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> 2005-06-07 Kazu Hirata <kazu@codesourcery.com>
* sbitmap.h (sbitmap_iterator, sbitmap_iter_init, * sbitmap.h (sbitmap_iterator, sbitmap_iter_init,
......
...@@ -67,6 +67,11 @@ ...@@ -67,6 +67,11 @@
(eq_attr "type" "store")) (eq_attr "type" "store"))
"z_e1,z_wr") "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 (define_insn_reservation "z_call" 5
(and (eq_attr "cpu" "z900,g5,g6") (and (eq_attr "cpu" "z900,g5,g6")
(eq_attr "type" "jsr")) (eq_attr "type" "jsr"))
......
...@@ -123,6 +123,11 @@ ...@@ -123,6 +123,11 @@
(eq_attr "type" "idiv")) (eq_attr "type" "idiv"))
"x-e1-np*10,x-wr-np") "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 ;; Multicycle insns
;; ;;
......
...@@ -163,6 +163,10 @@ static int s390_sr_alias_set = 0; ...@@ -163,6 +163,10 @@ static int s390_sr_alias_set = 0;
emitted. */ emitted. */
rtx s390_compare_op0, s390_compare_op1; 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 /* Structure used to hold the components of a S/390 memory
address. A legitimate address on S/390 is of the general address. A legitimate address on S/390 is of the general
form form
...@@ -609,10 +613,21 @@ rtx ...@@ -609,10 +613,21 @@ rtx
s390_emit_compare (enum rtx_code code, rtx op0, rtx op1) s390_emit_compare (enum rtx_code code, rtx op0, rtx op1)
{ {
enum machine_mode mode = s390_select_ccmode (code, op0, 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))); /* Do not output a redundant compare instruction if a compare_and_swap
return gen_rtx_fmt_ee (code, VOIDmode, cc, const0_rtx); 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 /* Emit a jump instruction to TARGET. If COND is NULL_RTX, emit an
......
...@@ -799,7 +799,7 @@ do { \ ...@@ -799,7 +799,7 @@ do { \
/* Define the information needed to generate branch and scc insns. This is /* 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 stored from the compare operation. Note that we can't use "rtx" here
since it hasn't been defined! */ 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. */ /* Relative costs of operations. */
......
...@@ -146,6 +146,10 @@ ...@@ -146,6 +146,10 @@
; TLS support ; TLS support
(UNSPECV_SET_TP 500) (UNSPECV_SET_TP 500)
; Atomic Support
(UNSPECV_MB 700)
(UNSPECV_CAS 701)
]) ])
;; ;;
...@@ -177,7 +181,7 @@ ...@@ -177,7 +181,7 @@
;; Instruction type attribute used for scheduling. ;; Instruction type attribute used for scheduling.
(define_attr "type" "none,integer,load,lr,la,larl,lm,stm, (define_attr "type" "none,integer,load,lr,la,larl,lm,stm,
cs,vs,store,idiv, cs,vs,store,sem,idiv,
imulhi,imulsi,imuldi, imulhi,imulsi,imuldi,
branch,jsr,fsimpdf,fsimpsf, branch,jsr,fsimpdf,fsimpsf,
floaddf,floadsf,fstoredf,fstoresf, floaddf,floadsf,fstoredf,fstoresf,
...@@ -6692,6 +6696,86 @@ ...@@ -6692,6 +6696,86 @@
(set_attr "atype" "agen")]) (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. ;;- Miscellaneous instructions.
;; ;;
......
2005-06-07 Adrian Straetling <straetling@de.ibm.com>
* config/cpu/s390/atomicity.h: (__exchange_and_add,
__atomic_add): Use the builtins for atomic memory operations.
2005-06-06 Paolo Carlini <pcarlini@suse.de> 2005-06-06 Paolo Carlini <pcarlini@suse.de>
PR libstdc++/21770 (cont: __gnu_debug::string) PR libstdc++/21770 (cont: __gnu_debug::string)
......
...@@ -34,22 +34,10 @@ namespace __gnu_cxx ...@@ -34,22 +34,10 @@ namespace __gnu_cxx
_Atomic_word _Atomic_word
__attribute__ ((__unused__)) __attribute__ ((__unused__))
__exchange_and_add(volatile _Atomic_word* __mem, int __val) __exchange_and_add(volatile _Atomic_word* __mem, int __val)
{ { return __sync_fetch_and_add(__mem, __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;
}
void void
__attribute__ ((__unused__)) __attribute__ ((__unused__))
__atomic_add(volatile _Atomic_word* __mem, int __val) __atomic_add(volatile _Atomic_word* __mem, int __val)
{ __exchange_and_add(__mem, __val); } { __sync_fetch_and_add(__mem, __val); }
} // namespace __gnu_cxx } // namespace __gnu_cxx
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment