1; RUN: opt -atomic-expand -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: 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 40define 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 76define 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