1; RUN: llc -verify-machineinstrs -mtriple=armv7-linux-gnu -O0 %s -o - | FileCheck %s 2; RUN: llc -verify-machineinstrs -mtriple=thumbv8-linux-gnu -O0 %s -o - | FileCheck %s 3; RUN: llc -verify-machineinstrs -mtriple=thumbv6m-none-eabi -O0 %s -o - | FileCheck %s --check-prefix=CHECK-T1 4 5; CHECK-T1-NOT: ldrex 6; CHECK-T1-NOT: strex 7 8define { i8, i1 } @test_cmpxchg_8(i8* %addr, i8 %desired, i8 %new) nounwind { 9; CHECK-LABEL: test_cmpxchg_8: 10; CHECK: dmb ish 11; CHECK: uxtb [[DESIRED:r[0-9]+]], [[DESIRED]] 12; CHECK: [[RETRY:.LBB[0-9]+_[0-9]+]]: 13; CHECK: ldrexb [[OLD:r[0-9]+]], [r0] 14; CHECK: cmp [[OLD]], [[DESIRED]] 15; CHECK: bne [[DONE:.LBB[0-9]+_[0-9]+]] 16; CHECK: strexb [[STATUS:r[0-9]+]], r2, [r0] 17; CHECK: cmp{{(\.w)?}} [[STATUS]], #0 18; CHECK: bne [[RETRY]] 19; CHECK: [[DONE]]: 20; Materialisation of a boolean is done with sub/clz/lsr 21; CHECK: uxtb [[CMP1:r[0-9]+]], [[DESIRED]] 22; CHECK: sub{{(s)?}} [[CMP1]], [[OLD]], [[CMP1]] 23; CHECK: clz [[CMP2:r[0-9]+]], [[CMP1]] 24; CHECK: lsr{{(s)?}} {{r[0-9]+}}, [[CMP2]], #5 25; CHECK: dmb ish 26 %res = cmpxchg i8* %addr, i8 %desired, i8 %new seq_cst monotonic 27 ret { i8, i1 } %res 28} 29 30define { i16, i1 } @test_cmpxchg_16(i16* %addr, i16 %desired, i16 %new) nounwind { 31; CHECK-LABEL: test_cmpxchg_16: 32; CHECK: dmb ish 33; CHECK: uxth [[DESIRED:r[0-9]+]], [[DESIRED]] 34; CHECK: [[RETRY:.LBB[0-9]+_[0-9]+]]: 35; CHECK: ldrexh [[OLD:r[0-9]+]], [r0] 36; CHECK: cmp [[OLD]], [[DESIRED]] 37; CHECK: bne [[DONE:.LBB[0-9]+_[0-9]+]] 38; CHECK: strexh [[STATUS:r[0-9]+]], r2, [r0] 39; CHECK: cmp{{(\.w)?}} [[STATUS]], #0 40; CHECK: bne [[RETRY]] 41; CHECK: [[DONE]]: 42; Materialisation of a boolean is done with sub/clz/lsr 43; CHECK: uxth [[CMP1:r[0-9]+]], [[DESIRED]] 44; CHECK: sub{{(s)?}} [[CMP1]], [[OLD]], [[CMP1]] 45; CHECK: clz [[CMP2:r[0-9]+]], [[CMP1]] 46; CHECK: lsr{{(s)?}} {{r[0-9]+}}, [[CMP2]], #5 47; CHECK: dmb ish 48 %res = cmpxchg i16* %addr, i16 %desired, i16 %new seq_cst monotonic 49 ret { i16, i1 } %res 50} 51 52define { i32, i1 } @test_cmpxchg_32(i32* %addr, i32 %desired, i32 %new) nounwind { 53; CHECK-LABEL: test_cmpxchg_32: 54; CHECK: dmb ish 55; CHECK-NOT: uxt 56; CHECK: [[RETRY:.LBB[0-9]+_[0-9]+]]: 57; CHECK: ldrex [[OLD:r[0-9]+]], [r0] 58; CHECK: cmp [[OLD]], [[DESIRED]] 59; CHECK: bne [[DONE:.LBB[0-9]+_[0-9]+]] 60; CHECK: strex [[STATUS:r[0-9]+]], r2, [r0] 61; CHECK: cmp{{(\.w)?}} [[STATUS]], #0 62; CHECK: bne [[RETRY]] 63; CHECK: [[DONE]]: 64; Materialisation of a boolean is done with sub/clz/lsr 65; CHECK: sub{{(s)?}} [[CMP1:r[0-9]+]], [[OLD]], [[DESIRED]] 66; CHECK: clz [[CMP2:r[0-9]+]], [[CMP1]] 67; CHECK: lsr{{(s)?}} {{r[0-9]+}}, [[CMP2]], #5 68; CHECK: dmb ish 69 %res = cmpxchg i32* %addr, i32 %desired, i32 %new seq_cst monotonic 70 ret { i32, i1 } %res 71} 72 73define { i64, i1 } @test_cmpxchg_64(i64* %addr, i64 %desired, i64 %new) nounwind { 74; CHECK-LABEL: test_cmpxchg_64: 75; CHECK: dmb ish 76; CHECK-NOT: uxt 77; CHECK: [[RETRY:.LBB[0-9]+_[0-9]+]]: 78; CHECK: ldrexd [[OLDLO:r[0-9]+]], [[OLDHI:r[0-9]+]], [r0] 79; CHECK: cmp [[OLDLO]], r6 80; CHECK: cmpeq [[OLDHI]], r7 81; CHECK: bne [[DONE:.LBB[0-9]+_[0-9]+]] 82; CHECK: strexd [[STATUS:r[0-9]+]], r4, r5, [r0] 83; CHECK: cmp{{(\.w)?}} [[STATUS]], #0 84; CHECK: bne [[RETRY]] 85; CHECK: [[DONE]]: 86; CHECK: dmb ish 87 %res = cmpxchg i64* %addr, i64 %desired, i64 %new seq_cst monotonic 88 ret { i64, i1 } %res 89} 90 91define { i64, i1 } @test_nontrivial_args(i64* %addr, i64 %desired, i64 %new) { 92; CHECK-LABEL: test_nontrivial_args: 93; CHECK: dmb ish 94; CHECK-NOT: uxt 95; CHECK: [[RETRY:.LBB[0-9]+_[0-9]+]]: 96; CHECK: ldrexd [[OLDLO:r[0-9]+]], [[OLDHI:r[0-9]+]], [r0] 97; CHECK: cmp [[OLDLO]], {{r[0-9]+}} 98; CHECK: cmpeq [[OLDHI]], {{r[0-9]+}} 99; CHECK: bne [[DONE:.LBB[0-9]+_[0-9]+]] 100; CHECK: strexd [[STATUS:r[0-9]+]], {{r[0-9]+}}, {{r[0-9]+}}, [r0] 101; CHECK: cmp{{(\.w)?}} [[STATUS]], #0 102; CHECK: bne [[RETRY]] 103; CHECK: [[DONE]]: 104; CHECK: dmb ish 105 106 %desired1 = add i64 %desired, 1 107 %new1 = add i64 %new, 1 108 %res = cmpxchg i64* %addr, i64 %desired1, i64 %new1 seq_cst seq_cst 109 ret { i64, i1 } %res 110} 111 112; The following used to trigger an assertion when creating a spill on thumb2 113; for a physreg with RC==GPRPairRegClass. 114; CHECK-LABEL: test_cmpxchg_spillbug: 115; CHECK: ldrexd 116; CHECK: strexd 117; CHECK: bne 118define void @test_cmpxchg_spillbug() { 119 %v = cmpxchg i64* undef, i64 undef, i64 undef seq_cst seq_cst 120 ret void 121} 122