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