aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAdrian Straetling <straetling@de.ibm.com>2005-06-07 16:35:27 +0000
committerUlrich Weigand <uweigand@gcc.gnu.org>2005-06-07 16:35:27 +0000
commite0374221d9a8296937d7943791de7267a9d7dafa (patch)
treebb3a25e110cedc41afc38795fab064c14523fc41 /gcc
parentb6e7e9af0465df9134110217990127a47bc5f5c5 (diff)
downloadgcc-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/ChangeLog14
-rw-r--r--gcc/config/s390/2064.md5
-rw-r--r--gcc/config/s390/2084.md5
-rw-r--r--gcc/config/s390/s390.c21
-rw-r--r--gcc/config/s390/s390.h2
-rw-r--r--gcc/config/s390/s390.md86
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.
;;