+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,
(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"))
(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
;;
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
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
/* 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. */
; TLS support
(UNSPECV_SET_TP 500)
+
+ ; Atomic Support
+ (UNSPECV_MB 700)
+ (UNSPECV_CAS 701)
])
;;
;; 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,
(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<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.
;;
+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>
PR libstdc++/21770 (cont: __gnu_debug::string)
_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