blob: 0253229c0d7fa91b8144e4b5d4e0df292a1afc6b [file] [log] [blame]
Geoff Berry62c1a1e2016-03-02 17:58:31 +00001; RUN: llc %s -o - -enable-shrink-wrap=true -disable-post-ra -disable-fp-elim | FileCheck %s --check-prefix=CHECK --check-prefix=ENABLE
2; RUN: llc %s -o - -enable-shrink-wrap=false -disable-post-ra -disable-fp-elim | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE
Quentin Colombet61b305e2015-05-05 17:38:16 +00003target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
4target 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.
Geoff Berrya5335642016-05-06 16:34:59 +000016; 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
Quentin Colombet61b305e2015-05-05 17:38:16 +000019;
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;
Matthias Braundc4b3e82018-01-19 02:45:38 +000025; Store %a in the alloca.
Jun Bum Limfc7d56d2018-01-29 19:56:42 +000026; CHECK: stur w0, {{\[}}[[SAVE_SP]], #-4]
27; Set the alloca address in the second argument.
28; CHECK-NEXT: sub x1, [[SAVE_SP]], #4
Quentin Colombet61b305e2015-05-05 17:38:16 +000029; Set the first argument to zero.
30; CHECK-NEXT: mov w0, wzr
31; CHECK-NEXT: bl _doSomething
Chuang-Yu Chengd3fb38c2016-04-05 14:06:20 +000032;
Quentin Colombet61b305e2015-05-05 17:38:16 +000033; Without shrink-wrapping, epilogue is in the exit block.
34; DISABLE: [[EXIT_LABEL]]:
35; Epilogue code.
Geoff Berrya5335642016-05-06 16:34:59 +000036; CHECK-NEXT: ldp x{{[0-9]+}}, [[CSR]], [sp, #16]
37; CHECK-NEXT: add sp, sp, #32
Quentin Colombet61b305e2015-05-05 17:38:16 +000038;
39; With shrink-wrapping, exit block is a simple return.
40; ENABLE: [[EXIT_LABEL]]:
41; CHECK-NEXT: ret
42define 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
47true:
48 store i32 %a, i32* %tmp, align 4
49 %tmp4 = call i32 @doSomething(i32 0, i32* %tmp)
50 br label %false
51
52false:
53 %tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ]
54 ret i32 %tmp.0
55}
56
57; Function Attrs: optsize
58declare 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
Tim Northoverdaa1c012016-06-16 01:42:25 +000076; CHECK-NEXT: mov [[IV:w[0-9]+]], #10
Quentin Colombet61b305e2015-05-05 17:38:16 +000077;
78; Next BB.
79; CHECK: [[LOOP:LBB[0-9_]+]]: ; %for.body
80; CHECK: bl _something
Chad Rosier6db9ff62017-06-23 19:20:12 +000081; CHECK-NEXT: subs [[IV]], [[IV]], #1
Matthias Braun325cd2c2016-11-11 01:34:21 +000082; CHECK-NEXT: add [[SUM]], w0, [[SUM]]
Chad Rosier6db9ff62017-06-23 19:20:12 +000083; CHECK-NEXT: b.ne [[LOOP]]
Quentin Colombet61b305e2015-05-05 17:38:16 +000084;
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
106define i32 @freqSaveAndRestoreOutsideLoop(i32 %cond, i32 %N) {
107entry:
108 %tobool = icmp eq i32 %cond, 0
109 br i1 %tobool, label %if.else, label %for.body
110
111for.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
120for.end: ; preds = %for.body
121 %shl = shl i32 %add, 3
122 br label %if.end
123
124if.else: ; preds = %entry
125 %mul = shl nsw i32 %N, 1
126 br label %if.end
127
128if.end: ; preds = %if.else, %for.end
129 %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ]
130 ret i32 %sum.1
131}
132
133declare 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
Tim Northoverdaa1c012016-06-16 01:42:25 +0000143; CHECK-NEXT: mov [[IV:w[0-9]+]], #10
Quentin Colombet61b305e2015-05-05 17:38:16 +0000144; Next BB.
145; CHECK: [[LOOP_LABEL:LBB[0-9_]+]]: ; %for.body
146; CHECK: bl _something
Chad Rosier6db9ff62017-06-23 19:20:12 +0000147; CHECK-NEXT: subs [[IV]], [[IV]], #1
Matthias Braun325cd2c2016-11-11 01:34:21 +0000148; CHECK-NEXT: add [[SUM]], w0, [[SUM]]
Chad Rosier6db9ff62017-06-23 19:20:12 +0000149; CHECK-NEXT: b.ne [[LOOP_LABEL]]
Quentin Colombet61b305e2015-05-05 17:38:16 +0000150; 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
156define i32 @freqSaveAndRestoreOutsideLoop2(i32 %cond) {
157entry:
158 br label %for.body
159
160for.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
169for.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
Tim Northoverdaa1c012016-06-16 01:42:25 +0000187; CHECK-NEXT: mov [[IV:w[0-9]+]], #10
Quentin Colombet61b305e2015-05-05 17:38:16 +0000188;
189; CHECK: [[LOOP_LABEL:LBB[0-9_]+]]: ; %for.body
190; CHECK: bl _something
Chad Rosier6db9ff62017-06-23 19:20:12 +0000191; CHECK-NEXT: subs [[IV]], [[IV]], #1
Matthias Braun325cd2c2016-11-11 01:34:21 +0000192; CHECK-NEXT: add [[SUM]], w0, [[SUM]]
Chad Rosier6db9ff62017-06-23 19:20:12 +0000193; CHECK-NEXT: b.ne [[LOOP_LABEL]]
Quentin Colombet61b305e2015-05-05 17:38:16 +0000194; 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
214define i32 @loopInfoSaveOutsideLoop(i32 %cond, i32 %N) {
215entry:
216 %tobool = icmp eq i32 %cond, 0
217 br i1 %tobool, label %if.else, label %for.body
218
219for.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
228for.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
233if.else: ; preds = %entry
234 %mul = shl nsw i32 %N, 1
235 br label %if.end
236
237if.end: ; preds = %if.else, %for.end
238 %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ]
239 ret i32 %sum.1
240}
241
242declare 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
Tim Northoverdaa1c012016-06-16 01:42:25 +0000258; CHECK-NEXT: mov [[IV:w[0-9]+]], #10
Quentin Colombet61b305e2015-05-05 17:38:16 +0000259;
260; CHECK: [[LOOP_LABEL:LBB[0-9_]+]]: ; %for.body
261; CHECK: bl _something
Chad Rosier6db9ff62017-06-23 19:20:12 +0000262; CHECK-NEXT: subs [[IV]], [[IV]], #1
Matthias Braun325cd2c2016-11-11 01:34:21 +0000263; CHECK-NEXT: add [[SUM]], w0, [[SUM]]
Chad Rosier6db9ff62017-06-23 19:20:12 +0000264; CHECK-NEXT: b.ne [[LOOP_LABEL]]
Quentin Colombet61b305e2015-05-05 17:38:16 +0000265; 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
284define i32 @loopInfoRestoreOutsideLoop(i32 %cond, i32 %N) #0 {
285entry:
286 %tobool = icmp eq i32 %cond, 0
287 br i1 %tobool, label %if.else, label %if.then
288
289if.then: ; preds = %entry
290 tail call void bitcast (void (...)* @somethingElse to void ()*)()
291 br label %for.body
292
293for.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
302for.end: ; preds = %for.body
303 %shl = shl i32 %add, 3
304 br label %if.end
305
306if.else: ; preds = %entry
307 %mul = shl nsw i32 %N, 1
308 br label %if.end
309
310if.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
320define i32 @emptyFrame() {
321entry:
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.
Chuang-Yu Chengd3fb38c2016-04-05 14:06:20 +0000335; CHECK: add [[VA_BASE:x[0-9]+]], sp, #16
Quentin Colombet61b305e2015-05-05 17:38:16 +0000336; CHECK-NEXT: cmp w1, #1
Matthias Braun325cd2c2016-11-11 01:34:21 +0000337; CHECK-NEXT: str [[VA_BASE]], [sp, #8]
338; CHECK-NEXT: mov [[SUM:w0]], wzr
Quentin Colombet61b305e2015-05-05 17:38:16 +0000339; 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]]]
Chad Rosier6db9ff62017-06-23 19:20:12 +0000346; CHECK-NEXT: subs w1, w1, #1
Matthias Braun325cd2c2016-11-11 01:34:21 +0000347; CHECK-NEXT: add [[SUM]], [[SUM]], [[VA_VAL]]
Chad Rosier6db9ff62017-06-23 19:20:12 +0000348; CHECK-NEXT: b.ne [[LOOP_LABEL]]
Kyle Buttb15c0662017-01-31 23:48:32 +0000349; CHECK-NEXT: [[IFEND_LABEL]]:
Quentin Colombet61b305e2015-05-05 17:38:16 +0000350; Epilogue code.
351; CHECK: add sp, sp, #16
352; CHECK-NEXT: ret
Matthias Braun325cd2c2016-11-11 01:34:21 +0000353;
Kyle Buttb15c0662017-01-31 23:48:32 +0000354; CHECK: [[ELSE_LABEL]]: ; %if.else
355; CHECK-NEXT: lsl w0, w1, #1
356; DISABLE-NEXT: add sp, sp, #16
357; CHECK-NEXT: ret
Quentin Colombet61b305e2015-05-05 17:38:16 +0000358define i32 @variadicFunc(i32 %cond, i32 %count, ...) #0 {
359entry:
360 %ap = alloca i8*, align 8
361 %tobool = icmp eq i32 %cond, 0
362 br i1 %tobool, label %if.else, label %if.then
363
364if.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
369
370for.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
378
379for.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
383
384if.else: ; preds = %entry
385 %mul = shl nsw i32 %count, 1
386 br label %if.end
387
388if.end: ; preds = %if.else, %for.end
389 %sum.1 = phi i32 [ %sum.0.lcssa, %for.end ], [ %mul, %if.else ]
390 ret i32 %sum.1
391}
392
393declare void @llvm.va_start(i8*)
394
395declare void @llvm.va_end(i8*)
396
397; Check that we handle inline asm correctly.
398; CHECK-LABEL: inlineAsm:
399;
400; ENABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]]
401;
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]!
405;
406; DISABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]]
407;
Tim Northoverdaa1c012016-06-16 01:42:25 +0000408; CHECK: mov [[IV:w[0-9]+]], #10
Quentin Colombet61b305e2015-05-05 17:38:16 +0000409;
410; CHECK: [[LOOP_LABEL:LBB[0-9_]+]]: ; %for.body
411; Inline asm statement.
Chad Rosier6db9ff62017-06-23 19:20:12 +0000412; CHECK: subs [[IV]], [[IV]], #1
Matthias Braun325cd2c2016-11-11 01:34:21 +0000413; CHECK: add x19, x19, #1
Chad Rosier6db9ff62017-06-23 19:20:12 +0000414; CHECK: b.ne [[LOOP_LABEL]]
Quentin Colombet61b305e2015-05-05 17:38:16 +0000415; 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
426define i32 @inlineAsm(i32 %cond, i32 %N) {
427entry:
428 %tobool = icmp eq i32 %cond, 0
429 br i1 %tobool, label %if.else, label %for.body
430
431for.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
437
438if.else: ; preds = %entry
439 %mul = shl nsw i32 %N, 1
440 br label %if.end
441
442if.end: ; preds = %for.body, %if.else
443 %sum.0 = phi i32 [ %mul, %if.else ], [ 0, %for.body ]
444 ret i32 %sum.0
445}
446
447; Check that we handle calls to variadic functions correctly.
448; CHECK-LABEL: callVariadicFunc:
449;
450; ENABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]]
451;
452; Prologue code.
Geoff Berrya5335642016-05-06 16:34:59 +0000453; 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
Quentin Colombet61b305e2015-05-05 17:38:16 +0000456;
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
465;
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
470;
471; Epilogue code.
Geoff Berrya5335642016-05-06 16:34:59 +0000472; CHECK: ldp [[CSR1]], [[CSR2]], [sp, #48]
473; CHECK-NEXT: add sp, sp, #64
Quentin Colombet61b305e2015-05-05 17:38:16 +0000474; CHECK-NEXT: ret
475;
476; ENABLE: [[ELSE_LABEL]]: ; %if.else
477; ENABLE-NEXT: lsl w0, w1, #1
478; ENABLE-NEXT: ret
479define i32 @callVariadicFunc(i32 %cond, i32 %N) {
480entry:
481 %tobool = icmp eq i32 %cond, 0
482 br i1 %tobool, label %if.else, label %if.then
483
484if.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
488
489if.else: ; preds = %entry
490 %mul = shl nsw i32 %N, 1
491 br label %if.end
492
493if.end: ; preds = %if.else, %if.then
494 %sum.0 = phi i32 [ %shl, %if.then ], [ %mul, %if.else ]
495 ret i32 %sum.0
496}
497
498declare i32 @someVariadicFunc(i32, ...)
Quentin Colombet8b984d12015-07-10 22:09:55 +0000499
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.
503;
504; CHECK-LABEL: noreturn:
505; DISABLE: stp
506;
Weiming Zhao812fde32016-07-29 23:33:48 +0000507; CHECK: cbnz w0, [[ABORT:LBB[0-9_]+]]
Quentin Colombet8b984d12015-07-10 22:09:55 +0000508;
Tim Northoverdaa1c012016-06-16 01:42:25 +0000509; CHECK: mov w0, #42
Quentin Colombet8b984d12015-07-10 22:09:55 +0000510;
511; DISABLE-NEXT: ldp
512;
513; CHECK-NEXT: ret
514;
515; CHECK: [[ABORT]]: ; %if.abort
516;
517; ENABLE: stp
518;
519; CHECK: bl _abort
520; ENABLE-NOT: ldp
521define i32 @noreturn(i8 signext %bad_thing) {
522entry:
523 %tobool = icmp eq i8 %bad_thing, 0
524 br i1 %tobool, label %if.end, label %if.abort
525
526if.abort:
527 tail call void @abort() #0
528 unreachable
529
530if.end:
531 ret i32 42
532}
533
534declare void @abort() #0
535
536attributes #0 = { noreturn nounwind }
Kit Bartona7bf96a2015-08-06 19:01:57 +0000537
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.
545;
546; CHECK-LABEL: infiniteloop
547; CHECK: ret
548define void @infiniteloop() {
549entry:
550 br i1 undef, label %if.then, label %if.end
551
552if.then:
553 %ptr = alloca i32, i32 4
554 br label %for.body
555
556for.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
562
563if.end:
564 ret void
565}
Quentin Colombetb4c68862015-09-17 23:21:34 +0000566
567; Another infinite loop test this time with a body bigger than just one block.
568; CHECK-LABEL: infiniteloop2
569; CHECK: ret
570define void @infiniteloop2() {
571entry:
572 br i1 undef, label %if.then, label %if.end
573
574if.then:
575 %ptr = alloca i32, i32 4
576 br label %for.body
577
578for.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
584
585body1:
586 tail call void asm sideeffect "nop", "~{x19}"()
587 br label %for.body
588
589body2:
590 tail call void asm sideeffect "nop", "~{x19}"()
591 br label %for.body
592
593if.end:
594 ret void
595}
596
597; Another infinite loop test this time with two nested infinite loop.
598; CHECK-LABEL: infiniteloop3
599; CHECK: ret
600define void @infiniteloop3() {
601entry:
602 br i1 undef, label %loop2a, label %body
603
604body: ; preds = %entry
605 br i1 undef, label %loop2a, label %end
606
607loop1: ; 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
613
614loop2a: ; 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
618
619loop2b: ; 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
624
625end:
626 ret void
627}
Geoff Berry7e4ba3d2016-02-19 18:27:32 +0000628
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]],
645
646define 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
652
653true:
654 store i32 %a, i32* %tmp, align 4
655 %tmp4 = load i32, i32* %tmp
656 br label %false
657
658false:
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
663}
664
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
674
675define 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
689
690true:
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
694
695false:
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
714
715 ret void
716}