[InstCombine] Signed saturation patterns
[llvm-complete.git] / test / CodeGen / AArch64 / arm64-fast-isel-conversion.ll
blobed03aec07e7da8465ba4d142aaa833ecc75b064a
1 ; RUN: llc -O0 -fast-isel -fast-isel-abort=1 -verify-machineinstrs -mtriple=arm64-apple-darwin -mcpu=cyclone < %s | FileCheck %s
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 x8, [sp]
13 ; CHECK: ; kill: def $w8 killed $w8 killed $x8
14 ; CHECK: str w8, [sp, #8]
15 ; CHECK: ldr w8, [sp, #8]
16 ; CHECK: strh w8, [sp, #12]
17 ; CHECK: ldrh w8, [sp, #12]
18 ; CHECK: strb w8, [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
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 w8, [sp, #15]
53 ; CHECK: strh w8, [sp, #12]
54 ; CHECK: ldrh w8, [sp, #12]
55 ; CHECK: str w8, [sp, #8]
56 ; CHECK: ldr w8, [sp, #8]
57 ; CHECK: mov x9, x8
58 ; CHECK: str x9, [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
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;
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;
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 w8, [sp, #15]
109 ; CHECK: strh w8, [sp, #12]
110 ; CHECK: ldrsh w8, [sp, #12]
111 ; CHECK: str w8, [sp, #8]
112 ; CHECK: ldrsw x9, [sp, #8]
113 ; CHECK: str x9, [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
137 ; Test sext i8 to i64
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
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
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
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 w8, w0, #0, #1
170 ; CHECK-NEXT: sxth      w0, w8
171   %conv = sext i1 %a to i16
172   ret i16 %conv
175 ; Test sext i1 to i8
176 define signext i8 @sext_i1_i8(i1 %a) nounwind ssp {
177 entry:
178 ; CHECK-LABEL: sext_i1_i8
179 ; CHECK: sbfx w8, w0, #0, #1
180 ; CHECK-NEXT: sxtb w0, w8
181   %conv = sext i1 %a to i8
182   ret i8 %conv
185 ; Test fpext
186 define double @fpext_(float %a) nounwind ssp {
187 entry:
188 ; CHECK-LABEL: fpext_
189 ; CHECK: fcvt d0, s0
190   %conv = fpext float %a to double
191   ret double %conv
194 ; Test fptrunc
195 define float @fptrunc_(double %a) nounwind ssp {
196 entry:
197 ; CHECK-LABEL: fptrunc_
198 ; CHECK: fcvt s0, d0
199   %conv = fptrunc double %a to float
200   ret float %conv
203 ; Test fptosi
204 define i32 @fptosi_ws(float %a) nounwind ssp {
205 entry:
206 ; CHECK-LABEL: fptosi_ws
207 ; CHECK: fcvtzs w0, s0
208   %conv = fptosi float %a to i32
209   ret i32 %conv
212 ; Test fptosi
213 define i32 @fptosi_wd(double %a) nounwind ssp {
214 entry:
215 ; CHECK-LABEL: fptosi_wd
216 ; CHECK: fcvtzs w0, d0
217   %conv = fptosi double %a to i32
218   ret i32 %conv
221 ; Test fptoui
222 define i32 @fptoui_ws(float %a) nounwind ssp {
223 entry:
224 ; CHECK-LABEL: fptoui_ws
225 ; CHECK: fcvtzu w0, s0
226   %conv = fptoui float %a to i32
227   ret i32 %conv
230 ; Test fptoui
231 define i32 @fptoui_wd(double %a) nounwind ssp {
232 entry:
233 ; CHECK-LABEL: fptoui_wd
234 ; CHECK: fcvtzu w0, d0
235   %conv = fptoui double %a to i32
236   ret i32 %conv
239 ; Test sitofp
240 define float @sitofp_sw_i1(i1 %a) nounwind ssp {
241 entry:
242 ; CHECK-LABEL: sitofp_sw_i1
243 ; CHECK: sbfx w8, w0, #0, #1
244 ; CHECK: scvtf s0, w8
245   %conv = sitofp i1 %a to float
246   ret float %conv
249 ; Test sitofp
250 define float @sitofp_sw_i8(i8 %a) nounwind ssp {
251 entry:
252 ; CHECK-LABEL: sitofp_sw_i8
253 ; CHECK: sxtb w8, w0
254 ; CHECK: scvtf s0, w8
255   %conv = sitofp i8 %a to float
256   ret float %conv
259 ; Test sitofp
260 define float @sitofp_sw_i16(i16 %a) nounwind ssp {
261 entry:
262 ; CHECK-LABEL: sitofp_sw_i16
263   %conv = sitofp i16 %a to float
264   ret float %conv
267 ; Test sitofp
268 define float @sitofp_sw(i32 %a) nounwind ssp {
269 entry:
270 ; CHECK-LABEL: sitofp_sw
271 ; CHECK: scvtf s0, w0
272   %conv = sitofp i32 %a to float
273   ret float %conv
276 ; Test sitofp
277 define float @sitofp_sx(i64 %a) nounwind ssp {
278 entry:
279 ; CHECK-LABEL: sitofp_sx
280 ; CHECK: scvtf s0, x0
281   %conv = sitofp i64 %a to float
282   ret float %conv
285 ; Test sitofp
286 define double @sitofp_dw(i32 %a) nounwind ssp {
287 entry:
288 ; CHECK-LABEL: sitofp_dw
289 ; CHECK: scvtf d0, w0
290   %conv = sitofp i32 %a to double
291   ret double %conv
294 ; Test sitofp
295 define double @sitofp_dx(i64 %a) nounwind ssp {
296 entry:
297 ; CHECK-LABEL: sitofp_dx
298 ; CHECK: scvtf d0, x0
299   %conv = sitofp i64 %a to double
300   ret double %conv
303 ; Test uitofp
304 define float @uitofp_sw_i1(i1 %a) nounwind ssp {
305 entry:
306 ; CHECK-LABEL: uitofp_sw_i1
307 ; CHECK: and w8, w0, #0x1
308 ; CHECK: ucvtf s0, w8
309   %conv = uitofp i1 %a to float
310   ret float %conv
313 ; Test uitofp
314 define float @uitofp_sw_i8(i8 %a) nounwind ssp {
315 entry:
316 ; CHECK-LABEL: uitofp_sw_i8
317   %conv = uitofp i8 %a to float
318   ret float %conv
321 ; Test uitofp
322 define float @uitofp_sw_i16(i16 %a) nounwind ssp {
323 entry:
324 ; CHECK-LABEL: uitofp_sw_i16
325   %conv = uitofp i16 %a to float
326   ret float %conv
329 ; Test uitofp
330 define float @uitofp_sw(i32 %a) nounwind ssp {
331 entry:
332 ; CHECK-LABEL: uitofp_sw
333 ; CHECK: ucvtf s0, w0
334   %conv = uitofp i32 %a to float
335   ret float %conv
338 ; Test uitofp
339 define float @uitofp_sx(i64 %a) nounwind ssp {
340 entry:
341 ; CHECK-LABEL: uitofp_sx
342 ; CHECK: ucvtf s0, x0
343   %conv = uitofp i64 %a to float
344   ret float %conv
347 ; Test uitofp
348 define double @uitofp_dw(i32 %a) nounwind ssp {
349 entry:
350 ; CHECK-LABEL: uitofp_dw
351 ; CHECK: ucvtf d0, w0
352   %conv = uitofp i32 %a to double
353   ret double %conv
356 ; Test uitofp
357 define double @uitofp_dx(i64 %a) nounwind ssp {
358 entry:
359 ; CHECK-LABEL: uitofp_dx
360 ; CHECK: ucvtf d0, x0
361   %conv = uitofp i64 %a to double
362   ret double %conv
365 define i32 @i64_trunc_i32(i64 %a) nounwind ssp {
366 entry:
367 ; CHECK-LABEL: i64_trunc_i32
368 ; CHECK-NOT: mov
369 ; CHECK: ret
370   %conv = trunc i64 %a to i32
371   ret i32 %conv
374 define zeroext i16 @i64_trunc_i16(i64 %a) nounwind ssp {
375 entry:
376 ; CHECK-LABEL: i64_trunc_i16
377 ; CHECK: and [[REG2:w[0-9]+]], w0, #0xffff
378 ; CHECK: uxth w0, [[REG2]]
379   %conv = trunc i64 %a to i16
380   ret i16 %conv
383 define zeroext i8 @i64_trunc_i8(i64 %a) nounwind ssp {
384 entry:
385 ; CHECK-LABEL: i64_trunc_i8
386 ; CHECK: and [[REG2:w[0-9]+]], w0, #0xff
387 ; CHECK: uxtb w0, [[REG2]]
388   %conv = trunc i64 %a to i8
389   ret i8 %conv
392 define zeroext i1 @i64_trunc_i1(i64 %a) nounwind ssp {
393 entry:
394 ; CHECK-LABEL: i64_trunc_i1
395 ; CHECK: and [[REG2:w[0-9]+]], w0, #0x1
396 ; CHECK: and w0, [[REG2]], #0x1
397   %conv = trunc i64 %a to i1
398   ret i1 %conv
401 ; rdar://15101939
402 define void @stack_trunc() nounwind {
403 ; CHECK-LABEL: stack_trunc
404 ; CHECK: sub  sp, sp, #16
405 ; CHECK: ldr  x[[REG:[0-9]+]], [sp]
406 ; CHECK: and  [[REG3:w[0-9]+]], w[[REG]], #0xff
407 ; CHECK: strb [[REG3]], [sp, #15]
408 ; CHECK: add  sp, sp, #16
409   %a = alloca i8, align 1
410   %b = alloca i64, align 8
411   %c = load i64, i64* %b, align 8
412   %d = trunc i64 %c to i8
413   store i8 %d, i8* %a, align 1
414   ret void
417 define zeroext i64 @zext_i8_i64(i8 zeroext %in) {
418 ; CHECK-LABEL: zext_i8_i64:
419 ; CHECK-NOT:   ubfx x0, {{x[0-9]+}}, #0, #8
420 ; CHECK:       ret
421   %big = zext i8 %in to i64
422   ret i64 %big
424 define zeroext i64 @zext_i16_i64(i16 zeroext %in) {
425 ; CHECK-LABEL: zext_i16_i64:
426 ; CHECK-NOT:   ubfx x0, {{x[0-9]+}}, #0, #16
427 ; CHECK:       ret
428   %big = zext i16 %in to i64
429   ret i64 %big
432 define float @bitcast_i32_to_float(i32 %a) {
433   %1 = bitcast i32 %a to float
434   ret float %1
437 define double @bitcast_i64_to_double(i64 %a) {
438   %1 = bitcast i64 %a to double
439   ret double %1
442 define i32 @bitcast_float_to_i32(float %a) {
443   %1 = bitcast float %a to i32
444   ret i32 %1
447 define i64 @bitcast_double_to_i64(double %a) {
448   %1 = bitcast double %a to i64
449   ret i64 %1