1 ; RUN: llc < %s -mtriple=armv7-apple-ios -verify-machineinstrs | FileCheck %s 2 ; RUN: llc < %s -mtriple=thumbv7-apple-ios -verify-machineinstrs | FileCheck %s 3 ; RUN: llc < %s -mtriple=thumbv6-apple-ios -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-T1 4 ; RUN: llc < %s -mtriple=thumbv6-apple-ios -verify-machineinstrs -mcpu=cortex-m0 | FileCheck %s --check-prefix=CHECK-T1 5 6 define void @func(i32 %argc, i8** %argv) nounwind { 7 entry: 8 %argc.addr = alloca i32 ; <i32*> [#uses=1] 9 %argv.addr = alloca i8** ; <i8***> [#uses=1] 10 %val1 = alloca i32 ; <i32*> [#uses=2] 11 %val2 = alloca i32 ; <i32*> [#uses=15] 12 %andt = alloca i32 ; <i32*> [#uses=2] 13 %ort = alloca i32 ; <i32*> [#uses=2] 14 %xort = alloca i32 ; <i32*> [#uses=2] 15 %old = alloca i32 ; <i32*> [#uses=18] 16 %temp = alloca i32 ; <i32*> [#uses=2] 17 store i32 %argc, i32* %argc.addr 18 store i8** %argv, i8*** %argv.addr 19 store i32 0, i32* %val1 20 store i32 31, i32* %val2 21 store i32 3855, i32* %andt 22 store i32 3855, i32* %ort 23 store i32 3855, i32* %xort 24 store i32 4, i32* %temp 25 %tmp = load i32* %temp 26 ; CHECK: ldrex 27 ; CHECK: add 28 ; CHECK: strex 29 ; CHECK-T1: blx ___sync_fetch_and_add_4 30 %0 = atomicrmw add i32* %val1, i32 %tmp monotonic 31 store i32 %0, i32* %old 32 ; CHECK: ldrex 33 ; CHECK: sub 34 ; CHECK: strex 35 ; CHECK-T1: blx ___sync_fetch_and_sub_4 36 %1 = atomicrmw sub i32* %val2, i32 30 monotonic 37 store i32 %1, i32* %old 38 ; CHECK: ldrex 39 ; CHECK: add 40 ; CHECK: strex 41 ; CHECK-T1: blx ___sync_fetch_and_add_4 42 %2 = atomicrmw add i32* %val2, i32 1 monotonic 43 store i32 %2, i32* %old 44 ; CHECK: ldrex 45 ; CHECK: sub 46 ; CHECK: strex 47 ; CHECK-T1: blx ___sync_fetch_and_sub_4 48 %3 = atomicrmw sub i32* %val2, i32 1 monotonic 49 store i32 %3, i32* %old 50 ; CHECK: ldrex 51 ; CHECK: and 52 ; CHECK: strex 53 ; CHECK-T1: blx ___sync_fetch_and_and_4 54 %4 = atomicrmw and i32* %andt, i32 4080 monotonic 55 store i32 %4, i32* %old 56 ; CHECK: ldrex 57 ; CHECK: or 58 ; CHECK: strex 59 ; CHECK-T1: blx ___sync_fetch_and_or_4 60 %5 = atomicrmw or i32* %ort, i32 4080 monotonic 61 store i32 %5, i32* %old 62 ; CHECK: ldrex 63 ; CHECK: eor 64 ; CHECK: strex 65 ; CHECK-T1: blx ___sync_fetch_and_xor_4 66 %6 = atomicrmw xor i32* %xort, i32 4080 monotonic 67 store i32 %6, i32* %old 68 ; CHECK: ldrex 69 ; CHECK: cmp 70 ; CHECK: strex 71 ; CHECK-T1: blx ___sync_fetch_and_min_4 72 %7 = atomicrmw min i32* %val2, i32 16 monotonic 73 store i32 %7, i32* %old 74 %neg = sub i32 0, 1 75 ; CHECK: ldrex 76 ; CHECK: cmp 77 ; CHECK: strex 78 ; CHECK-T1: blx ___sync_fetch_and_min_4 79 %8 = atomicrmw min i32* %val2, i32 %neg monotonic 80 store i32 %8, i32* %old 81 ; CHECK: ldrex 82 ; CHECK: cmp 83 ; CHECK: strex 84 ; CHECK-T1: blx ___sync_fetch_and_max_4 85 %9 = atomicrmw max i32* %val2, i32 1 monotonic 86 store i32 %9, i32* %old 87 ; CHECK: ldrex 88 ; CHECK: cmp 89 ; CHECK: strex 90 ; CHECK-T1: blx ___sync_fetch_and_max_4 91 %10 = atomicrmw max i32* %val2, i32 0 monotonic 92 store i32 %10, i32* %old 93 ; CHECK: ldrex 94 ; CHECK: cmp 95 ; CHECK: strex 96 ; CHECK-T1: blx ___sync_fetch_and_umin_4 97 %11 = atomicrmw umin i32* %val2, i32 16 monotonic 98 store i32 %11, i32* %old 99 %uneg = sub i32 0, 1 100 ; CHECK: ldrex 101 ; CHECK: cmp 102 ; CHECK: strex 103 ; CHECK-T1: blx ___sync_fetch_and_umin_4 104 %12 = atomicrmw umin i32* %val2, i32 %uneg monotonic 105 store i32 %12, i32* %old 106 ; CHECK: ldrex 107 ; CHECK: cmp 108 ; CHECK: strex 109 ; CHECK-T1: blx ___sync_fetch_and_umax_4 110 %13 = atomicrmw umax i32* %val2, i32 1 monotonic 111 store i32 %13, i32* %old 112 ; CHECK: ldrex 113 ; CHECK: cmp 114 ; CHECK: strex 115 ; CHECK-T1: blx ___sync_fetch_and_umax_4 116 %14 = atomicrmw umax i32* %val2, i32 0 monotonic 117 store i32 %14, i32* %old 118 119 ret void 120 } 121 122 define void @func2() nounwind { 123 entry: 124 %val = alloca i16 125 %old = alloca i16 126 store i16 31, i16* %val 127 ; CHECK: ldrex 128 ; CHECK: cmp 129 ; CHECK: strex 130 ; CHECK-T1: blx ___sync_fetch_and_umin_2 131 %0 = atomicrmw umin i16* %val, i16 16 monotonic 132 store i16 %0, i16* %old 133 %uneg = sub i16 0, 1 134 ; CHECK: ldrex 135 ; CHECK: cmp 136 ; CHECK: strex 137 ; CHECK-T1: blx ___sync_fetch_and_umin_2 138 %1 = atomicrmw umin i16* %val, i16 %uneg monotonic 139 store i16 %1, i16* %old 140 ; CHECK: ldrex 141 ; CHECK: cmp 142 ; CHECK: strex 143 ; CHECK-T1: blx ___sync_fetch_and_umax_2 144 %2 = atomicrmw umax i16* %val, i16 1 monotonic 145 store i16 %2, i16* %old 146 ; CHECK: ldrex 147 ; CHECK: cmp 148 ; CHECK: strex 149 ; CHECK-T1: blx ___sync_fetch_and_umax_2 150 %3 = atomicrmw umax i16* %val, i16 0 monotonic 151 store i16 %3, i16* %old 152 ret void 153 } 154 155 define void @func3() nounwind { 156 entry: 157 %val = alloca i8 158 %old = alloca i8 159 store i8 31, i8* %val 160 ; CHECK: ldrex 161 ; CHECK: cmp 162 ; CHECK: strex 163 ; CHECK-T1: blx ___sync_fetch_and_umin_1 164 %0 = atomicrmw umin i8* %val, i8 16 monotonic 165 store i8 %0, i8* %old 166 ; CHECK: ldrex 167 ; CHECK: cmp 168 ; CHECK: strex 169 ; CHECK-T1: blx ___sync_fetch_and_umin_1 170 %uneg = sub i8 0, 1 171 %1 = atomicrmw umin i8* %val, i8 %uneg monotonic 172 store i8 %1, i8* %old 173 ; CHECK: ldrex 174 ; CHECK: cmp 175 ; CHECK: strex 176 ; CHECK-T1: blx ___sync_fetch_and_umax_1 177 %2 = atomicrmw umax i8* %val, i8 1 monotonic 178 store i8 %2, i8* %old 179 ; CHECK: ldrex 180 ; CHECK: cmp 181 ; CHECK: strex 182 ; CHECK-T1: blx ___sync_fetch_and_umax_1 183 %3 = atomicrmw umax i8* %val, i8 0 monotonic 184 store i8 %3, i8* %old 185 ret void 186 } 187 188 ; CHECK: func4 189 ; This function should not need to use callee-saved registers. 190 ; rdar://problem/12203728 191 ; CHECK-NOT: r4 192 define i32 @func4(i32* %p) nounwind optsize ssp { 193 entry: 194 %0 = atomicrmw add i32* %p, i32 1 monotonic 195 ret i32 %0 196 } 197 198 define i32 @test_cmpxchg_fail_order(i32 *%addr, i32 %desired, i32 %new) { 199 ; CHECK-LABEL: test_cmpxchg_fail_order: 200 201 %pair = cmpxchg i32* %addr, i32 %desired, i32 %new seq_cst monotonic 202 %oldval = extractvalue { i32, i1 } %pair, 0 203 ; CHECK: dmb ish 204 ; CHECK: [[LOOP_BB:\.?LBB[0-9]+_1]]: 205 ; CHECK: ldrex [[OLDVAL:r[0-9]+]], [r[[ADDR:[0-9]+]]] 206 ; CHECK: cmp [[OLDVAL]], r1 207 ; CHECK: bxne lr 208 ; CHECK: strex [[SUCCESS:r[0-9]+]], r2, [r[[ADDR]]] 209 ; CHECK: cmp [[SUCCESS]], #0 210 ; CHECK: bne [[LOOP_BB]] 211 ; CHECK: dmb ish 212 ; CHECK: bx lr 213 214 ret i32 %oldval 215 } 216 217 define i32 @test_cmpxchg_fail_order1(i32 *%addr, i32 %desired, i32 %new) { 218 ; CHECK-LABEL: test_cmpxchg_fail_order1: 219 220 %pair = cmpxchg i32* %addr, i32 %desired, i32 %new acquire acquire 221 %oldval = extractvalue { i32, i1 } %pair, 0 222 ; CHECK-NOT: dmb ish 223 ; CHECK: [[LOOP_BB:\.?LBB[0-9]+_1]]: 224 ; CHECK: ldrex [[OLDVAL:r[0-9]+]], [r[[ADDR:[0-9]+]]] 225 ; CHECK: cmp [[OLDVAL]], r1 226 ; CHECK: bne [[END_BB:\.?LBB[0-9]+_[0-9]+]] 227 ; CHECK: strex [[SUCCESS:r[0-9]+]], r2, [r[[ADDR]]] 228 ; CHECK: cmp [[SUCCESS]], #0 229 ; CHECK: bne [[LOOP_BB]] 230 ; CHECK: [[END_BB]]: 231 ; CHECK: dmb ish 232 ; CHECK: bx lr 233 234 ret i32 %oldval 235 } 236