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