429 lines · plain
1; RUN: llc < %s -mtriple=armv7-apple-ios -verify-machineinstrs | FileCheck %s --check-prefix=CHECK --check-prefix CHECK-ARMV72; RUN: llc < %s -mtriple=thumbv7-apple-ios -verify-machineinstrs | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-T23; RUN: llc < %s -mtriple=thumbv6-apple-ios -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-T14; RUN: llc < %s -mtriple=thumbv6-apple-ios -verify-machineinstrs -mcpu=cortex-m0 | FileCheck %s --check-prefix=CHECK-T1-M05; RUN: llc < %s -mtriple=thumbv7--none-eabi -thread-model single -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-BAREMETAL6 7target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"8 9; CHECK-LABEL: _func:10define void @func(i32 %argc, ptr %argv) nounwind {11entry:12 %argc.addr = alloca i32 ; <ptr> [#uses=1]13 %argv.addr = alloca ptr ; <ptr> [#uses=1]14 %val1 = alloca i32 ; <ptr> [#uses=2]15 %val2 = alloca i32 ; <ptr> [#uses=15]16 %andt = alloca i32 ; <ptr> [#uses=2]17 %ort = alloca i32 ; <ptr> [#uses=2]18 %xort = alloca i32 ; <ptr> [#uses=2]19 %old = alloca i32 ; <ptr> [#uses=18]20 %temp = alloca i32 ; <ptr> [#uses=2]21 store i32 %argc, ptr %argc.addr22 store ptr %argv, ptr %argv.addr23 store i32 0, ptr %val124 store i32 31, ptr %val225 store i32 3855, ptr %andt26 store i32 3855, ptr %ort27 store i32 3855, ptr %xort28 store i32 4, ptr %temp29 %tmp = load i32, ptr %temp30 call void asm sideeffect "", "~{memory},~{dirflag},~{fpsr},~{flags}"()31 ; CHECK: ldrex32 ; CHECK: add33 ; CHECK: strex34 ; CHECK-T1: bl ___sync_fetch_and_add_435 ; CHECK-T1-M0: bl ___atomic_fetch_add_436 ; CHECK-BAREMETAL: add37 ; CHECK-BAREMETAL-NOT: __sync38 %0 = atomicrmw add ptr %val1, i32 %tmp monotonic39 store i32 %0, ptr %old40 call void asm sideeffect "", "~{memory},~{dirflag},~{fpsr},~{flags}"()41 ; CHECK: ldrex42 ; CHECK: sub43 ; CHECK: strex44 ; CHECK-T1: bl ___sync_fetch_and_sub_445 ; CHECK-T1-M0: bl ___atomic_fetch_sub_446 ; CHECK-BAREMETAL: sub47 ; CHECK-BAREMETAL-NOT: __sync48 %1 = atomicrmw sub ptr %val2, i32 30 monotonic49 store i32 %1, ptr %old50 call void asm sideeffect "", "~{memory},~{dirflag},~{fpsr},~{flags}"()51 ; CHECK: ldrex52 ; CHECK: add53 ; CHECK: strex54 ; CHECK-T1: bl ___sync_fetch_and_add_455 ; CHECK-T1-M0: bl ___atomic_fetch_add_456 ; CHECK-BAREMETAL: add57 ; CHECK-BAREMETAL-NOT: __sync58 %2 = atomicrmw add ptr %val2, i32 1 monotonic59 store i32 %2, ptr %old60 call void asm sideeffect "", "~{memory},~{dirflag},~{fpsr},~{flags}"()61 ; CHECK: ldrex62 ; CHECK: sub63 ; CHECK: strex64 ; CHECK-T1: bl ___sync_fetch_and_sub_465 ; CHECK-T1-M0: bl ___atomic_fetch_sub_466 ; CHECK-BAREMETAL: sub67 ; CHECK-BAREMETAL-NOT: __sync68 %3 = atomicrmw sub ptr %val2, i32 1 monotonic69 store i32 %3, ptr %old70 call void asm sideeffect "", "~{memory},~{dirflag},~{fpsr},~{flags}"()71 ; CHECK: ldrex72 ; CHECK: and73 ; CHECK: strex74 ; CHECK-T1: bl ___sync_fetch_and_and_475 ; CHECK-T1-M0: bl ___atomic_fetch_and_476 ; CHECK-BAREMETAL: and77 ; CHECK-BAREMETAL-NOT: __sync78 %4 = atomicrmw and ptr %andt, i32 4080 monotonic79 store i32 %4, ptr %old80 call void asm sideeffect "", "~{memory},~{dirflag},~{fpsr},~{flags}"()81 ; CHECK: ldrex82 ; CHECK: or83 ; CHECK: strex84 ; CHECK-T1: bl ___sync_fetch_and_or_485 ; CHECK-T1-M0: bl ___atomic_fetch_or_486 ; CHECK-BAREMETAL: or87 ; CHECK-BAREMETAL-NOT: __sync88 %5 = atomicrmw or ptr %ort, i32 4080 monotonic89 store i32 %5, ptr %old90 call void asm sideeffect "", "~{memory},~{dirflag},~{fpsr},~{flags}"()91 ; CHECK: ldrex92 ; CHECK: eor93 ; CHECK: strex94 ; CHECK-T1: bl ___sync_fetch_and_xor_495 ; CHECK-T1-M0: bl ___atomic_fetch_xor_496 ; CHECK-BAREMETAL: eor97 ; CHECK-BAREMETAL-NOT: __sync98 %6 = atomicrmw xor ptr %xort, i32 4080 monotonic99 store i32 %6, ptr %old100 call void asm sideeffect "", "~{memory},~{dirflag},~{fpsr},~{flags}"()101 ; CHECK: ldrex102 ; CHECK: cmp103 ; CHECK: strex104 ; CHECK-T1: bl ___sync_fetch_and_min_4105 ; CHECK-T1-M0: bl ___atomic_compare_exchange_4106 ; CHECK-BAREMETAL: cmp107 ; CHECK-BAREMETAL-NOT: __sync108 %7 = atomicrmw min ptr %val2, i32 16 monotonic109 store i32 %7, ptr %old110 call void asm sideeffect "", "~{memory},~{dirflag},~{fpsr},~{flags}"()111 %neg = sub i32 0, 1112 ; CHECK: ldrex113 ; CHECK: cmp114 ; CHECK: strex115 ; CHECK-T1: bl ___sync_fetch_and_min_4116 ; CHECK-T1-M0: bl ___atomic_compare_exchange_4117 ; CHECK-BAREMETAL: cmp118 ; CHECK-BAREMETAL-NOT: __sync119 %8 = atomicrmw min ptr %val2, i32 %neg monotonic120 store i32 %8, ptr %old121 call void asm sideeffect "", "~{memory},~{dirflag},~{fpsr},~{flags}"()122 ; CHECK: ldrex123 ; CHECK: cmp124 ; CHECK: strex125 ; CHECK-T1: bl ___sync_fetch_and_max_4126 ; CHECK-T1-M0: bl ___atomic_compare_exchange_4127 ; CHECK-BAREMETAL: cmp128 ; CHECK-BAREMETAL-NOT: __sync129 %9 = atomicrmw max ptr %val2, i32 1 monotonic130 store i32 %9, ptr %old131 call void asm sideeffect "", "~{memory},~{dirflag},~{fpsr},~{flags}"()132 ; CHECK: ldrex133 ; CHECK: bic134 ; CHECK-NOT: cmp135 ; CHECK: strex136 ; CHECK-T1: bl ___sync_fetch_and_max_4137 ; CHECK-T1-M0: bl ___atomic_compare_exchange_4138 ; CHECK-BAREMETAL: bic139 ; CHECK-BAREMETAL-NOT: __sync140 %10 = atomicrmw max ptr %val2, i32 0 monotonic141 store i32 %10, ptr %old142 call void asm sideeffect "", "~{memory},~{dirflag},~{fpsr},~{flags}"()143 ; CHECK: ldrex144 ; CHECK: cmp145 ; CHECK: strex146 ; CHECK-T1: bl ___sync_fetch_and_umin_4147 ; CHECK-T1-M0: bl ___atomic_compare_exchange_4148 ; CHECK-BAREMETAL: cmp149 ; CHECK-BAREMETAL-NOT: __sync150 %11 = atomicrmw umin ptr %val2, i32 16 monotonic151 store i32 %11, ptr %old152 call void asm sideeffect "", "~{memory},~{dirflag},~{fpsr},~{flags}"()153 %uneg = sub i32 0, 1154 ; CHECK: ldrex155 ; CHECK: cmp156 ; CHECK: strex157 ; CHECK-T1: bl ___sync_fetch_and_umin_4158 ; CHECK-T1-M0: bl ___atomic_compare_exchange_4159 ; CHECK-BAREMETAL: cmp160 ; CHECK-BAREMETAL-NOT: __sync161 %12 = atomicrmw umin ptr %val2, i32 %uneg monotonic162 store i32 %12, ptr %old163 call void asm sideeffect "", "~{memory},~{dirflag},~{fpsr},~{flags}"()164 ; CHECK: ldrex165 ; CHECK: strex166 ; CHECK: cmp167 ; CHECK-T1: bl ___sync_fetch_and_umax_4168 ; CHECK-T1-M0: bl ___atomic_compare_exchange_4169 ; CHECK-BAREMETAL: cmp170 ; CHECK-BAREMETAL-NOT: __sync171 %13 = atomicrmw umax ptr %val2, i32 1 monotonic172 store i32 %13, ptr %old173 call void asm sideeffect "", "~{memory},~{dirflag},~{fpsr},~{flags}"()174 ; CHECK: ldrex175 ; CHECK: strex176 ; CHECK: cmp177 ; CHECK-T1: bl ___sync_fetch_and_umax_4178 ; CHECK-T1-M0: bl ___atomic_compare_exchange_4179 ; CHECK-BAREMETAL: cmp180 ; CHECK-BAREMETAL-NOT: __sync181 %14 = atomicrmw umax ptr %val2, i32 0 monotonic182 store i32 %14, ptr %old183 184 ret void185}186 187; CHECK-LABEL: _func2:188define void @func2() nounwind {189entry:190 %val = alloca i16191 %old = alloca i16192 store i16 31, ptr %val193 ; CHECK: ldrex194 ; CHECK: strex195 ; CHECK: cmp196 ; CHECK-T1: bl ___sync_fetch_and_umin_2197 ; CHECK-T1-M0: bl ___atomic_compare_exchange_2198 ; CHECK-BAREMETAL: cmp199 ; CHECK-BAREMETAL-NOT: __sync200 %0 = atomicrmw umin ptr %val, i16 16 monotonic201 store i16 %0, ptr %old202 %uneg = sub i16 0, 1203 ; CHECK: ldrex204 ; CHECK: strex205 ; CHECK: cmp206 ; CHECK-T1: bl ___sync_fetch_and_umin_2207 ; CHECK-T1-M0: bl ___atomic_compare_exchange_2208 ; CHECK-BAREMETAL: cmp209 ; CHECK-BAREMETAL-NOT: __sync210 %1 = atomicrmw umin ptr %val, i16 %uneg monotonic211 store i16 %1, ptr %old212 ; CHECK: ldrex213 ; CHECK: cmp214 ; CHECK: strex215 ; CHECK-T1: bl ___sync_fetch_and_umax_2216 ; CHECK-T1-M0: bl ___atomic_compare_exchange_2217 ; CHECK-BAREMETAL: cmp218 ; CHECK-BAREMETAL-NOT: __sync219 %2 = atomicrmw umax ptr %val, i16 1 monotonic220 store i16 %2, ptr %old221 ; CHECK: ldrex222 ; CHECK: strex223 ; CHECK: cmp224 ; CHECK-T1: bl ___sync_fetch_and_umax_2225 ; CHECK-T1-M0: bl ___atomic_compare_exchange_2226 ; CHECK-BAREMETAL: cmp227 ; CHECK-BAREMETAL-NOT: __sync228 %3 = atomicrmw umax ptr %val, i16 0 monotonic229 store i16 %3, ptr %old230 ret void231}232 233; CHECK-LABEL: _func3:234define void @func3() nounwind {235entry:236 %val = alloca i8237 %old = alloca i8238 store i8 31, ptr %val239 ; CHECK: ldrex240 ; CHECK: strex241 ; CHECK: cmp242 ; CHECK-T1: bl ___sync_fetch_and_umin_1243 ; CHECK-T1-M0: bl ___atomic_compare_exchange_1244 ; CHECK-BAREMETAL: cmp245 ; CHECK-BAREMETAL-NOT: __sync246 %0 = atomicrmw umin ptr %val, i8 16 monotonic247 store i8 %0, ptr %old248 ; CHECK: ldrex249 ; CHECK: strex250 ; CHECK: cmp251 ; CHECK-T1: bl ___sync_fetch_and_umin_1252 ; CHECK-T1-M0: bl ___atomic_compare_exchange_1253 ; CHECK-BAREMETAL: cmp254 ; CHECK-BAREMETAL-NOT: __sync255 %uneg = sub i8 0, 1256 %1 = atomicrmw umin ptr %val, i8 %uneg monotonic257 store i8 %1, ptr %old258 ; CHECK: ldrex259 ; CHECK: strex260 ; CHECK: cmp261 ; CHECK-T1: bl ___sync_fetch_and_umax_1262 ; CHECK-T1-M0: bl ___atomic_compare_exchange_1263 ; CHECK-BAREMETAL: cmp264 ; CHECK-BAREMETAL-NOT: __sync265 %2 = atomicrmw umax ptr %val, i8 1 monotonic266 store i8 %2, ptr %old267 ; CHECK: ldrex268 ; CHECK: strex269 ; CHECK: cmp270 ; CHECK-T1: bl ___sync_fetch_and_umax_1271 ; CHECK-T1-M0: bl ___atomic_compare_exchange_1272 ; CHECK-BAREMETAL: cmp273 ; CHECK-BAREMETAL-NOT: __sync274 %3 = atomicrmw umax ptr %val, i8 0 monotonic275 store i8 %3, ptr %old276 ret void277}278 279; CHECK-LABEL: _func4:280; This function should not need to use callee-saved registers.281; rdar://problem/12203728282; CHECK-NOT: r4283define i32 @func4(ptr %p) nounwind optsize ssp {284entry:285 %0 = atomicrmw add ptr %p, i32 1 monotonic286 ret i32 %0287}288 289define i32 @test_cmpxchg_fail_order(ptr %addr, i32 %desired, i32 %new) {290; CHECK-LABEL: test_cmpxchg_fail_order:291 292 %pair = cmpxchg ptr %addr, i32 %desired, i32 %new seq_cst monotonic293 %oldval = extractvalue { i32, i1 } %pair, 0294; CHECK-ARMV7: mov r[[ADDR:[0-9]+]], r0295; CHECK-ARMV7: ldrex [[OLDVAL:r[0-9]+]], [r0]296; CHECK-ARMV7: cmp [[OLDVAL]], r1297; CHECK-ARMV7: bne [[FAIL_BB:\.?LBB[0-9]+_[0-9]+]]298; CHECK-ARMV7: dmb ish299; CHECK-ARMV7: [[LOOP_BB:\.?LBB.*]]:300; CHECK-ARMV7: strex [[SUCCESS:r[0-9]+]], r2, [r[[ADDR]]]301; CHECK-ARMV7: cmp [[SUCCESS]], #0302; CHECK-ARMV7: beq [[SUCCESS_BB:\.?LBB.*]]303; CHECK-ARMV7: ldrex [[OLDVAL]], [r[[ADDR]]]304; CHECK-ARMV7: cmp [[OLDVAL]], r1305; CHECK-ARMV7: beq [[LOOP_BB]]306; CHECK-ARMV7: [[FAIL_BB]]:307; CHECK-ARMV7: clrex308; CHECK-ARMV7: bx lr309; CHECK-ARMV7: [[SUCCESS_BB]]:310; CHECK-ARMV7: dmb ish311; CHECK-ARMV7: bx lr312 313; CHECK-T2: mov r[[ADDR:[0-9]+]], r0314; CHECK-T2: ldrex [[OLDVAL:r[0-9]+]], [r0]315; CHECK-T2: cmp [[OLDVAL]], r1316; CHECK-T2: bne [[FAIL_BB:\.?LBB.*]]317; CHECK-T2: dmb ish318; CHECK-T2: [[LOOP_BB:\.?LBB.*]]:319; CHECK-T2: strex [[SUCCESS:r[0-9]+]], r2, [r[[ADDR]]]320; CHECK-T2: cmp [[SUCCESS]], #0321; CHECK-T2: dmbeq ish322; CHECK-T2: bxeq lr323; CHECK-T2: ldrex [[OLDVAL]], [r[[ADDR]]]324; CHECK-T2: cmp [[OLDVAL]], r1325; CHECK-T2: beq [[LOOP_BB]]326; CHECK-T2: clrex327 328 ret i32 %oldval329}330 331define i32 @test_cmpxchg_fail_order1(ptr %addr, i32 %desired, i32 %new) {332; CHECK-LABEL: test_cmpxchg_fail_order1:333 334 %pair = cmpxchg ptr %addr, i32 %desired, i32 %new acquire acquire335 %oldval = extractvalue { i32, i1 } %pair, 0336; CHECK-NOT: dmb ish337; CHECK: [[LOOP_BB:\.?LBB[0-9]+_1]]:338; CHECK: ldrex [[OLDVAL:r[0-9]+]], [r[[ADDR:[0-9]+]]]339; CHECK: cmp [[OLDVAL]], r1340; CHECK: bne [[FAIL_BB:\.?LBB[0-9]+_[0-9]+]]341; CHECK: strex [[SUCCESS:r[0-9]+]], r2, [r[[ADDR]]]342; CHECK: cmp [[SUCCESS]], #0343; CHECK: bne [[LOOP_BB]]344; CHECK: dmb ish345; CHECK: bx lr346; CHECK: [[FAIL_BB]]:347; CHECK-NEXT: clrex348; CHECK: dmb ish349; CHECK: bx lr350 351 ret i32 %oldval352}353 354define i32 @load_load_add_acquire(ptr %mem1, ptr %mem2) nounwind {355; CHECK-LABEL: load_load_add_acquire356 %val1 = load atomic i32, ptr %mem1 acquire, align 4357 %val2 = load atomic i32, ptr %mem2 acquire, align 4358 %tmp = add i32 %val1, %val2359 360; CHECK: ldr {{r[0-9]}}, [r0]361; CHECK: dmb362; CHECK: ldr {{r[0-9]}}, [r1]363; CHECK: dmb364; CHECK: add r0,365 366; CHECK-T1-M0: __atomic_load_4367; CHECK-T1-M0: __atomic_load_4368 369; CHECK-T1: ___sync_val_compare_and_swap_4370; CHECK-T1: ___sync_val_compare_and_swap_4371 372; CHECK-BAREMETAL: ldr {{r[0-9]}}, [r0]373; CHECK-BAREMETAL-NOT: dmb374; CHECK-BAREMETAL: ldr {{r[0-9]}}, [r1]375; CHECK-BAREMETAL-NOT: dmb376; CHECK-BAREMETAL: add r0,377 378 ret i32 %tmp379}380 381define void @store_store_release(ptr %mem1, i32 %val1, ptr %mem2, i32 %val2) {382; CHECK-LABEL: store_store_release383 store atomic i32 %val1, ptr %mem1 release, align 4384 store atomic i32 %val2, ptr %mem2 release, align 4385 386; CHECK: dmb387; CHECK: str r1, [r0]388; CHECK: dmb389; CHECK: str r3, [r2]390 391; CHECK-T1: ___sync_lock_test_and_set392; CHECK-T1: ___sync_lock_test_and_set393 394; CHECK-T1-M0: __atomic_store_4395; CHECK-T1-M0: __atomic_store_4396 397; CHECK-BAREMETAL-NOT: dmb398; CHECK-BAREMETAL: str r1, [r0]399; CHECK-BAREMETAL-NOT: dmb400; CHECK-BAREMETAL: str r3, [r2]401 402 ret void403}404 405define void @load_fence_store_monotonic(ptr %mem1, ptr %mem2) {406; CHECK-LABEL: load_fence_store_monotonic407 %val = load atomic i32, ptr %mem1 monotonic, align 4408 fence seq_cst409 store atomic i32 %val, ptr %mem2 monotonic, align 4410 411; CHECK: ldr [[R0:r[0-9]]], [r0]412; CHECK: dmb413; CHECK: str [[R0]], [r1]414 415; CHECK-T1-M0: __atomic_load_4416; CHECK-T1-M0: dmb417; CHECK-T1-M0: __atomic_store_4418 419; CHECK-T1: ldr [[R0:r[0-9]]], [{{r[0-9]+}}]420; CHECK-T1: {{dmb|bl ___sync_synchronize}}421; CHECK-T1: str [[R0]], [{{r[0-9]+}}]422 423; CHECK-BAREMETAL: ldr [[R0:r[0-9]]], [r0]424; CHECK-BAREMETAL-NOT: dmb425; CHECK-BAREMETAL: str [[R0]], [r1]426 427 ret void428}429