Revert r354244 "[DAGCombiner] Eliminate dead stores to stack."
[llvm-complete.git] / test / CodeGen / AArch64 / arm64-shrink-wrapping.ll
blobb98cb7a6676d533da3f8dc5ad47a60054e47b98e
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.
8 ; CHECK-LABEL: foo:
10 ; Compare the arguments and jump to exit.
11 ; No prologue needed.
12 ; ENABLE: cmp w0, w1
13 ; ENABLE-NEXT: b.ge [[EXIT_LABEL:LBB[0-9_]+]]
15 ; Prologue code.
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.
22 ; DISABLE: cmp w0, w1
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]]:
35 ; Epilogue code.
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]]:
41 ; CHECK-NEXT: ret
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
47 true:
48   store i32 %a, i32* %tmp, align 4
49   %tmp4 = call i32 @doSomething(i32 0, i32* %tmp)
50   br label %false
52 false:
53   %tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ]
54   ret i32 %tmp.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
62 ; is outside.
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_]+]]
68 ; Prologue code.
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
78 ; Next BB.
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]]
85 ; Next BB.
86 ; Copy SUM into the returned register + << 3.
87 ; CHECK: lsl w0, [[SUM]], #3
89 ; Jump to epilogue.
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
97 ; Epilogue code.
98 ; CHECK: ldp [[CSR3]], [[CSR4]], [sp, #16]
99 ; CHECK-NEXT: ldp [[CSR1]], [[CSR2]], [sp], #32
100 ; CHECK-NEXT: ret
102 ; ENABLE: [[ELSE_LABEL]]: ; %if.else
103 ; Shift second argument by one and store into returned register.
104 ; ENABLE: lsl w0, w1, #1
105 ; ENABLE: ret
106 define i32 @freqSaveAndRestoreOutsideLoop(i32 %cond, i32 %N) {
107 entry:
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
122   br label %if.end
124 if.else:                                          ; preds = %entry
125   %mul = shl nsw i32 %N, 1
126   br label %if.end
128 if.end:                                           ; preds = %if.else, %for.end
129   %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ]
130   ret i32 %sum.1
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:
138 ; Prologue code.
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
144 ; Next BB.
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]]
150 ; Next BB.
151 ; CHECK: ; %for.end
152 ; CHECK: mov w0, [[SUM]]
153 ; CHECK-NEXT: ldp [[CSR3]], [[CSR4]], [sp, #16]
154 ; CHECK-NEXT: ldp [[CSR1]], [[CSR2]], [sp], #32
155 ; CHECK-NEXT: ret
156 define i32 @freqSaveAndRestoreOutsideLoop2(i32 %cond) {
157 entry:
158   br label %for.body
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
170   ret i32 %add
173 ; Check with a more complex case that we do not have save within the loop and
174 ; restore outside.
175 ; CHECK-LABEL: loopInfoSaveOutsideLoop:
177 ; ENABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]]
179 ; Prologue code.
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]]
194 ; Next BB.
195 ; CHECK: bl _somethingElse
196 ; CHECK-NEXT: lsl w0, [[SUM]], #3
198 ; Jump to epilogue.
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
205 ; Epilogue code.
206 ; CHECK-NEXT: ldp [[CSR3]], [[CSR4]], [sp, #16]
207 ; CHECK-NEXT: ldp [[CSR1]], [[CSR2]], [sp], #32
208 ; CHECK-NEXT: ret
210 ; ENABLE: [[ELSE_LABEL]]: ; %if.else
211 ; Shift second argument by one and store into returned register.
212 ; ENABLE: lsl w0, w1, #1
213 ; ENABLE: ret
214 define i32 @loopInfoSaveOutsideLoop(i32 %cond, i32 %N) {
215 entry:
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
231   br label %if.end
233 if.else:                                          ; preds = %entry
234   %mul = shl nsw i32 %N, 1
235   br label %if.end
237 if.end:                                           ; preds = %if.else, %for.end
238   %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ]
239   ret i32 %sum.1
242 declare void @somethingElse(...)
244 ; Check with a more complex case that we do not have restore within the loop and
245 ; save outside.
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]]
265 ; Next BB.
266 ; CHECK: lsl w0, [[SUM]], #3
268 ; Jump to epilogue.
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
275 ; Epilogue code.
276 ; CHECK: ldp [[CSR3]], [[CSR4]], [sp, #16]
277 ; CHECK-NEXT: ldp [[CSR1]], [[CSR2]], [sp], #32
278 ; CHECK-NEXT: ret
280 ; ENABLE: [[ELSE_LABEL]]: ; %if.else
281 ; Shift second argument by one and store into returned register.
282 ; ENABLE: lsl w0, w1, #1
283 ; ENABLE: ret
284 define i32 @loopInfoRestoreOutsideLoop(i32 %cond, i32 %N) nounwind {
285 entry:
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 ()*)()
291   br label %for.body
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
304   br label %if.end
306 if.else:                                          ; preds = %entry
307   %mul = shl nsw i32 %N, 1
308   br label %if.end
310 if.end:                                           ; preds = %if.else, %for.end
311   %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ]
312   ret i32 %sum.1
315 ; Check that we handle function with no frame information correctly.
316 ; CHECK-LABEL: emptyFrame:
317 ; CHECK: ; %entry
318 ; CHECK-NEXT: mov w0, wzr
319 ; CHECK-NEXT: ret
320 define i32 @emptyFrame() {
321 entry:
322   ret i32 0
325 ; Check that we handle variadic function correctly.
326 ; CHECK-LABEL: variadicFunc:
328 ; ENABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]]
330 ; Prologue code.
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]]:
350 ; Epilogue code.
351 ; CHECK: add sp, sp, #16
352 ; CHECK-NEXT: ret
354 ; CHECK: [[ELSE_LABEL]]: ; %if.else
355 ; CHECK-NEXT: lsl w0, w1, #1
356 ; DISABLE-NEXT: add sp, sp, #16
357 ; CHECK-NEXT: ret
358 define i32 @variadicFunc(i32 %cond, i32 %count, ...) nounwind {
359 entry:
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)
382   br label %if.end
384 if.else:                                          ; preds = %entry
385   %mul = shl nsw i32 %count, 1
386   br label %if.end
388 if.end:                                           ; preds = %if.else, %for.end
389   %sum.1 = phi i32 [ %sum.0.lcssa, %for.end ], [ %mul, %if.else ]
390   ret i32 %sum.1
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_]+]]
402 ; Prologue code.
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]]
415 ; Next BB.
416 ; CHECK: mov w0, wzr
417 ; Epilogue code.
418 ; CHECK-NEXT: ldp [[CSR1]], [[CSR2]], [sp], #16
419 ; CHECK-NEXT: ret
420 ; Next BB.
421 ; CHECK: [[ELSE_LABEL]]: ; %if.else
422 ; CHECK-NEXT: lsl w0, w1, #1
423 ; Epilogue code.
424 ; DISABLE-NEXT: ldp [[CSR1]], [[CSR2]], [sp], #16
425 ; CHECK-NEXT: ret
426 define i32 @inlineAsm(i32 %cond, i32 %N) {
427 entry:
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
440   br label %if.end
442 if.end:                                           ; preds = %for.body, %if.else
443   %sum.0 = phi i32 [ %mul, %if.else ], [ 0, %for.body ]
444   ret i32 %sum.0
447 ; Check that we handle calls to variadic functions correctly.
448 ; CHECK-LABEL: callVariadicFunc:
450 ; ENABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]]
452 ; Prologue code.
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
471 ; Epilogue code.
472 ; CHECK: ldp [[CSR1]], [[CSR2]], [sp, #48]
473 ; CHECK-NEXT: add sp, sp, #64
474 ; CHECK-NEXT: ret
476 ; ENABLE: [[ELSE_LABEL]]: ; %if.else
477 ; ENABLE-NEXT: lsl w0, w1, #1
478 ; ENABLE-NEXT: ret
479 define i32 @callVariadicFunc(i32 %cond, i32 %N) {
480 entry:
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
487   br label %if.end
489 if.else:                                          ; preds = %entry
490   %mul = shl nsw i32 %N, 1
491   br label %if.end
493 if.end:                                           ; preds = %if.else, %if.then
494   %sum.0 = phi i32 [ %shl, %if.then ], [ %mul, %if.else ]
495   ret i32 %sum.0
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:
505 ; DISABLE: stp
507 ; CHECK: cbnz w0, [[ABORT:LBB[0-9_]+]]
509 ; CHECK: mov w0, #42
511 ; DISABLE-NEXT: ldp
513 ; CHECK-NEXT: ret
515 ; CHECK: [[ABORT]]: ; %if.abort
517 ; ENABLE: stp
519 ; CHECK: bl _abort
520 ; ENABLE-NOT: ldp
521 define i32 @noreturn(i8 signext %bad_thing) {
522 entry:
523   %tobool = icmp eq i8 %bad_thing, 0
524   br i1 %tobool, label %if.end, label %if.abort
526 if.abort:
527   tail call void @abort() #0
528   unreachable
530 if.end:
531   ret i32 42
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
547 ; CHECK: ret
548 define void @infiniteloop() {
549 entry:
550   br i1 undef, label %if.then, label %if.end
552 if.then:
553   %ptr = alloca i32, i32 4
554   br label %for.body
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
561   br label %for.body
563 if.end:
564   ret void
567 ; Another infinite loop test this time with a body bigger than just one block.
568 ; CHECK-LABEL: infiniteloop2
569 ; CHECK: ret
570 define void @infiniteloop2() {
571 entry:
572   br i1 undef, label %if.then, label %if.end
574 if.then:
575   %ptr = alloca i32, i32 4
576   br label %for.body
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
585 body1:
586   tail call void asm sideeffect "nop", "~{x19}"()
587   br label %for.body
589 body2:
590   tail call void asm sideeffect "nop", "~{x19}"()
591   br label %for.body
593 if.end:
594   ret void
597 ; Another infinite loop test this time with two nested infinite loop.
598 ; CHECK-LABEL: infiniteloop3
599 ; CHECK: ret
600 define void @infiniteloop3() {
601 entry:
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 ]
617   br label %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
623   br label %loop1
625 end:
626   ret void
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]!
637 ; CHECK: mov x29, sp
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
653 true:
654   store i32 %a, i32* %tmp, align 4
655   %tmp4 = load i32, i32* %tmp
656   br label %false
658 false:
659   %tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ]
660   store i32 %shl1, i32* %ptr1
661   store i32 %shl2, i32* %ptr2
662   ret i32 %tmp.0
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
690 true:
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
693   br label %false
695 false:
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
715   ret void