This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] s390: support for builtin atomics


Hi,

this patch implements support for builtin atomics for s390.
Bootstrapped and regtested on mainline for s390, s390x.
Ok to apply?

Bye,
Adrian


2005-06-06  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: Export s390_compare_emitted.

libstdc++/ChangeLog:	
	* config/cpu/s390/atomicity.h: (__exchange_and_add, 
	__atomic_add):Use the builtins for atomic memory operations.


Index: gcc/config/s390/s390.md
===================================================================
*** gcc/config/s390/s390.md.orig	2005-06-06 20:38:34.000000000 +0200
--- gcc/config/s390/s390.md	2005-06-06 22:32:58.495026268 +0200
***************
*** 146,151 ****
--- 146,155 ----
  
     ; TLS support
     (UNSPECV_SET_TP		500)
+ 
+    ; Atomic Support
+    (UNSPECV_MB			700)
+    (UNSPECV_CAS			701)
    ])
  
  ;;
***************
*** 177,183 ****
  ;; Instruction type attribute used for scheduling.
  
  (define_attr "type" "none,integer,load,lr,la,larl,lm,stm,
! 	             cs,vs,store,idiv,
                       imulhi,imulsi,imuldi,
  		     branch,jsr,fsimpdf,fsimpsf,
  		     floaddf,floadsf,fstoredf,fstoresf,
--- 181,187 ----
  ;; Instruction type attribute used for scheduling.
  
  (define_attr "type" "none,integer,load,lr,la,larl,lm,stm,
! 	             cs,vs,store,sem,idiv,
                       imulhi,imulsi,imuldi,
  		     branch,jsr,fsimpdf,fsimpsf,
  		     floaddf,floadsf,fstoredf,fstoresf,
***************
*** 6692,6697 ****
--- 6696,6781 ----
     (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: gcc/config/s390/2064.md
===================================================================
*** gcc/config/s390/2064.md.orig	2005-06-06 20:38:34.000000000 +0200
--- gcc/config/s390/2064.md	2005-06-06 20:39:45.000000000 +0200
***************
*** 67,72 ****
--- 67,77 ----
         (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: gcc/config/s390/2084.md
===================================================================
*** gcc/config/s390/2084.md.orig	2005-06-06 20:38:34.000000000 +0200
--- gcc/config/s390/2084.md	2005-06-06 20:39:45.000000000 +0200
***************
*** 123,128 ****
--- 123,133 ----
         (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: libstdc++-v3/config/cpu/s390/atomicity.h
===================================================================
*** libstdc++-v3/config/cpu/s390/atomicity.h.orig	2005-06-06 20:38:29.000000000 +0200
--- libstdc++-v3/config/cpu/s390/atomicity.h	2005-06-06 20:39:46.000000000 +0200
*************** namespace __gnu_cxx
*** 34,55 ****
    _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;
!   }
    
    void
    __attribute__ ((__unused__))
    __atomic_add(volatile _Atomic_word* __mem, int __val)
!   { __exchange_and_add(__mem, __val); }
  } // namespace __gnu_cxx
--- 34,43 ----
    _Atomic_word 
    __attribute__ ((__unused__))
    __exchange_and_add(volatile _Atomic_word* __mem, int __val)
!   { return __sync_fetch_and_add(__mem, __val); }
    
    void
    __attribute__ ((__unused__))
    __atomic_add(volatile _Atomic_word* __mem, int __val)
!   { __sync_fetch_and_add(__mem, __val); }
  } // namespace __gnu_cxx
Index: gcc/config/s390/s390.c
===================================================================
*** gcc/config/s390/s390.c.orig	2005-06-06 20:39:00.000000000 +0200
--- gcc/config/s390/s390.c	2005-06-06 20:39:46.000000000 +0200
*************** static int s390_sr_alias_set = 0;
*** 163,168 ****
--- 163,172 ----
     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
*************** rtx
*** 609,618 ****
  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);
  
!   emit_insn (gen_rtx_SET (VOIDmode, cc, gen_rtx_COMPARE (mode, op0, op1)));
!   return gen_rtx_fmt_ee (code, VOIDmode, cc, const0_rtx);
  }
  
  /* Emit a jump instruction to TARGET.  If COND is NULL_RTX, emit an
--- 613,633 ----
  s390_emit_compare (enum rtx_code code, rtx op0, rtx op1)
  {
    enum machine_mode mode = s390_select_ccmode (code, op0, op1);
!   rtx ret = NULL_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: gcc/config/s390/s390.h
===================================================================
*** gcc/config/s390/s390.h.orig	2005-06-06 20:38:34.000000000 +0200
--- gcc/config/s390/s390.h	2005-06-06 20:39:46.000000000 +0200
*************** do {									\
*** 799,805 ****
  /* 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;
  
  
  /* Relative costs of operations.  */
--- 799,805 ----
  /* 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, *s390_compare_emitted;
  
  
  /* Relative costs of operations.  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]