[AArch64] Fix bug in prolog clobbering live reg when shrink wrapping.
[oota-llvm.git] / test / CodeGen / AArch64 / arm64-fast-isel-conversion.ll
1 ; RUN: llc -O0 -fast-isel-abort=1 -verify-machineinstrs -mtriple=arm64-apple-darwin -mcpu=cyclone < %s | FileCheck %s
2
3 ;; Test various conversions.
4 define zeroext i32 @trunc_(i8 zeroext %a, i16 zeroext %b, i32 %c, i64 %d) nounwind ssp {
5 entry:
6 ; CHECK-LABEL: trunc_
7 ; CHECK: sub sp, sp, #16
8 ; CHECK: strb w0, [sp, #15]
9 ; CHECK: strh w1, [sp, #12]
10 ; CHECK: str w2, [sp, #8]
11 ; CHECK: str x3, [sp]
12 ; CHECK: ldr x3, [sp]
13 ; CHECK: mov x0, x3
14 ; CHECK: str w0, [sp, #8]
15 ; CHECK: ldr w0, [sp, #8]
16 ; CHECK: strh w0, [sp, #12]
17 ; CHECK: ldrh w0, [sp, #12]
18 ; CHECK: strb w0, [sp, #15]
19 ; CHECK: ldrb w0, [sp, #15]
20 ; CHECK: add sp, sp, #16
21 ; CHECK: ret
22   %a.addr = alloca i8, align 1
23   %b.addr = alloca i16, align 2
24   %c.addr = alloca i32, align 4
25   %d.addr = alloca i64, align 8
26   store i8 %a, i8* %a.addr, align 1
27   store i16 %b, i16* %b.addr, align 2
28   store i32 %c, i32* %c.addr, align 4
29   store i64 %d, i64* %d.addr, align 8
30   %tmp = load i64, i64* %d.addr, align 8
31   %conv = trunc i64 %tmp to i32
32   store i32 %conv, i32* %c.addr, align 4
33   %tmp1 = load i32, i32* %c.addr, align 4
34   %conv2 = trunc i32 %tmp1 to i16
35   store i16 %conv2, i16* %b.addr, align 2
36   %tmp3 = load i16, i16* %b.addr, align 2
37   %conv4 = trunc i16 %tmp3 to i8
38   store i8 %conv4, i8* %a.addr, align 1
39   %tmp5 = load i8, i8* %a.addr, align 1
40   %conv6 = zext i8 %tmp5 to i32
41   ret i32 %conv6
42 }
43
44 define i64 @zext_(i8 zeroext %a, i16 zeroext %b, i32 %c, i64 %d) nounwind ssp {
45 entry:
46 ; CHECK-LABEL: zext_
47 ; CHECK: sub sp, sp, #16
48 ; CHECK: strb w0, [sp, #15]
49 ; CHECK: strh w1, [sp, #12]
50 ; CHECK: str w2, [sp, #8]
51 ; CHECK: str x3, [sp]
52 ; CHECK: ldrb w0, [sp, #15]
53 ; CHECK: strh w0, [sp, #12]
54 ; CHECK: ldrh w0, [sp, #12]
55 ; CHECK: str w0, [sp, #8]
56 ; CHECK: ldr w0, [sp, #8]
57 ; CHECK: mov x3, x0
58 ; CHECK: str x3, [sp]
59 ; CHECK: ldr x0, [sp]
60 ; CHECK: ret
61   %a.addr = alloca i8, align 1
62   %b.addr = alloca i16, align 2
63   %c.addr = alloca i32, align 4
64   %d.addr = alloca i64, align 8
65   store i8 %a, i8* %a.addr, align 1
66   store i16 %b, i16* %b.addr, align 2
67   store i32 %c, i32* %c.addr, align 4
68   store i64 %d, i64* %d.addr, align 8
69   %tmp = load i8, i8* %a.addr, align 1
70   %conv = zext i8 %tmp to i16
71   store i16 %conv, i16* %b.addr, align 2
72   %tmp1 = load i16, i16* %b.addr, align 2
73   %conv2 = zext i16 %tmp1 to i32
74   store i32 %conv2, i32* %c.addr, align 4
75   %tmp3 = load i32, i32* %c.addr, align 4
76   %conv4 = zext i32 %tmp3 to i64
77   store i64 %conv4, i64* %d.addr, align 8
78   %tmp5 = load i64, i64* %d.addr, align 8
79   ret i64 %tmp5
80 }
81
82 define i32 @zext_i1_i32(i1 zeroext %a) nounwind ssp {
83 entry:
84 ; CHECK-LABEL: zext_i1_i32
85 ; CHECK-NOT:   and w0, w0, #0x1
86 ; CHECK:       ret
87   %conv = zext i1 %a to i32
88   ret i32 %conv;
89 }
90
91 define i64 @zext_i1_i64(i1 zeroext %a) nounwind ssp {
92 entry:
93 ; CHECK-LABEL: zext_i1_i64
94 ; CHECK-NOT:   and w0, w0, #0x1
95 ; CHECK:       ret
96   %conv = zext i1 %a to i64
97   ret i64 %conv;
98 }
99
100 define i64 @sext_(i8 signext %a, i16 signext %b, i32 %c, i64 %d) nounwind ssp {
101 entry:
102 ; CHECK-LABEL: sext_
103 ; CHECK: sub sp, sp, #16
104 ; CHECK: strb w0, [sp, #15]
105 ; CHECK: strh w1, [sp, #12]
106 ; CHECK: str w2, [sp, #8]
107 ; CHECK: str x3, [sp]
108 ; CHECK: ldrsb w0, [sp, #15]
109 ; CHECK: strh w0, [sp, #12]
110 ; CHECK: ldrsh w0, [sp, #12]
111 ; CHECK: str w0, [sp, #8]
112 ; CHECK: ldrsw x3, [sp, #8]
113 ; CHECK: str x3, [sp]
114 ; CHECK: ldr x0, [sp]
115 ; CHECK: ret
116   %a.addr = alloca i8, align 1
117   %b.addr = alloca i16, align 2
118   %c.addr = alloca i32, align 4
119   %d.addr = alloca i64, align 8
120   store i8 %a, i8* %a.addr, align 1
121   store i16 %b, i16* %b.addr, align 2
122   store i32 %c, i32* %c.addr, align 4
123   store i64 %d, i64* %d.addr, align 8
124   %tmp = load i8, i8* %a.addr, align 1
125   %conv = sext i8 %tmp to i16
126   store i16 %conv, i16* %b.addr, align 2
127   %tmp1 = load i16, i16* %b.addr, align 2
128   %conv2 = sext i16 %tmp1 to i32
129   store i32 %conv2, i32* %c.addr, align 4
130   %tmp3 = load i32, i32* %c.addr, align 4
131   %conv4 = sext i32 %tmp3 to i64
132   store i64 %conv4, i64* %d.addr, align 8
133   %tmp5 = load i64, i64* %d.addr, align 8
134   ret i64 %tmp5
135 }
136
137 ; Test sext i8 to i64
138
139 define zeroext i64 @sext_i8_i64(i8 zeroext %in) {
140 ; CHECK-LABEL: sext_i8_i64:
141 ; CHECK: mov x[[TMP:[0-9]+]], x0
142 ; CHECK: sxtb x0, w[[TMP]]
143   %big = sext i8 %in to i64
144   ret i64 %big
145 }
146
147 define zeroext i64 @sext_i16_i64(i16 zeroext %in) {
148 ; CHECK-LABEL: sext_i16_i64:
149 ; CHECK: mov x[[TMP:[0-9]+]], x0
150 ; CHECK: sxth x0, w[[TMP]]
151   %big = sext i16 %in to i64
152   ret i64 %big
153 }
154
155 ; Test sext i1 to i32
156 define i32 @sext_i1_i32(i1 signext %a) nounwind ssp {
157 entry:
158 ; CHECK-LABEL: sext_i1_i32
159 ; CHECK-NOT:   sbfx w0, w0, #0, #1
160 ; CHECK:       ret
161   %conv = sext i1 %a to i32
162   ret i32 %conv
163 }
164
165 ; Test sext i1 to i16
166 define signext i16 @sext_i1_i16(i1 %a) nounwind ssp {
167 entry:
168 ; CHECK-LABEL: sext_i1_i16
169 ; CHECK: sbfx w0, w0, #0, #1
170   %conv = sext i1 %a to i16
171   ret i16 %conv
172 }
173
174 ; Test sext i1 to i8
175 define signext i8 @sext_i1_i8(i1 %a) nounwind ssp {
176 entry:
177 ; CHECK-LABEL: sext_i1_i8
178 ; CHECK: sbfx w0, w0, #0, #1
179   %conv = sext i1 %a to i8
180   ret i8 %conv
181 }
182
183 ; Test fpext
184 define double @fpext_(float %a) nounwind ssp {
185 entry:
186 ; CHECK-LABEL: fpext_
187 ; CHECK: fcvt d0, s0
188   %conv = fpext float %a to double
189   ret double %conv
190 }
191
192 ; Test fptrunc
193 define float @fptrunc_(double %a) nounwind ssp {
194 entry:
195 ; CHECK-LABEL: fptrunc_
196 ; CHECK: fcvt s0, d0
197   %conv = fptrunc double %a to float
198   ret float %conv
199 }
200
201 ; Test fptosi
202 define i32 @fptosi_ws(float %a) nounwind ssp {
203 entry:
204 ; CHECK-LABEL: fptosi_ws
205 ; CHECK: fcvtzs w0, s0
206   %conv = fptosi float %a to i32
207   ret i32 %conv
208 }
209
210 ; Test fptosi
211 define i32 @fptosi_wd(double %a) nounwind ssp {
212 entry:
213 ; CHECK-LABEL: fptosi_wd
214 ; CHECK: fcvtzs w0, d0
215   %conv = fptosi double %a to i32
216   ret i32 %conv
217 }
218
219 ; Test fptoui
220 define i32 @fptoui_ws(float %a) nounwind ssp {
221 entry:
222 ; CHECK-LABEL: fptoui_ws
223 ; CHECK: fcvtzu w0, s0
224   %conv = fptoui float %a to i32
225   ret i32 %conv
226 }
227
228 ; Test fptoui
229 define i32 @fptoui_wd(double %a) nounwind ssp {
230 entry:
231 ; CHECK-LABEL: fptoui_wd
232 ; CHECK: fcvtzu w0, d0
233   %conv = fptoui double %a to i32
234   ret i32 %conv
235 }
236
237 ; Test sitofp
238 define float @sitofp_sw_i1(i1 %a) nounwind ssp {
239 entry:
240 ; CHECK-LABEL: sitofp_sw_i1
241 ; CHECK: sbfx w0, w0, #0, #1
242 ; CHECK: scvtf s0, w0
243   %conv = sitofp i1 %a to float
244   ret float %conv
245 }
246
247 ; Test sitofp
248 define float @sitofp_sw_i8(i8 %a) nounwind ssp {
249 entry:
250 ; CHECK-LABEL: sitofp_sw_i8
251 ; CHECK: sxtb w0, w0
252 ; CHECK: scvtf s0, w0
253   %conv = sitofp i8 %a to float
254   ret float %conv
255 }
256
257 ; Test sitofp
258 define float @sitofp_sw_i16(i16 %a) nounwind ssp {
259 entry:
260 ; CHECK-LABEL: sitofp_sw_i16
261   %conv = sitofp i16 %a to float
262   ret float %conv
263 }
264
265 ; Test sitofp
266 define float @sitofp_sw(i32 %a) nounwind ssp {
267 entry:
268 ; CHECK-LABEL: sitofp_sw
269 ; CHECK: scvtf s0, w0
270   %conv = sitofp i32 %a to float
271   ret float %conv
272 }
273
274 ; Test sitofp
275 define float @sitofp_sx(i64 %a) nounwind ssp {
276 entry:
277 ; CHECK-LABEL: sitofp_sx
278 ; CHECK: scvtf s0, x0
279   %conv = sitofp i64 %a to float
280   ret float %conv
281 }
282
283 ; Test sitofp
284 define double @sitofp_dw(i32 %a) nounwind ssp {
285 entry:
286 ; CHECK-LABEL: sitofp_dw
287 ; CHECK: scvtf d0, w0
288   %conv = sitofp i32 %a to double
289   ret double %conv
290 }
291
292 ; Test sitofp
293 define double @sitofp_dx(i64 %a) nounwind ssp {
294 entry:
295 ; CHECK-LABEL: sitofp_dx
296 ; CHECK: scvtf d0, x0
297   %conv = sitofp i64 %a to double
298   ret double %conv
299 }
300
301 ; Test uitofp
302 define float @uitofp_sw_i1(i1 %a) nounwind ssp {
303 entry:
304 ; CHECK-LABEL: uitofp_sw_i1
305 ; CHECK: and w0, w0, #0x1
306 ; CHECK: ucvtf s0, w0
307   %conv = uitofp i1 %a to float
308   ret float %conv
309 }
310
311 ; Test uitofp
312 define float @uitofp_sw_i8(i8 %a) nounwind ssp {
313 entry:
314 ; CHECK-LABEL: uitofp_sw_i8
315   %conv = uitofp i8 %a to float
316   ret float %conv
317 }
318
319 ; Test uitofp
320 define float @uitofp_sw_i16(i16 %a) nounwind ssp {
321 entry:
322 ; CHECK-LABEL: uitofp_sw_i16
323   %conv = uitofp i16 %a to float
324   ret float %conv
325 }
326
327 ; Test uitofp
328 define float @uitofp_sw(i32 %a) nounwind ssp {
329 entry:
330 ; CHECK-LABEL: uitofp_sw
331 ; CHECK: ucvtf s0, w0
332   %conv = uitofp i32 %a to float
333   ret float %conv
334 }
335
336 ; Test uitofp
337 define float @uitofp_sx(i64 %a) nounwind ssp {
338 entry:
339 ; CHECK-LABEL: uitofp_sx
340 ; CHECK: ucvtf s0, x0
341   %conv = uitofp i64 %a to float
342   ret float %conv
343 }
344
345 ; Test uitofp
346 define double @uitofp_dw(i32 %a) nounwind ssp {
347 entry:
348 ; CHECK-LABEL: uitofp_dw
349 ; CHECK: ucvtf d0, w0
350   %conv = uitofp i32 %a to double
351   ret double %conv
352 }
353
354 ; Test uitofp
355 define double @uitofp_dx(i64 %a) nounwind ssp {
356 entry:
357 ; CHECK-LABEL: uitofp_dx
358 ; CHECK: ucvtf d0, x0
359   %conv = uitofp i64 %a to double
360   ret double %conv
361 }
362
363 define i32 @i64_trunc_i32(i64 %a) nounwind ssp {
364 entry:
365 ; CHECK-LABEL: i64_trunc_i32
366 ; CHECK: mov x1, x0
367   %conv = trunc i64 %a to i32
368   ret i32 %conv
369 }
370
371 define zeroext i16 @i64_trunc_i16(i64 %a) nounwind ssp {
372 entry:
373 ; CHECK-LABEL: i64_trunc_i16
374 ; CHECK: mov x[[REG:[0-9]+]], x0
375 ; CHECK: and [[REG2:w[0-9]+]], w[[REG]], #0xffff
376 ; CHECK: uxth w0, [[REG2]]
377   %conv = trunc i64 %a to i16
378   ret i16 %conv
379 }
380
381 define zeroext i8 @i64_trunc_i8(i64 %a) nounwind ssp {
382 entry:
383 ; CHECK-LABEL: i64_trunc_i8
384 ; CHECK: mov x[[REG:[0-9]+]], x0
385 ; CHECK: and [[REG2:w[0-9]+]], w[[REG]], #0xff
386 ; CHECK: uxtb w0, [[REG2]]
387   %conv = trunc i64 %a to i8
388   ret i8 %conv
389 }
390
391 define zeroext i1 @i64_trunc_i1(i64 %a) nounwind ssp {
392 entry:
393 ; CHECK-LABEL: i64_trunc_i1
394 ; CHECK: mov x[[REG:[0-9]+]], x0
395 ; CHECK: and [[REG2:w[0-9]+]], w[[REG]], #0x1
396 ; CHECK: and w0, [[REG2]], #0x1
397   %conv = trunc i64 %a to i1
398   ret i1 %conv
399 }
400
401 ; rdar://15101939
402 define void @stack_trunc() nounwind {
403 ; CHECK-LABEL: stack_trunc
404 ; CHECK: sub  sp, sp, #16
405 ; CHECK: ldr  [[REG:x[0-9]+]], [sp]
406 ; CHECK: mov  x[[REG2:[0-9]+]], [[REG]]
407 ; CHECK: and  [[REG3:w[0-9]+]], w[[REG2]], #0xff
408 ; CHECK: strb [[REG3]], [sp, #15]
409 ; CHECK: add  sp, sp, #16
410   %a = alloca i8, align 1
411   %b = alloca i64, align 8
412   %c = load i64, i64* %b, align 8
413   %d = trunc i64 %c to i8
414   store i8 %d, i8* %a, align 1
415   ret void
416 }
417
418 define zeroext i64 @zext_i8_i64(i8 zeroext %in) {
419 ; CHECK-LABEL: zext_i8_i64:
420 ; CHECK-NOT:   ubfx x0, {{x[0-9]+}}, #0, #8
421 ; CHECK:       ret
422   %big = zext i8 %in to i64
423   ret i64 %big
424 }
425 define zeroext i64 @zext_i16_i64(i16 zeroext %in) {
426 ; CHECK-LABEL: zext_i16_i64:
427 ; CHECK-NOT:   ubfx x0, {{x[0-9]+}}, #0, #16
428 ; CHECK:       ret
429   %big = zext i16 %in to i64
430   ret i64 %big
431 }
432
433 define float @bitcast_i32_to_float(i32 %a) {
434   %1 = bitcast i32 %a to float
435   ret float %1
436 }
437
438 define double @bitcast_i64_to_double(i64 %a) {
439   %1 = bitcast i64 %a to double
440   ret double %1
441 }
442
443 define i32 @bitcast_float_to_i32(float %a) {
444   %1 = bitcast float %a to i32
445   ret i32 %1
446 }
447
448 define i64 @bitcast_double_to_i64(double %a) {
449   %1 = bitcast double %a to i64
450   ret i64 %1
451 }
452