1 ; RUN: llc %s -o - -enable-shrink-wrap=true -disable-post-ra -frame-pointer=all | FileCheck %s --check-prefix=CHECK --check-prefix=ENABLE
2 ; RUN: llc %s -o - -enable-shrink-wrap=false -disable-post-ra -frame-pointer=all | 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: sub sp, sp, #32
17 ; CHECK-NEXT: stp [[SAVE_SP:x[0-9]+]], [[CSR:x[0-9]+]], [sp, #16]
18 ; CHECK-NEXT: add [[SAVE_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: ldp x{{[0-9]+}}, [[CSR]], [sp, #16]
37 ; CHECK-NEXT: add sp, sp, #32
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: mov [[IV:w[0-9]+]], #10
79 ; CHECK: [[LOOP:LBB[0-9_]+]]: ; %for.body
80 ; CHECK: bl _something
81 ; CHECK-NEXT: subs [[IV]], [[IV]], #1
82 ; CHECK-NEXT: add [[SUM]], w0, [[SUM]]
83 ; CHECK-NEXT: b.ne [[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: mov [[IV:w[0-9]+]], #10
145 ; CHECK: [[LOOP_LABEL:LBB[0-9_]+]]: ; %for.body
146 ; CHECK: bl _something
147 ; CHECK-NEXT: subs [[IV]], [[IV]], #1
148 ; CHECK-NEXT: add [[SUM]], w0, [[SUM]]
149 ; CHECK-NEXT: b.ne [[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: mov [[IV:w[0-9]+]], #10
189 ; CHECK: [[LOOP_LABEL:LBB[0-9_]+]]: ; %for.body
190 ; CHECK: bl _something
191 ; CHECK-NEXT: subs [[IV]], [[IV]], #1
192 ; CHECK-NEXT: add [[SUM]], w0, [[SUM]]
193 ; CHECK-NEXT: b.ne [[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: mov [[IV:w[0-9]+]], #10
260 ; CHECK: [[LOOP_LABEL:LBB[0-9_]+]]: ; %for.body
261 ; CHECK: bl _something
262 ; CHECK-NEXT: subs [[IV]], [[IV]], #1
263 ; CHECK-NEXT: add [[SUM]], w0, [[SUM]]
264 ; CHECK-NEXT: b.ne [[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) nounwind {
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: add [[VA_BASE:x[0-9]+]], sp, #16
336 ; CHECK-NEXT: cmp w1, #1
337 ; CHECK-NEXT: str [[VA_BASE]], [sp, #8]
338 ; CHECK-NEXT: mov [[SUM:w0]], wzr
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: subs w1, w1, #1
347 ; CHECK-NEXT: add [[SUM]], [[SUM]], [[VA_VAL]]
348 ; CHECK-NEXT: b.ne [[LOOP_LABEL]]
349 ; CHECK-NEXT: [[IFEND_LABEL]]:
351 ; CHECK: add sp, sp, #16
354 ; CHECK: [[ELSE_LABEL]]: ; %if.else
355 ; CHECK-NEXT: lsl w0, w1, #1
356 ; DISABLE-NEXT: add sp, sp, #16
358 define i32 @variadicFunc(i32 %cond, i32 %count, ...) nounwind {
360 %ap = alloca i8*, align 8
361 %tobool = icmp eq i32 %cond, 0
362 br i1 %tobool, label %if.else, label %if.then
364 if.then: ; preds = %entry
365 %ap1 = bitcast i8** %ap to i8*
366 call void @llvm.va_start(i8* %ap1)
367 %cmp6 = icmp sgt i32 %count, 0
368 br i1 %cmp6, label %for.body, label %for.end
370 for.body: ; preds = %if.then, %for.body
371 %i.08 = phi i32 [ %inc, %for.body ], [ 0, %if.then ]
372 %sum.07 = phi i32 [ %add, %for.body ], [ 0, %if.then ]
373 %0 = va_arg i8** %ap, i32
374 %add = add nsw i32 %sum.07, %0
375 %inc = add nuw nsw i32 %i.08, 1
376 %exitcond = icmp eq i32 %inc, %count
377 br i1 %exitcond, label %for.end, label %for.body
379 for.end: ; preds = %for.body, %if.then
380 %sum.0.lcssa = phi i32 [ 0, %if.then ], [ %add, %for.body ]
381 call void @llvm.va_end(i8* %ap1)
384 if.else: ; preds = %entry
385 %mul = shl nsw i32 %count, 1
388 if.end: ; preds = %if.else, %for.end
389 %sum.1 = phi i32 [ %sum.0.lcssa, %for.end ], [ %mul, %if.else ]
393 declare void @llvm.va_start(i8*)
395 declare void @llvm.va_end(i8*)
397 ; Check that we handle inline asm correctly.
398 ; CHECK-LABEL: inlineAsm:
400 ; ENABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]]
403 ; Make sure we save the CSR used in the inline asm: x19.
404 ; CHECK: stp [[CSR1:x[0-9]+]], [[CSR2:x19]], [sp, #-16]!
406 ; DISABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]]
408 ; CHECK: mov [[IV:w[0-9]+]], #10
410 ; CHECK: [[LOOP_LABEL:LBB[0-9_]+]]: ; %for.body
411 ; Inline asm statement.
412 ; CHECK: subs [[IV]], [[IV]], #1
413 ; CHECK: add x19, x19, #1
414 ; CHECK: b.ne [[LOOP_LABEL]]
418 ; CHECK-NEXT: ldp [[CSR1]], [[CSR2]], [sp], #16
421 ; CHECK: [[ELSE_LABEL]]: ; %if.else
422 ; CHECK-NEXT: lsl w0, w1, #1
424 ; DISABLE-NEXT: ldp [[CSR1]], [[CSR2]], [sp], #16
426 define i32 @inlineAsm(i32 %cond, i32 %N) {
428 %tobool = icmp eq i32 %cond, 0
429 br i1 %tobool, label %if.else, label %for.body
431 for.body: ; preds = %entry, %for.body
432 %i.03 = phi i32 [ %inc, %for.body ], [ 0, %entry ]
433 tail call void asm sideeffect "add x19, x19, #1", "~{x19}"()
434 %inc = add nuw nsw i32 %i.03, 1
435 %exitcond = icmp eq i32 %inc, 10
436 br i1 %exitcond, label %if.end, label %for.body
438 if.else: ; preds = %entry
439 %mul = shl nsw i32 %N, 1
442 if.end: ; preds = %for.body, %if.else
443 %sum.0 = phi i32 [ %mul, %if.else ], [ 0, %for.body ]
447 ; Check that we handle calls to variadic functions correctly.
448 ; CHECK-LABEL: callVariadicFunc:
450 ; ENABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]]
453 ; CHECK: sub sp, sp, #64
454 ; CHECK-NEXT: stp [[CSR1:x[0-9]+]], [[CSR2:x[0-9]+]], [sp, #48]
455 ; CHECK-NEXT: add [[NEW_SP:x[0-9]+]], sp, #48
457 ; DISABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]]
458 ; Setup of the varags.
459 ; CHECK: stp x1, x1, [sp, #32]
460 ; CHECK-NEXT: stp x1, x1, [sp, #16]
461 ; CHECK-NEXT: stp x1, x1, [sp]
462 ; CHECK-NEXT: mov w0, w1
463 ; CHECK-NEXT: bl _someVariadicFunc
464 ; CHECK-NEXT: lsl w0, w0, #3
466 ; DISABLE: b [[IFEND_LABEL:LBB[0-9_]+]]
467 ; DISABLE: [[ELSE_LABEL]]: ; %if.else
468 ; DISABLE-NEXT: lsl w0, w1, #1
469 ; DISABLE: [[IFEND_LABEL]]: ; %if.end
472 ; CHECK: ldp [[CSR1]], [[CSR2]], [sp, #48]
473 ; CHECK-NEXT: add sp, sp, #64
476 ; ENABLE: [[ELSE_LABEL]]: ; %if.else
477 ; ENABLE-NEXT: lsl w0, w1, #1
479 define i32 @callVariadicFunc(i32 %cond, i32 %N) {
481 %tobool = icmp eq i32 %cond, 0
482 br i1 %tobool, label %if.else, label %if.then
484 if.then: ; preds = %entry
485 %call = tail call i32 (i32, ...) @someVariadicFunc(i32 %N, i32 %N, i32 %N, i32 %N, i32 %N, i32 %N, i32 %N)
486 %shl = shl i32 %call, 3
489 if.else: ; preds = %entry
490 %mul = shl nsw i32 %N, 1
493 if.end: ; preds = %if.else, %if.then
494 %sum.0 = phi i32 [ %shl, %if.then ], [ %mul, %if.else ]
498 declare i32 @someVariadicFunc(i32, ...)
500 ; Make sure we do not insert unreachable code after noreturn function.
501 ; Although this is not incorrect to insert such code, it is useless
502 ; and it hurts the binary size.
504 ; CHECK-LABEL: noreturn:
507 ; CHECK: cbnz w0, [[ABORT:LBB[0-9_]+]]
515 ; CHECK: [[ABORT]]: ; %if.abort
521 define i32 @noreturn(i8 signext %bad_thing) {
523 %tobool = icmp eq i8 %bad_thing, 0
524 br i1 %tobool, label %if.end, label %if.abort
527 tail call void @abort() #0
534 declare void @abort() #0
536 attributes #0 = { noreturn nounwind }
538 ; Make sure that we handle infinite loops properly When checking that the Save
539 ; and Restore blocks are control flow equivalent, the loop searches for the
540 ; immediate (post) dominator for the (restore) save blocks. When either the Save
541 ; or Restore block is located in an infinite loop the only immediate (post)
542 ; dominator is itself. In this case, we cannot perform shrink wrapping, but we
543 ; should return gracefully and continue compilation.
544 ; The only condition for this test is the compilation finishes correctly.
546 ; CHECK-LABEL: infiniteloop
548 define void @infiniteloop() {
550 br i1 undef, label %if.then, label %if.end
553 %ptr = alloca i32, i32 4
556 for.body: ; preds = %for.body, %entry
557 %sum.03 = phi i32 [ 0, %if.then ], [ %add, %for.body ]
558 %call = tail call i32 bitcast (i32 (...)* @something to i32 ()*)()
559 %add = add nsw i32 %call, %sum.03
560 store i32 %add, i32* %ptr
567 ; Another infinite loop test this time with a body bigger than just one block.
568 ; CHECK-LABEL: infiniteloop2
570 define void @infiniteloop2() {
572 br i1 undef, label %if.then, label %if.end
575 %ptr = alloca i32, i32 4
578 for.body: ; preds = %for.body, %entry
579 %sum.03 = phi i32 [ 0, %if.then ], [ %add, %body1 ], [ 1, %body2]
580 %call = tail call i32 asm "mov $0, #0", "=r,~{x19}"()
581 %add = add nsw i32 %call, %sum.03
582 store i32 %add, i32* %ptr
583 br i1 undef, label %body1, label %body2
586 tail call void asm sideeffect "nop", "~{x19}"()
590 tail call void asm sideeffect "nop", "~{x19}"()
597 ; Another infinite loop test this time with two nested infinite loop.
598 ; CHECK-LABEL: infiniteloop3
600 define void @infiniteloop3() {
602 br i1 undef, label %loop2a, label %body
604 body: ; preds = %entry
605 br i1 undef, label %loop2a, label %end
607 loop1: ; preds = %loop2a, %loop2b
608 %var.phi = phi i32* [ %next.phi, %loop2b ], [ %var, %loop2a ]
609 %next.phi = phi i32* [ %next.load, %loop2b ], [ %next.var, %loop2a ]
610 %0 = icmp eq i32* %var, null
611 %next.load = load i32*, i32** undef
612 br i1 %0, label %loop2a, label %loop2b
614 loop2a: ; preds = %loop1, %body, %entry
615 %var = phi i32* [ null, %body ], [ null, %entry ], [ %next.phi, %loop1 ]
616 %next.var = phi i32* [ undef, %body ], [ null, %entry ], [ %next.load, %loop1 ]
619 loop2b: ; preds = %loop1
620 %gep1 = bitcast i32* %var.phi to i32*
621 %next.ptr = bitcast i32* %gep1 to i32**
622 store i32* %next.phi, i32** %next.ptr
629 ; Re-aligned stack pointer. See bug 26642. Avoid clobbering live
630 ; values in the prologue when re-aligning the stack pointer.
631 ; CHECK-LABEL: stack_realign:
632 ; ENABLE-DAG: lsl w[[LSL1:[0-9]+]], w0, w1
633 ; ENABLE-DAG: lsl w[[LSL2:[0-9]+]], w1, w0
634 ; DISABLE-NOT: lsl w[[LSL1:[0-9]+]], w0, w1
635 ; DISABLE-NOT: lsl w[[LSL2:[0-9]+]], w1, w0
636 ; CHECK: stp x29, x30, [sp, #-16]!
638 ; ENABLE-NOT: sub x[[LSL1]], sp, #16
639 ; ENABLE-NOT: sub x[[LSL2]], sp, #16
640 ; DISABLE: sub x{{[0-9]+}}, sp, #16
641 ; DISABLE-DAG: lsl w[[LSL1:[0-9]+]], w0, w1
642 ; DISABLE-DAG: lsl w[[LSL2:[0-9]+]], w1, w0
643 ; CHECK-DAG: str w[[LSL1]],
644 ; CHECK-DAG: str w[[LSL2]],
646 define i32 @stack_realign(i32 %a, i32 %b, i32* %ptr1, i32* %ptr2) {
647 %tmp = alloca i32, align 32
648 %shl1 = shl i32 %a, %b
649 %shl2 = shl i32 %b, %a
650 %tmp2 = icmp slt i32 %a, %b
651 br i1 %tmp2, label %true, label %false
654 store i32 %a, i32* %tmp, align 4
655 %tmp4 = load i32, i32* %tmp
659 %tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ]
660 store i32 %shl1, i32* %ptr1
661 store i32 %shl2, i32* %ptr2
665 ; Re-aligned stack pointer with all caller-save regs live. See bug
666 ; 26642. In this case we currently avoid shrink wrapping because
667 ; ensuring we have a scratch register to re-align the stack pointer is
668 ; too complicated. Output should be the same for both enabled and
669 ; disabled shrink wrapping.
670 ; CHECK-LABEL: stack_realign2:
671 ; CHECK: stp {{x[0-9]+}}, {{x[0-9]+}}, [sp, #-{{[0-9]+}}]!
672 ; CHECK: add x29, sp, #{{[0-9]+}}
673 ; CHECK: lsl {{w[0-9]+}}, w0, w1
675 define void @stack_realign2(i32 %a, i32 %b, i32* %ptr1, i32* %ptr2, i32* %ptr3, i32* %ptr4, i32* %ptr5, i32* %ptr6) {
676 %tmp = alloca i32, align 32
677 %tmp1 = shl i32 %a, %b
678 %tmp2 = shl i32 %b, %a
679 %tmp3 = lshr i32 %a, %b
680 %tmp4 = lshr i32 %b, %a
681 %tmp5 = add i32 %b, %a
682 %tmp6 = sub i32 %b, %a
683 %tmp7 = add i32 %tmp1, %tmp2
684 %tmp8 = sub i32 %tmp2, %tmp3
685 %tmp9 = add i32 %tmp3, %tmp4
686 %tmp10 = add i32 %tmp4, %tmp5
687 %cmp = icmp slt i32 %a, %b
688 br i1 %cmp, label %true, label %false
691 store i32 %a, i32* %tmp, align 4
692 call void asm sideeffect "nop", "~{x19},~{x20},~{x21},~{x22},~{x23},~{x24},~{x25},~{x26},~{x27},~{x28}"() nounwind
696 store i32 %tmp1, i32* %ptr1, align 4
697 store i32 %tmp2, i32* %ptr2, align 4
698 store i32 %tmp3, i32* %ptr3, align 4
699 store i32 %tmp4, i32* %ptr4, align 4
700 store i32 %tmp5, i32* %ptr5, align 4
701 store i32 %tmp6, i32* %ptr6, align 4
702 %idx1 = getelementptr inbounds i32, i32* %ptr1, i64 1
703 store i32 %a, i32* %idx1, align 4
704 %idx2 = getelementptr inbounds i32, i32* %ptr1, i64 2
705 store i32 %b, i32* %idx2, align 4
706 %idx3 = getelementptr inbounds i32, i32* %ptr1, i64 3
707 store i32 %tmp7, i32* %idx3, align 4
708 %idx4 = getelementptr inbounds i32, i32* %ptr1, i64 4
709 store i32 %tmp8, i32* %idx4, align 4
710 %idx5 = getelementptr inbounds i32, i32* %ptr1, i64 5
711 store i32 %tmp9, i32* %idx5, align 4
712 %idx6 = getelementptr inbounds i32, i32* %ptr1, i64 6
713 store i32 %tmp10, i32* %idx6, align 4