mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-29 14:40:25 +00:00
4b2698cf19
Fixes two latent bugs: - There was no fence inserted before expanded seq_cst load (unsound on Power) - There was only a fence release before seq_cst stores (again unsound, in particular on Power) It is not even clear if this is correct on ARM swift processors (where release fences are DMB ishst instead of DMB ish). This behaviour is currently preserved on ARM Swift as it is not clear whether it is incorrect. I would love to get documentation stating whether it is correct or not. These two bugs were not triggered because Power is not (yet) using this pass, and these behaviours happen to be (mostly?) working on ARM (although they completely butchered the semantics of the llvm IR). See: http://lists.cs.uiuc.edu/pipermail/llvmdev/2014-August/075821.html for an example of the problems that can be caused by the second of these bugs. I couldn't see a way of fixing these in a completely target-independent way without adding lots of unnecessary fences on ARM, hence the target-dependent parts of this patch. This patch implements the new target-dependent parts only for ARM (the default of not doing anything is enough for AArch64), other architectures will use this infrastructure in later patches. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@217076 91177308-0d34-0410-b5e6-96231b3b80d8
99 lines
3.5 KiB
LLVM
99 lines
3.5 KiB
LLVM
; RUN: opt -atomic-expand -S -mtriple=thumbv7s-apple-ios7.0 %s | FileCheck %s
|
|
|
|
define i32 @test_cmpxchg_seq_cst(i32* %addr, i32 %desired, i32 %new) {
|
|
; CHECK-LABEL: @test_cmpxchg_seq_cst
|
|
; Intrinsic for "dmb ishst" is then expected
|
|
; CHECK: call void @llvm.arm.dmb(i32 10)
|
|
; CHECK: br label %[[START:.*]]
|
|
|
|
; CHECK: [[START]]:
|
|
; CHECK: [[LOADED:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* %addr)
|
|
; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i32 [[LOADED]], %desired
|
|
; CHECK: br i1 [[SHOULD_STORE]], label %[[TRY_STORE:.*]], label %[[FAILURE_BB:.*]]
|
|
|
|
; CHECK: [[TRY_STORE]]:
|
|
; CHECK: [[STREX:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 %new, i32* %addr)
|
|
; CHECK: [[SUCCESS:%.*]] = icmp eq i32 [[STREX]], 0
|
|
; CHECK: br i1 [[SUCCESS]], label %[[SUCCESS_BB:.*]], label %[[FAILURE_BB]]
|
|
|
|
; CHECK: [[SUCCESS_BB]]:
|
|
; CHECK: call void @llvm.arm.dmb(i32 11)
|
|
; CHECK: br label %[[END:.*]]
|
|
|
|
; CHECK: [[FAILURE_BB]]:
|
|
; CHECK: call void @llvm.arm.dmb(i32 11)
|
|
; CHECK: br label %[[END]]
|
|
|
|
; CHECK: [[END]]:
|
|
; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ]
|
|
; CHECK: ret i32 [[LOADED]]
|
|
|
|
%pair = cmpxchg weak i32* %addr, i32 %desired, i32 %new seq_cst seq_cst
|
|
%oldval = extractvalue { i32, i1 } %pair, 0
|
|
ret i32 %oldval
|
|
}
|
|
|
|
define i1 @test_cmpxchg_weak_fail(i32* %addr, i32 %desired, i32 %new) {
|
|
; CHECK-LABEL: @test_cmpxchg_weak_fail
|
|
; CHECK: call void @llvm.arm.dmb(i32 10)
|
|
; CHECK: br label %[[START:.*]]
|
|
|
|
; CHECK: [[START]]:
|
|
; CHECK: [[LOADED:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* %addr)
|
|
; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i32 [[LOADED]], %desired
|
|
; CHECK: br i1 [[SHOULD_STORE]], label %[[TRY_STORE:.*]], label %[[FAILURE_BB:.*]]
|
|
|
|
; CHECK: [[TRY_STORE]]:
|
|
; CHECK: [[STREX:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 %new, i32* %addr)
|
|
; CHECK: [[SUCCESS:%.*]] = icmp eq i32 [[STREX]], 0
|
|
; CHECK: br i1 [[SUCCESS]], label %[[SUCCESS_BB:.*]], label %[[FAILURE_BB:.*]]
|
|
|
|
; CHECK: [[SUCCESS_BB]]:
|
|
; CHECK: call void @llvm.arm.dmb(i32 11)
|
|
; CHECK: br label %[[END:.*]]
|
|
|
|
; CHECK: [[FAILURE_BB]]:
|
|
; CHECK-NOT: dmb
|
|
; CHECK: br label %[[END]]
|
|
|
|
; CHECK: [[END]]:
|
|
; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ]
|
|
; CHECK: ret i1 [[SUCCESS]]
|
|
|
|
%pair = cmpxchg weak i32* %addr, i32 %desired, i32 %new seq_cst monotonic
|
|
%oldval = extractvalue { i32, i1 } %pair, 1
|
|
ret i1 %oldval
|
|
}
|
|
|
|
define i32 @test_cmpxchg_monotonic(i32* %addr, i32 %desired, i32 %new) {
|
|
; CHECK-LABEL: @test_cmpxchg_monotonic
|
|
; CHECK-NOT: dmb
|
|
; CHECK: br label %[[START:.*]]
|
|
|
|
; CHECK: [[START]]:
|
|
; CHECK: [[LOADED:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* %addr)
|
|
; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i32 [[LOADED]], %desired
|
|
; CHECK: br i1 [[SHOULD_STORE]], label %[[TRY_STORE:.*]], label %[[FAILURE_BB:.*]]
|
|
|
|
; CHECK: [[TRY_STORE]]:
|
|
; CHECK: [[STREX:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 %new, i32* %addr)
|
|
; CHECK: [[SUCCESS:%.*]] = icmp eq i32 [[STREX]], 0
|
|
; CHECK: br i1 [[SUCCESS]], label %[[SUCCESS_BB:.*]], label %[[FAILURE_BB:.*]]
|
|
|
|
; CHECK: [[SUCCESS_BB]]:
|
|
; CHECK-NOT: dmb
|
|
; CHECK: br label %[[END:.*]]
|
|
|
|
; CHECK: [[FAILURE_BB]]:
|
|
; CHECK-NOT: dmb
|
|
; CHECK: br label %[[END]]
|
|
|
|
; CHECK: [[END]]:
|
|
; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ]
|
|
; CHECK: ret i32 [[LOADED]]
|
|
|
|
%pair = cmpxchg weak i32* %addr, i32 %desired, i32 %new monotonic monotonic
|
|
%oldval = extractvalue { i32, i1 } %pair, 0
|
|
ret i32 %oldval
|
|
}
|