ARM64: initial backend import
[oota-llvm.git] / test / CodeGen / ARM64 / fast-isel-conversion.ll
1 ; RUN: llc < %s -O0 -fast-isel-abort -mtriple=arm64-apple-darwin | 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: uxtw x3, w0
61 ; CHECK: str x3, [sp]
62 ; CHECK: ldr x0, [sp], #16
63 ; CHECK: ret
64   %a.addr = alloca i8, align 1
65   %b.addr = alloca i16, align 2
66   %c.addr = alloca i32, align 4
67   %d.addr = alloca i64, align 8
68   store i8 %a, i8* %a.addr, align 1
69   store i16 %b, i16* %b.addr, align 2
70   store i32 %c, i32* %c.addr, align 4
71   store i64 %d, i64* %d.addr, align 8
72   %tmp = load i8* %a.addr, align 1
73   %conv = zext i8 %tmp to i16
74   store i16 %conv, i16* %b.addr, align 2
75   %tmp1 = load i16* %b.addr, align 2
76   %conv2 = zext i16 %tmp1 to i32
77   store i32 %conv2, i32* %c.addr, align 4
78   %tmp3 = load i32* %c.addr, align 4
79   %conv4 = zext i32 %tmp3 to i64
80   store i64 %conv4, i64* %d.addr, align 8
81   %tmp5 = load i64* %d.addr, align 8
82   ret i64 %tmp5
83 }
84
85 define i32 @zext_i1_i32(i1 zeroext %a) nounwind ssp {
86 entry:
87 ; CHECK: @zext_i1_i32
88 ; CHECK: and w0, w0, #0x1
89   %conv = zext i1 %a to i32
90   ret i32 %conv;
91 }
92
93 define i64 @zext_i1_i64(i1 zeroext %a) nounwind ssp {
94 entry:
95 ; CHECK: @zext_i1_i64
96 ; CHECK: and w0, w0, #0x1
97   %conv = zext i1 %a to i64
98   ret i64 %conv;
99 }
100
101 define i64 @sext_(i8 signext %a, i16 signext %b, i32 %c, i64 %d) nounwind ssp {
102 entry:
103 ; CHECK: sext_
104 ; CHECK: sub sp, sp, #16
105 ; CHECK: strb w0, [sp, #15]
106 ; CHECK: strh w1, [sp, #12]
107 ; CHECK: str w2, [sp, #8]
108 ; CHECK: str x3, [sp]
109 ; CHECK: ldrb w0, [sp, #15]
110 ; CHECK: sxtb w0, w0
111 ; CHECK: strh w0, [sp, #12]
112 ; CHECK: ldrh w0, [sp, #12]
113 ; CHECK: sxth w0, w0
114 ; CHECK: str w0, [sp, #8]
115 ; CHECK: ldr w0, [sp, #8]
116 ; CHECK: sxtw x3, w0
117 ; CHECK: str x3, [sp]
118 ; CHECK: ldr x0, [sp], #16
119 ; CHECK: ret
120   %a.addr = alloca i8, align 1
121   %b.addr = alloca i16, align 2
122   %c.addr = alloca i32, align 4
123   %d.addr = alloca i64, align 8
124   store i8 %a, i8* %a.addr, align 1
125   store i16 %b, i16* %b.addr, align 2
126   store i32 %c, i32* %c.addr, align 4
127   store i64 %d, i64* %d.addr, align 8
128   %tmp = load i8* %a.addr, align 1
129   %conv = sext i8 %tmp to i16
130   store i16 %conv, i16* %b.addr, align 2
131   %tmp1 = load i16* %b.addr, align 2
132   %conv2 = sext i16 %tmp1 to i32
133   store i32 %conv2, i32* %c.addr, align 4
134   %tmp3 = load i32* %c.addr, align 4
135   %conv4 = sext i32 %tmp3 to i64
136   store i64 %conv4, i64* %d.addr, align 8
137   %tmp5 = load i64* %d.addr, align 8
138   ret i64 %tmp5
139 }
140
141 ; Test sext i8 to i64
142 define i64 @sext_2(i8 signext %a) nounwind ssp {
143 entry:
144 ; CHECK: sext_2
145 ; CHECK: sxtb x0, w0
146   %conv = sext i8 %a to i64
147   ret i64 %conv
148 }
149
150 ; Test sext i1 to i32
151 define i32 @sext_i1_i32(i1 signext %a) nounwind ssp {
152 entry:
153 ; CHECK: sext_i1_i32
154 ; CHECK: sbfm w0, w0, #0, #0
155   %conv = sext i1 %a to i32
156   ret i32 %conv
157 }
158
159 ; Test sext i1 to i16
160 define signext i16 @sext_i1_i16(i1 %a) nounwind ssp {
161 entry:
162 ; CHECK: sext_i1_i16
163 ; CHECK: sbfm w0, w0, #0, #0
164   %conv = sext i1 %a to i16
165   ret i16 %conv
166 }
167
168 ; Test sext i1 to i8
169 define signext i8 @sext_i1_i8(i1 %a) nounwind ssp {
170 entry:
171 ; CHECK: sext_i1_i8
172 ; CHECK: sbfm w0, w0, #0, #0
173   %conv = sext i1 %a to i8
174   ret i8 %conv
175 }
176
177 ; Test fpext
178 define double @fpext_(float %a) nounwind ssp {
179 entry:
180 ; CHECK: fpext_
181 ; CHECK: fcvt d0, s0
182   %conv = fpext float %a to double
183   ret double %conv
184 }
185
186 ; Test fptrunc
187 define float @fptrunc_(double %a) nounwind ssp {
188 entry:
189 ; CHECK: fptrunc_
190 ; CHECK: fcvt s0, d0
191   %conv = fptrunc double %a to float
192   ret float %conv
193 }
194
195 ; Test fptosi
196 define i32 @fptosi_ws(float %a) nounwind ssp {
197 entry:
198 ; CHECK: fptosi_ws
199 ; CHECK: fcvtzs w0, s0
200   %conv = fptosi float %a to i32
201   ret i32 %conv
202 }
203
204 ; Test fptosi
205 define i32 @fptosi_wd(double %a) nounwind ssp {
206 entry:
207 ; CHECK: fptosi_wd
208 ; CHECK: fcvtzs w0, d0
209   %conv = fptosi double %a to i32
210   ret i32 %conv
211 }
212
213 ; Test fptoui
214 define i32 @fptoui_ws(float %a) nounwind ssp {
215 entry:
216 ; CHECK: fptoui_ws
217 ; CHECK: fcvtzu w0, s0
218   %conv = fptoui float %a to i32
219   ret i32 %conv
220 }
221
222 ; Test fptoui
223 define i32 @fptoui_wd(double %a) nounwind ssp {
224 entry:
225 ; CHECK: fptoui_wd
226 ; CHECK: fcvtzu w0, d0
227   %conv = fptoui double %a to i32
228   ret i32 %conv
229 }
230
231 ; Test sitofp
232 define float @sitofp_sw_i1(i1 %a) nounwind ssp {
233 entry:
234 ; CHECK: sitofp_sw_i1
235 ; CHECK: sbfm w0, w0, #0, #0
236 ; CHECK: scvtf s0, w0
237   %conv = sitofp i1 %a to float
238   ret float %conv
239 }
240
241 ; Test sitofp
242 define float @sitofp_sw_i8(i8 %a) nounwind ssp {
243 entry:
244 ; CHECK: sitofp_sw_i8
245 ; CHECK: sxtb w0, w0
246 ; CHECK: scvtf s0, w0
247   %conv = sitofp i8 %a to float
248   ret float %conv
249 }
250
251 ; Test sitofp
252 define float @sitofp_sw_i16(i16 %a) nounwind ssp {
253 entry:
254 ; CHECK: sitofp_sw_i16
255 ; CHECK: sxth w0, w0
256 ; CHECK: scvtf s0, w0
257   %conv = sitofp i16 %a to float
258   ret float %conv
259 }
260
261 ; Test sitofp
262 define float @sitofp_sw(i32 %a) nounwind ssp {
263 entry:
264 ; CHECK: sitofp_sw
265 ; CHECK: scvtf s0, w0
266   %conv = sitofp i32 %a to float
267   ret float %conv
268 }
269
270 ; Test sitofp
271 define float @sitofp_sx(i64 %a) nounwind ssp {
272 entry:
273 ; CHECK: sitofp_sx
274 ; CHECK: scvtf s0, x0
275   %conv = sitofp i64 %a to float
276   ret float %conv
277 }
278
279 ; Test sitofp
280 define double @sitofp_dw(i32 %a) nounwind ssp {
281 entry:
282 ; CHECK: sitofp_dw
283 ; CHECK: scvtf d0, w0
284   %conv = sitofp i32 %a to double
285   ret double %conv
286 }
287
288 ; Test sitofp
289 define double @sitofp_dx(i64 %a) nounwind ssp {
290 entry:
291 ; CHECK: sitofp_dx
292 ; CHECK: scvtf d0, x0
293   %conv = sitofp i64 %a to double
294   ret double %conv
295 }
296
297 ; Test uitofp
298 define float @uitofp_sw_i1(i1 %a) nounwind ssp {
299 entry:
300 ; CHECK: uitofp_sw_i1
301 ; CHECK: and w0, w0, #0x1
302 ; CHECK: ucvtf s0, w0
303   %conv = uitofp i1 %a to float
304   ret float %conv
305 }
306
307 ; Test uitofp
308 define float @uitofp_sw_i8(i8 %a) nounwind ssp {
309 entry:
310 ; CHECK: uitofp_sw_i8
311 ; CHECK: uxtb w0, w0
312 ; CHECK: ucvtf s0, w0
313   %conv = uitofp i8 %a to float
314   ret float %conv
315 }
316
317 ; Test uitofp
318 define float @uitofp_sw_i16(i16 %a) nounwind ssp {
319 entry:
320 ; CHECK: uitofp_sw_i16
321 ; CHECK: uxth w0, w0
322 ; CHECK: ucvtf s0, w0
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: 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: 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: 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: 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: 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: 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: 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: 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: 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* %b, align 8
413   %d = trunc i64 %c to i8
414   store i8 %d, i8* %a, align 1
415   ret void
416 }