1; RUN: opt -atomic-expand -codegen-opt-level=1 -S -mtriple=thumbv7s-apple-ios7.0 %s | FileCheck %s 2 3define 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 43define 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 82define 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 118define 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