1 ; RUN: llc %s -o - -enable-shrink-wrap=true -ifcvt-fn-start=1 -ifcvt-fn-stop=0 -mtriple=thumb-macho \
2 ; RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=ENABLE --check-prefix=ENABLE-V4T
3 ; RUN: llc %s -o - -enable-shrink-wrap=true -ifcvt-fn-start=1 -ifcvt-fn-stop=0 -mtriple=thumbv5-macho \
4 ; RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=ENABLE --check-prefix=ENABLE-V5T
5 ; RUN: llc %s -o - -enable-shrink-wrap=false -ifcvt-fn-start=1 -ifcvt-fn-stop=0 -mtriple=thumb-macho \
6 ; RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE --check-prefix=DISABLE-V4T
7 ; RUN: llc %s -o - -enable-shrink-wrap=false -ifcvt-fn-start=1 -ifcvt-fn-stop=0 -mtriple=thumbv5-macho \
8 ; RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE --check-prefix=DISABLE-V5T
10 ; Note: Lots of tests use inline asm instead of regular calls.
11 ; This allows to have a better control on what the allocation will do.
12 ; Otherwise, we may have spill right in the entry block, defeating
13 ; shrink-wrapping. Moreover, some of the inline asm statements (nop)
14 ; are here to ensure that the related paths do not end up as critical
16 ; Also disable the late if-converter as it makes harder to reason on
19 ; Initial motivating example: Simple diamond with a call just on one side.
22 ; Compare the arguments and jump to exit.
25 ; ENABLE-NEXT: bge [[EXIT_LABEL:LBB[0-9_]+]]
28 ; CHECK: push {r7, lr}
31 ; Compare the arguments and jump to exit.
32 ; After the prologue is set.
34 ; DISABLE-NEXT: bge [[EXIT_LABEL:LBB[0-9_]+]]
36 ; Store %a in the alloca.
37 ; CHECK: str r0, [sp, #4]
38 ; Set the alloca address in the second argument.
39 ; Set the first argument to zero.
41 ; CHECK-NEXT: add r1, sp, #4
44 ; With shrink-wrapping, epilogue is just after the call.
45 ; ENABLE-NEXT: add sp, #8
46 ; ENABLE-V5T-NEXT: pop {r7, pc}
47 ; ENABLE-V4T-NEXT: pop {r7}
48 ; ENABLE-V4T-NEXT: pop {r1}
49 ; ENABLE-V4T-NEXT: mov lr, r1
51 ; CHECK: [[EXIT_LABEL]]:
53 ; Without shrink-wrapping, epilogue is in the exit block.
54 ; Epilogue code. (What we pop does not matter.)
56 ; DISABLE-V5T-NEXT: pop {r7, pc}
57 ; DISABLE-V4T-NEXT: pop {r7}
58 ; DISABLE-V4T-NEXT: pop {r1}
59 ; DISABLE-V4T-NEXT: bx r1
62 define i32 @foo(i32 %a, i32 %b) {
63 %tmp = alloca i32, align 4
64 %tmp2 = icmp slt i32 %a, %b
65 br i1 %tmp2, label %true, label %false
68 store i32 %a, i32* %tmp, align 4
69 %tmp4 = call i32 @doSomething(i32 0, i32* %tmp)
73 %tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ]
78 ; Same, but the final BB is non-trivial, so we don't duplicate the return inst.
81 ; With shrink-wrapping, epilogue is just after the call.
83 ; ENABLE-NEXT: add sp, #8
84 ; ENABLE-NEXT: pop {r7}
85 ; ENABLE-NEXT: pop {r0}
86 ; ENABLE-NEXT: mov lr, r0
90 ; Without shrink-wrapping, epilogue is in the exit block.
91 ; Epilogue code. (What we pop does not matter.)
93 ; DISABLE-V5T-NEXT: pop {r7, pc}
94 ; DISABLE-V4T-NEXT: pop {r7}
95 ; DISABLE-V4T-NEXT: pop {r1}
96 ; DISABLE-V4T-NEXT: bx r1
99 define i32 @bar(i32 %a, i32 %b) {
100 %tmp = alloca i32, align 4
101 %tmp2 = icmp slt i32 %a, %b
102 br i1 %tmp2, label %true, label %false
105 store i32 %a, i32* %tmp, align 4
106 %tmp4 = call i32 @doSomething(i32 0, i32* %tmp)
113 ; Function Attrs: optsize
114 declare i32 @doSomething(i32, i32*)
117 ; Check that we do not perform the restore inside the loop whereas the save
119 ; CHECK-LABEL: freqSaveAndRestoreOutsideLoop:
121 ; Shrink-wrapping allows to skip the prologue in the else case.
123 ; ENABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]]
126 ; Make sure we save the CSR used in the inline asm: r4.
127 ; CHECK: push {r4, lr}
129 ; DISABLE: cmp r0, #0
130 ; DISABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]]
132 ; SUM is in r0 because it is coalesced with the second
133 ; argument on the else path.
134 ; CHECK: movs [[SUM:r0]], #0
135 ; CHECK-NEXT: movs [[IV:r[0-9]+]], #10
138 ; CHECK: [[LOOP:LBB[0-9_]+]]: @ %for.body
139 ; CHECK: movs [[TMP:r[0-9]+]], #1
140 ; CHECK: adds [[SUM]], [[TMP]], [[SUM]]
141 ; CHECK-NEXT: subs [[IV]], [[IV]], #1
142 ; CHECK-NEXT: bne [[LOOP]]
146 ; CHECK: lsls [[SUM]], [[SUM]], #3
148 ; Duplicated epilogue.
149 ; DISABLE-V5T: pop {r4, pc}
150 ; DISABLE-V4T: b [[END_LABEL:LBB[0-9_]+]]
152 ; CHECK: [[ELSE_LABEL]]: @ %if.else
153 ; Shift second argument by one and store into returned register.
154 ; CHECK: lsls r0, r1, #1
155 ; DISABLE-V5T-NEXT: pop {r4, pc}
156 ; DISABLE-V4T-NEXT: [[END_LABEL]]: @ %if.end
157 ; DISABLE-V4T-NEXT: pop {r4}
158 ; DISABLE-V4T-NEXT: pop {r1}
159 ; DISABLE-V4T-NEXT: bx r1
161 ; ENABLE-V5T-NEXT: {{LBB[0-9_]+}}: @ %if.end
163 define i32 @freqSaveAndRestoreOutsideLoop(i32 %cond, i32 %N) {
165 %tobool = icmp eq i32 %cond, 0
166 br i1 %tobool, label %if.else, label %for.preheader
169 tail call void asm "nop", ""()
172 for.body: ; preds = %entry, %for.body
173 %i.05 = phi i32 [ %inc, %for.body ], [ 0, %for.preheader ]
174 %sum.04 = phi i32 [ %add, %for.body ], [ 0, %for.preheader ]
175 %call = tail call i32 asm sideeffect "movs $0, #1", "=r,~{r4}"()
176 %add = add nsw i32 %call, %sum.04
177 %inc = add nuw nsw i32 %i.05, 1
178 %exitcond = icmp eq i32 %inc, 10
179 br i1 %exitcond, label %for.end, label %for.body
181 for.end: ; preds = %for.body
182 %shl = shl i32 %add, 3
185 if.else: ; preds = %entry
186 %mul = shl nsw i32 %N, 1
189 if.end: ; preds = %if.else, %for.end
190 %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ]
194 declare i32 @something(...)
196 ; Check that we do not perform the shrink-wrapping inside the loop even
197 ; though that would be legal. The cost model must prevent that.
198 ; CHECK-LABEL: freqSaveAndRestoreOutsideLoop2:
200 ; Make sure we save the CSR used in the inline asm: r4.
204 ; CHECK: movs [[SUM:r0]], #0
205 ; CHECK-NEXT: movs [[IV:r[0-9]+]], #10
207 ; CHECK: [[LOOP_LABEL:LBB[0-9_]+]]: @ %for.body
208 ; CHECK: movs [[TMP:r[0-9]+]], #1
209 ; CHECK: adds [[SUM]], [[TMP]], [[SUM]]
210 ; CHECK-NEXT: subs [[IV]], [[IV]], #1
211 ; CHECK-NEXT: bne [[LOOP_LABEL]]
217 define i32 @freqSaveAndRestoreOutsideLoop2(i32 %cond) {
219 br label %for.preheader
222 tail call void asm "nop", ""()
225 for.body: ; preds = %for.body, %entry
226 %i.04 = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]
227 %sum.03 = phi i32 [ 0, %for.preheader ], [ %add, %for.body ]
228 %call = tail call i32 asm sideeffect "movs $0, #1", "=r,~{r4}"()
229 %add = add nsw i32 %call, %sum.03
230 %inc = add nuw nsw i32 %i.04, 1
231 %exitcond = icmp eq i32 %inc, 10
232 br i1 %exitcond, label %for.exit, label %for.body
235 tail call void asm "nop", ""()
238 for.end: ; preds = %for.body
242 ; Check with a more complex case that we do not have save within the loop and
244 ; CHECK-LABEL: loopInfoSaveOutsideLoop:
247 ; ENABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]]
250 ; Make sure we save the CSR used in the inline asm: r4.
251 ; CHECK: push {r4, lr}
253 ; DISABLE: cmp r0, #0
254 ; DISABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]]
256 ; SUM is in r0 because it is coalesced with the second
257 ; argument on the else path.
258 ; CHECK: movs [[SUM:r0]], #0
259 ; CHECK-NEXT: movs [[IV:r[0-9]+]], #10
262 ; CHECK: [[LOOP:LBB[0-9_]+]]: @ %for.body
263 ; CHECK: movs [[TMP:r[0-9]+]], #1
264 ; CHECK: adds [[SUM]], [[TMP]], [[SUM]]
265 ; CHECK-NEXT: subs [[IV]], [[IV]], #1
266 ; CHECK-NEXT: bne [[LOOP]]
270 ; CHECK: lsls [[SUM]], [[SUM]], #3
271 ; ENABLE-V5T-NEXT: pop {r4, pc}
272 ; ENABLE-V4T-NEXT: pop {r4}
273 ; ENABLE-V4T-NEXT: pop {r1}
274 ; ENABLE-V4T-NEXT: bx r1
276 ; Duplicated epilogue.
277 ; DISABLE-V5T: pop {r4, pc}
278 ; DISABLE-V4T: b [[END_LABEL:LBB[0-9_]+]]
280 ; CHECK: [[ELSE_LABEL]]: @ %if.else
281 ; Shift second argument by one and store into returned register.
282 ; CHECK: lsls r0, r1, #1
283 ; DISABLE-V5T-NEXT: pop {r4, pc}
284 ; DISABLE-V4T-NEXT: [[END_LABEL]]: @ %if.end
285 ; DISABLE-V4T-NEXT: pop {r4}
286 ; DISABLE-V4T-NEXT: pop {r1}
287 ; DISABLE-V4T-NEXT: bx r1
289 ; ENABLE-V5T-NEXT: {{LBB[0-9_]+}}: @ %if.end
291 define i32 @loopInfoSaveOutsideLoop(i32 %cond, i32 %N) {
293 %tobool = icmp eq i32 %cond, 0
294 br i1 %tobool, label %if.else, label %for.preheader
297 tail call void asm "nop", ""()
300 for.body: ; preds = %entry, %for.body
301 %i.05 = phi i32 [ %inc, %for.body ], [ 0, %for.preheader ]
302 %sum.04 = phi i32 [ %add, %for.body ], [ 0, %for.preheader ]
303 %call = tail call i32 asm sideeffect "movs $0, #1", "=r,~{r4}"()
304 %add = add nsw i32 %call, %sum.04
305 %inc = add nuw nsw i32 %i.05, 1
306 %exitcond = icmp eq i32 %inc, 10
307 br i1 %exitcond, label %for.end, label %for.body
309 for.end: ; preds = %for.body
310 tail call void asm "nop", "~{r4}"()
311 %shl = shl i32 %add, 3
314 if.else: ; preds = %entry
315 %mul = shl nsw i32 %N, 1
318 if.end: ; preds = %if.else, %for.end
319 %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ]
323 declare void @somethingElse(...)
325 ; Check with a more complex case that we do not have restore within the loop and
327 ; CHECK-LABEL: loopInfoRestoreOutsideLoop:
330 ; ENABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]]
333 ; Make sure we save the CSR used in the inline asm: r4.
334 ; CHECK: push {r4, lr}
336 ; DISABLE-NEXT: cmp r0, #0
337 ; DISABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]]
339 ; SUM is in r0 because it is coalesced with the second
340 ; argument on the else path.
341 ; CHECK: movs [[SUM:r0]], #0
342 ; CHECK-NEXT: movs [[IV:r[0-9]+]], #10
345 ; CHECK: [[LOOP:LBB[0-9_]+]]: @ %for.body
346 ; CHECK: movs [[TMP:r[0-9]+]], #1
347 ; CHECK: adds [[SUM]], [[TMP]], [[SUM]]
348 ; CHECK-NEXT: subs [[IV]], [[IV]], #1
349 ; CHECK-NEXT: bne [[LOOP]]
353 ; CHECK: lsls [[SUM]], [[SUM]], #3
354 ; ENABLE-V5T-NEXT: pop {r4, pc}
355 ; ENABLE-V4T-NEXT: pop {r4}
356 ; ENABLE-V4T-NEXT: pop {r1}
357 ; ENABLE-V4T-NEXT: bx r1
359 ; Duplicated epilogue.
360 ; DISABLE-V5T: pop {r4, pc}
361 ; DISABLE-V4T: b [[END_LABEL:LBB[0-9_]+]]
363 ; CHECK: [[ELSE_LABEL]]: @ %if.else
364 ; Shift second argument by one and store into returned register.
365 ; CHECK: lsls r0, r1, #1
366 ; DISABLE-V5T-NEXT: pop {r4, pc}
367 ; DISABLE-V4T-NEXT: [[END_LABEL]]: @ %if.end
368 ; DISABLE-V4T-NEXT: pop {r4}
369 ; DISABLE-V4T-NEXT: pop {r1}
370 ; DISABLE-V4T-NEXT: bx r1
372 ; ENABLE-V5T-NEXT: {{LBB[0-9_]+}}: @ %if.end
374 define i32 @loopInfoRestoreOutsideLoop(i32 %cond, i32 %N) #0 {
376 %tobool = icmp eq i32 %cond, 0
377 br i1 %tobool, label %if.else, label %if.then
379 if.then: ; preds = %entry
380 tail call void asm "nop", "~{r4}"()
383 for.body: ; preds = %for.body, %if.then
384 %i.05 = phi i32 [ 0, %if.then ], [ %inc, %for.body ]
385 %sum.04 = phi i32 [ 0, %if.then ], [ %add, %for.body ]
386 %call = tail call i32 asm sideeffect "movs $0, #1", "=r,~{r4}"()
387 %add = add nsw i32 %call, %sum.04
388 %inc = add nuw nsw i32 %i.05, 1
389 %exitcond = icmp eq i32 %inc, 10
390 br i1 %exitcond, label %for.end, label %for.body
392 for.end: ; preds = %for.body
393 %shl = shl i32 %add, 3
396 if.else: ; preds = %entry
397 %mul = shl nsw i32 %N, 1
400 if.end: ; preds = %if.else, %for.end
401 %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ]
405 ; Check that we handle function with no frame information correctly.
406 ; CHECK-LABEL: emptyFrame:
408 ; CHECK-NEXT: movs r0, #0
410 define i32 @emptyFrame() {
415 ; Check that we handle inline asm correctly.
416 ; CHECK-LABEL: inlineAsm:
419 ; ENABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]]
422 ; Make sure we save the CSR used in the inline asm: r4.
423 ; CHECK: push {r4, lr}
425 ; DISABLE: cmp r0, #0
426 ; DISABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]]
428 ; CHECK: movs [[IV:r[0-9]+]], #10
431 ; CHECK: [[LOOP:LBB[0-9_]+]]: @ %for.body
433 ; CHECK: subs [[IV]], [[IV]], #1
434 ; CHECK-NEXT: bne [[LOOP]]
438 ; ENABLE-V5T-NEXT: pop {r4, pc}
439 ; ENABLE-V4T-NEXT: pop {r4}
440 ; ENABLE-V4T-NEXT: pop {r1}
441 ; ENABLE-V4T-NEXT: bx r1
443 ; Duplicated epilogue.
444 ; DISABLE-V5T-NEXT: pop {r4, pc}
445 ; DISABLE-V4T-NEXT: b [[END_LABEL:LBB[0-9_]+]]
447 ; CHECK: [[ELSE_LABEL]]: @ %if.else
448 ; Shift second argument by one and store into returned register.
449 ; CHECK: lsls r0, r1, #1
450 ; DISABLE-V5T-NEXT: pop {r4, pc}
451 ; DISABLE-V4T-NEXT: [[END_LABEL]]: @ %if.end
452 ; DISABLE-V4T-NEXT: pop {r4}
453 ; DISABLE-V4T-NEXT: pop {r1}
454 ; DISABLE-V4T-NEXT: bx r1
456 ; ENABLE-V5T-NEXT: {{LBB[0-9_]+}}: @ %if.end
458 define i32 @inlineAsm(i32 %cond, i32 %N) {
460 %tobool = icmp eq i32 %cond, 0
461 br i1 %tobool, label %if.else, label %for.preheader
464 tail call void asm "nop", ""()
467 for.body: ; preds = %entry, %for.body
468 %i.03 = phi i32 [ %inc, %for.body ], [ 0, %for.preheader ]
469 tail call void asm sideeffect "movs r4, #1", "~{r4}"()
470 %inc = add nuw nsw i32 %i.03, 1
471 %exitcond = icmp eq i32 %inc, 10
472 br i1 %exitcond, label %for.exit, label %for.body
475 tail call void asm "nop", ""()
478 if.else: ; preds = %entry
479 %mul = shl nsw i32 %N, 1
482 if.end: ; preds = %for.body, %if.else
483 %sum.0 = phi i32 [ %mul, %if.else ], [ 0, %for.exit ]
487 ; Check that we handle calls to variadic functions correctly.
488 ; CHECK-LABEL: callVariadicFunc:
491 ; ENABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]]
494 ; CHECK: push {[[TMP:r[0-9]+]], lr}
497 ; DISABLE: cmp r0, #0
498 ; DISABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]]
500 ; Setup of the varags.
501 ; CHECK: mov [[TMP_SP:r[0-9]+]], sp
502 ; CHECK-NEXT: str r1, {{\[}}[[TMP_SP]]]
503 ; CHECK-NEXT: str r1, {{\[}}[[TMP_SP]], #4]
504 ; CHECK-NEXT: str r1, {{\[}}[[TMP_SP]], #8]
505 ; Thumb has quite a strange way for moving stuff
506 ; in around. Oh well, match the current sequence.
508 ; CHECK-NEXT: pop {r0}
510 ; CHECK-NEXT: pop {r2}
512 ; CHECK-NEXT: pop {r3}
514 ; CHECK-NEXT: lsls r0, r0, #3
516 ; ENABLE-NEXT: add sp, #16
517 ; ENABLE-V5T-NEXT: pop {[[TMP]], pc}
518 ; ENABLE-V4T-NEXT: pop {[[TMP]]}
519 ; ENABLE-V4T-NEXT: pop {r1}
520 ; ENABLE-V4T-NEXT: bx r1
522 ; Duplicated epilogue.
523 ; DISABLE-V5T-NEXT: add sp, #16
524 ; DISABLE-V5T-NEXT: pop {[[TMP]], pc}
525 ; DISABLE-V4T-NEXT: b [[END_LABEL:LBB[0-9_]+]]
527 ; CHECK: [[ELSE_LABEL]]: @ %if.else
528 ; Shift second argument by one and store into returned register.
529 ; CHECK: lsls r0, r1, #1
532 ; ENABLE-V5T-NEXT: {{LBB[0-9_]+}}: @ %if.end
535 ; DISABLE-V4T-NEXT: [[END_LABEL]]: @ %if.end
536 ; DISABLE-NEXT: add sp, #16
537 ; DISABLE-V5T-NEXT: pop {[[TMP]], pc}
538 ; DISABLE-V4T-NEXT: pop {[[TMP]]}
539 ; DISABLE-V4T-NEXT: pop {r1}
540 ; DISABLE-V4T-NEXT: bx r1
541 define i32 @callVariadicFunc(i32 %cond, i32 %N) {
543 %tobool = icmp eq i32 %cond, 0
544 br i1 %tobool, label %if.else, label %if.then
546 if.then: ; preds = %entry
547 %call = tail call i32 (i32, ...) @someVariadicFunc(i32 %N, i32 %N, i32 %N, i32 %N, i32 %N, i32 %N, i32 %N)
548 %shl = shl i32 %call, 3
551 if.else: ; preds = %entry
552 %mul = shl nsw i32 %N, 1
555 if.end: ; preds = %if.else, %if.then
556 %sum.0 = phi i32 [ %shl, %if.then ], [ %mul, %if.else ]
560 declare i32 @someVariadicFunc(i32, ...)
562 ; Make sure we do not insert unreachable code after noreturn function.
563 ; Although this is not incorrect to insert such code, it is useless
564 ; and it hurts the binary size.
566 ; CHECK-LABEL: noreturn:
570 ; CHECK-NEXT: bne [[ABORT:LBB[0-9_]+]]
572 ; CHECK: movs r0, #42
578 ; CHECK: [[ABORT]]: @ %if.abort
584 define i32 @noreturn(i8 signext %bad_thing) {
586 %tobool = icmp eq i8 %bad_thing, 0
587 br i1 %tobool, label %if.end, label %if.abort
590 %call = tail call i32 asm sideeffect "movs $0, #1", "=r,~{r4}"()
591 tail call void @abort() #0
598 declare void @abort() #0
600 define i32 @b_to_bx(i32 %value) {
601 ; CHECK-LABEL: b_to_bx:
602 ; DISABLE: push {r7, lr}
604 ; CHECK-NEXT: bgt [[ELSE_LABEL:LBB[0-9_]+]]
605 ; ENABLE: push {r7, lr}
608 ; DISABLE-V5-NEXT: pop {r7, pc}
609 ; DISABLE-V4T-NEXT: b [[END_LABEL:LBB[0-9_]+]]
611 ; ENABLE-V5-NEXT: pop {r7, pc}
612 ; ENABLE-V4-NEXT: pop {r7}
613 ; ENABLE-V4-NEXT: pop {r1}
614 ; ENABLE-V4-NEXT: bx r1
616 ; CHECK: [[ELSE_LABEL]]: @ %if.else
617 ; CHECK-NEXT: lsls r0, r1, #1
618 ; DISABLE-V5-NEXT: pop {r7, pc}
619 ; DISABLE-V4T-NEXT: [[END_LABEL]]: @ %if.end
620 ; DISABLE-V4T-NEXT: pop {r7}
621 ; DISABLE-V4T-NEXT: pop {r1}
622 ; DISABLE-V4T-NEXT: bx r1
624 ; ENABLE-V5T-NEXT: {{LBB[0-9_]+}}: @ %if.end
628 %cmp = icmp slt i32 %value, 50
629 br i1 %cmp, label %if.then, label %if.else
632 %div = sdiv i32 5000, %value
636 %mul = shl nsw i32 %value, 1
640 %value.addr.0 = phi i32 [ %div, %if.then ], [ %mul, %if.else ]
641 ret i32 %value.addr.0
644 define i1 @beq_to_bx(i32* %y, i32 %head) {
645 ; CHECK-LABEL: beq_to_bx:
646 ; DISABLE: push {r4, lr}
648 ; CHECK-NEXT: beq [[EXIT_LABEL:LBB[0-9_]+]]
649 ; ENABLE: push {r4, lr}
652 ; ENABLE-NEXT: pop {r4}
653 ; ENABLE-NEXT: mov r12, r{{.*}}
654 ; ENABLE-NEXT: pop {r0}
655 ; ENABLE-NEXT: mov lr, r0
656 ; ENABLE-NEXT: mov r0, r12
657 ; CHECK-NEXT: beq [[EXIT_LABEL]]
659 ; CHECK: str r1, [r2]
660 ; CHECK: str r3, [r2]
661 ; CHECK-NEXT: movs r0, #0
662 ; CHECK-NEXT: [[EXIT_LABEL]]: @ %cleanup
664 ; DISABLE-V5-NEXT: pop {r4, pc}
665 ; DISABLE-V4T-NEXT: pop {r4}
666 ; DISABLE-V4T-NEXT: pop {r1}
667 ; DISABLE-V4T-NEXT: bx r1
670 %cmp = icmp eq i32* %y, null
671 br i1 %cmp, label %cleanup, label %if.end
674 %z = load i32, i32* %y, align 4
676 %cmp2 = icmp eq i32 %and, 0
677 br i1 %cmp2, label %cleanup, label %if.end4
680 store i32 %head, i32* %y, align 4
681 store volatile i32 %z, i32* %y, align 4
685 %retval.0 = phi i1 [ 0, %if.end4 ], [ 1, %entry ], [ 1, %if.end ]
689 attributes #0 = { noreturn nounwind }