1; RUN: llc -mtriple=arm64_32-apple-ios7.0 -o - %s | FileCheck %s 2; RUN: llc -mtriple=arm64_32-apple-ios7.0 -mattr=+outline-atomics -o - %s | FileCheck %s -check-prefix=OUTLINE-ATOMICS 3 4define i8 @test_load_8(i8* %addr) { 5; CHECK-LABAL: test_load_8: 6; CHECK: ldarb w0, [x0] 7 %val = load atomic i8, i8* %addr seq_cst, align 1 8 ret i8 %val 9} 10 11define i16 @test_load_16(i16* %addr) { 12; CHECK-LABAL: test_load_16: 13; CHECK: ldarh w0, [x0] 14 %val = load atomic i16, i16* %addr acquire, align 2 15 ret i16 %val 16} 17 18define i32 @test_load_32(i32* %addr) { 19; CHECK-LABAL: test_load_32: 20; CHECK: ldar w0, [x0] 21 %val = load atomic i32, i32* %addr seq_cst, align 4 22 ret i32 %val 23} 24 25define i64 @test_load_64(i64* %addr) { 26; CHECK-LABAL: test_load_64: 27; CHECK: ldar x0, [x0] 28 %val = load atomic i64, i64* %addr seq_cst, align 8 29 ret i64 %val 30} 31 32define i8* @test_load_ptr(i8** %addr) { 33; CHECK-LABAL: test_load_ptr: 34; CHECK: ldar w0, [x0] 35 %val = load atomic i8*, i8** %addr seq_cst, align 8 36 ret i8* %val 37} 38 39define void @test_store_8(i8* %addr) { 40; CHECK-LABAL: test_store_8: 41; CHECK: stlrb wzr, [x0] 42 store atomic i8 0, i8* %addr seq_cst, align 1 43 ret void 44} 45 46define void @test_store_16(i16* %addr) { 47; CHECK-LABAL: test_store_16: 48; CHECK: stlrh wzr, [x0] 49 store atomic i16 0, i16* %addr seq_cst, align 2 50 ret void 51} 52 53define void @test_store_32(i32* %addr) { 54; CHECK-LABAL: test_store_32: 55; CHECK: stlr wzr, [x0] 56 store atomic i32 0, i32* %addr seq_cst, align 4 57 ret void 58} 59 60define void @test_store_64(i64* %addr) { 61; CHECK-LABAL: test_store_64: 62; CHECK: stlr xzr, [x0] 63 store atomic i64 0, i64* %addr seq_cst, align 8 64 ret void 65} 66 67define void @test_store_ptr(i8** %addr) { 68; CHECK-LABAL: test_store_ptr: 69; CHECK: stlr wzr, [x0] 70 store atomic i8* null, i8** %addr seq_cst, align 8 71 ret void 72} 73 74declare i64 @llvm.aarch64.ldxr.p0i8(i8* %addr) 75declare i64 @llvm.aarch64.ldxr.p0i16(i16* %addr) 76declare i64 @llvm.aarch64.ldxr.p0i32(i32* %addr) 77declare i64 @llvm.aarch64.ldxr.p0i64(i64* %addr) 78 79define i8 @test_ldxr_8(i8* %addr) { 80; CHECK-LABEL: test_ldxr_8: 81; CHECK: ldxrb w0, [x0] 82 83 %val = call i64 @llvm.aarch64.ldxr.p0i8(i8* %addr) 84 %val8 = trunc i64 %val to i8 85 ret i8 %val8 86} 87 88define i16 @test_ldxr_16(i16* %addr) { 89; CHECK-LABEL: test_ldxr_16: 90; CHECK: ldxrh w0, [x0] 91 92 %val = call i64 @llvm.aarch64.ldxr.p0i16(i16* %addr) 93 %val16 = trunc i64 %val to i16 94 ret i16 %val16 95} 96 97define i32 @test_ldxr_32(i32* %addr) { 98; CHECK-LABEL: test_ldxr_32: 99; CHECK: ldxr w0, [x0] 100 101 %val = call i64 @llvm.aarch64.ldxr.p0i32(i32* %addr) 102 %val32 = trunc i64 %val to i32 103 ret i32 %val32 104} 105 106define i64 @test_ldxr_64(i64* %addr) { 107; CHECK-LABEL: test_ldxr_64: 108; CHECK: ldxr x0, [x0] 109 110 %val = call i64 @llvm.aarch64.ldxr.p0i64(i64* %addr) 111 ret i64 %val 112} 113 114declare i64 @llvm.aarch64.ldaxr.p0i8(i8* %addr) 115declare i64 @llvm.aarch64.ldaxr.p0i16(i16* %addr) 116declare i64 @llvm.aarch64.ldaxr.p0i32(i32* %addr) 117declare i64 @llvm.aarch64.ldaxr.p0i64(i64* %addr) 118 119define i8 @test_ldaxr_8(i8* %addr) { 120; CHECK-LABEL: test_ldaxr_8: 121; CHECK: ldaxrb w0, [x0] 122 123 %val = call i64 @llvm.aarch64.ldaxr.p0i8(i8* %addr) 124 %val8 = trunc i64 %val to i8 125 ret i8 %val8 126} 127 128define i16 @test_ldaxr_16(i16* %addr) { 129; CHECK-LABEL: test_ldaxr_16: 130; CHECK: ldaxrh w0, [x0] 131 132 %val = call i64 @llvm.aarch64.ldaxr.p0i16(i16* %addr) 133 %val16 = trunc i64 %val to i16 134 ret i16 %val16 135} 136 137define i32 @test_ldaxr_32(i32* %addr) { 138; CHECK-LABEL: test_ldaxr_32: 139; CHECK: ldaxr w0, [x0] 140 141 %val = call i64 @llvm.aarch64.ldaxr.p0i32(i32* %addr) 142 %val32 = trunc i64 %val to i32 143 ret i32 %val32 144} 145 146define i64 @test_ldaxr_64(i64* %addr) { 147; CHECK-LABEL: test_ldaxr_64: 148; CHECK: ldaxr x0, [x0] 149 150 %val = call i64 @llvm.aarch64.ldaxr.p0i64(i64* %addr) 151 ret i64 %val 152} 153 154declare i32 @llvm.aarch64.stxr.p0i8(i64, i8*) 155declare i32 @llvm.aarch64.stxr.p0i16(i64, i16*) 156declare i32 @llvm.aarch64.stxr.p0i32(i64, i32*) 157declare i32 @llvm.aarch64.stxr.p0i64(i64, i64*) 158 159define i32 @test_stxr_8(i8* %addr, i8 %val) { 160; CHECK-LABEL: test_stxr_8: 161; CHECK: stxrb [[TMP:w[0-9]+]], w1, [x0] 162; CHECK: mov w0, [[TMP]] 163 164 %extval = zext i8 %val to i64 165 %success = call i32 @llvm.aarch64.stxr.p0i8(i64 %extval, i8* %addr) 166 ret i32 %success 167} 168 169define i32 @test_stxr_16(i16* %addr, i16 %val) { 170; CHECK-LABEL: test_stxr_16: 171; CHECK: stxrh [[TMP:w[0-9]+]], w1, [x0] 172; CHECK: mov w0, [[TMP]] 173 174 %extval = zext i16 %val to i64 175 %success = call i32 @llvm.aarch64.stxr.p0i16(i64 %extval, i16* %addr) 176 ret i32 %success 177} 178 179define i32 @test_stxr_32(i32* %addr, i32 %val) { 180; CHECK-LABEL: test_stxr_32: 181; CHECK: stxr [[TMP:w[0-9]+]], w1, [x0] 182; CHECK: mov w0, [[TMP]] 183 184 %extval = zext i32 %val to i64 185 %success = call i32 @llvm.aarch64.stxr.p0i32(i64 %extval, i32* %addr) 186 ret i32 %success 187} 188 189define i32 @test_stxr_64(i64* %addr, i64 %val) { 190; CHECK-LABEL: test_stxr_64: 191; CHECK: stxr [[TMP:w[0-9]+]], x1, [x0] 192; CHECK: mov w0, [[TMP]] 193 194 %success = call i32 @llvm.aarch64.stxr.p0i64(i64 %val, i64* %addr) 195 ret i32 %success 196} 197 198declare i32 @llvm.aarch64.stlxr.p0i8(i64, i8*) 199declare i32 @llvm.aarch64.stlxr.p0i16(i64, i16*) 200declare i32 @llvm.aarch64.stlxr.p0i32(i64, i32*) 201declare i32 @llvm.aarch64.stlxr.p0i64(i64, i64*) 202 203define i32 @test_stlxr_8(i8* %addr, i8 %val) { 204; CHECK-LABEL: test_stlxr_8: 205; CHECK: stlxrb [[TMP:w[0-9]+]], w1, [x0] 206; CHECK: mov w0, [[TMP]] 207 208 %extval = zext i8 %val to i64 209 %success = call i32 @llvm.aarch64.stlxr.p0i8(i64 %extval, i8* %addr) 210 ret i32 %success 211} 212 213define i32 @test_stlxr_16(i16* %addr, i16 %val) { 214; CHECK-LABEL: test_stlxr_16: 215; CHECK: stlxrh [[TMP:w[0-9]+]], w1, [x0] 216; CHECK: mov w0, [[TMP]] 217 218 %extval = zext i16 %val to i64 219 %success = call i32 @llvm.aarch64.stlxr.p0i16(i64 %extval, i16* %addr) 220 ret i32 %success 221} 222 223define i32 @test_stlxr_32(i32* %addr, i32 %val) { 224; CHECK-LABEL: test_stlxr_32: 225; CHECK: stlxr [[TMP:w[0-9]+]], w1, [x0] 226; CHECK: mov w0, [[TMP]] 227 228 %extval = zext i32 %val to i64 229 %success = call i32 @llvm.aarch64.stlxr.p0i32(i64 %extval, i32* %addr) 230 ret i32 %success 231} 232 233define i32 @test_stlxr_64(i64* %addr, i64 %val) { 234; CHECK-LABEL: test_stlxr_64: 235; CHECK: stlxr [[TMP:w[0-9]+]], x1, [x0] 236; CHECK: mov w0, [[TMP]] 237 238 %success = call i32 @llvm.aarch64.stlxr.p0i64(i64 %val, i64* %addr) 239 ret i32 %success 240} 241 242define {i8*, i1} @test_cmpxchg_ptr(i8** %addr, i8* %cmp, i8* %new) { 243; OUTLINE-ATOMICS: bl ___aarch64_cas4_acq_rel 244; CHECK-LABEL: test_cmpxchg_ptr: 245; CHECK: [[LOOP:LBB[0-9]+_[0-9]+]]: 246; CHECK: ldaxr [[OLD:w[0-9]+]], [x0] 247; CHECK: cmp [[OLD]], w1 248; CHECK: b.ne [[DONE:LBB[0-9]+_[0-9]+]] 249; CHECK: stlxr [[SUCCESS:w[0-9]+]], w2, [x0] 250; CHECK: cbnz [[SUCCESS]], [[LOOP]] 251 252; CHECK: mov w1, #1 253; CHECK: mov w0, [[OLD]] 254; CHECK: ret 255 256; CHECK: [[DONE]]: 257; CHECK: clrex 258; CHECK: mov w1, wzr 259; CHECK: mov w0, [[OLD]] 260; CHECK: ret 261 %res = cmpxchg i8** %addr, i8* %cmp, i8* %new acq_rel acquire 262 ret {i8*, i1} %res 263} 264