1 ; RUN: opt -atomic-expand -S -mtriple=thumbv7s-apple-ios7.0 %s | FileCheck %s 2 3 define i32 @test_cmpxchg_seq_cst(i32* %addr, i32 %desired, i32 %new) { 4 ; CHECK-LABEL: @test_cmpxchg_seq_cst 5 ; Intrinsic for "dmb ishst" is then expected 6 ; CHECK: call void @llvm.arm.dmb(i32 10) 7 ; CHECK: br label %[[START:.*]] 8 9 ; CHECK: [[START]]: 10 ; CHECK: [[LOADED:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* %addr) 11 ; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i32 [[LOADED]], %desired 12 ; CHECK: br i1 [[SHOULD_STORE]], label %[[TRY_STORE:.*]], label %[[NO_STORE_BB:.*]] 13 14 ; CHECK: [[TRY_STORE]]: 15 ; CHECK: [[STREX:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 %new, i32* %addr) 16 ; CHECK: [[SUCCESS:%.*]] = icmp eq i32 [[STREX]], 0 17 ; CHECK: br i1 [[SUCCESS]], label %[[SUCCESS_BB:.*]], label %[[FAILURE_BB:.*]] 18 19 ; CHECK: [[SUCCESS_BB]]: 20 ; CHECK: call void @llvm.arm.dmb(i32 11) 21 ; CHECK: br label %[[END:.*]] 22 23 ; CHECK: [[NO_STORE_BB]]: 24 ; CHECK: call void @llvm.arm.clrex() 25 ; CHECK: br label %[[FAILURE_BB]] 26 27 ; CHECK: [[FAILURE_BB]]: 28 ; CHECK: call void @llvm.arm.dmb(i32 11) 29 ; CHECK: br label %[[END]] 30 31 ; CHECK: [[END]]: 32 ; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ] 33 ; CHECK: ret i32 [[LOADED]] 34 35 %pair = cmpxchg weak i32* %addr, i32 %desired, i32 %new seq_cst seq_cst 36 %oldval = extractvalue { i32, i1 } %pair, 0 37 ret i32 %oldval 38 } 39 40 define i1 @test_cmpxchg_weak_fail(i32* %addr, i32 %desired, i32 %new) { 41 ; CHECK-LABEL: @test_cmpxchg_weak_fail 42 ; CHECK: call void @llvm.arm.dmb(i32 10) 43 ; CHECK: br label %[[START:.*]] 44 45 ; CHECK: [[START]]: 46 ; CHECK: [[LOADED:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* %addr) 47 ; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i32 [[LOADED]], %desired 48 ; CHECK: br i1 [[SHOULD_STORE]], label %[[TRY_STORE:.*]], label %[[NO_STORE_BB:.*]] 49 50 ; CHECK: [[TRY_STORE]]: 51 ; CHECK: [[STREX:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 %new, i32* %addr) 52 ; CHECK: [[SUCCESS:%.*]] = icmp eq i32 [[STREX]], 0 53 ; CHECK: br i1 [[SUCCESS]], label %[[SUCCESS_BB:.*]], label %[[FAILURE_BB:.*]] 54 55 ; CHECK: [[SUCCESS_BB]]: 56 ; CHECK: call void @llvm.arm.dmb(i32 11) 57 ; CHECK: br label %[[END:.*]] 58 59 ; CHECK: [[NO_STORE_BB]]: 60 ; CHECK: call void @llvm.arm.clrex() 61 ; CHECK: br label %[[FAILURE_BB]] 62 63 ; CHECK: [[FAILURE_BB]]: 64 ; CHECK-NOT: dmb 65 ; CHECK: br label %[[END]] 66 67 ; CHECK: [[END]]: 68 ; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ] 69 ; CHECK: ret i1 [[SUCCESS]] 70 71 %pair = cmpxchg weak i32* %addr, i32 %desired, i32 %new seq_cst monotonic 72 %oldval = extractvalue { i32, i1 } %pair, 1 73 ret i1 %oldval 74 } 75 76 define i32 @test_cmpxchg_monotonic(i32* %addr, i32 %desired, i32 %new) { 77 ; CHECK-LABEL: @test_cmpxchg_monotonic 78 ; CHECK-NOT: dmb 79 ; CHECK: br label %[[START:.*]] 80 81 ; CHECK: [[START]]: 82 ; CHECK: [[LOADED:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* %addr) 83 ; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i32 [[LOADED]], %desired 84 ; CHECK: br i1 [[SHOULD_STORE]], label %[[TRY_STORE:.*]], label %[[NO_STORE_BB:.*]] 85 86 ; CHECK: [[TRY_STORE]]: 87 ; CHECK: [[STREX:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 %new, i32* %addr) 88 ; CHECK: [[SUCCESS:%.*]] = icmp eq i32 [[STREX]], 0 89 ; CHECK: br i1 [[SUCCESS]], label %[[SUCCESS_BB:.*]], label %[[FAILURE_BB:.*]] 90 91 ; CHECK: [[SUCCESS_BB]]: 92 ; CHECK-NOT: dmb 93 ; CHECK: br label %[[END:.*]] 94 95 ; CHECK: [[NO_STORE_BB]]: 96 ; CHECK: call void @llvm.arm.clrex() 97 ; CHECK: br label %[[FAILURE_BB]] 98 99 ; CHECK: [[FAILURE_BB]]: 100 ; CHECK-NOT: dmb 101 ; CHECK: br label %[[END]] 102 103 ; CHECK: [[END]]: 104 ; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ] 105 ; CHECK: ret i32 [[LOADED]] 106 107 %pair = cmpxchg weak i32* %addr, i32 %desired, i32 %new monotonic monotonic 108 %oldval = extractvalue { i32, i1 } %pair, 0 109 ret i32 %oldval 110 } 111