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: cmp [[IV]], #0
143 ; CHECK-NEXT: bne [[LOOP]]
147 ; CHECK: lsls [[SUM]], [[SUM]], #3
149 ; Duplicated epilogue.
150 ; DISABLE-V5T: pop {r4, pc}
151 ; DISABLE-V4T: b [[END_LABEL:LBB[0-9_]+]]
153 ; CHECK: [[ELSE_LABEL]]: @ %if.else
154 ; Shift second argument by one and store into returned register.
155 ; CHECK: lsls r0, r1, #1
156 ; DISABLE-V5T-NEXT: pop {r4, pc}
157 ; DISABLE-V4T-NEXT: [[END_LABEL]]: @ %if.end
158 ; DISABLE-V4T-NEXT: pop {r4}
159 ; DISABLE-V4T-NEXT: pop {r1}
160 ; DISABLE-V4T-NEXT: bx r1
162 ; ENABLE-V5T-NEXT: {{LBB[0-9_]+}}: @ %if.end
164 define i32 @freqSaveAndRestoreOutsideLoop(i32 %cond, i32 %N) {
166 %tobool = icmp eq i32 %cond, 0
167 br i1 %tobool, label %if.else, label %for.preheader
170 tail call void asm "nop", ""()
173 for.body: ; preds = %entry, %for.body
174 %i.05 = phi i32 [ %inc, %for.body ], [ 0, %for.preheader ]
175 %sum.04 = phi i32 [ %add, %for.body ], [ 0, %for.preheader ]
176 %call = tail call i32 asm sideeffect "movs $0, #1", "=r,~{r4}"()
177 %add = add nsw i32 %call, %sum.04
178 %inc = add nuw nsw i32 %i.05, 1
179 %exitcond = icmp eq i32 %inc, 10
180 br i1 %exitcond, label %for.end, label %for.body
182 for.end: ; preds = %for.body
183 %shl = shl i32 %add, 3
186 if.else: ; preds = %entry
187 %mul = shl nsw i32 %N, 1
190 if.end: ; preds = %if.else, %for.end
191 %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ]
195 declare i32 @something(...)
197 ; Check that we do not perform the shrink-wrapping inside the loop even
198 ; though that would be legal. The cost model must prevent that.
199 ; CHECK-LABEL: freqSaveAndRestoreOutsideLoop2:
201 ; Make sure we save the CSR used in the inline asm: r4.
205 ; CHECK: movs [[SUM:r0]], #0
206 ; CHECK-NEXT: movs [[IV:r[0-9]+]], #10
208 ; CHECK: [[LOOP_LABEL:LBB[0-9_]+]]: @ %for.body
209 ; CHECK: movs [[TMP:r[0-9]+]], #1
210 ; CHECK: adds [[SUM]], [[TMP]], [[SUM]]
211 ; CHECK-NEXT: subs [[IV]], [[IV]], #1
212 ; CHECK-NEXT: cmp [[IV]], #0
213 ; CHECK-NEXT: bne [[LOOP_LABEL]]
219 define i32 @freqSaveAndRestoreOutsideLoop2(i32 %cond) {
221 br label %for.preheader
224 tail call void asm "nop", ""()
227 for.body: ; preds = %for.body, %entry
228 %i.04 = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]
229 %sum.03 = phi i32 [ 0, %for.preheader ], [ %add, %for.body ]
230 %call = tail call i32 asm sideeffect "movs $0, #1", "=r,~{r4}"()
231 %add = add nsw i32 %call, %sum.03
232 %inc = add nuw nsw i32 %i.04, 1
233 %exitcond = icmp eq i32 %inc, 10
234 br i1 %exitcond, label %for.exit, label %for.body
237 tail call void asm "nop", ""()
240 for.end: ; preds = %for.body
244 ; Check with a more complex case that we do not have save within the loop and
246 ; CHECK-LABEL: loopInfoSaveOutsideLoop:
249 ; ENABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]]
252 ; Make sure we save the CSR used in the inline asm: r4.
253 ; CHECK: push {r4, lr}
255 ; DISABLE: cmp r0, #0
256 ; DISABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]]
258 ; SUM is in r0 because it is coalesced with the second
259 ; argument on the else path.
260 ; CHECK: movs [[SUM:r0]], #0
261 ; CHECK-NEXT: movs [[IV:r[0-9]+]], #10
264 ; CHECK: [[LOOP:LBB[0-9_]+]]: @ %for.body
265 ; CHECK: movs [[TMP:r[0-9]+]], #1
266 ; CHECK: adds [[SUM]], [[TMP]], [[SUM]]
267 ; CHECK-NEXT: subs [[IV]], [[IV]], #1
268 ; CHECK-NEXT: cmp [[IV]], #0
269 ; CHECK-NEXT: bne [[LOOP]]
273 ; CHECK: lsls [[SUM]], [[SUM]], #3
274 ; ENABLE-V5T-NEXT: pop {r4, pc}
275 ; ENABLE-V4T-NEXT: pop {r4}
276 ; ENABLE-V4T-NEXT: pop {r1}
277 ; ENABLE-V4T-NEXT: bx r1
279 ; Duplicated epilogue.
280 ; DISABLE-V5T: pop {r4, pc}
281 ; DISABLE-V4T: b [[END_LABEL:LBB[0-9_]+]]
283 ; CHECK: [[ELSE_LABEL]]: @ %if.else
284 ; Shift second argument by one and store into returned register.
285 ; CHECK: lsls r0, r1, #1
286 ; DISABLE-V5T-NEXT: pop {r4, pc}
287 ; DISABLE-V4T-NEXT: [[END_LABEL]]: @ %if.end
288 ; DISABLE-V4T-NEXT: pop {r4}
289 ; DISABLE-V4T-NEXT: pop {r1}
290 ; DISABLE-V4T-NEXT: bx r1
292 ; ENABLE-V5T-NEXT: {{LBB[0-9_]+}}: @ %if.end
294 define i32 @loopInfoSaveOutsideLoop(i32 %cond, i32 %N) {
296 %tobool = icmp eq i32 %cond, 0
297 br i1 %tobool, label %if.else, label %for.preheader
300 tail call void asm "nop", ""()
303 for.body: ; preds = %entry, %for.body
304 %i.05 = phi i32 [ %inc, %for.body ], [ 0, %for.preheader ]
305 %sum.04 = phi i32 [ %add, %for.body ], [ 0, %for.preheader ]
306 %call = tail call i32 asm sideeffect "movs $0, #1", "=r,~{r4}"()
307 %add = add nsw i32 %call, %sum.04
308 %inc = add nuw nsw i32 %i.05, 1
309 %exitcond = icmp eq i32 %inc, 10
310 br i1 %exitcond, label %for.end, label %for.body
312 for.end: ; preds = %for.body
313 tail call void asm "nop", "~{r4}"()
314 %shl = shl i32 %add, 3
317 if.else: ; preds = %entry
318 %mul = shl nsw i32 %N, 1
321 if.end: ; preds = %if.else, %for.end
322 %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ]
326 declare void @somethingElse(...)
328 ; Check with a more complex case that we do not have restore within the loop and
330 ; CHECK-LABEL: loopInfoRestoreOutsideLoop:
333 ; ENABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]]
336 ; Make sure we save the CSR used in the inline asm: r4.
337 ; CHECK: push {r4, lr}
339 ; DISABLE-NEXT: cmp r0, #0
340 ; DISABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]]
342 ; SUM is in r0 because it is coalesced with the second
343 ; argument on the else path.
344 ; CHECK: movs [[SUM:r0]], #0
345 ; CHECK-NEXT: movs [[IV:r[0-9]+]], #10
348 ; CHECK: [[LOOP:LBB[0-9_]+]]: @ %for.body
349 ; CHECK: movs [[TMP:r[0-9]+]], #1
350 ; CHECK: adds [[SUM]], [[TMP]], [[SUM]]
351 ; CHECK-NEXT: subs [[IV]], [[IV]], #1
352 ; CHECK-NEXT: cmp [[IV]], #0
353 ; CHECK-NEXT: bne [[LOOP]]
357 ; CHECK: lsls [[SUM]], [[SUM]], #3
358 ; ENABLE-V5T-NEXT: pop {r4, pc}
359 ; ENABLE-V4T-NEXT: pop {r4}
360 ; ENABLE-V4T-NEXT: pop {r1}
361 ; ENABLE-V4T-NEXT: bx r1
363 ; Duplicated epilogue.
364 ; DISABLE-V5T: pop {r4, pc}
365 ; DISABLE-V4T: b [[END_LABEL:LBB[0-9_]+]]
367 ; CHECK: [[ELSE_LABEL]]: @ %if.else
368 ; Shift second argument by one and store into returned register.
369 ; CHECK: lsls r0, r1, #1
370 ; DISABLE-V5T-NEXT: pop {r4, pc}
371 ; DISABLE-V4T-NEXT: [[END_LABEL]]: @ %if.end
372 ; DISABLE-V4T-NEXT: pop {r4}
373 ; DISABLE-V4T-NEXT: pop {r1}
374 ; DISABLE-V4T-NEXT: bx r1
376 ; ENABLE-V5T-NEXT: {{LBB[0-9_]+}}: @ %if.end
378 define i32 @loopInfoRestoreOutsideLoop(i32 %cond, i32 %N) #0 {
380 %tobool = icmp eq i32 %cond, 0
381 br i1 %tobool, label %if.else, label %if.then
383 if.then: ; preds = %entry
384 tail call void asm "nop", "~{r4}"()
387 for.body: ; preds = %for.body, %if.then
388 %i.05 = phi i32 [ 0, %if.then ], [ %inc, %for.body ]
389 %sum.04 = phi i32 [ 0, %if.then ], [ %add, %for.body ]
390 %call = tail call i32 asm sideeffect "movs $0, #1", "=r,~{r4}"()
391 %add = add nsw i32 %call, %sum.04
392 %inc = add nuw nsw i32 %i.05, 1
393 %exitcond = icmp eq i32 %inc, 10
394 br i1 %exitcond, label %for.end, label %for.body
396 for.end: ; preds = %for.body
397 %shl = shl i32 %add, 3
400 if.else: ; preds = %entry
401 %mul = shl nsw i32 %N, 1
404 if.end: ; preds = %if.else, %for.end
405 %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ]
409 ; Check that we handle function with no frame information correctly.
410 ; CHECK-LABEL: emptyFrame:
412 ; CHECK-NEXT: movs r0, #0
414 define i32 @emptyFrame() {
419 ; Check that we handle inline asm correctly.
420 ; CHECK-LABEL: inlineAsm:
423 ; ENABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]]
426 ; Make sure we save the CSR used in the inline asm: r4.
427 ; CHECK: push {r4, lr}
429 ; DISABLE: cmp r0, #0
430 ; DISABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]]
432 ; CHECK: movs [[IV:r[0-9]+]], #10
435 ; CHECK: [[LOOP:LBB[0-9_]+]]: @ %for.body
437 ; CHECK: subs [[IV]], [[IV]], #1
438 ; CHECK-NEXT: cmp [[IV]], #0
439 ; CHECK-NEXT: bne [[LOOP]]
443 ; ENABLE-V5T-NEXT: pop {r4, pc}
444 ; ENABLE-V4T-NEXT: pop {r4}
445 ; ENABLE-V4T-NEXT: pop {r1}
446 ; ENABLE-V4T-NEXT: bx r1
448 ; Duplicated epilogue.
449 ; DISABLE-V5T-NEXT: pop {r4, pc}
450 ; DISABLE-V4T-NEXT: b [[END_LABEL:LBB[0-9_]+]]
452 ; CHECK: [[ELSE_LABEL]]: @ %if.else
453 ; Shift second argument by one and store into returned register.
454 ; CHECK: lsls r0, r1, #1
455 ; DISABLE-V5T-NEXT: pop {r4, pc}
456 ; DISABLE-V4T-NEXT: [[END_LABEL]]: @ %if.end
457 ; DISABLE-V4T-NEXT: pop {r4}
458 ; DISABLE-V4T-NEXT: pop {r1}
459 ; DISABLE-V4T-NEXT: bx r1
461 ; ENABLE-V5T-NEXT: {{LBB[0-9_]+}}: @ %if.end
463 define i32 @inlineAsm(i32 %cond, i32 %N) {
465 %tobool = icmp eq i32 %cond, 0
466 br i1 %tobool, label %if.else, label %for.preheader
469 tail call void asm "nop", ""()
472 for.body: ; preds = %entry, %for.body
473 %i.03 = phi i32 [ %inc, %for.body ], [ 0, %for.preheader ]
474 tail call void asm sideeffect "movs r4, #1", "~{r4}"()
475 %inc = add nuw nsw i32 %i.03, 1
476 %exitcond = icmp eq i32 %inc, 10
477 br i1 %exitcond, label %for.exit, label %for.body
480 tail call void asm "nop", ""()
483 if.else: ; preds = %entry
484 %mul = shl nsw i32 %N, 1
487 if.end: ; preds = %for.body, %if.else
488 %sum.0 = phi i32 [ %mul, %if.else ], [ 0, %for.exit ]
492 ; Check that we handle calls to variadic functions correctly.
493 ; CHECK-LABEL: callVariadicFunc:
496 ; ENABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]]
499 ; CHECK: push {[[TMP:r[0-9]+]], lr}
502 ; DISABLE: cmp r0, #0
503 ; DISABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]]
505 ; Setup of the varags.
506 ; CHECK: mov [[TMP_SP:r[0-9]+]], sp
507 ; CHECK-NEXT: str r1, {{\[}}[[TMP_SP]]]
508 ; CHECK-NEXT: str r1, {{\[}}[[TMP_SP]], #4]
509 ; CHECK-NEXT: str r1, {{\[}}[[TMP_SP]], #8]
510 ; Thumb has quite a strange way for moving stuff
511 ; in around. Oh well, match the current sequence.
513 ; CHECK-NEXT: pop {r0}
515 ; CHECK-NEXT: pop {r2}
517 ; CHECK-NEXT: pop {r3}
519 ; CHECK-NEXT: lsls r0, r0, #3
521 ; ENABLE-NEXT: add sp, #16
522 ; ENABLE-V5T-NEXT: pop {[[TMP]], pc}
523 ; ENABLE-V4T-NEXT: pop {[[TMP]]}
524 ; ENABLE-V4T-NEXT: pop {r1}
525 ; ENABLE-V4T-NEXT: bx r1
527 ; Duplicated epilogue.
528 ; DISABLE-V5T-NEXT: add sp, #16
529 ; DISABLE-V5T-NEXT: pop {[[TMP]], pc}
530 ; DISABLE-V4T-NEXT: b [[END_LABEL:LBB[0-9_]+]]
532 ; CHECK: [[ELSE_LABEL]]: @ %if.else
533 ; Shift second argument by one and store into returned register.
534 ; CHECK: lsls r0, r1, #1
537 ; ENABLE-V5T-NEXT: {{LBB[0-9_]+}}: @ %if.end
540 ; DISABLE-V4T-NEXT: [[END_LABEL]]: @ %if.end
541 ; DISABLE-NEXT: add sp, #16
542 ; DISABLE-V5T-NEXT: pop {[[TMP]], pc}
543 ; DISABLE-V4T-NEXT: pop {[[TMP]]}
544 ; DISABLE-V4T-NEXT: pop {r1}
545 ; DISABLE-V4T-NEXT: bx r1
546 define i32 @callVariadicFunc(i32 %cond, i32 %N) {
548 %tobool = icmp eq i32 %cond, 0
549 br i1 %tobool, label %if.else, label %if.then
551 if.then: ; preds = %entry
552 %call = tail call i32 (i32, ...) @someVariadicFunc(i32 %N, i32 %N, i32 %N, i32 %N, i32 %N, i32 %N, i32 %N)
553 %shl = shl i32 %call, 3
556 if.else: ; preds = %entry
557 %mul = shl nsw i32 %N, 1
560 if.end: ; preds = %if.else, %if.then
561 %sum.0 = phi i32 [ %shl, %if.then ], [ %mul, %if.else ]
565 declare i32 @someVariadicFunc(i32, ...)
567 ; Make sure we do not insert unreachable code after noreturn function.
568 ; Although this is not incorrect to insert such code, it is useless
569 ; and it hurts the binary size.
571 ; CHECK-LABEL: noreturn:
574 ; CHECK: movs [[TMP:r[0-9]+]], #255
575 ; CHECK-NEXT: tst r0, [[TMP]]
576 ; CHECK-NEXT: bne [[ABORT:LBB[0-9_]+]]
578 ; CHECK: movs r0, #42
584 ; CHECK: [[ABORT]]: @ %if.abort
590 define i32 @noreturn(i8 signext %bad_thing) {
592 %tobool = icmp eq i8 %bad_thing, 0
593 br i1 %tobool, label %if.end, label %if.abort
596 %call = tail call i32 asm sideeffect "movs $0, #1", "=r,~{r4}"()
597 tail call void @abort() #0
604 declare void @abort() #0
606 define i32 @b_to_bx(i32 %value) {
607 ; CHECK-LABEL: b_to_bx:
608 ; DISABLE: push {r7, lr}
610 ; CHECK-NEXT: bgt [[ELSE_LABEL:LBB[0-9_]+]]
611 ; ENABLE: push {r7, lr}
614 ; DISABLE-V5-NEXT: pop {r7, pc}
615 ; DISABLE-V4T-NEXT: b [[END_LABEL:LBB[0-9_]+]]
617 ; ENABLE-V5-NEXT: pop {r7, pc}
618 ; ENABLE-V4-NEXT: pop {r7}
619 ; ENABLE-V4-NEXT: pop {r1}
620 ; ENABLE-V4-NEXT: bx r1
622 ; CHECK: [[ELSE_LABEL]]: @ %if.else
623 ; CHECK-NEXT: lsls r0, r1, #1
624 ; DISABLE-V5-NEXT: pop {r7, pc}
625 ; DISABLE-V4T-NEXT: [[END_LABEL]]: @ %if.end
626 ; DISABLE-V4T-NEXT: pop {r7}
627 ; DISABLE-V4T-NEXT: pop {r1}
628 ; DISABLE-V4T-NEXT: bx r1
630 ; ENABLE-V5T-NEXT: {{LBB[0-9_]+}}: @ %if.end
634 %cmp = icmp slt i32 %value, 50
635 br i1 %cmp, label %if.then, label %if.else
638 %div = sdiv i32 5000, %value
642 %mul = shl nsw i32 %value, 1
646 %value.addr.0 = phi i32 [ %div, %if.then ], [ %mul, %if.else ]
647 ret i32 %value.addr.0
650 define i1 @beq_to_bx(i32* %y, i32 %head) {
651 ; CHECK-LABEL: beq_to_bx:
652 ; DISABLE: push {r4, lr}
654 ; CHECK-NEXT: beq [[EXIT_LABEL:LBB[0-9_]+]]
655 ; ENABLE: push {r4, lr}
658 ; ENABLE-NEXT: pop {r4}
659 ; ENABLE-NEXT: pop {r3}
660 ; ENABLE-NEXT: mov lr, r3
661 ; CHECK-NEXT: beq [[EXIT_LABEL]]
663 ; CHECK: str r1, [r2]
664 ; CHECK-NEXT: movs r0, #0
665 ; CHECK-NEXT: [[EXIT_LABEL]]: @ %cleanup
667 ; DISABLE-V5-NEXT: pop {r4, pc}
668 ; DISABLE-V4T-NEXT: pop {r4}
669 ; DISABLE-V4T-NEXT: pop {r1}
670 ; DISABLE-V4T-NEXT: bx r1
673 %cmp = icmp eq i32* %y, null
674 br i1 %cmp, label %cleanup, label %if.end
677 %z = load i32, i32* %y, align 4
679 %cmp2 = icmp eq i32 %and, 0
680 br i1 %cmp2, label %cleanup, label %if.end4
683 store i32 %head, i32* %y, align 4
687 %retval.0 = phi i1 [ 0, %if.end4 ], [ 1, %entry ], [ 1, %if.end ]
691 attributes #0 = { noreturn nounwind }