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 8 define { 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 ; CHECK: cmp{{(\.w)?}} [[OLD]], [[DESIRED]] 21 ; CHECK: {{moveq|movweq}} {{r[0-9]+}}, #1 22 ; CHECK: dmb ish 23 %res = cmpxchg i8* %addr, i8 %desired, i8 %new seq_cst monotonic 24 ret { i8, i1 } %res 25 } 26 27 define { i16, i1 } @test_cmpxchg_16(i16* %addr, i16 %desired, i16 %new) nounwind { 28 ; CHECK-LABEL: test_cmpxchg_16: 29 ; CHECK: dmb ish 30 ; CHECK: uxth [[DESIRED:r[0-9]+]], [[DESIRED]] 31 ; CHECK: [[RETRY:.LBB[0-9]+_[0-9]+]]: 32 ; CHECK: ldrexh [[OLD:r[0-9]+]], [r0] 33 ; CHECK: cmp [[OLD]], [[DESIRED]] 34 ; CHECK: bne [[DONE:.LBB[0-9]+_[0-9]+]] 35 ; CHECK: strexh [[STATUS:r[0-9]+]], r2, [r0] 36 ; CHECK: cmp{{(\.w)?}} [[STATUS]], #0 37 ; CHECK: bne [[RETRY]] 38 ; CHECK: [[DONE]]: 39 ; CHECK: cmp{{(\.w)?}} [[OLD]], [[DESIRED]] 40 ; CHECK: {{moveq|movweq}} {{r[0-9]+}}, #1 41 ; CHECK: dmb ish 42 %res = cmpxchg i16* %addr, i16 %desired, i16 %new seq_cst monotonic 43 ret { i16, i1 } %res 44 } 45 46 define { i32, i1 } @test_cmpxchg_32(i32* %addr, i32 %desired, i32 %new) nounwind { 47 ; CHECK-LABEL: test_cmpxchg_32: 48 ; CHECK: dmb ish 49 ; CHECK-NOT: uxt 50 ; CHECK: [[RETRY:.LBB[0-9]+_[0-9]+]]: 51 ; CHECK: ldrex [[OLD:r[0-9]+]], [r0] 52 ; CHECK: cmp [[OLD]], [[DESIRED]] 53 ; CHECK: bne [[DONE:.LBB[0-9]+_[0-9]+]] 54 ; CHECK: strex [[STATUS:r[0-9]+]], r2, [r0] 55 ; CHECK: cmp{{(\.w)?}} [[STATUS]], #0 56 ; CHECK: bne [[RETRY]] 57 ; CHECK: [[DONE]]: 58 ; CHECK: cmp{{(\.w)?}} [[OLD]], [[DESIRED]] 59 ; CHECK: {{moveq|movweq}} {{r[0-9]+}}, #1 60 ; CHECK: dmb ish 61 %res = cmpxchg i32* %addr, i32 %desired, i32 %new seq_cst monotonic 62 ret { i32, i1 } %res 63 } 64 65 define { i64, i1 } @test_cmpxchg_64(i64* %addr, i64 %desired, i64 %new) nounwind { 66 ; CHECK-LABEL: test_cmpxchg_64: 67 ; CHECK: dmb ish 68 ; CHECK-NOT: uxt 69 ; CHECK: [[RETRY:.LBB[0-9]+_[0-9]+]]: 70 ; CHECK: ldrexd [[OLDLO:r[0-9]+]], [[OLDHI:r[0-9]+]], [r0] 71 ; CHECK: cmp [[OLDLO]], r6 72 ; CHECK: sbcs{{(\.w)?}} [[STATUS:r[0-9]+]], [[OLDHI]], r7 73 ; CHECK: bne [[DONE:.LBB[0-9]+_[0-9]+]] 74 ; CHECK: strexd [[STATUS]], r4, r5, [r0] 75 ; CHECK: cmp{{(\.w)?}} [[STATUS]], #0 76 ; CHECK: bne [[RETRY]] 77 ; CHECK: [[DONE]]: 78 ; CHECK: dmb ish 79 %res = cmpxchg i64* %addr, i64 %desired, i64 %new seq_cst monotonic 80 ret { i64, i1 } %res 81 } 82 83 define { i64, i1 } @test_nontrivial_args(i64* %addr, i64 %desired, i64 %new) { 84 ; CHECK-LABEL: test_nontrivial_args: 85 ; CHECK: dmb ish 86 ; CHECK-NOT: uxt 87 ; CHECK: [[RETRY:.LBB[0-9]+_[0-9]+]]: 88 ; CHECK: ldrexd [[OLDLO:r[0-9]+]], [[OLDHI:r[0-9]+]], [r0] 89 ; CHECK: cmp [[OLDLO]], {{r[0-9]+}} 90 ; CHECK: sbcs{{(\.w)?}} [[STATUS:r[0-9]+]], [[OLDHI]], {{r[0-9]+}} 91 ; CHECK: bne [[DONE:.LBB[0-9]+_[0-9]+]] 92 ; CHECK: strexd [[STATUS]], {{r[0-9]+}}, {{r[0-9]+}}, [r0] 93 ; CHECK: cmp{{(\.w)?}} [[STATUS]], #0 94 ; CHECK: bne [[RETRY]] 95 ; CHECK: [[DONE]]: 96 ; CHECK: dmb ish 97 98 %desired1 = add i64 %desired, 1 99 %new1 = add i64 %new, 1 100 %res = cmpxchg i64* %addr, i64 %desired1, i64 %new1 seq_cst seq_cst 101 ret { i64, i1 } %res 102 } 103 104 ; The following used to trigger an assertion when creating a spill on thumb2 105 ; for a physreg with RC==GPRPairRegClass. 106 ; CHECK-LABEL: test_cmpxchg_spillbug: 107 ; CHECK: ldrexd 108 ; CHECK: strexd 109 ; CHECK: bne 110 define void @test_cmpxchg_spillbug() { 111 %v = cmpxchg i64* undef, i64 undef, i64 undef seq_cst seq_cst 112 ret void 113 } 114