1 ; RUN: opt -atomic-expand -codegen-opt-level=1 -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: br label %[[START:.*]] 7 8 ; CHECK: [[START]]: 9 ; CHECK: [[LOADED:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* %addr) 10 ; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i32 [[LOADED]], %desired 11 ; CHECK: br i1 [[SHOULD_STORE]], label %[[FENCED_STORE:.*]], label %[[NO_STORE_BB:.*]] 12 13 ; CHECK: [[FENCED_STORE]]: 14 ; CHECK: call void @llvm.arm.dmb(i32 10) 15 ; CHECK: br label %[[TRY_STORE:.*]] 16 17 ; CHECK: [[TRY_STORE]]: 18 ; CHECK: [[STREX:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 %new, i32* %addr) 19 ; CHECK: [[SUCCESS:%.*]] = icmp eq i32 [[STREX]], 0 20 ; CHECK: br i1 [[SUCCESS]], label %[[SUCCESS_BB:.*]], label %[[FAILURE_BB:.*]] 21 22 ; CHECK: [[SUCCESS_BB]]: 23 ; CHECK: call void @llvm.arm.dmb(i32 11) 24 ; CHECK: br label %[[END:.*]] 25 26 ; CHECK: [[NO_STORE_BB]]: 27 ; CHECK: call void @llvm.arm.clrex() 28 ; CHECK: br label %[[FAILURE_BB]] 29 30 ; CHECK: [[FAILURE_BB]]: 31 ; CHECK: call void @llvm.arm.dmb(i32 11) 32 ; CHECK: br label %[[END]] 33 34 ; CHECK: [[END]]: 35 ; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ] 36 ; CHECK: ret i32 [[LOADED]] 37 38 %pair = cmpxchg weak i32* %addr, i32 %desired, i32 %new seq_cst seq_cst 39 %oldval = extractvalue { i32, i1 } %pair, 0 40 ret i32 %oldval 41 } 42 43 define i1 @test_cmpxchg_weak_fail(i32* %addr, i32 %desired, i32 %new) { 44 ; CHECK-LABEL: @test_cmpxchg_weak_fail 45 ; CHECK: br label %[[START:.*]] 46 47 ; CHECK: [[START]]: 48 ; CHECK: [[LOADED:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* %addr) 49 ; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i32 [[LOADED]], %desired 50 ; CHECK: br i1 [[SHOULD_STORE]], label %[[FENCED_STORE:.*]], label %[[NO_STORE_BB:.*]] 51 52 ; CHECK: [[FENCED_STORE]]: 53 ; CHECK: call void @llvm.arm.dmb(i32 10) 54 ; CHECK: br label %[[TRY_STORE:.*]] 55 56 ; CHECK: [[TRY_STORE]]: 57 ; CHECK: [[STREX:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 %new, i32* %addr) 58 ; CHECK: [[SUCCESS:%.*]] = icmp eq i32 [[STREX]], 0 59 ; CHECK: br i1 [[SUCCESS]], label %[[SUCCESS_BB:.*]], label %[[FAILURE_BB:.*]] 60 61 ; CHECK: [[SUCCESS_BB]]: 62 ; CHECK: call void @llvm.arm.dmb(i32 11) 63 ; CHECK: br label %[[END:.*]] 64 65 ; CHECK: [[NO_STORE_BB]]: 66 ; CHECK: call void @llvm.arm.clrex() 67 ; CHECK: br label %[[FAILURE_BB]] 68 69 ; CHECK: [[FAILURE_BB]]: 70 ; CHECK-NOT: dmb 71 ; CHECK: br label %[[END]] 72 73 ; CHECK: [[END]]: 74 ; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ] 75 ; CHECK: ret i1 [[SUCCESS]] 76 77 %pair = cmpxchg weak i32* %addr, i32 %desired, i32 %new seq_cst monotonic 78 %oldval = extractvalue { i32, i1 } %pair, 1 79 ret i1 %oldval 80 } 81 82 define i32 @test_cmpxchg_monotonic(i32* %addr, i32 %desired, i32 %new) { 83 ; CHECK-LABEL: @test_cmpxchg_monotonic 84 ; CHECK-NOT: dmb 85 ; CHECK: br label %[[START:.*]] 86 87 ; CHECK: [[START]]: 88 ; CHECK: [[LOADED:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* %addr) 89 ; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i32 [[LOADED]], %desired 90 ; CHECK: br i1 [[SHOULD_STORE]], label %[[TRY_STORE:.*]], label %[[NO_STORE_BB:.*]] 91 92 ; CHECK: [[TRY_STORE]]: 93 ; CHECK: [[STREX:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 %new, i32* %addr) 94 ; CHECK: [[SUCCESS:%.*]] = icmp eq i32 [[STREX]], 0 95 ; CHECK: br i1 [[SUCCESS]], label %[[SUCCESS_BB:.*]], label %[[FAILURE_BB:.*]] 96 97 ; CHECK: [[SUCCESS_BB]]: 98 ; CHECK-NOT: dmb 99 ; CHECK: br label %[[END:.*]] 100 101 ; CHECK: [[NO_STORE_BB]]: 102 ; CHECK: call void @llvm.arm.clrex() 103 ; CHECK: br label %[[FAILURE_BB]] 104 105 ; CHECK: [[FAILURE_BB]]: 106 ; CHECK-NOT: dmb 107 ; CHECK: br label %[[END]] 108 109 ; CHECK: [[END]]: 110 ; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ] 111 ; CHECK: ret i32 [[LOADED]] 112 113 %pair = cmpxchg weak i32* %addr, i32 %desired, i32 %new monotonic monotonic 114 %oldval = extractvalue { i32, i1 } %pair, 0 115 ret i32 %oldval 116 } 117 118 define i32 @test_cmpxchg_seq_cst_minsize(i32* %addr, i32 %desired, i32 %new) minsize { 119 ; CHECK-LABEL: @test_cmpxchg_seq_cst_minsize 120 ; CHECK: br label %[[START:.*]] 121 122 ; CHECK: [[START]]: 123 ; CHECK: [[LOADED:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* %addr) 124 ; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i32 [[LOADED]], %desired 125 ; CHECK: br i1 [[SHOULD_STORE]], label %[[FENCED_STORE:.*]], label %[[NO_STORE_BB:.*]] 126 127 ; CHECK: [[FENCED_STORE]]: 128 ; CHECK: call void @llvm.arm.dmb(i32 10) 129 ; CHECK: br label %[[TRY_STORE:.*]] 130 131 ; CHECK: [[TRY_STORE]]: 132 ; CHECK: [[STREX:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 %new, i32* %addr) 133 ; CHECK: [[SUCCESS:%.*]] = icmp eq i32 [[STREX]], 0 134 ; CHECK: br i1 [[SUCCESS]], label %[[SUCCESS_BB:.*]], label %[[FAILURE_BB:.*]] 135 136 ; CHECK: [[SUCCESS_BB]]: 137 ; CHECK: call void @llvm.arm.dmb(i32 11) 138 ; CHECK: br label %[[END:.*]] 139 140 ; CHECK: [[NO_STORE_BB]]: 141 ; CHECK: call void @llvm.arm.clrex() 142 ; CHECK: br label %[[FAILURE_BB]] 143 144 ; CHECK: [[FAILURE_BB]]: 145 ; CHECK: call void @llvm.arm.dmb(i32 11) 146 ; CHECK: br label %[[END]] 147 148 ; CHECK: [[END]]: 149 ; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ] 150 ; CHECK: ret i32 [[LOADED]] 151 152 %pair = cmpxchg weak i32* %addr, i32 %desired, i32 %new seq_cst seq_cst 153 %oldval = extractvalue { i32, i1 } %pair, 0 154 ret i32 %oldval 155 } 156