
In PowerPC, the AtomicCmpXchgInst is lowered to ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS. However, this node does not handle the weak attribute of AtomicCmpXchgInst. As a result, when compiling C++ atomic_compare_exchange_weak_explicit, the generated assembly includes a "reservation lost" loop — i.e., it branches back and retries if the stwcx. (store-conditional) fails. This differs from GCC’s codegen, which does not include that loop for weak compare-exchange. Since PowerPC uses LL/SC-style atomic instructions, the patch enables AtomicExpandImpl::expandAtomicCmpXchg for PowerPC. With this, the weak attribute is properly respected, and the "reservation lost" loop is removed for weak operations. --------- Co-authored-by: Matt Arsenault <arsenm2@gmail.com>
373 lines
16 KiB
LLVM
373 lines
16 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc -mcpu=ppc -mtriple=powerpc64-unknown-linux-gnu < %s | FileCheck %s
|
|
|
|
define i8 @atomicrmw_usub_cond_i8(ptr %ptr, i8 %val) {
|
|
; CHECK-LABEL: atomicrmw_usub_cond_i8:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: sync
|
|
; CHECK-NEXT: rldicr 5, 3, 0, 61
|
|
; CHECK-NEXT: not 3, 3
|
|
; CHECK-NEXT: li 6, 255
|
|
; CHECK-NEXT: lwz 8, 0(5)
|
|
; CHECK-NEXT: rlwinm 3, 3, 3, 27, 28
|
|
; CHECK-NEXT: slw 6, 6, 3
|
|
; CHECK-NEXT: not 6, 6
|
|
; CHECK-NEXT: clrlwi 7, 4, 24
|
|
; CHECK-NEXT: b .LBB0_2
|
|
; CHECK-NEXT: .LBB0_1: # %cmpxchg.nostore
|
|
; CHECK-NEXT: # in Loop: Header=BB0_2 Depth=1
|
|
; CHECK-NEXT: mr 8, 9
|
|
; CHECK-NEXT: .LBB0_2: # %atomicrmw.start
|
|
; CHECK-NEXT: # =>This Loop Header: Depth=1
|
|
; CHECK-NEXT: # Child Loop BB0_5 Depth 2
|
|
; CHECK-NEXT: srw 9, 8, 3
|
|
; CHECK-NEXT: clrlwi 10, 9, 24
|
|
; CHECK-NEXT: cmplw 10, 7
|
|
; CHECK-NEXT: blt 0, .LBB0_4
|
|
; CHECK-NEXT: # %bb.3: # in Loop: Header=BB0_2 Depth=1
|
|
; CHECK-NEXT: sub 9, 9, 4
|
|
; CHECK-NEXT: .LBB0_4: # %atomicrmw.start
|
|
; CHECK-NEXT: # in Loop: Header=BB0_2 Depth=1
|
|
; CHECK-NEXT: clrlwi 9, 9, 24
|
|
; CHECK-NEXT: slw 9, 9, 3
|
|
; CHECK-NEXT: and 10, 8, 6
|
|
; CHECK-NEXT: or 10, 10, 9
|
|
; CHECK-NEXT: .LBB0_5: # %cmpxchg.start
|
|
; CHECK-NEXT: # Parent Loop BB0_2 Depth=1
|
|
; CHECK-NEXT: # => This Inner Loop Header: Depth=2
|
|
; CHECK-NEXT: lwarx 9, 0, 5
|
|
; CHECK-NEXT: cmplw 9, 8
|
|
; CHECK-NEXT: bne 0, .LBB0_1
|
|
; CHECK-NEXT: # %bb.6: # %cmpxchg.fencedstore
|
|
; CHECK-NEXT: # in Loop: Header=BB0_5 Depth=2
|
|
; CHECK-NEXT: stwcx. 10, 0, 5
|
|
; CHECK-NEXT: bne 0, .LBB0_5
|
|
; CHECK-NEXT: # %bb.7:
|
|
; CHECK-NEXT: mr 8, 9
|
|
; CHECK-NEXT: # %bb.8: # %atomicrmw.end
|
|
; CHECK-NEXT: srw 3, 9, 3
|
|
; CHECK-NEXT: lwsync
|
|
; CHECK-NEXT: blr
|
|
%result = atomicrmw usub_cond ptr %ptr, i8 %val seq_cst
|
|
ret i8 %result
|
|
}
|
|
|
|
define i16 @atomicrmw_usub_cond_i16(ptr %ptr, i16 %val) {
|
|
; CHECK-LABEL: atomicrmw_usub_cond_i16:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: sync
|
|
; CHECK-NEXT: rldicr 5, 3, 0, 61
|
|
; CHECK-NEXT: clrlwi 3, 3, 30
|
|
; CHECK-NEXT: lis 6, 0
|
|
; CHECK-NEXT: xori 3, 3, 2
|
|
; CHECK-NEXT: lwz 8, 0(5)
|
|
; CHECK-NEXT: ori 6, 6, 65535
|
|
; CHECK-NEXT: slwi 3, 3, 3
|
|
; CHECK-NEXT: slw 6, 6, 3
|
|
; CHECK-NEXT: not 6, 6
|
|
; CHECK-NEXT: clrlwi 7, 4, 16
|
|
; CHECK-NEXT: b .LBB1_2
|
|
; CHECK-NEXT: .LBB1_1: # %cmpxchg.nostore
|
|
; CHECK-NEXT: # in Loop: Header=BB1_2 Depth=1
|
|
; CHECK-NEXT: mr 8, 9
|
|
; CHECK-NEXT: .LBB1_2: # %atomicrmw.start
|
|
; CHECK-NEXT: # =>This Loop Header: Depth=1
|
|
; CHECK-NEXT: # Child Loop BB1_5 Depth 2
|
|
; CHECK-NEXT: srw 9, 8, 3
|
|
; CHECK-NEXT: clrlwi 10, 9, 16
|
|
; CHECK-NEXT: cmplw 10, 7
|
|
; CHECK-NEXT: blt 0, .LBB1_4
|
|
; CHECK-NEXT: # %bb.3: # in Loop: Header=BB1_2 Depth=1
|
|
; CHECK-NEXT: sub 9, 9, 4
|
|
; CHECK-NEXT: .LBB1_4: # %atomicrmw.start
|
|
; CHECK-NEXT: # in Loop: Header=BB1_2 Depth=1
|
|
; CHECK-NEXT: clrlwi 9, 9, 16
|
|
; CHECK-NEXT: slw 9, 9, 3
|
|
; CHECK-NEXT: and 10, 8, 6
|
|
; CHECK-NEXT: or 10, 10, 9
|
|
; CHECK-NEXT: .LBB1_5: # %cmpxchg.start
|
|
; CHECK-NEXT: # Parent Loop BB1_2 Depth=1
|
|
; CHECK-NEXT: # => This Inner Loop Header: Depth=2
|
|
; CHECK-NEXT: lwarx 9, 0, 5
|
|
; CHECK-NEXT: cmplw 9, 8
|
|
; CHECK-NEXT: bne 0, .LBB1_1
|
|
; CHECK-NEXT: # %bb.6: # %cmpxchg.fencedstore
|
|
; CHECK-NEXT: # in Loop: Header=BB1_5 Depth=2
|
|
; CHECK-NEXT: stwcx. 10, 0, 5
|
|
; CHECK-NEXT: bne 0, .LBB1_5
|
|
; CHECK-NEXT: # %bb.7:
|
|
; CHECK-NEXT: mr 8, 9
|
|
; CHECK-NEXT: # %bb.8: # %atomicrmw.end
|
|
; CHECK-NEXT: srw 3, 9, 3
|
|
; CHECK-NEXT: lwsync
|
|
; CHECK-NEXT: blr
|
|
%result = atomicrmw usub_cond ptr %ptr, i16 %val seq_cst
|
|
ret i16 %result
|
|
}
|
|
|
|
define i32 @atomicrmw_usub_cond_i32(ptr %ptr, i32 %val) {
|
|
; CHECK-LABEL: atomicrmw_usub_cond_i32:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: sync
|
|
; CHECK-NEXT: lwz 6, 0(3)
|
|
; CHECK-NEXT: b .LBB2_2
|
|
; CHECK-NEXT: .LBB2_1: # %cmpxchg.nostore
|
|
; CHECK-NEXT: # in Loop: Header=BB2_2 Depth=1
|
|
; CHECK-NEXT: mr 6, 5
|
|
; CHECK-NEXT: .LBB2_2: # %atomicrmw.start
|
|
; CHECK-NEXT: # =>This Loop Header: Depth=1
|
|
; CHECK-NEXT: # Child Loop BB2_5 Depth 2
|
|
; CHECK-NEXT: cmplw 6, 4
|
|
; CHECK-NEXT: bge 0, .LBB2_4
|
|
; CHECK-NEXT: # %bb.3: # %atomicrmw.start
|
|
; CHECK-NEXT: # in Loop: Header=BB2_2 Depth=1
|
|
; CHECK-NEXT: mr 7, 6
|
|
; CHECK-NEXT: b .LBB2_5
|
|
; CHECK-NEXT: .LBB2_4: # in Loop: Header=BB2_2 Depth=1
|
|
; CHECK-NEXT: sub 7, 6, 4
|
|
; CHECK-NEXT: .LBB2_5: # %cmpxchg.start
|
|
; CHECK-NEXT: # Parent Loop BB2_2 Depth=1
|
|
; CHECK-NEXT: # => This Inner Loop Header: Depth=2
|
|
; CHECK-NEXT: lwarx 5, 0, 3
|
|
; CHECK-NEXT: cmplw 5, 6
|
|
; CHECK-NEXT: bne 0, .LBB2_1
|
|
; CHECK-NEXT: # %bb.6: # %cmpxchg.fencedstore
|
|
; CHECK-NEXT: # in Loop: Header=BB2_5 Depth=2
|
|
; CHECK-NEXT: stwcx. 7, 0, 3
|
|
; CHECK-NEXT: bne 0, .LBB2_5
|
|
; CHECK-NEXT: # %bb.7:
|
|
; CHECK-NEXT: mr 6, 5
|
|
; CHECK-NEXT: # %bb.8: # %atomicrmw.end
|
|
; CHECK-NEXT: mr 3, 5
|
|
; CHECK-NEXT: lwsync
|
|
; CHECK-NEXT: blr
|
|
%result = atomicrmw usub_cond ptr %ptr, i32 %val seq_cst
|
|
ret i32 %result
|
|
}
|
|
|
|
define i64 @atomicrmw_usub_cond_i64(ptr %ptr, i64 %val) {
|
|
; CHECK-LABEL: atomicrmw_usub_cond_i64:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: sync
|
|
; CHECK-NEXT: ld 6, 0(3)
|
|
; CHECK-NEXT: b .LBB3_2
|
|
; CHECK-NEXT: .LBB3_1: # %cmpxchg.nostore
|
|
; CHECK-NEXT: # in Loop: Header=BB3_2 Depth=1
|
|
; CHECK-NEXT: mr 6, 5
|
|
; CHECK-NEXT: .LBB3_2: # %atomicrmw.start
|
|
; CHECK-NEXT: # =>This Loop Header: Depth=1
|
|
; CHECK-NEXT: # Child Loop BB3_5 Depth 2
|
|
; CHECK-NEXT: cmpld 6, 4
|
|
; CHECK-NEXT: bge 0, .LBB3_4
|
|
; CHECK-NEXT: # %bb.3: # %atomicrmw.start
|
|
; CHECK-NEXT: # in Loop: Header=BB3_2 Depth=1
|
|
; CHECK-NEXT: mr 7, 6
|
|
; CHECK-NEXT: b .LBB3_5
|
|
; CHECK-NEXT: .LBB3_4: # in Loop: Header=BB3_2 Depth=1
|
|
; CHECK-NEXT: sub 7, 6, 4
|
|
; CHECK-NEXT: .LBB3_5: # %cmpxchg.start
|
|
; CHECK-NEXT: # Parent Loop BB3_2 Depth=1
|
|
; CHECK-NEXT: # => This Inner Loop Header: Depth=2
|
|
; CHECK-NEXT: ldarx 5, 0, 3
|
|
; CHECK-NEXT: cmpld 5, 6
|
|
; CHECK-NEXT: bne 0, .LBB3_1
|
|
; CHECK-NEXT: # %bb.6: # %cmpxchg.fencedstore
|
|
; CHECK-NEXT: # in Loop: Header=BB3_5 Depth=2
|
|
; CHECK-NEXT: stdcx. 7, 0, 3
|
|
; CHECK-NEXT: bne 0, .LBB3_5
|
|
; CHECK-NEXT: # %bb.7:
|
|
; CHECK-NEXT: mr 6, 5
|
|
; CHECK-NEXT: # %bb.8: # %atomicrmw.end
|
|
; CHECK-NEXT: mr 3, 5
|
|
; CHECK-NEXT: lwsync
|
|
; CHECK-NEXT: blr
|
|
%result = atomicrmw usub_cond ptr %ptr, i64 %val seq_cst
|
|
ret i64 %result
|
|
}
|
|
|
|
define i8 @atomicrmw_usub_sat_i8(ptr %ptr, i8 %val) {
|
|
; CHECK-LABEL: atomicrmw_usub_sat_i8:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: sync
|
|
; CHECK-NEXT: rldicr 5, 3, 0, 61
|
|
; CHECK-NEXT: not 3, 3
|
|
; CHECK-NEXT: li 6, 255
|
|
; CHECK-NEXT: lwz 7, 0(5)
|
|
; CHECK-NEXT: rlwinm 3, 3, 3, 27, 28
|
|
; CHECK-NEXT: slw 6, 6, 3
|
|
; CHECK-NEXT: not 6, 6
|
|
; CHECK-NEXT: clrlwi 4, 4, 24
|
|
; CHECK-NEXT: b .LBB4_2
|
|
; CHECK-NEXT: .LBB4_1: # %cmpxchg.nostore
|
|
; CHECK-NEXT: # in Loop: Header=BB4_2 Depth=1
|
|
; CHECK-NEXT: mr 7, 8
|
|
; CHECK-NEXT: .LBB4_2: # %atomicrmw.start
|
|
; CHECK-NEXT: # =>This Loop Header: Depth=1
|
|
; CHECK-NEXT: # Child Loop BB4_5 Depth 2
|
|
; CHECK-NEXT: srw 8, 7, 3
|
|
; CHECK-NEXT: clrlwi 9, 8, 24
|
|
; CHECK-NEXT: sub 8, 9, 4
|
|
; CHECK-NEXT: cmplw 8, 9
|
|
; CHECK-NEXT: li 9, 0
|
|
; CHECK-NEXT: bgt 0, .LBB4_4
|
|
; CHECK-NEXT: # %bb.3: # %atomicrmw.start
|
|
; CHECK-NEXT: # in Loop: Header=BB4_2 Depth=1
|
|
; CHECK-NEXT: mr 9, 8
|
|
; CHECK-NEXT: .LBB4_4: # %atomicrmw.start
|
|
; CHECK-NEXT: # in Loop: Header=BB4_2 Depth=1
|
|
; CHECK-NEXT: slw 8, 9, 3
|
|
; CHECK-NEXT: and 9, 7, 6
|
|
; CHECK-NEXT: or 9, 9, 8
|
|
; CHECK-NEXT: .LBB4_5: # %cmpxchg.start
|
|
; CHECK-NEXT: # Parent Loop BB4_2 Depth=1
|
|
; CHECK-NEXT: # => This Inner Loop Header: Depth=2
|
|
; CHECK-NEXT: lwarx 8, 0, 5
|
|
; CHECK-NEXT: cmplw 8, 7
|
|
; CHECK-NEXT: bne 0, .LBB4_1
|
|
; CHECK-NEXT: # %bb.6: # %cmpxchg.fencedstore
|
|
; CHECK-NEXT: # in Loop: Header=BB4_5 Depth=2
|
|
; CHECK-NEXT: stwcx. 9, 0, 5
|
|
; CHECK-NEXT: bne 0, .LBB4_5
|
|
; CHECK-NEXT: # %bb.7:
|
|
; CHECK-NEXT: mr 7, 8
|
|
; CHECK-NEXT: # %bb.8: # %atomicrmw.end
|
|
; CHECK-NEXT: srw 3, 8, 3
|
|
; CHECK-NEXT: lwsync
|
|
; CHECK-NEXT: blr
|
|
%result = atomicrmw usub_sat ptr %ptr, i8 %val seq_cst
|
|
ret i8 %result
|
|
}
|
|
|
|
define i16 @atomicrmw_usub_sat_i16(ptr %ptr, i16 %val) {
|
|
; CHECK-LABEL: atomicrmw_usub_sat_i16:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: sync
|
|
; CHECK-NEXT: rldicr 5, 3, 0, 61
|
|
; CHECK-NEXT: clrlwi 3, 3, 30
|
|
; CHECK-NEXT: lis 6, 0
|
|
; CHECK-NEXT: xori 3, 3, 2
|
|
; CHECK-NEXT: lwz 7, 0(5)
|
|
; CHECK-NEXT: ori 6, 6, 65535
|
|
; CHECK-NEXT: slwi 3, 3, 3
|
|
; CHECK-NEXT: slw 6, 6, 3
|
|
; CHECK-NEXT: not 6, 6
|
|
; CHECK-NEXT: clrlwi 4, 4, 16
|
|
; CHECK-NEXT: b .LBB5_2
|
|
; CHECK-NEXT: .LBB5_1: # %cmpxchg.nostore
|
|
; CHECK-NEXT: # in Loop: Header=BB5_2 Depth=1
|
|
; CHECK-NEXT: mr 7, 8
|
|
; CHECK-NEXT: .LBB5_2: # %atomicrmw.start
|
|
; CHECK-NEXT: # =>This Loop Header: Depth=1
|
|
; CHECK-NEXT: # Child Loop BB5_5 Depth 2
|
|
; CHECK-NEXT: srw 8, 7, 3
|
|
; CHECK-NEXT: clrlwi 9, 8, 16
|
|
; CHECK-NEXT: sub 8, 9, 4
|
|
; CHECK-NEXT: cmplw 8, 9
|
|
; CHECK-NEXT: li 9, 0
|
|
; CHECK-NEXT: bgt 0, .LBB5_4
|
|
; CHECK-NEXT: # %bb.3: # %atomicrmw.start
|
|
; CHECK-NEXT: # in Loop: Header=BB5_2 Depth=1
|
|
; CHECK-NEXT: mr 9, 8
|
|
; CHECK-NEXT: .LBB5_4: # %atomicrmw.start
|
|
; CHECK-NEXT: # in Loop: Header=BB5_2 Depth=1
|
|
; CHECK-NEXT: slw 8, 9, 3
|
|
; CHECK-NEXT: and 9, 7, 6
|
|
; CHECK-NEXT: or 9, 9, 8
|
|
; CHECK-NEXT: .LBB5_5: # %cmpxchg.start
|
|
; CHECK-NEXT: # Parent Loop BB5_2 Depth=1
|
|
; CHECK-NEXT: # => This Inner Loop Header: Depth=2
|
|
; CHECK-NEXT: lwarx 8, 0, 5
|
|
; CHECK-NEXT: cmplw 8, 7
|
|
; CHECK-NEXT: bne 0, .LBB5_1
|
|
; CHECK-NEXT: # %bb.6: # %cmpxchg.fencedstore
|
|
; CHECK-NEXT: # in Loop: Header=BB5_5 Depth=2
|
|
; CHECK-NEXT: stwcx. 9, 0, 5
|
|
; CHECK-NEXT: bne 0, .LBB5_5
|
|
; CHECK-NEXT: # %bb.7:
|
|
; CHECK-NEXT: mr 7, 8
|
|
; CHECK-NEXT: # %bb.8: # %atomicrmw.end
|
|
; CHECK-NEXT: srw 3, 8, 3
|
|
; CHECK-NEXT: lwsync
|
|
; CHECK-NEXT: blr
|
|
%result = atomicrmw usub_sat ptr %ptr, i16 %val seq_cst
|
|
ret i16 %result
|
|
}
|
|
|
|
define i32 @atomicrmw_usub_sat_i32(ptr %ptr, i32 %val) {
|
|
; CHECK-LABEL: atomicrmw_usub_sat_i32:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: sync
|
|
; CHECK-NEXT: lwz 6, 0(3)
|
|
; CHECK-NEXT: b .LBB6_2
|
|
; CHECK-NEXT: .LBB6_1: # %cmpxchg.nostore
|
|
; CHECK-NEXT: # in Loop: Header=BB6_2 Depth=1
|
|
; CHECK-NEXT: mr 6, 5
|
|
; CHECK-NEXT: .LBB6_2: # %atomicrmw.start
|
|
; CHECK-NEXT: # =>This Loop Header: Depth=1
|
|
; CHECK-NEXT: # Child Loop BB6_4 Depth 2
|
|
; CHECK-NEXT: sub 5, 6, 4
|
|
; CHECK-NEXT: cmplw 5, 6
|
|
; CHECK-NEXT: li 7, 0
|
|
; CHECK-NEXT: bgt 0, .LBB6_4
|
|
; CHECK-NEXT: # %bb.3: # %atomicrmw.start
|
|
; CHECK-NEXT: # in Loop: Header=BB6_2 Depth=1
|
|
; CHECK-NEXT: mr 7, 5
|
|
; CHECK-NEXT: .LBB6_4: # %cmpxchg.start
|
|
; CHECK-NEXT: # Parent Loop BB6_2 Depth=1
|
|
; CHECK-NEXT: # => This Inner Loop Header: Depth=2
|
|
; CHECK-NEXT: lwarx 5, 0, 3
|
|
; CHECK-NEXT: cmplw 5, 6
|
|
; CHECK-NEXT: bne 0, .LBB6_1
|
|
; CHECK-NEXT: # %bb.5: # %cmpxchg.fencedstore
|
|
; CHECK-NEXT: # in Loop: Header=BB6_4 Depth=2
|
|
; CHECK-NEXT: stwcx. 7, 0, 3
|
|
; CHECK-NEXT: bne 0, .LBB6_4
|
|
; CHECK-NEXT: # %bb.6:
|
|
; CHECK-NEXT: mr 6, 5
|
|
; CHECK-NEXT: # %bb.7: # %atomicrmw.end
|
|
; CHECK-NEXT: mr 3, 5
|
|
; CHECK-NEXT: lwsync
|
|
; CHECK-NEXT: blr
|
|
%result = atomicrmw usub_sat ptr %ptr, i32 %val seq_cst
|
|
ret i32 %result
|
|
}
|
|
|
|
define i64 @atomicrmw_usub_sat_i64(ptr %ptr, i64 %val) {
|
|
; CHECK-LABEL: atomicrmw_usub_sat_i64:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: sync
|
|
; CHECK-NEXT: ld 6, 0(3)
|
|
; CHECK-NEXT: b .LBB7_2
|
|
; CHECK-NEXT: .LBB7_1: # %cmpxchg.nostore
|
|
; CHECK-NEXT: # in Loop: Header=BB7_2 Depth=1
|
|
; CHECK-NEXT: mr 6, 5
|
|
; CHECK-NEXT: .LBB7_2: # %atomicrmw.start
|
|
; CHECK-NEXT: # =>This Loop Header: Depth=1
|
|
; CHECK-NEXT: # Child Loop BB7_4 Depth 2
|
|
; CHECK-NEXT: subc 5, 6, 4
|
|
; CHECK-NEXT: li 7, 0
|
|
; CHECK-NEXT: addze. 8, 7
|
|
; CHECK-NEXT: beq 0, .LBB7_4
|
|
; CHECK-NEXT: # %bb.3: # %atomicrmw.start
|
|
; CHECK-NEXT: # in Loop: Header=BB7_2 Depth=1
|
|
; CHECK-NEXT: mr 7, 5
|
|
; CHECK-NEXT: .LBB7_4: # %cmpxchg.start
|
|
; CHECK-NEXT: # Parent Loop BB7_2 Depth=1
|
|
; CHECK-NEXT: # => This Inner Loop Header: Depth=2
|
|
; CHECK-NEXT: ldarx 5, 0, 3
|
|
; CHECK-NEXT: cmpld 5, 6
|
|
; CHECK-NEXT: bne 0, .LBB7_1
|
|
; CHECK-NEXT: # %bb.5: # %cmpxchg.fencedstore
|
|
; CHECK-NEXT: # in Loop: Header=BB7_4 Depth=2
|
|
; CHECK-NEXT: stdcx. 7, 0, 3
|
|
; CHECK-NEXT: bne 0, .LBB7_4
|
|
; CHECK-NEXT: # %bb.6:
|
|
; CHECK-NEXT: mr 6, 5
|
|
; CHECK-NEXT: # %bb.7: # %atomicrmw.end
|
|
; CHECK-NEXT: mr 3, 5
|
|
; CHECK-NEXT: lwsync
|
|
; CHECK-NEXT: blr
|
|
%result = atomicrmw usub_sat ptr %ptr, i64 %val seq_cst
|
|
ret i64 %result
|
|
}
|