1 ; RUN: llc < %s -O0 -fast-isel-abort -mtriple=arm64-apple-darwin | FileCheck %s
3 ;; Test various conversions.
4 define zeroext i32 @trunc_(i8 zeroext %a, i16 zeroext %b, i32 %c, i64 %d) nounwind ssp {
7 ; CHECK: sub sp, sp, #16
8 ; CHECK: strb w0, [sp, #15]
9 ; CHECK: strh w1, [sp, #12]
10 ; CHECK: str w2, [sp, #8]
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]
21 ; CHECK: add sp, sp, #16
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
45 define i64 @zext_(i8 zeroext %a, i16 zeroext %b, i32 %c, i64 %d) nounwind ssp {
48 ; CHECK: sub sp, sp, #16
49 ; CHECK: strb w0, [sp, #15]
50 ; CHECK: strh w1, [sp, #12]
51 ; CHECK: str w2, [sp, #8]
53 ; CHECK: ldrb w0, [sp, #15]
55 ; CHECK: strh w0, [sp, #12]
56 ; CHECK: ldrh w0, [sp, #12]
58 ; CHECK: str w0, [sp, #8]
59 ; CHECK: ldr w0, [sp, #8]
62 ; CHECK: ldr x0, [sp], #16
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
85 define i32 @zext_i1_i32(i1 zeroext %a) nounwind ssp {
88 ; CHECK: and w0, w0, #0x1
89 %conv = zext i1 %a to i32
93 define i64 @zext_i1_i64(i1 zeroext %a) nounwind ssp {
96 ; CHECK: and w0, w0, #0x1
97 %conv = zext i1 %a to i64
101 define i64 @sext_(i8 signext %a, i16 signext %b, i32 %c, i64 %d) nounwind ssp {
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]
111 ; CHECK: strh w0, [sp, #12]
112 ; CHECK: ldrh w0, [sp, #12]
114 ; CHECK: str w0, [sp, #8]
115 ; CHECK: ldr w0, [sp, #8]
117 ; CHECK: str x3, [sp]
118 ; CHECK: ldr x0, [sp], #16
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
141 ; Test sext i8 to i64
142 define i64 @sext_2(i8 signext %a) nounwind ssp {
146 %conv = sext i8 %a to i64
150 ; Test sext i1 to i32
151 define i32 @sext_i1_i32(i1 signext %a) nounwind ssp {
154 ; CHECK: sbfm w0, w0, #0, #0
155 %conv = sext i1 %a to i32
159 ; Test sext i1 to i16
160 define signext i16 @sext_i1_i16(i1 %a) nounwind ssp {
163 ; CHECK: sbfm w0, w0, #0, #0
164 %conv = sext i1 %a to i16
169 define signext i8 @sext_i1_i8(i1 %a) nounwind ssp {
172 ; CHECK: sbfm w0, w0, #0, #0
173 %conv = sext i1 %a to i8
178 define double @fpext_(float %a) nounwind ssp {
182 %conv = fpext float %a to double
187 define float @fptrunc_(double %a) nounwind ssp {
191 %conv = fptrunc double %a to float
196 define i32 @fptosi_ws(float %a) nounwind ssp {
199 ; CHECK: fcvtzs w0, s0
200 %conv = fptosi float %a to i32
205 define i32 @fptosi_wd(double %a) nounwind ssp {
208 ; CHECK: fcvtzs w0, d0
209 %conv = fptosi double %a to i32
214 define i32 @fptoui_ws(float %a) nounwind ssp {
217 ; CHECK: fcvtzu w0, s0
218 %conv = fptoui float %a to i32
223 define i32 @fptoui_wd(double %a) nounwind ssp {
226 ; CHECK: fcvtzu w0, d0
227 %conv = fptoui double %a to i32
232 define float @sitofp_sw_i1(i1 %a) nounwind ssp {
234 ; CHECK: sitofp_sw_i1
235 ; CHECK: sbfm w0, w0, #0, #0
236 ; CHECK: scvtf s0, w0
237 %conv = sitofp i1 %a to float
242 define float @sitofp_sw_i8(i8 %a) nounwind ssp {
244 ; CHECK: sitofp_sw_i8
246 ; CHECK: scvtf s0, w0
247 %conv = sitofp i8 %a to float
252 define float @sitofp_sw_i16(i16 %a) nounwind ssp {
254 ; CHECK: sitofp_sw_i16
256 ; CHECK: scvtf s0, w0
257 %conv = sitofp i16 %a to float
262 define float @sitofp_sw(i32 %a) nounwind ssp {
265 ; CHECK: scvtf s0, w0
266 %conv = sitofp i32 %a to float
271 define float @sitofp_sx(i64 %a) nounwind ssp {
274 ; CHECK: scvtf s0, x0
275 %conv = sitofp i64 %a to float
280 define double @sitofp_dw(i32 %a) nounwind ssp {
283 ; CHECK: scvtf d0, w0
284 %conv = sitofp i32 %a to double
289 define double @sitofp_dx(i64 %a) nounwind ssp {
292 ; CHECK: scvtf d0, x0
293 %conv = sitofp i64 %a to double
298 define float @uitofp_sw_i1(i1 %a) nounwind ssp {
300 ; CHECK: uitofp_sw_i1
301 ; CHECK: and w0, w0, #0x1
302 ; CHECK: ucvtf s0, w0
303 %conv = uitofp i1 %a to float
308 define float @uitofp_sw_i8(i8 %a) nounwind ssp {
310 ; CHECK: uitofp_sw_i8
312 ; CHECK: ucvtf s0, w0
313 %conv = uitofp i8 %a to float
318 define float @uitofp_sw_i16(i16 %a) nounwind ssp {
320 ; CHECK: uitofp_sw_i16
322 ; CHECK: ucvtf s0, w0
323 %conv = uitofp i16 %a to float
328 define float @uitofp_sw(i32 %a) nounwind ssp {
331 ; CHECK: ucvtf s0, w0
332 %conv = uitofp i32 %a to float
337 define float @uitofp_sx(i64 %a) nounwind ssp {
340 ; CHECK: ucvtf s0, x0
341 %conv = uitofp i64 %a to float
346 define double @uitofp_dw(i32 %a) nounwind ssp {
349 ; CHECK: ucvtf d0, w0
350 %conv = uitofp i32 %a to double
355 define double @uitofp_dx(i64 %a) nounwind ssp {
358 ; CHECK: ucvtf d0, x0
359 %conv = uitofp i64 %a to double
363 define i32 @i64_trunc_i32(i64 %a) nounwind ssp {
365 ; CHECK: i64_trunc_i32
367 %conv = trunc i64 %a to i32
371 define zeroext i16 @i64_trunc_i16(i64 %a) nounwind ssp {
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
381 define zeroext i8 @i64_trunc_i8(i64 %a) nounwind ssp {
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
391 define zeroext i1 @i64_trunc_i1(i64 %a) nounwind ssp {
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
402 define void @stack_trunc() nounwind {
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