7d7005d82a0b0e508bba094ea05f3ce94a11d818
[oota-llvm.git] / test / CodeGen / AArch64 / arm64-shrink-wrapping.ll
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"
5
6
7 ; Initial motivating example: Simple diamond with a call just on one side.
8 ; CHECK-LABEL: foo:
9 ;
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_]+]]
14 ;
15 ; Prologue code.
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
19 ;
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_]+]]
24 ;
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
32
33 ; Without shrink-wrapping, epilogue is in the exit block.
34 ; DISABLE: [[EXIT_LABEL]]:
35 ; Epilogue code.
36 ; CHECK-NEXT: mov sp, [[SAVE_SP]]
37 ; CHECK-NEXT: ldp [[SAVE_SP]], [[CSR]], [sp], #16
38 ;
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
46
47 true:
48   store i32 %a, i32* %tmp, align 4
49   %tmp4 = call i32 @doSomething(i32 0, i32* %tmp)
50   br label %false
51
52 false:
53   %tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ]
54   ret i32 %tmp.0
55 }
56
57 ; Function Attrs: optsize
58 declare i32 @doSomething(i32, i32*)
59
60
61 ; Check that we do not perform the restore inside the loop whereas the save
62 ; is outside.
63 ; CHECK-LABEL: freqSaveAndRestoreOutsideLoop:
64 ;
65 ; Shrink-wrapping allows to skip the prologue in the else case.
66 ; ENABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]]
67 ;
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
72 ;
73 ; DISABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]]
74 ;
75 ; CHECK: mov [[SUM:w[0-9]+]], wzr
76 ; CHECK-NEXT: movz [[IV:w[0-9]+]], #0xa
77 ;
78 ; Next BB.
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]]
84 ;
85 ; Next BB.
86 ; Copy SUM into the returned register + << 3.
87 ; CHECK: lsl w0, [[SUM]], #3
88 ;
89 ; Jump to epilogue.
90 ; DISABLE: b [[EPILOG_BB:LBB[0-9_]+]]
91 ;
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
96 ;
97 ; Epilogue code.
98 ; CHECK: ldp [[CSR3]], [[CSR4]], [sp, #16]
99 ; CHECK-NEXT: ldp [[CSR1]], [[CSR2]], [sp], #32
100 ; CHECK-NEXT: ret
101 ;
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
110
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
119
120 for.end:                                          ; preds = %for.body
121   %shl = shl i32 %add, 3
122   br label %if.end
123
124 if.else:                                          ; preds = %entry
125   %mul = shl nsw i32 %N, 1
126   br label %if.end
127
128 if.end:                                           ; preds = %if.else, %for.end
129   %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ]
130   ret i32 %sum.1
131 }
132
133 declare i32 @something(...)
134
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: movz [[IV:w[0-9]+]], #0xa
144 ; Next BB.
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]]
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
159
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
168
169 for.end:                                          ; preds = %for.body
170   ret i32 %add
171 }
172
173 ; Check with a more complex case that we do not have save within the loop and
174 ; restore outside.
175 ; CHECK-LABEL: loopInfoSaveOutsideLoop:
176 ;
177 ; ENABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]]
178 ;
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
183 ;
184 ; DISABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]]
185 ;
186 ; CHECK: mov [[SUM:w[0-9]+]], wzr
187 ; CHECK-NEXT: movz [[IV:w[0-9]+]], #0xa
188 ;
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]]
194 ; Next BB.
195 ; CHECK: bl _somethingElse
196 ; CHECK-NEXT: lsl w0, [[SUM]], #3
197 ;
198 ; Jump to epilogue.
199 ; DISABLE: b [[EPILOG_BB:LBB[0-9_]+]]
200 ;
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
209 ;
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
218
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
227
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
232
233 if.else:                                          ; preds = %entry
234   %mul = shl nsw i32 %N, 1
235   br label %if.end
236
237 if.end:                                           ; preds = %if.else, %for.end
238   %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ]
239   ret i32 %sum.1
240 }
241
242 declare void @somethingElse(...)
243
244 ; Check with a more complex case that we do not have restore within the loop and
245 ; save outside.
246 ; CHECK-LABEL: loopInfoRestoreOutsideLoop:
247 ;
248 ; ENABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]]
249 ;
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
253 ;
254 ; DISABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]]
255 ;
256 ; CHECK: bl _somethingElse
257 ; CHECK-NEXT: mov [[SUM:w[0-9]+]], wzr
258 ; CHECK-NEXT: movz [[IV:w[0-9]+]], #0xa
259 ;
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]]
265 ; Next BB.
266 ; CHECK: lsl w0, [[SUM]], #3
267 ;
268 ; Jump to epilogue.
269 ; DISABLE: b [[EPILOG_BB:LBB[0-9_]+]]
270 ;
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
279 ;
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) #0 {
285 entry:
286   %tobool = icmp eq i32 %cond, 0
287   br i1 %tobool, label %if.else, label %if.then
288
289 if.then:                                          ; preds = %entry
290   tail call void bitcast (void (...)* @somethingElse to void ()*)()
291   br label %for.body
292
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
301
302 for.end:                                          ; preds = %for.body
303   %shl = shl i32 %add, 3
304   br label %if.end
305
306 if.else:                                          ; preds = %entry
307   %mul = shl nsw i32 %N, 1
308   br label %if.end
309
310 if.end:                                           ; preds = %if.else, %for.end
311   %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ]
312   ret i32 %sum.1
313 }
314
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
323 }
324
325 ; Check that we handle variadic function correctly.
326 ; CHECK-LABEL: variadicFunc:
327 ;
328 ; ENABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]]
329 ;
330 ; Prologue code.
331 ; CHECK: sub sp, sp, #16
332 ; DISABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]]
333 ;
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_]+]]
340 ;
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]]
349 ;
350 ; DISABLE-NEXT: b [[IFEND_LABEL]]
351 ; DISABLE: [[ELSE_LABEL]]: ; %if.else
352 ; DISABLE: lsl w0, w1, #1
353 ;
354 ; CHECK: [[IFEND_LABEL]]:
355 ; Epilogue code.
356 ; CHECK: add sp, sp, #16
357 ; CHECK-NEXT: ret
358 ;
359 ; ENABLE: [[ELSE_LABEL]]: ; %if.else
360 ; ENABLE: lsl w0, w1, #1
361 ; ENABLE-NEXT: ret
362 define i32 @variadicFunc(i32 %cond, i32 %count, ...) #0 {
363 entry:
364   %ap = alloca i8*, align 8
365   %tobool = icmp eq i32 %cond, 0
366   br i1 %tobool, label %if.else, label %if.then
367
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
373
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
382
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)
386   br label %if.end
387
388 if.else:                                          ; preds = %entry
389   %mul = shl nsw i32 %count, 1
390   br label %if.end
391
392 if.end:                                           ; preds = %if.else, %for.end
393   %sum.1 = phi i32 [ %sum.0.lcssa, %for.end ], [ %mul, %if.else ]
394   ret i32 %sum.1
395 }
396
397 declare void @llvm.va_start(i8*)
398
399 declare void @llvm.va_end(i8*)
400
401 ; Check that we handle inline asm correctly.
402 ; CHECK-LABEL: inlineAsm:
403 ;
404 ; ENABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]]
405 ;
406 ; Prologue code.
407 ; Make sure we save the CSR used in the inline asm: x19.
408 ; CHECK: stp [[CSR1:x[0-9]+]], [[CSR2:x19]], [sp, #-16]!
409 ;
410 ; DISABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]]
411 ;
412 ; CHECK: movz [[IV:w[0-9]+]], #0xa
413 ;
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]]
419 ; Next BB.
420 ; CHECK: mov w0, wzr
421 ; Epilogue code.
422 ; CHECK-NEXT: ldp [[CSR1]], [[CSR2]], [sp], #16
423 ; CHECK-NEXT: ret
424 ; Next BB.
425 ; CHECK: [[ELSE_LABEL]]: ; %if.else
426 ; CHECK-NEXT: lsl w0, w1, #1
427 ; Epilogue code.
428 ; DISABLE-NEXT: ldp [[CSR1]], [[CSR2]], [sp], #16
429 ; CHECK-NEXT: ret
430 define i32 @inlineAsm(i32 %cond, i32 %N) {
431 entry:
432   %tobool = icmp eq i32 %cond, 0
433   br i1 %tobool, label %if.else, label %for.body
434
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
441
442 if.else:                                          ; preds = %entry
443   %mul = shl nsw i32 %N, 1
444   br label %if.end
445
446 if.end:                                           ; preds = %for.body, %if.else
447   %sum.0 = phi i32 [ %mul, %if.else ], [ 0, %for.body ]
448   ret i32 %sum.0
449 }
450
451 ; Check that we handle calls to variadic functions correctly.
452 ; CHECK-LABEL: callVariadicFunc:
453 ;
454 ; ENABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]]
455 ;
456 ; Prologue code.
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
460 ;
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
469 ;
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
474 ;
475 ; Epilogue code.
476 ; CHECK: mov sp, [[NEW_SP]]
477 ; CHECK-NEXT: ldp [[CSR1]], [[CSR2]], [sp], #16
478 ; CHECK-NEXT: ret
479 ;
480 ; ENABLE: [[ELSE_LABEL]]: ; %if.else
481 ; ENABLE-NEXT: lsl w0, w1, #1
482 ; ENABLE-NEXT: ret
483 define i32 @callVariadicFunc(i32 %cond, i32 %N) {
484 entry:
485   %tobool = icmp eq i32 %cond, 0
486   br i1 %tobool, label %if.else, label %if.then
487
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
491   br label %if.end
492
493 if.else:                                          ; preds = %entry
494   %mul = shl nsw i32 %N, 1
495   br label %if.end
496
497 if.end:                                           ; preds = %if.else, %if.then
498   %sum.0 = phi i32 [ %shl, %if.then ], [ %mul, %if.else ]
499   ret i32 %sum.0
500 }
501
502 declare i32 @someVariadicFunc(i32, ...)
503
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.
507 ;
508 ; CHECK-LABEL: noreturn:
509 ; DISABLE: stp
510 ;
511 ; CHECK: and [[TEST:w[0-9]+]], w0, #0xff
512 ; CHECK-NEXT: cbnz [[TEST]], [[ABORT:LBB[0-9_]+]]
513 ;
514 ; CHECK: movz w0, #0x2a
515 ;
516 ; DISABLE-NEXT: ldp
517 ;
518 ; CHECK-NEXT: ret
519 ;
520 ; CHECK: [[ABORT]]: ; %if.abort
521 ;
522 ; ENABLE: stp
523 ;
524 ; CHECK: bl _abort
525 ; ENABLE-NOT: ldp
526 define i32 @noreturn(i8 signext %bad_thing) {
527 entry:
528   %tobool = icmp eq i8 %bad_thing, 0
529   br i1 %tobool, label %if.end, label %if.abort
530
531 if.abort:
532   tail call void @abort() #0
533   unreachable
534
535 if.end:
536   ret i32 42
537 }
538
539 declare void @abort() #0
540
541 attributes #0 = { noreturn nounwind }
542
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.
550 ;
551 ; CHECK-LABEL: infiniteloop
552 ; CHECK: ret
553 define void @infiniteloop() {
554 entry:
555   br i1 undef, label %if.then, label %if.end
556
557 if.then:
558   %ptr = alloca i32, i32 4
559   br label %for.body
560
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
566   br label %for.body
567
568 if.end:
569   ret void
570 }
571
572 ; Another infinite loop test this time with a body bigger than just one block.
573 ; CHECK-LABEL: infiniteloop2
574 ; CHECK: ret
575 define void @infiniteloop2() {
576 entry:
577   br i1 undef, label %if.then, label %if.end
578
579 if.then:
580   %ptr = alloca i32, i32 4
581   br label %for.body
582
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
589
590 body1:
591   tail call void asm sideeffect "nop", "~{x19}"()
592   br label %for.body
593
594 body2:
595   tail call void asm sideeffect "nop", "~{x19}"()
596   br label %for.body
597
598 if.end:
599   ret void
600 }
601
602 ; Another infinite loop test this time with two nested infinite loop.
603 ; CHECK-LABEL: infiniteloop3
604 ; CHECK: ret
605 define void @infiniteloop3() {
606 entry:
607   br i1 undef, label %loop2a, label %body
608
609 body:                                             ; preds = %entry
610   br i1 undef, label %loop2a, label %end
611
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
618
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 ]
622   br label %loop1
623
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
628   br label %loop1
629
630 end:
631   ret void
632 }