This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch] s390: support for __sync_lock_test_and_set
- From: Adrian Straetling <straetling at de dot ibm dot com>
- To: gcc-patches at gcc dot gnu dot org, "Weigand, Ulrich" <uweigand at de dot ibm dot com>
- Date: Fri, 30 Sep 2005 15:05:11 +0200
- Subject: [patch] s390: support for __sync_lock_test_and_set
Hi,
this patch enables support for __sync_lock_test_and_set for all integer
modes.
Bootstrapped and regtested on s390 and s390x. The patch introduces two testcase failures:
gcc.dg/ia64-sync-1.c
gcc.dg/ia64-sync-2.c
These testcases check the memory location for the value 1 after invoking __sync_lock_test_and_set.
However, the test_and_set instruction on s390(x) stores 0xff into the
memory location, which should be ok since the documentation states that
'the true contents of the memory are implementation defined'.
As discussed with rth, the best solution should be to just check that the
memory is non-null. I'll post that patch as well.
bye,
Adrian
2005-09-30 Adrian Straetling <straetling@de.ibm.com>
* config/s390/s390.md: ("UNSPEC_TS") New constant.
("movstrictsi"): Add "ipm".
("*sne"): Rename into "*snesi".
("*snedi","sync_lock_test_and_set<mode>",
"sync_lock_test_and_setqi"): New patterns.
* config/s390/s390.c: (s390_canonicalize_comparison): Allow
more modes for EQ/NE simplification.
Index: gcc/config/s390/s390.md
===================================================================
*** gcc/config/s390/s390.md.orig 2005-08-29 19:38:01.000000000 +0200
--- gcc/config/s390/s390.md 2005-08-30 22:29:36.613160285 +0200
***************
*** 162,167 ****
--- 162,168 ----
; Atomic Support
(UNSPECV_MB 700)
(UNSPECV_CAS 701)
+ (UNSPECV_TS 702)
])
;;
***************
*** 1453,1468 ****
;
(define_insn "movstrictsi"
! [(set (strict_low_part (match_operand:SI 0 "register_operand" "+d,d,d,d"))
! (match_operand:SI 1 "general_operand" "d,R,T,t"))]
"TARGET_64BIT"
"@
lr\t%0,%1
l\t%0,%1
ly\t%0,%1
! ear\t%0,%1"
! [(set_attr "op_type" "RR,RX,RXY,RRE")
! (set_attr "type" "lr,load,load,*")])
;
; movdf instruction pattern(s).
--- 1454,1470 ----
;
(define_insn "movstrictsi"
! [(set (strict_low_part (match_operand:SI 0 "register_operand" "+d,d,d,d,d"))
! (match_operand:SI 1 "general_operand" "d,R,T,t,c"))]
"TARGET_64BIT"
"@
lr\t%0,%1
l\t%0,%1
ly\t%0,%1
! ear\t%0,%1
! ipm\t%0"
! [(set_attr "op_type" "RR,RX,RXY,RRE,RRE")
! (set_attr "type" "lr,load,load,*,*")])
;
; movdf instruction pattern(s).
***************
*** 4200,4206 ****
PUT_MODE (operands[1], SImode);
})
! (define_insn_and_split "*sne"
[(set (match_operand:SI 0 "register_operand" "=d")
(ne:SI (match_operand:CCZ1 1 "register_operand" "0")
(const_int 0)))
--- 4202,4223 ----
PUT_MODE (operands[1], SImode);
})
! (define_insn_and_split "*snedi"
! [(set (match_operand:DI 0 "register_operand" "=d")
! (ne:DI (reg:CCZ1 CC_REGNUM)
! (const_int 0)))
! (clobber (reg:CC CC_REGNUM))]
! "TARGET_64BIT"
! "#"
! "reload_completed"
! [(set (match_dup 0) (const_int 0))
! (set (strict_low_part (match_dup 1)) (reg:SI CC_REGNUM))
! (parallel
! [(set (match_dup 1) (ashiftrt:SI (match_dup 1) (const_int 28)))
! (clobber (reg:CC CC_REGNUM))])]
! "operands[1] = gen_lowpart (SImode, operands[0]);")
!
! (define_insn_and_split "*snesi"
[(set (match_operand:SI 0 "register_operand" "=d")
(ne:SI (match_operand:CCZ1 1 "register_operand" "0")
(const_int 0)))
***************
*** 7174,7179 ****
--- 7191,7241 ----
(set_attr "type" "sem")])
+ ;
+ ; test and set pattern.
+ ;
+
+ (define_expand "sync_lock_test_and_set<mode>"
+ [(parallel
+ [(set (match_dup 1)
+ (unspec_volatile:QI
+ [(match_operand:QI 1 "memory_operand" "")
+ (match_operand:QI 2 "const_int_operand" "")]
+ UNSPECV_TS))
+ (set (reg:CCZ1 CC_REGNUM)
+ (compare:CCZ1 (match_dup 1)
+ (const_int 0)))])
+ (parallel
+ [(set (match_operand:INT 0 "register_operand" "")
+ (match_dup 3))
+ (clobber (reg:CC CC_REGNUM))])]
+ ""
+ {
+ if (INTVAL (operands[2]) != 1)
+ FAIL;
+
+ if (<MODE>mode != DImode)
+ operands[0] = gen_lowpart (SImode, operands[0]);
+ /* Adjust address to the least significant byte. */
+ operands[1] = adjust_address (operands[1], QImode, GET_MODE_SIZE(<MODE>mode)
+ - GET_MODE_SIZE (QImode));
+ /* Emit comparison with CC. */
+ operands[3] = gen_rtx_fmt_ee (NE, (<MODE>mode == DImode) ? DImode : SImode,
+ gen_rtx_REG (CCZ1mode, CC_REGNUM), const0_rtx);
+ })
+
+ (define_insn "*sync_lock_test_and_setqi"
+ [(set (match_operand:QI 0 "memory_operand" "+Q")
+ (unspec_volatile:QI [(match_dup 0) (const_int 1)] UNSPECV_TS))
+ (set (reg:CCZ1 CC_REGNUM)
+ (compare:CCZ1 (match_dup 0)
+ (const_int 0)))]
+ ""
+ "ts\t%S0"
+ [(set_attr "op_type" "S")
+ (set_attr "type" "sem")])
+
+
;;
;;- Miscellaneous instructions.
;;
Index: gcc/config/s390/s390.c
===================================================================
*** gcc/config/s390/s390.c.orig 2005-08-29 19:38:01.000000000 +0200
--- gcc/config/s390/s390.c 2005-08-30 22:31:45.493160285 +0200
*************** s390_canonicalize_comparison (enum rtx_c
*** 696,702 ****
/* Simplify cascaded EQ, NE with const0_rtx. */
if ((*code == NE || *code == EQ)
&& (GET_CODE (*op0) == EQ || GET_CODE (*op0) == NE)
! && GET_MODE (*op0) == SImode
&& GET_MODE (XEXP (*op0, 0)) == CCZ1mode
&& REG_P (XEXP (*op0, 0))
&& XEXP (*op0, 1) == const0_rtx
--- 696,702 ----
/* Simplify cascaded EQ, NE with const0_rtx. */
if ((*code == NE || *code == EQ)
&& (GET_CODE (*op0) == EQ || GET_CODE (*op0) == NE)
! && INTEGRAL_MODE_P (GET_MODE (*op0))
&& GET_MODE (XEXP (*op0, 0)) == CCZ1mode
&& REG_P (XEXP (*op0, 0))
&& XEXP (*op0, 1) == const0_rtx