1 ; RUN: llc %s -o - -enable-shrink-wrap=true | FileCheck %s --check-prefix=CHECK --check-prefix=ENABLE
2 ; RUN: llc %s -o - -enable-shrink-wrap=false | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE
3 target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
4 target triple = "arm64-apple-ios"
7 ; Initial motivating example: Simple diamond with a call just on one side.
10 ; Compare the arguments and jump to exit.
13 ; ENABLE-NEXT: b.ge [[EXIT_LABEL:LBB[0-9_]+]]
16 ; CHECK: stp [[SAVE_SP:x[0-9]+]], [[CSR:x[0-9]+]], [sp, #-16]!
17 ; CHECK-NEXT: mov [[SAVE_SP]], sp
18 ; CHECK-NEXT: sub sp, sp, #16
20 ; Compare the arguments and jump to exit.
21 ; After the prologue is set.
23 ; DISABLE-NEXT: b.ge [[EXIT_LABEL:LBB[0-9_]+]]
25 ; Store %a in the alloca.
26 ; CHECK: stur w0, {{\[}}[[SAVE_SP]], #-4]
27 ; Set the alloca address in the second argument.
28 ; CHECK-NEXT: sub x1, [[SAVE_SP]], #4
29 ; Set the first argument to zero.
30 ; CHECK-NEXT: mov w0, wzr
31 ; CHECK-NEXT: bl _doSomething
33 ; Without shrink-wrapping, epilogue is in the exit block.
34 ; DISABLE: [[EXIT_LABEL]]:
36 ; CHECK-NEXT: mov sp, [[SAVE_SP]]
37 ; CHECK-NEXT: ldp [[SAVE_SP]], [[CSR]], [sp], #16
39 ; With shrink-wrapping, exit block is a simple return.
40 ; ENABLE: [[EXIT_LABEL]]:
42 define i32 @foo(i32 %a, i32 %b) {
43 %tmp = alloca i32, align 4
44 %tmp2 = icmp slt i32 %a, %b
45 br i1 %tmp2, label %true, label %false
48 store i32 %a, i32* %tmp, align 4
49 %tmp4 = call i32 @doSomething(i32 0, i32* %tmp)
53 %tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ]
57 ; Function Attrs: optsize
58 declare i32 @doSomething(i32, i32*)
61 ; Check that we do not perform the restore inside the loop whereas the save
63 ; CHECK-LABEL: freqSaveAndRestoreOutsideLoop:
65 ; Shrink-wrapping allows to skip the prologue in the else case.
66 ; ENABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]]
69 ; CHECK: stp [[CSR1:x[0-9]+]], [[CSR2:x[0-9]+]], [sp, #-32]!
70 ; CHECK-NEXT: stp [[CSR3:x[0-9]+]], [[CSR4:x[0-9]+]], [sp, #16]
71 ; CHECK-NEXT: add [[NEW_SP:x[0-9]+]], sp, #16
73 ; DISABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]]
75 ; CHECK: mov [[SUM:w[0-9]+]], wzr
76 ; CHECK-NEXT: movz [[IV:w[0-9]+]], #0xa
79 ; CHECK: [[LOOP:LBB[0-9_]+]]: ; %for.body
80 ; CHECK: bl _something
81 ; CHECK-NEXT: add [[SUM]], w0, [[SUM]]
82 ; CHECK-NEXT: sub [[IV]], [[IV]], #1
83 ; CHECK-NEXT: cbnz [[IV]], [[LOOP]]
86 ; Copy SUM into the returned register + << 3.
87 ; CHECK: lsl w0, [[SUM]], #3
90 ; DISABLE: b [[EPILOG_BB:LBB[0-9_]+]]
92 ; DISABLE: [[ELSE_LABEL]]: ; %if.else
93 ; Shift second argument by one and store into returned register.
94 ; DISABLE: lsl w0, w1, #1
95 ; DISABLE: [[EPILOG_BB]]: ; %if.end
98 ; CHECK: ldp [[CSR3]], [[CSR4]], [sp, #16]
99 ; CHECK-NEXT: ldp [[CSR1]], [[CSR2]], [sp], #32
102 ; ENABLE: [[ELSE_LABEL]]: ; %if.else
103 ; Shift second argument by one and store into returned register.
104 ; ENABLE: lsl w0, w1, #1
106 define i32 @freqSaveAndRestoreOutsideLoop(i32 %cond, i32 %N) {
108 %tobool = icmp eq i32 %cond, 0
109 br i1 %tobool, label %if.else, label %for.body
111 for.body: ; preds = %entry, %for.body
112 %i.05 = phi i32 [ %inc, %for.body ], [ 0, %entry ]
113 %sum.04 = phi i32 [ %add, %for.body ], [ 0, %entry ]
114 %call = tail call i32 bitcast (i32 (...)* @something to i32 ()*)()
115 %add = add nsw i32 %call, %sum.04
116 %inc = add nuw nsw i32 %i.05, 1
117 %exitcond = icmp eq i32 %inc, 10
118 br i1 %exitcond, label %for.end, label %for.body
120 for.end: ; preds = %for.body
121 %shl = shl i32 %add, 3
124 if.else: ; preds = %entry
125 %mul = shl nsw i32 %N, 1
128 if.end: ; preds = %if.else, %for.end
129 %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ]
133 declare i32 @something(...)
135 ; Check that we do not perform the shrink-wrapping inside the loop even
136 ; though that would be legal. The cost model must prevent that.
137 ; CHECK-LABEL: freqSaveAndRestoreOutsideLoop2:
139 ; CHECK: stp [[CSR1:x[0-9]+]], [[CSR2:x[0-9]+]], [sp, #-32]!
140 ; CHECK-NEXT: stp [[CSR3:x[0-9]+]], [[CSR4:x[0-9]+]], [sp, #16]
141 ; CHECK-NEXT: add [[NEW_SP:x[0-9]+]], sp, #16
142 ; CHECK: mov [[SUM:w[0-9]+]], wzr
143 ; CHECK-NEXT: movz [[IV:w[0-9]+]], #0xa
145 ; CHECK: [[LOOP_LABEL:LBB[0-9_]+]]: ; %for.body
146 ; CHECK: bl _something
147 ; CHECK-NEXT: add [[SUM]], w0, [[SUM]]
148 ; CHECK-NEXT: sub [[IV]], [[IV]], #1
149 ; CHECK-NEXT: cbnz [[IV]], [[LOOP_LABEL]]
152 ; CHECK: mov w0, [[SUM]]
153 ; CHECK-NEXT: ldp [[CSR3]], [[CSR4]], [sp, #16]
154 ; CHECK-NEXT: ldp [[CSR1]], [[CSR2]], [sp], #32
156 define i32 @freqSaveAndRestoreOutsideLoop2(i32 %cond) {
160 for.body: ; preds = %for.body, %entry
161 %i.04 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
162 %sum.03 = phi i32 [ 0, %entry ], [ %add, %for.body ]
163 %call = tail call i32 bitcast (i32 (...)* @something to i32 ()*)()
164 %add = add nsw i32 %call, %sum.03
165 %inc = add nuw nsw i32 %i.04, 1
166 %exitcond = icmp eq i32 %inc, 10
167 br i1 %exitcond, label %for.end, label %for.body
169 for.end: ; preds = %for.body
173 ; Check with a more complex case that we do not have save within the loop and
175 ; CHECK-LABEL: loopInfoSaveOutsideLoop:
177 ; ENABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]]
180 ; CHECK: stp [[CSR1:x[0-9]+]], [[CSR2:x[0-9]+]], [sp, #-32]!
181 ; CHECK-NEXT: stp [[CSR3:x[0-9]+]], [[CSR4:x[0-9]+]], [sp, #16]
182 ; CHECK-NEXT: add [[NEW_SP:x[0-9]+]], sp, #16
184 ; DISABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]]
186 ; CHECK: mov [[SUM:w[0-9]+]], wzr
187 ; CHECK-NEXT: movz [[IV:w[0-9]+]], #0xa
189 ; CHECK: [[LOOP_LABEL:LBB[0-9_]+]]: ; %for.body
190 ; CHECK: bl _something
191 ; CHECK-NEXT: add [[SUM]], w0, [[SUM]]
192 ; CHECK-NEXT: sub [[IV]], [[IV]], #1
193 ; CHECK-NEXT: cbnz [[IV]], [[LOOP_LABEL]]
195 ; CHECK: bl _somethingElse
196 ; CHECK-NEXT: lsl w0, [[SUM]], #3
199 ; DISABLE: b [[EPILOG_BB:LBB[0-9_]+]]
201 ; DISABLE: [[ELSE_LABEL]]: ; %if.else
202 ; Shift second argument by one and store into returned register.
203 ; DISABLE: lsl w0, w1, #1
204 ; DISABLE: [[EPILOG_BB]]: ; %if.end
206 ; CHECK-NEXT: ldp [[CSR3]], [[CSR4]], [sp, #16]
207 ; CHECK-NEXT: ldp [[CSR1]], [[CSR2]], [sp], #32
210 ; ENABLE: [[ELSE_LABEL]]: ; %if.else
211 ; Shift second argument by one and store into returned register.
212 ; ENABLE: lsl w0, w1, #1
214 define i32 @loopInfoSaveOutsideLoop(i32 %cond, i32 %N) {
216 %tobool = icmp eq i32 %cond, 0
217 br i1 %tobool, label %if.else, label %for.body
219 for.body: ; preds = %entry, %for.body
220 %i.05 = phi i32 [ %inc, %for.body ], [ 0, %entry ]
221 %sum.04 = phi i32 [ %add, %for.body ], [ 0, %entry ]
222 %call = tail call i32 bitcast (i32 (...)* @something to i32 ()*)()
223 %add = add nsw i32 %call, %sum.04
224 %inc = add nuw nsw i32 %i.05, 1
225 %exitcond = icmp eq i32 %inc, 10
226 br i1 %exitcond, label %for.end, label %for.body
228 for.end: ; preds = %for.body
229 tail call void bitcast (void (...)* @somethingElse to void ()*)()
230 %shl = shl i32 %add, 3
233 if.else: ; preds = %entry
234 %mul = shl nsw i32 %N, 1
237 if.end: ; preds = %if.else, %for.end
238 %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ]
242 declare void @somethingElse(...)
244 ; Check with a more complex case that we do not have restore within the loop and
246 ; CHECK-LABEL: loopInfoRestoreOutsideLoop:
248 ; ENABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]]
250 ; CHECK: stp [[CSR1:x[0-9]+]], [[CSR2:x[0-9]+]], [sp, #-32]!
251 ; CHECK-NEXT: stp [[CSR3:x[0-9]+]], [[CSR4:x[0-9]+]], [sp, #16]
252 ; CHECK-NEXT: add [[NEW_SP:x[0-9]+]], sp, #16
254 ; DISABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]]
256 ; CHECK: bl _somethingElse
257 ; CHECK-NEXT: mov [[SUM:w[0-9]+]], wzr
258 ; CHECK-NEXT: movz [[IV:w[0-9]+]], #0xa
260 ; CHECK: [[LOOP_LABEL:LBB[0-9_]+]]: ; %for.body
261 ; CHECK: bl _something
262 ; CHECK-NEXT: add [[SUM]], w0, [[SUM]]
263 ; CHECK-NEXT: sub [[IV]], [[IV]], #1
264 ; CHECK-NEXT: cbnz [[IV]], [[LOOP_LABEL]]
266 ; CHECK: lsl w0, [[SUM]], #3
269 ; DISABLE: b [[EPILOG_BB:LBB[0-9_]+]]
271 ; DISABLE: [[ELSE_LABEL]]: ; %if.else
272 ; Shift second argument by one and store into returned register.
273 ; DISABLE: lsl w0, w1, #1
274 ; DISABLE: [[EPILOG_BB]]: ; %if.end
276 ; CHECK: ldp [[CSR3]], [[CSR4]], [sp, #16]
277 ; CHECK-NEXT: ldp [[CSR1]], [[CSR2]], [sp], #32
280 ; ENABLE: [[ELSE_LABEL]]: ; %if.else
281 ; Shift second argument by one and store into returned register.
282 ; ENABLE: lsl w0, w1, #1
284 define i32 @loopInfoRestoreOutsideLoop(i32 %cond, i32 %N) #0 {
286 %tobool = icmp eq i32 %cond, 0
287 br i1 %tobool, label %if.else, label %if.then
289 if.then: ; preds = %entry
290 tail call void bitcast (void (...)* @somethingElse to void ()*)()
293 for.body: ; preds = %for.body, %if.then
294 %i.05 = phi i32 [ 0, %if.then ], [ %inc, %for.body ]
295 %sum.04 = phi i32 [ 0, %if.then ], [ %add, %for.body ]
296 %call = tail call i32 bitcast (i32 (...)* @something to i32 ()*)()
297 %add = add nsw i32 %call, %sum.04
298 %inc = add nuw nsw i32 %i.05, 1
299 %exitcond = icmp eq i32 %inc, 10
300 br i1 %exitcond, label %for.end, label %for.body
302 for.end: ; preds = %for.body
303 %shl = shl i32 %add, 3
306 if.else: ; preds = %entry
307 %mul = shl nsw i32 %N, 1
310 if.end: ; preds = %if.else, %for.end
311 %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ]
315 ; Check that we handle function with no frame information correctly.
316 ; CHECK-LABEL: emptyFrame:
318 ; CHECK-NEXT: mov w0, wzr
320 define i32 @emptyFrame() {
325 ; Check that we handle variadic function correctly.
326 ; CHECK-LABEL: variadicFunc:
328 ; ENABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]]
331 ; CHECK: sub sp, sp, #16
332 ; DISABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]]
334 ; Sum is merged with the returned register.
335 ; CHECK: mov [[SUM:w0]], wzr
336 ; CHECK-NEXT: add [[VA_BASE:x[0-9]+]], sp, #16
337 ; CHECK-NEXT: str [[VA_BASE]], [sp, #8]
338 ; CHECK-NEXT: cmp w1, #1
339 ; CHECK-NEXT: b.lt [[IFEND_LABEL:LBB[0-9_]+]]
341 ; CHECK: [[LOOP_LABEL:LBB[0-9_]+]]: ; %for.body
342 ; CHECK: ldr [[VA_ADDR:x[0-9]+]], [sp, #8]
343 ; CHECK-NEXT: add [[NEXT_VA_ADDR:x[0-9]+]], [[VA_ADDR]], #8
344 ; CHECK-NEXT: str [[NEXT_VA_ADDR]], [sp, #8]
345 ; CHECK-NEXT: ldr [[VA_VAL:w[0-9]+]], {{\[}}[[VA_ADDR]]]
346 ; CHECK-NEXT: add [[SUM]], [[SUM]], [[VA_VAL]]
347 ; CHECK-NEXT: sub w1, w1, #1
348 ; CHECK-NEXT: cbnz w1, [[LOOP_LABEL]]
350 ; DISABLE-NEXT: b [[IFEND_LABEL]]
351 ; DISABLE: [[ELSE_LABEL]]: ; %if.else
352 ; DISABLE: lsl w0, w1, #1
354 ; CHECK: [[IFEND_LABEL]]:
356 ; CHECK: add sp, sp, #16
359 ; ENABLE: [[ELSE_LABEL]]: ; %if.else
360 ; ENABLE: lsl w0, w1, #1
362 define i32 @variadicFunc(i32 %cond, i32 %count, ...) #0 {
364 %ap = alloca i8*, align 8
365 %tobool = icmp eq i32 %cond, 0
366 br i1 %tobool, label %if.else, label %if.then
368 if.then: ; preds = %entry
369 %ap1 = bitcast i8** %ap to i8*
370 call void @llvm.va_start(i8* %ap1)
371 %cmp6 = icmp sgt i32 %count, 0
372 br i1 %cmp6, label %for.body, label %for.end
374 for.body: ; preds = %if.then, %for.body
375 %i.08 = phi i32 [ %inc, %for.body ], [ 0, %if.then ]
376 %sum.07 = phi i32 [ %add, %for.body ], [ 0, %if.then ]
377 %0 = va_arg i8** %ap, i32
378 %add = add nsw i32 %sum.07, %0
379 %inc = add nuw nsw i32 %i.08, 1
380 %exitcond = icmp eq i32 %inc, %count
381 br i1 %exitcond, label %for.end, label %for.body
383 for.end: ; preds = %for.body, %if.then
384 %sum.0.lcssa = phi i32 [ 0, %if.then ], [ %add, %for.body ]
385 call void @llvm.va_end(i8* %ap1)
388 if.else: ; preds = %entry
389 %mul = shl nsw i32 %count, 1
392 if.end: ; preds = %if.else, %for.end
393 %sum.1 = phi i32 [ %sum.0.lcssa, %for.end ], [ %mul, %if.else ]
397 declare void @llvm.va_start(i8*)
399 declare void @llvm.va_end(i8*)
401 ; Check that we handle inline asm correctly.
402 ; CHECK-LABEL: inlineAsm:
404 ; ENABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]]
407 ; Make sure we save the CSR used in the inline asm: x19.
408 ; CHECK: stp [[CSR1:x[0-9]+]], [[CSR2:x19]], [sp, #-16]!
410 ; DISABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]]
412 ; CHECK: movz [[IV:w[0-9]+]], #0xa
414 ; CHECK: [[LOOP_LABEL:LBB[0-9_]+]]: ; %for.body
415 ; Inline asm statement.
416 ; CHECK: add x19, x19, #1
417 ; CHECK: sub [[IV]], [[IV]], #1
418 ; CHECK-NEXT: cbnz [[IV]], [[LOOP_LABEL]]
422 ; CHECK-NEXT: ldp [[CSR1]], [[CSR2]], [sp], #16
425 ; CHECK: [[ELSE_LABEL]]: ; %if.else
426 ; CHECK-NEXT: lsl w0, w1, #1
428 ; DISABLE-NEXT: ldp [[CSR1]], [[CSR2]], [sp], #16
430 define i32 @inlineAsm(i32 %cond, i32 %N) {
432 %tobool = icmp eq i32 %cond, 0
433 br i1 %tobool, label %if.else, label %for.body
435 for.body: ; preds = %entry, %for.body
436 %i.03 = phi i32 [ %inc, %for.body ], [ 0, %entry ]
437 tail call void asm sideeffect "add x19, x19, #1", "~{x19}"()
438 %inc = add nuw nsw i32 %i.03, 1
439 %exitcond = icmp eq i32 %inc, 10
440 br i1 %exitcond, label %if.end, label %for.body
442 if.else: ; preds = %entry
443 %mul = shl nsw i32 %N, 1
446 if.end: ; preds = %for.body, %if.else
447 %sum.0 = phi i32 [ %mul, %if.else ], [ 0, %for.body ]
451 ; Check that we handle calls to variadic functions correctly.
452 ; CHECK-LABEL: callVariadicFunc:
454 ; ENABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]]
457 ; CHECK: stp [[CSR1:x[0-9]+]], [[CSR2:x[0-9]+]], [sp, #-16]!
458 ; CHECK-NEXT: mov [[NEW_SP:x[0-9]+]], sp
459 ; CHECK-NEXT: sub sp, sp, #48
461 ; DISABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]]
462 ; Setup of the varags.
463 ; CHECK: stp x1, x1, [sp, #32]
464 ; CHECK-NEXT: stp x1, x1, [sp, #16]
465 ; CHECK-NEXT: stp x1, x1, [sp]
466 ; CHECK-NEXT: mov w0, w1
467 ; CHECK-NEXT: bl _someVariadicFunc
468 ; CHECK-NEXT: lsl w0, w0, #3
470 ; DISABLE: b [[IFEND_LABEL:LBB[0-9_]+]]
471 ; DISABLE: [[ELSE_LABEL]]: ; %if.else
472 ; DISABLE-NEXT: lsl w0, w1, #1
473 ; DISABLE: [[IFEND_LABEL]]: ; %if.end
476 ; CHECK: mov sp, [[NEW_SP]]
477 ; CHECK-NEXT: ldp [[CSR1]], [[CSR2]], [sp], #16
480 ; ENABLE: [[ELSE_LABEL]]: ; %if.else
481 ; ENABLE-NEXT: lsl w0, w1, #1
483 define i32 @callVariadicFunc(i32 %cond, i32 %N) {
485 %tobool = icmp eq i32 %cond, 0
486 br i1 %tobool, label %if.else, label %if.then
488 if.then: ; preds = %entry
489 %call = tail call i32 (i32, ...) @someVariadicFunc(i32 %N, i32 %N, i32 %N, i32 %N, i32 %N, i32 %N, i32 %N)
490 %shl = shl i32 %call, 3
493 if.else: ; preds = %entry
494 %mul = shl nsw i32 %N, 1
497 if.end: ; preds = %if.else, %if.then
498 %sum.0 = phi i32 [ %shl, %if.then ], [ %mul, %if.else ]
502 declare i32 @someVariadicFunc(i32, ...)
504 ; Make sure we do not insert unreachable code after noreturn function.
505 ; Although this is not incorrect to insert such code, it is useless
506 ; and it hurts the binary size.
508 ; CHECK-LABEL: noreturn:
511 ; CHECK: and [[TEST:w[0-9]+]], w0, #0xff
512 ; CHECK-NEXT: cbnz [[TEST]], [[ABORT:LBB[0-9_]+]]
514 ; CHECK: movz w0, #0x2a
520 ; CHECK: [[ABORT]]: ; %if.abort
526 define i32 @noreturn(i8 signext %bad_thing) {
528 %tobool = icmp eq i8 %bad_thing, 0
529 br i1 %tobool, label %if.end, label %if.abort
532 tail call void @abort() #0
539 declare void @abort() #0
541 attributes #0 = { noreturn nounwind }
543 ; Make sure that we handle infinite loops properly When checking that the Save
544 ; and Restore blocks are control flow equivalent, the loop searches for the
545 ; immediate (post) dominator for the (restore) save blocks. When either the Save
546 ; or Restore block is located in an infinite loop the only immediate (post)
547 ; dominator is itself. In this case, we cannot perform shrink wrapping, but we
548 ; should return gracefully and continue compilation.
549 ; The only condition for this test is the compilation finishes correctly.
551 ; CHECK-LABEL: infiniteloop
553 define void @infiniteloop() {
555 br i1 undef, label %if.then, label %if.end
558 %ptr = alloca i32, i32 4
561 for.body: ; preds = %for.body, %entry
562 %sum.03 = phi i32 [ 0, %if.then ], [ %add, %for.body ]
563 %call = tail call i32 bitcast (i32 (...)* @something to i32 ()*)()
564 %add = add nsw i32 %call, %sum.03
565 store i32 %add, i32* %ptr
572 ; Another infinite loop test this time with a body bigger than just one block.
573 ; CHECK-LABEL: infiniteloop2
575 define void @infiniteloop2() {
577 br i1 undef, label %if.then, label %if.end
580 %ptr = alloca i32, i32 4
583 for.body: ; preds = %for.body, %entry
584 %sum.03 = phi i32 [ 0, %if.then ], [ %add, %body1 ], [ 1, %body2]
585 %call = tail call i32 asm "mov $0, #0", "=r,~{x19}"()
586 %add = add nsw i32 %call, %sum.03
587 store i32 %add, i32* %ptr
588 br i1 undef, label %body1, label %body2
591 tail call void asm sideeffect "nop", "~{x19}"()
595 tail call void asm sideeffect "nop", "~{x19}"()
602 ; Another infinite loop test this time with two nested infinite loop.
603 ; CHECK-LABEL: infiniteloop3
605 define void @infiniteloop3() {
607 br i1 undef, label %loop2a, label %body
609 body: ; preds = %entry
610 br i1 undef, label %loop2a, label %end
612 loop1: ; preds = %loop2a, %loop2b
613 %var.phi = phi i32* [ %next.phi, %loop2b ], [ %var, %loop2a ]
614 %next.phi = phi i32* [ %next.load, %loop2b ], [ %next.var, %loop2a ]
615 %0 = icmp eq i32* %var, null
616 %next.load = load i32*, i32** undef
617 br i1 %0, label %loop2a, label %loop2b
619 loop2a: ; preds = %loop1, %body, %entry
620 %var = phi i32* [ null, %body ], [ null, %entry ], [ %next.phi, %loop1 ]
621 %next.var = phi i32* [ undef, %body ], [ null, %entry ], [ %next.load, %loop1 ]
624 loop2b: ; preds = %loop1
625 %gep1 = bitcast i32* %var.phi to i32*
626 %next.ptr = bitcast i32* %gep1 to i32**
627 store i32* %next.phi, i32** %next.ptr