s390.md: ("UNSPECV_MB", "UNSPECV_CAS"): New constants.
authorAdrian Straetling <straetling@de.ibm.com>
Tue, 7 Jun 2005 16:35:27 +0000 (16:35 +0000)
committerUlrich Weigand <uweigand@gcc.gnu.org>
Tue, 7 Jun 2005 16:35:27 +0000 (16:35 +0000)
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

gcc/ChangeLog
gcc/config/s390/2064.md
gcc/config/s390/2084.md
gcc/config/s390/s390.c
gcc/config/s390/s390.h
gcc/config/s390/s390.md
libstdc++-v3/ChangeLog
libstdc++-v3/config/cpu/s390/atomicity.h

index 9e99ca669b70de563f3f1f99b3f4b31815e26728..6796d23fee138eb7f76a56a703153ab58893a3bb 100644 (file)
@@ -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,
index 04564eb86f3d3965176878082af84975298e68b7..4c757acf1effab7c552a615ab49fcbe542d91d29 100644 (file)
        (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"))
index 05681c5b9dcba8f0da08e42064a2efe6e928c0b4..ca106c0f680ab40a7216e65571fa007b01c3228c 100644 (file)
        (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
 ;;
index 354f55e26fb65413362c32e8364ebd77ceeccb4a..54661eddbc6f8f826bdd008b86d5fd74979e4bae 100644 (file)
@@ -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
index 84d035357b72d2b0af8716fc31251ae7a9dbac00..f04f1387f48fad475034d4cfa2b1c45294fba0b1 100644 (file)
@@ -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.  */
index 93f805ed7f99502cd2fe40f5f9c903270548f520..34ecc7ccd60e7cc8e13472edb0dea9be5cf831ae 100644 (file)
 
    ; 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.
 ;;
index 3522320468dbcb3c53037fbdbac6d9133259430c..37f3fc3a782a30ad97c32c5851d3026d7480fb85 100644 (file)
@@ -1,3 +1,8 @@
+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)
index cf903b321f4d77e25dd3472648c8474d7ba7a1de..5a235940c8ce24ed8965671d92a7ad5302166143 100644 (file)
@@ -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