1; RUN: llc < %s -mtriple=armv7-apple-ios | FileCheck %s 2; RUN: llc < %s -mtriple=thumbv7-none-linux-gnueabihf -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-THUMB 3 4define i64 @test1(i64* %ptr, i64 %val) { 5; CHECK-LABEL: test1: 6; CHECK: dmb {{ish$}} 7; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]] 8; CHECK: adds [[REG3:(r[0-9]?[02468])]], [[REG1]] 9; CHECK: adc [[REG4:(r[0-9]?[13579])]], [[REG2]] 10; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 11; CHECK: cmp 12; CHECK: bne 13; CHECK: dmb {{ish$}} 14 15; CHECK-THUMB-LABEL: test1: 16; CHECK-THUMB: dmb {{ish$}} 17; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]] 18; CHECK-THUMB: adds.w [[REG3:[a-z0-9]+]], [[REG1]] 19; CHECK-THUMB: adc.w [[REG4:[a-z0-9]+]], [[REG2]] 20; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 21; CHECK-THUMB: cmp 22; CHECK-THUMB: bne 23; CHECK-THUMB: dmb {{ish$}} 24 25 %r = atomicrmw add i64* %ptr, i64 %val seq_cst 26 ret i64 %r 27} 28 29define i64 @test2(i64* %ptr, i64 %val) { 30; CHECK-LABEL: test2: 31; CHECK: dmb {{ish$}} 32; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]] 33; CHECK: subs [[REG3:(r[0-9]?[02468])]], [[REG1]] 34; CHECK: sbc [[REG4:(r[0-9]?[13579])]], [[REG2]] 35; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 36; CHECK: cmp 37; CHECK: bne 38; CHECK: dmb {{ish$}} 39 40; CHECK-THUMB-LABEL: test2: 41; CHECK-THUMB: dmb {{ish$}} 42; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]] 43; CHECK-THUMB: subs.w [[REG3:[a-z0-9]+]], [[REG1]] 44; CHECK-THUMB: sbc.w [[REG4:[a-z0-9]+]], [[REG2]] 45; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 46; CHECK-THUMB: cmp 47; CHECK-THUMB: bne 48; CHECK-THUMB: dmb {{ish$}} 49 50 %r = atomicrmw sub i64* %ptr, i64 %val seq_cst 51 ret i64 %r 52} 53 54define i64 @test3(i64* %ptr, i64 %val) { 55; CHECK-LABEL: test3: 56; CHECK: dmb {{ish$}} 57; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]] 58; CHECK: and [[REG3:(r[0-9]?[02468])]], [[REG1]] 59; CHECK: and [[REG4:(r[0-9]?[13579])]], [[REG2]] 60; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 61; CHECK: cmp 62; CHECK: bne 63; CHECK: dmb {{ish$}} 64 65; CHECK-THUMB-LABEL: test3: 66; CHECK-THUMB: dmb {{ish$}} 67; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]] 68; CHECK-THUMB: and.w [[REG3:[a-z0-9]+]], [[REG1]] 69; CHECK-THUMB: and.w [[REG4:[a-z0-9]+]], [[REG2]] 70; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 71; CHECK-THUMB: cmp 72; CHECK-THUMB: bne 73; CHECK-THUMB: dmb {{ish$}} 74 75 %r = atomicrmw and i64* %ptr, i64 %val seq_cst 76 ret i64 %r 77} 78 79define i64 @test4(i64* %ptr, i64 %val) { 80; CHECK-LABEL: test4: 81; CHECK: dmb {{ish$}} 82; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]] 83; CHECK: orr [[REG3:(r[0-9]?[02468])]], [[REG1]] 84; CHECK: orr [[REG4:(r[0-9]?[13579])]], [[REG2]] 85; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 86; CHECK: cmp 87; CHECK: bne 88; CHECK: dmb {{ish$}} 89 90; CHECK-THUMB-LABEL: test4: 91; CHECK-THUMB: dmb {{ish$}} 92; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]] 93; CHECK-THUMB: orr.w [[REG3:[a-z0-9]+]], [[REG1]] 94; CHECK-THUMB: orr.w [[REG4:[a-z0-9]+]], [[REG2]] 95; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 96; CHECK-THUMB: cmp 97; CHECK-THUMB: bne 98; CHECK-THUMB: dmb {{ish$}} 99 100 %r = atomicrmw or i64* %ptr, i64 %val seq_cst 101 ret i64 %r 102} 103 104define i64 @test5(i64* %ptr, i64 %val) { 105; CHECK-LABEL: test5: 106; CHECK: dmb {{ish$}} 107; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]] 108; CHECK: eor [[REG3:(r[0-9]?[02468])]], [[REG1]] 109; CHECK: eor [[REG4:(r[0-9]?[13579])]], [[REG2]] 110; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 111; CHECK: cmp 112; CHECK: bne 113; CHECK: dmb {{ish$}} 114 115; CHECK-THUMB-LABEL: test5: 116; CHECK-THUMB: dmb {{ish$}} 117; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]] 118; CHECK-THUMB: eor.w [[REG3:[a-z0-9]+]], [[REG1]] 119; CHECK-THUMB: eor.w [[REG4:[a-z0-9]+]], [[REG2]] 120; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 121; CHECK-THUMB: cmp 122; CHECK-THUMB: bne 123; CHECK-THUMB: dmb {{ish$}} 124 125 %r = atomicrmw xor i64* %ptr, i64 %val seq_cst 126 ret i64 %r 127} 128 129define i64 @test6(i64* %ptr, i64 %val) { 130; CHECK-LABEL: test6: 131; CHECK: dmb {{ish$}} 132; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]] 133; CHECK: strexd {{[a-z0-9]+}}, {{r[0-9]?[02468]}}, {{r[0-9]?[13579]}} 134; CHECK: cmp 135; CHECK: bne 136; CHECK: dmb {{ish$}} 137 138; CHECK-THUMB-LABEL: test6: 139; CHECK-THUMB: dmb {{ish$}} 140; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]] 141; CHECK-THUMB: strexd {{[a-z0-9]+}}, {{[a-z0-9]+}}, {{[a-z0-9]+}} 142; CHECK-THUMB: cmp 143; CHECK-THUMB: bne 144; CHECK-THUMB: dmb {{ish$}} 145 146 %r = atomicrmw xchg i64* %ptr, i64 %val seq_cst 147 ret i64 %r 148} 149 150define i64 @test7(i64* %ptr, i64 %val1, i64 %val2) { 151; CHECK-LABEL: test7: 152; CHECK: dmb {{ish$}} 153; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]] 154; CHECK: cmp [[REG1]] 155; CHECK: cmpeq [[REG2]] 156; CHECK: bne 157; CHECK: strexd {{[a-z0-9]+}}, {{r[0-9]?[02468]}}, {{r[0-9]?[13579]}} 158; CHECK: cmp 159; CHECK: bne 160; CHECK: dmb {{ish$}} 161 162; CHECK-THUMB-LABEL: test7: 163; CHECK-THUMB: dmb {{ish$}} 164; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]] 165; CHECK-THUMB: cmp [[REG1]] 166; CHECK-THUMB: it eq 167; CHECK-THUMB: cmpeq [[REG2]] 168; CHECK-THUMB: bne 169; CHECK-THUMB: strexd {{[a-z0-9]+}}, {{[a-z0-9]+}}, {{[a-z0-9]+}} 170; CHECK-THUMB: cmp 171; CHECK-THUMB: bne 172; CHECK-THUMB: dmb {{ish$}} 173 174 %r = cmpxchg i64* %ptr, i64 %val1, i64 %val2 seq_cst 175 ret i64 %r 176} 177 178; Compiles down to a single ldrexd 179define i64 @test8(i64* %ptr) { 180; CHECK-LABEL: test8: 181; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]] 182; CHECK: dmb {{ish$}} 183 184; CHECK-THUMB-LABEL: test8: 185; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]] 186; CHECK-THUMB: dmb {{ish$}} 187 188 %r = load atomic i64* %ptr seq_cst, align 8 189 ret i64 %r 190} 191 192; Compiles down to atomicrmw xchg; there really isn't any more efficient 193; way to write it. 194define void @test9(i64* %ptr, i64 %val) { 195; CHECK-LABEL: test9: 196; CHECK: dmb {{ish$}} 197; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]] 198; CHECK: strexd {{[a-z0-9]+}}, {{r[0-9]?[02468]}}, {{r[0-9]?[13579]}} 199; CHECK: cmp 200; CHECK: bne 201; CHECK: dmb {{ish$}} 202 203; CHECK-THUMB-LABEL: test9: 204; CHECK-THUMB: dmb {{ish$}} 205; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]] 206; CHECK-THUMB: strexd {{[a-z0-9]+}}, {{[a-z0-9]+}}, {{[a-z0-9]+}} 207; CHECK-THUMB: cmp 208; CHECK-THUMB: bne 209; CHECK-THUMB: dmb {{ish$}} 210 211 store atomic i64 %val, i64* %ptr seq_cst, align 8 212 ret void 213} 214 215define i64 @test10(i64* %ptr, i64 %val) { 216; CHECK-LABEL: test10: 217; CHECK: dmb {{ish$}} 218; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]] 219; CHECK: subs {{[a-z0-9]+}}, [[REG1]], [[REG3:(r[0-9]?[02468])]] 220; CHECK: sbcs {{[a-z0-9]+}}, [[REG2]], [[REG4:(r[0-9]?[13579])]] 221; CHECK: blt 222; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 223; CHECK: cmp 224; CHECK: bne 225; CHECK: dmb {{ish$}} 226 227; CHECK-THUMB-LABEL: test10: 228; CHECK-THUMB: dmb {{ish$}} 229; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]] 230; CHECK-THUMB: subs.w {{[a-z0-9]+}}, [[REG1]], [[REG3:[a-z0-9]+]] 231; CHECK-THUMB: sbcs.w {{[a-z0-9]+}}, [[REG2]], [[REG4:[a-z0-9]+]] 232; CHECK-THUMB: blt 233; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 234; CHECK-THUMB: cmp 235; CHECK-THUMB: bne 236; CHECK-THUMB: dmb {{ish$}} 237 238 %r = atomicrmw min i64* %ptr, i64 %val seq_cst 239 ret i64 %r 240} 241 242define i64 @test11(i64* %ptr, i64 %val) { 243; CHECK-LABEL: test11: 244; CHECK: dmb {{ish$}} 245; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]] 246; CHECK: subs {{[a-z0-9]+}}, [[REG1]], [[REG3:(r[0-9]?[02468])]] 247; CHECK: sbcs {{[a-z0-9]+}}, [[REG2]], [[REG4:(r[0-9]?[13579])]] 248; CHECK: blo 249; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 250; CHECK: cmp 251; CHECK: bne 252; CHECK: dmb {{ish$}} 253 254 255; CHECK-THUMB-LABEL: test11: 256; CHECK-THUMB: dmb {{ish$}} 257; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]] 258; CHECK-THUMB: subs.w {{[a-z0-9]+}}, [[REG1]], [[REG3:[a-z0-9]+]] 259; CHECK-THUMB: sbcs.w {{[a-z0-9]+}}, [[REG2]], [[REG4:[a-z0-9]+]] 260; CHECK-THUMB: blo 261; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 262; CHECK-THUMB: cmp 263; CHECK-THUMB: bne 264; CHECK-THUMB: dmb {{ish$}} 265 266 %r = atomicrmw umin i64* %ptr, i64 %val seq_cst 267 ret i64 %r 268} 269 270define i64 @test12(i64* %ptr, i64 %val) { 271; CHECK-LABEL: test12: 272; CHECK: dmb {{ish$}} 273; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]] 274; CHECK: subs {{[a-z0-9]+}}, [[REG1]], [[REG3:(r[0-9]?[02468])]] 275; CHECK: sbcs {{[a-z0-9]+}}, [[REG2]], [[REG4:(r[0-9]?[13579])]] 276; CHECK: bge 277; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 278; CHECK: cmp 279; CHECK: bne 280; CHECK: dmb {{ish$}} 281 282; CHECK-THUMB-LABEL: test12: 283; CHECK-THUMB: dmb {{ish$}} 284; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]] 285; CHECK-THUMB: subs.w {{[a-z0-9]+}}, [[REG1]], [[REG3:[a-z0-9]+]] 286; CHECK-THUMB: sbcs.w {{[a-z0-9]+}}, [[REG2]], [[REG4:[a-z0-9]+]] 287; CHECK-THUMB: bge 288; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 289; CHECK-THUMB: cmp 290; CHECK-THUMB: bne 291; CHECK-THUMB: dmb {{ish$}} 292 293 %r = atomicrmw max i64* %ptr, i64 %val seq_cst 294 ret i64 %r 295} 296 297define i64 @test13(i64* %ptr, i64 %val) { 298; CHECK-LABEL: test13: 299; CHECK: dmb {{ish$}} 300; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]] 301; CHECK: subs {{[a-z0-9]+}}, [[REG1]], [[REG3:(r[0-9]?[02468])]] 302; CHECK: sbcs {{[a-z0-9]+}}, [[REG2]], [[REG4:(r[0-9]?[13579])]] 303; CHECK: bhs 304; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 305; CHECK: cmp 306; CHECK: bne 307; CHECK: dmb {{ish$}} 308 309; CHECK-THUMB-LABEL: test13: 310; CHECK-THUMB: dmb {{ish$}} 311; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]] 312; CHECK-THUMB: subs.w {{[a-z0-9]+}}, [[REG1]], [[REG3:[a-z0-9]+]] 313; CHECK-THUMB: sbcs.w {{[a-z0-9]+}}, [[REG2]], [[REG4:[a-z0-9]+]] 314; CHECK-THUMB: bhs 315; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 316; CHECK-THUMB: cmp 317; CHECK-THUMB: bne 318; CHECK-THUMB: dmb {{ish$}} 319 %r = atomicrmw umax i64* %ptr, i64 %val seq_cst 320 ret i64 %r 321} 322 323