1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=thumbv6m-none-eabi < %s | FileCheck %s --check-prefixes=CHECK,NO-ATOMIC32 3; RUN: llc -mtriple=thumbv6m-none-eabi -mattr=+atomics-32 < %s | FileCheck %s --check-prefixes=CHECK,ATOMIC32 4 5define i8 @load8(ptr %p) { 6; NO-ATOMIC32-LABEL: load8: 7; NO-ATOMIC32: @ %bb.0: 8; NO-ATOMIC32-NEXT: .save {r7, lr} 9; NO-ATOMIC32-NEXT: push {r7, lr} 10; NO-ATOMIC32-NEXT: movs r1, #5 11; NO-ATOMIC32-NEXT: bl __atomic_load_1 12; NO-ATOMIC32-NEXT: pop {r7, pc} 13; 14; ATOMIC32-LABEL: load8: 15; ATOMIC32: @ %bb.0: 16; ATOMIC32-NEXT: ldrb r0, [r0] 17; ATOMIC32-NEXT: dmb sy 18; ATOMIC32-NEXT: bx lr 19 %v = load atomic i8, ptr %p seq_cst, align 1 20 ret i8 %v 21} 22 23define void @store8(ptr %p) { 24; NO-ATOMIC32-LABEL: store8: 25; NO-ATOMIC32: @ %bb.0: 26; NO-ATOMIC32-NEXT: .save {r7, lr} 27; NO-ATOMIC32-NEXT: push {r7, lr} 28; NO-ATOMIC32-NEXT: movs r1, #0 29; NO-ATOMIC32-NEXT: movs r2, #5 30; NO-ATOMIC32-NEXT: bl __atomic_store_1 31; NO-ATOMIC32-NEXT: pop {r7, pc} 32; 33; ATOMIC32-LABEL: store8: 34; ATOMIC32: @ %bb.0: 35; ATOMIC32-NEXT: dmb sy 36; ATOMIC32-NEXT: movs r1, #0 37; ATOMIC32-NEXT: strb r1, [r0] 38; ATOMIC32-NEXT: dmb sy 39; ATOMIC32-NEXT: bx lr 40 store atomic i8 0, ptr %p seq_cst, align 1 41 ret void 42} 43 44define i8 @rmw8(ptr %p) { 45; NO-ATOMIC32-LABEL: rmw8: 46; NO-ATOMIC32: @ %bb.0: 47; NO-ATOMIC32-NEXT: .save {r7, lr} 48; NO-ATOMIC32-NEXT: push {r7, lr} 49; NO-ATOMIC32-NEXT: movs r1, #1 50; NO-ATOMIC32-NEXT: movs r2, #5 51; NO-ATOMIC32-NEXT: bl __atomic_fetch_add_1 52; NO-ATOMIC32-NEXT: pop {r7, pc} 53; 54; ATOMIC32-LABEL: rmw8: 55; ATOMIC32: @ %bb.0: 56; ATOMIC32-NEXT: .save {r7, lr} 57; ATOMIC32-NEXT: push {r7, lr} 58; ATOMIC32-NEXT: dmb sy 59; ATOMIC32-NEXT: movs r1, #1 60; ATOMIC32-NEXT: bl __sync_fetch_and_add_1 61; ATOMIC32-NEXT: dmb sy 62; ATOMIC32-NEXT: pop {r7, pc} 63 %v = atomicrmw add ptr %p, i8 1 seq_cst, align 1 64 ret i8 %v 65} 66 67define i8 @cmpxchg8(ptr %p) { 68; NO-ATOMIC32-LABEL: cmpxchg8: 69; NO-ATOMIC32: @ %bb.0: 70; NO-ATOMIC32-NEXT: .save {r7, lr} 71; NO-ATOMIC32-NEXT: push {r7, lr} 72; NO-ATOMIC32-NEXT: .pad #8 73; NO-ATOMIC32-NEXT: sub sp, #8 74; NO-ATOMIC32-NEXT: add r1, sp, #4 75; NO-ATOMIC32-NEXT: movs r2, #0 76; NO-ATOMIC32-NEXT: strb r2, [r1] 77; NO-ATOMIC32-NEXT: movs r3, #5 78; NO-ATOMIC32-NEXT: str r3, [sp] 79; NO-ATOMIC32-NEXT: movs r2, #1 80; NO-ATOMIC32-NEXT: bl __atomic_compare_exchange_1 81; NO-ATOMIC32-NEXT: ldr r0, [sp, #4] 82; NO-ATOMIC32-NEXT: add sp, #8 83; NO-ATOMIC32-NEXT: pop {r7, pc} 84; 85; ATOMIC32-LABEL: cmpxchg8: 86; ATOMIC32: @ %bb.0: 87; ATOMIC32-NEXT: .save {r7, lr} 88; ATOMIC32-NEXT: push {r7, lr} 89; ATOMIC32-NEXT: dmb sy 90; ATOMIC32-NEXT: movs r1, #0 91; ATOMIC32-NEXT: movs r2, #1 92; ATOMIC32-NEXT: bl __sync_val_compare_and_swap_1 93; ATOMIC32-NEXT: dmb sy 94; ATOMIC32-NEXT: pop {r7, pc} 95 %res = cmpxchg ptr %p, i8 0, i8 1 seq_cst seq_cst 96 %res.0 = extractvalue { i8, i1 } %res, 0 97 ret i8 %res.0 98} 99 100define i16 @load16(ptr %p) { 101; NO-ATOMIC32-LABEL: load16: 102; NO-ATOMIC32: @ %bb.0: 103; NO-ATOMIC32-NEXT: .save {r7, lr} 104; NO-ATOMIC32-NEXT: push {r7, lr} 105; NO-ATOMIC32-NEXT: movs r1, #5 106; NO-ATOMIC32-NEXT: bl __atomic_load_2 107; NO-ATOMIC32-NEXT: pop {r7, pc} 108; 109; ATOMIC32-LABEL: load16: 110; ATOMIC32: @ %bb.0: 111; ATOMIC32-NEXT: ldrh r0, [r0] 112; ATOMIC32-NEXT: dmb sy 113; ATOMIC32-NEXT: bx lr 114 %v = load atomic i16, ptr %p seq_cst, align 2 115 ret i16 %v 116} 117 118define void @store16(ptr %p) { 119; NO-ATOMIC32-LABEL: store16: 120; NO-ATOMIC32: @ %bb.0: 121; NO-ATOMIC32-NEXT: .save {r7, lr} 122; NO-ATOMIC32-NEXT: push {r7, lr} 123; NO-ATOMIC32-NEXT: movs r1, #0 124; NO-ATOMIC32-NEXT: movs r2, #5 125; NO-ATOMIC32-NEXT: bl __atomic_store_2 126; NO-ATOMIC32-NEXT: pop {r7, pc} 127; 128; ATOMIC32-LABEL: store16: 129; ATOMIC32: @ %bb.0: 130; ATOMIC32-NEXT: dmb sy 131; ATOMIC32-NEXT: movs r1, #0 132; ATOMIC32-NEXT: strh r1, [r0] 133; ATOMIC32-NEXT: dmb sy 134; ATOMIC32-NEXT: bx lr 135 store atomic i16 0, ptr %p seq_cst, align 2 136 ret void 137} 138 139define i16 @rmw16(ptr %p) { 140; NO-ATOMIC32-LABEL: rmw16: 141; NO-ATOMIC32: @ %bb.0: 142; NO-ATOMIC32-NEXT: .save {r7, lr} 143; NO-ATOMIC32-NEXT: push {r7, lr} 144; NO-ATOMIC32-NEXT: movs r1, #1 145; NO-ATOMIC32-NEXT: movs r2, #5 146; NO-ATOMIC32-NEXT: bl __atomic_fetch_add_2 147; NO-ATOMIC32-NEXT: pop {r7, pc} 148; 149; ATOMIC32-LABEL: rmw16: 150; ATOMIC32: @ %bb.0: 151; ATOMIC32-NEXT: .save {r7, lr} 152; ATOMIC32-NEXT: push {r7, lr} 153; ATOMIC32-NEXT: dmb sy 154; ATOMIC32-NEXT: movs r1, #1 155; ATOMIC32-NEXT: bl __sync_fetch_and_add_2 156; ATOMIC32-NEXT: dmb sy 157; ATOMIC32-NEXT: pop {r7, pc} 158 %v = atomicrmw add ptr %p, i16 1 seq_cst, align 2 159 ret i16 %v 160} 161 162define i16 @cmpxchg16(ptr %p) { 163; NO-ATOMIC32-LABEL: cmpxchg16: 164; NO-ATOMIC32: @ %bb.0: 165; NO-ATOMIC32-NEXT: .save {r7, lr} 166; NO-ATOMIC32-NEXT: push {r7, lr} 167; NO-ATOMIC32-NEXT: .pad #8 168; NO-ATOMIC32-NEXT: sub sp, #8 169; NO-ATOMIC32-NEXT: add r1, sp, #4 170; NO-ATOMIC32-NEXT: movs r2, #0 171; NO-ATOMIC32-NEXT: strh r2, [r1] 172; NO-ATOMIC32-NEXT: movs r3, #5 173; NO-ATOMIC32-NEXT: str r3, [sp] 174; NO-ATOMIC32-NEXT: movs r2, #1 175; NO-ATOMIC32-NEXT: bl __atomic_compare_exchange_2 176; NO-ATOMIC32-NEXT: ldr r0, [sp, #4] 177; NO-ATOMIC32-NEXT: add sp, #8 178; NO-ATOMIC32-NEXT: pop {r7, pc} 179; 180; ATOMIC32-LABEL: cmpxchg16: 181; ATOMIC32: @ %bb.0: 182; ATOMIC32-NEXT: .save {r7, lr} 183; ATOMIC32-NEXT: push {r7, lr} 184; ATOMIC32-NEXT: dmb sy 185; ATOMIC32-NEXT: movs r1, #0 186; ATOMIC32-NEXT: movs r2, #1 187; ATOMIC32-NEXT: bl __sync_val_compare_and_swap_2 188; ATOMIC32-NEXT: dmb sy 189; ATOMIC32-NEXT: pop {r7, pc} 190 %res = cmpxchg ptr %p, i16 0, i16 1 seq_cst seq_cst 191 %res.0 = extractvalue { i16, i1 } %res, 0 192 ret i16 %res.0 193} 194 195define i32 @load32(ptr %p) { 196; NO-ATOMIC32-LABEL: load32: 197; NO-ATOMIC32: @ %bb.0: 198; NO-ATOMIC32-NEXT: .save {r7, lr} 199; NO-ATOMIC32-NEXT: push {r7, lr} 200; NO-ATOMIC32-NEXT: movs r1, #5 201; NO-ATOMIC32-NEXT: bl __atomic_load_4 202; NO-ATOMIC32-NEXT: pop {r7, pc} 203; 204; ATOMIC32-LABEL: load32: 205; ATOMIC32: @ %bb.0: 206; ATOMIC32-NEXT: ldr r0, [r0] 207; ATOMIC32-NEXT: dmb sy 208; ATOMIC32-NEXT: bx lr 209 %v = load atomic i32, ptr %p seq_cst, align 4 210 ret i32 %v 211} 212 213define void @store32(ptr %p) { 214; NO-ATOMIC32-LABEL: store32: 215; NO-ATOMIC32: @ %bb.0: 216; NO-ATOMIC32-NEXT: .save {r7, lr} 217; NO-ATOMIC32-NEXT: push {r7, lr} 218; NO-ATOMIC32-NEXT: movs r1, #0 219; NO-ATOMIC32-NEXT: movs r2, #5 220; NO-ATOMIC32-NEXT: bl __atomic_store_4 221; NO-ATOMIC32-NEXT: pop {r7, pc} 222; 223; ATOMIC32-LABEL: store32: 224; ATOMIC32: @ %bb.0: 225; ATOMIC32-NEXT: dmb sy 226; ATOMIC32-NEXT: movs r1, #0 227; ATOMIC32-NEXT: str r1, [r0] 228; ATOMIC32-NEXT: dmb sy 229; ATOMIC32-NEXT: bx lr 230 store atomic i32 0, ptr %p seq_cst, align 4 231 ret void 232} 233 234define i32 @rmw32(ptr %p) { 235; NO-ATOMIC32-LABEL: rmw32: 236; NO-ATOMIC32: @ %bb.0: 237; NO-ATOMIC32-NEXT: .save {r7, lr} 238; NO-ATOMIC32-NEXT: push {r7, lr} 239; NO-ATOMIC32-NEXT: movs r1, #1 240; NO-ATOMIC32-NEXT: movs r2, #5 241; NO-ATOMIC32-NEXT: bl __atomic_fetch_add_4 242; NO-ATOMIC32-NEXT: pop {r7, pc} 243; 244; ATOMIC32-LABEL: rmw32: 245; ATOMIC32: @ %bb.0: 246; ATOMIC32-NEXT: .save {r7, lr} 247; ATOMIC32-NEXT: push {r7, lr} 248; ATOMIC32-NEXT: dmb sy 249; ATOMIC32-NEXT: movs r1, #1 250; ATOMIC32-NEXT: bl __sync_fetch_and_add_4 251; ATOMIC32-NEXT: dmb sy 252; ATOMIC32-NEXT: pop {r7, pc} 253 %v = atomicrmw add ptr %p, i32 1 seq_cst, align 4 254 ret i32 %v 255} 256 257define i32 @cmpxchg32(ptr %p) { 258; NO-ATOMIC32-LABEL: cmpxchg32: 259; NO-ATOMIC32: @ %bb.0: 260; NO-ATOMIC32-NEXT: .save {r7, lr} 261; NO-ATOMIC32-NEXT: push {r7, lr} 262; NO-ATOMIC32-NEXT: .pad #8 263; NO-ATOMIC32-NEXT: sub sp, #8 264; NO-ATOMIC32-NEXT: movs r1, #0 265; NO-ATOMIC32-NEXT: str r1, [sp, #4] 266; NO-ATOMIC32-NEXT: movs r3, #5 267; NO-ATOMIC32-NEXT: str r3, [sp] 268; NO-ATOMIC32-NEXT: add r1, sp, #4 269; NO-ATOMIC32-NEXT: movs r2, #1 270; NO-ATOMIC32-NEXT: bl __atomic_compare_exchange_4 271; NO-ATOMIC32-NEXT: ldr r0, [sp, #4] 272; NO-ATOMIC32-NEXT: add sp, #8 273; NO-ATOMIC32-NEXT: pop {r7, pc} 274; 275; ATOMIC32-LABEL: cmpxchg32: 276; ATOMIC32: @ %bb.0: 277; ATOMIC32-NEXT: .save {r7, lr} 278; ATOMIC32-NEXT: push {r7, lr} 279; ATOMIC32-NEXT: dmb sy 280; ATOMIC32-NEXT: movs r1, #0 281; ATOMIC32-NEXT: movs r2, #1 282; ATOMIC32-NEXT: bl __sync_val_compare_and_swap_4 283; ATOMIC32-NEXT: dmb sy 284; ATOMIC32-NEXT: pop {r7, pc} 285 %res = cmpxchg ptr %p, i32 0, i32 1 seq_cst seq_cst 286 %res.0 = extractvalue { i32, i1 } %res, 0 287 ret i32 %res.0 288} 289 290define i64 @load64(ptr %p) { 291; CHECK-LABEL: load64: 292; CHECK: @ %bb.0: 293; CHECK-NEXT: .save {r7, lr} 294; CHECK-NEXT: push {r7, lr} 295; CHECK-NEXT: movs r1, #5 296; CHECK-NEXT: bl __atomic_load_8 297; CHECK-NEXT: pop {r7, pc} 298 %v = load atomic i64, ptr %p seq_cst, align 8 299 ret i64 %v 300} 301 302define void @store64(ptr %p) { 303; CHECK-LABEL: store64: 304; CHECK: @ %bb.0: 305; CHECK-NEXT: .save {r7, lr} 306; CHECK-NEXT: push {r7, lr} 307; CHECK-NEXT: .pad #8 308; CHECK-NEXT: sub sp, #8 309; CHECK-NEXT: movs r1, #5 310; CHECK-NEXT: str r1, [sp] 311; CHECK-NEXT: movs r2, #0 312; CHECK-NEXT: mov r3, r2 313; CHECK-NEXT: bl __atomic_store_8 314; CHECK-NEXT: add sp, #8 315; CHECK-NEXT: pop {r7, pc} 316 store atomic i64 0, ptr %p seq_cst, align 8 317 ret void 318} 319 320define i64 @rmw64(ptr %p) { 321; CHECK-LABEL: rmw64: 322; CHECK: @ %bb.0: 323; CHECK-NEXT: .save {r7, lr} 324; CHECK-NEXT: push {r7, lr} 325; CHECK-NEXT: .pad #8 326; CHECK-NEXT: sub sp, #8 327; CHECK-NEXT: movs r1, #5 328; CHECK-NEXT: str r1, [sp] 329; CHECK-NEXT: movs r2, #1 330; CHECK-NEXT: movs r3, #0 331; CHECK-NEXT: bl __atomic_fetch_add_8 332; CHECK-NEXT: add sp, #8 333; CHECK-NEXT: pop {r7, pc} 334 %v = atomicrmw add ptr %p, i64 1 seq_cst, align 8 335 ret i64 %v 336} 337 338define i64 @cmpxchg64(ptr %p) { 339; CHECK-LABEL: cmpxchg64: 340; CHECK: @ %bb.0: 341; CHECK-NEXT: .save {r7, lr} 342; CHECK-NEXT: push {r7, lr} 343; CHECK-NEXT: .pad #16 344; CHECK-NEXT: sub sp, #16 345; CHECK-NEXT: movs r3, #0 346; CHECK-NEXT: str r3, [sp, #12] 347; CHECK-NEXT: str r3, [sp, #8] 348; CHECK-NEXT: movs r1, #5 349; CHECK-NEXT: str r1, [sp] 350; CHECK-NEXT: str r1, [sp, #4] 351; CHECK-NEXT: add r1, sp, #8 352; CHECK-NEXT: movs r2, #1 353; CHECK-NEXT: bl __atomic_compare_exchange_8 354; CHECK-NEXT: ldr r1, [sp, #12] 355; CHECK-NEXT: ldr r0, [sp, #8] 356; CHECK-NEXT: add sp, #16 357; CHECK-NEXT: pop {r7, pc} 358 %res = cmpxchg ptr %p, i64 0, i64 1 seq_cst seq_cst 359 %res.0 = extractvalue { i64, i1 } %res, 0 360 ret i64 %res.0 361} 362