xref: /llvm-project/llvm/test/CodeGen/AArch64/fptrunc.ll (revision 5a81a559d69fb84e1e8ef623ac4b642081c14c51)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3
2; RUN: llc -mtriple=aarch64 -global-isel=0 -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SD
3; RUN: llc -mtriple=aarch64 -global-isel=1 -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-GI
4; RUN: llc -mtriple=aarch64 -global-isel=1 -mattr=+fullfp16,+bf16 -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-GI
5
6define float @fptrunc_f64_f32(double %a) {
7; CHECK-LABEL: fptrunc_f64_f32:
8; CHECK:       // %bb.0: // %entry
9; CHECK-NEXT:    fcvt s0, d0
10; CHECK-NEXT:    ret
11entry:
12  %c = fptrunc double %a to float
13  ret float %c
14}
15
16define half @fptrunc_f64_f16(double %a) {
17; CHECK-LABEL: fptrunc_f64_f16:
18; CHECK:       // %bb.0: // %entry
19; CHECK-NEXT:    fcvt h0, d0
20; CHECK-NEXT:    ret
21entry:
22  %c = fptrunc double %a to half
23  ret half %c
24}
25
26define half @fptrunc_f32_f16(float %a) {
27; CHECK-LABEL: fptrunc_f32_f16:
28; CHECK:       // %bb.0: // %entry
29; CHECK-NEXT:    fcvt h0, s0
30; CHECK-NEXT:    ret
31entry:
32  %c = fptrunc float %a to half
33  ret half %c
34}
35
36
37define half @fptrunc_f128_f16(fp128 %a) {
38; CHECK-SD-LABEL: fptrunc_f128_f16:
39; CHECK-SD:       // %bb.0: // %entry
40; CHECK-SD-NEXT:    str x30, [sp, #-16]! // 8-byte Folded Spill
41; CHECK-SD-NEXT:    .cfi_def_cfa_offset 16
42; CHECK-SD-NEXT:    .cfi_offset w30, -16
43; CHECK-SD-NEXT:    bl __trunctfhf2
44; CHECK-SD-NEXT:    ldr x30, [sp], #16 // 8-byte Folded Reload
45; CHECK-SD-NEXT:    ret
46;
47; CHECK-GI-LABEL: fptrunc_f128_f16:
48; CHECK-GI:       // %bb.0: // %entry
49; CHECK-GI-NEXT:    b __trunctfhf2
50entry:
51  %c = fptrunc fp128 %a to half
52  ret half %c
53}
54
55define float @fptrunc_f128_f32(fp128 %a) {
56; CHECK-SD-LABEL: fptrunc_f128_f32:
57; CHECK-SD:       // %bb.0: // %entry
58; CHECK-SD-NEXT:    str x30, [sp, #-16]! // 8-byte Folded Spill
59; CHECK-SD-NEXT:    .cfi_def_cfa_offset 16
60; CHECK-SD-NEXT:    .cfi_offset w30, -16
61; CHECK-SD-NEXT:    bl __trunctfsf2
62; CHECK-SD-NEXT:    ldr x30, [sp], #16 // 8-byte Folded Reload
63; CHECK-SD-NEXT:    ret
64;
65; CHECK-GI-LABEL: fptrunc_f128_f32:
66; CHECK-GI:       // %bb.0: // %entry
67; CHECK-GI-NEXT:    b __trunctfsf2
68entry:
69  %c = fptrunc fp128 %a to float
70  ret float %c
71}
72
73define double @fptrunc_f128_f64(fp128 %a) {
74; CHECK-SD-LABEL: fptrunc_f128_f64:
75; CHECK-SD:       // %bb.0: // %entry
76; CHECK-SD-NEXT:    str x30, [sp, #-16]! // 8-byte Folded Spill
77; CHECK-SD-NEXT:    .cfi_def_cfa_offset 16
78; CHECK-SD-NEXT:    .cfi_offset w30, -16
79; CHECK-SD-NEXT:    bl __trunctfdf2
80; CHECK-SD-NEXT:    ldr x30, [sp], #16 // 8-byte Folded Reload
81; CHECK-SD-NEXT:    ret
82;
83; CHECK-GI-LABEL: fptrunc_f128_f64:
84; CHECK-GI:       // %bb.0: // %entry
85; CHECK-GI-NEXT:    b __trunctfdf2
86entry:
87  %c = fptrunc fp128 %a to double
88  ret double %c
89}
90
91define <2 x half> @fptrunc_v2f128_v2f16(<2 x fp128> %a) {
92; CHECK-SD-LABEL: fptrunc_v2f128_v2f16:
93; CHECK-SD:       // %bb.0: // %entry
94; CHECK-SD-NEXT:    sub sp, sp, #48
95; CHECK-SD-NEXT:    str x30, [sp, #32] // 8-byte Folded Spill
96; CHECK-SD-NEXT:    .cfi_def_cfa_offset 48
97; CHECK-SD-NEXT:    .cfi_offset w30, -16
98; CHECK-SD-NEXT:    str q0, [sp] // 16-byte Folded Spill
99; CHECK-SD-NEXT:    mov v0.16b, v1.16b
100; CHECK-SD-NEXT:    bl __trunctfhf2
101; CHECK-SD-NEXT:    // kill: def $h0 killed $h0 def $q0
102; CHECK-SD-NEXT:    str q0, [sp, #16] // 16-byte Folded Spill
103; CHECK-SD-NEXT:    ldr q0, [sp] // 16-byte Folded Reload
104; CHECK-SD-NEXT:    bl __trunctfhf2
105; CHECK-SD-NEXT:    ldr q1, [sp, #16] // 16-byte Folded Reload
106; CHECK-SD-NEXT:    // kill: def $h0 killed $h0 def $q0
107; CHECK-SD-NEXT:    ldr x30, [sp, #32] // 8-byte Folded Reload
108; CHECK-SD-NEXT:    mov v0.h[1], v1.h[0]
109; CHECK-SD-NEXT:    // kill: def $d0 killed $d0 killed $q0
110; CHECK-SD-NEXT:    add sp, sp, #48
111; CHECK-SD-NEXT:    ret
112;
113; CHECK-GI-LABEL: fptrunc_v2f128_v2f16:
114; CHECK-GI:       // %bb.0: // %entry
115; CHECK-GI-NEXT:    sub sp, sp, #64
116; CHECK-GI-NEXT:    str x30, [sp, #48] // 8-byte Folded Spill
117; CHECK-GI-NEXT:    .cfi_def_cfa_offset 64
118; CHECK-GI-NEXT:    .cfi_offset w30, -16
119; CHECK-GI-NEXT:    mov v2.d[0], x8
120; CHECK-GI-NEXT:    str q1, [sp] // 16-byte Folded Spill
121; CHECK-GI-NEXT:    mov v2.d[1], x8
122; CHECK-GI-NEXT:    str q2, [sp, #32] // 16-byte Folded Spill
123; CHECK-GI-NEXT:    bl __trunctfhf2
124; CHECK-GI-NEXT:    // kill: def $h0 killed $h0 def $q0
125; CHECK-GI-NEXT:    str q0, [sp, #16] // 16-byte Folded Spill
126; CHECK-GI-NEXT:    ldr q0, [sp] // 16-byte Folded Reload
127; CHECK-GI-NEXT:    bl __trunctfhf2
128; CHECK-GI-NEXT:    // kill: def $h0 killed $h0 def $q0
129; CHECK-GI-NEXT:    str q0, [sp] // 16-byte Folded Spill
130; CHECK-GI-NEXT:    ldr q0, [sp, #32] // 16-byte Folded Reload
131; CHECK-GI-NEXT:    bl __trunctfhf2
132; CHECK-GI-NEXT:    ldr q0, [sp, #32] // 16-byte Folded Reload
133; CHECK-GI-NEXT:    bl __trunctfhf2
134; CHECK-GI-NEXT:    ldp q1, q0, [sp] // 32-byte Folded Reload
135; CHECK-GI-NEXT:    ldr x30, [sp, #48] // 8-byte Folded Reload
136; CHECK-GI-NEXT:    mov v0.h[1], v1.h[0]
137; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 killed $q0
138; CHECK-GI-NEXT:    add sp, sp, #64
139; CHECK-GI-NEXT:    ret
140entry:
141  %c = fptrunc <2 x fp128> %a to <2 x half>
142  ret <2 x half> %c
143}
144
145
146define <2 x float> @fptrunc_v2f128_v2f32(<2 x fp128> %a) {
147; CHECK-SD-LABEL: fptrunc_v2f128_v2f32:
148; CHECK-SD:       // %bb.0: // %entry
149; CHECK-SD-NEXT:    sub sp, sp, #48
150; CHECK-SD-NEXT:    str x30, [sp, #32] // 8-byte Folded Spill
151; CHECK-SD-NEXT:    .cfi_def_cfa_offset 48
152; CHECK-SD-NEXT:    .cfi_offset w30, -16
153; CHECK-SD-NEXT:    str q0, [sp] // 16-byte Folded Spill
154; CHECK-SD-NEXT:    mov v0.16b, v1.16b
155; CHECK-SD-NEXT:    bl __trunctfsf2
156; CHECK-SD-NEXT:    // kill: def $s0 killed $s0 def $q0
157; CHECK-SD-NEXT:    str q0, [sp, #16] // 16-byte Folded Spill
158; CHECK-SD-NEXT:    ldr q0, [sp] // 16-byte Folded Reload
159; CHECK-SD-NEXT:    bl __trunctfsf2
160; CHECK-SD-NEXT:    ldr q1, [sp, #16] // 16-byte Folded Reload
161; CHECK-SD-NEXT:    // kill: def $s0 killed $s0 def $q0
162; CHECK-SD-NEXT:    ldr x30, [sp, #32] // 8-byte Folded Reload
163; CHECK-SD-NEXT:    mov v0.s[1], v1.s[0]
164; CHECK-SD-NEXT:    // kill: def $d0 killed $d0 killed $q0
165; CHECK-SD-NEXT:    add sp, sp, #48
166; CHECK-SD-NEXT:    ret
167;
168; CHECK-GI-LABEL: fptrunc_v2f128_v2f32:
169; CHECK-GI:       // %bb.0: // %entry
170; CHECK-GI-NEXT:    sub sp, sp, #48
171; CHECK-GI-NEXT:    str x30, [sp, #32] // 8-byte Folded Spill
172; CHECK-GI-NEXT:    .cfi_def_cfa_offset 48
173; CHECK-GI-NEXT:    .cfi_offset w30, -16
174; CHECK-GI-NEXT:    str q1, [sp] // 16-byte Folded Spill
175; CHECK-GI-NEXT:    bl __trunctfsf2
176; CHECK-GI-NEXT:    // kill: def $s0 killed $s0 def $q0
177; CHECK-GI-NEXT:    str q0, [sp, #16] // 16-byte Folded Spill
178; CHECK-GI-NEXT:    ldr q0, [sp] // 16-byte Folded Reload
179; CHECK-GI-NEXT:    bl __trunctfsf2
180; CHECK-GI-NEXT:    ldr q1, [sp, #16] // 16-byte Folded Reload
181; CHECK-GI-NEXT:    // kill: def $s0 killed $s0 def $q0
182; CHECK-GI-NEXT:    ldr x30, [sp, #32] // 8-byte Folded Reload
183; CHECK-GI-NEXT:    mov v1.s[1], v0.s[0]
184; CHECK-GI-NEXT:    fmov d0, d1
185; CHECK-GI-NEXT:    add sp, sp, #48
186; CHECK-GI-NEXT:    ret
187entry:
188  %c = fptrunc <2 x fp128> %a to <2 x float>
189  ret <2 x float> %c
190}
191
192
193define <2 x double> @fptrunc_v2f128_v2f64(<2 x fp128> %a) {
194; CHECK-SD-LABEL: fptrunc_v2f128_v2f64:
195; CHECK-SD:       // %bb.0: // %entry
196; CHECK-SD-NEXT:    sub sp, sp, #48
197; CHECK-SD-NEXT:    str x30, [sp, #32] // 8-byte Folded Spill
198; CHECK-SD-NEXT:    .cfi_def_cfa_offset 48
199; CHECK-SD-NEXT:    .cfi_offset w30, -16
200; CHECK-SD-NEXT:    str q0, [sp] // 16-byte Folded Spill
201; CHECK-SD-NEXT:    mov v0.16b, v1.16b
202; CHECK-SD-NEXT:    bl __trunctfdf2
203; CHECK-SD-NEXT:    // kill: def $d0 killed $d0 def $q0
204; CHECK-SD-NEXT:    str q0, [sp, #16] // 16-byte Folded Spill
205; CHECK-SD-NEXT:    ldr q0, [sp] // 16-byte Folded Reload
206; CHECK-SD-NEXT:    bl __trunctfdf2
207; CHECK-SD-NEXT:    ldr q1, [sp, #16] // 16-byte Folded Reload
208; CHECK-SD-NEXT:    // kill: def $d0 killed $d0 def $q0
209; CHECK-SD-NEXT:    ldr x30, [sp, #32] // 8-byte Folded Reload
210; CHECK-SD-NEXT:    mov v0.d[1], v1.d[0]
211; CHECK-SD-NEXT:    add sp, sp, #48
212; CHECK-SD-NEXT:    ret
213;
214; CHECK-GI-LABEL: fptrunc_v2f128_v2f64:
215; CHECK-GI:       // %bb.0: // %entry
216; CHECK-GI-NEXT:    sub sp, sp, #48
217; CHECK-GI-NEXT:    str x30, [sp, #32] // 8-byte Folded Spill
218; CHECK-GI-NEXT:    .cfi_def_cfa_offset 48
219; CHECK-GI-NEXT:    .cfi_offset w30, -16
220; CHECK-GI-NEXT:    str q1, [sp] // 16-byte Folded Spill
221; CHECK-GI-NEXT:    bl __trunctfdf2
222; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
223; CHECK-GI-NEXT:    str q0, [sp, #16] // 16-byte Folded Spill
224; CHECK-GI-NEXT:    ldr q0, [sp] // 16-byte Folded Reload
225; CHECK-GI-NEXT:    bl __trunctfdf2
226; CHECK-GI-NEXT:    ldr q1, [sp, #16] // 16-byte Folded Reload
227; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
228; CHECK-GI-NEXT:    ldr x30, [sp, #32] // 8-byte Folded Reload
229; CHECK-GI-NEXT:    mov v1.d[1], v0.d[0]
230; CHECK-GI-NEXT:    mov v0.16b, v1.16b
231; CHECK-GI-NEXT:    add sp, sp, #48
232; CHECK-GI-NEXT:    ret
233entry:
234  %c = fptrunc <2 x fp128> %a to <2 x double>
235  ret <2 x double> %c
236}
237
238define <2 x float> @fptrunc_v2f64_v2f32(<2 x double> %a) {
239; CHECK-LABEL: fptrunc_v2f64_v2f32:
240; CHECK:       // %bb.0: // %entry
241; CHECK-NEXT:    fcvtn v0.2s, v0.2d
242; CHECK-NEXT:    ret
243entry:
244  %c = fptrunc <2 x double> %a to <2 x float>
245  ret <2 x float> %c
246}
247
248define <3 x float> @fptrunc_v3f64_v3f32(<3 x double> %a) {
249; CHECK-SD-LABEL: fptrunc_v3f64_v3f32:
250; CHECK-SD:       // %bb.0: // %entry
251; CHECK-SD-NEXT:    // kill: def $d0 killed $d0 def $q0
252; CHECK-SD-NEXT:    // kill: def $d1 killed $d1 def $q1
253; CHECK-SD-NEXT:    // kill: def $d2 killed $d2 def $q2
254; CHECK-SD-NEXT:    mov v0.d[1], v1.d[0]
255; CHECK-SD-NEXT:    fcvtn v0.2s, v0.2d
256; CHECK-SD-NEXT:    fcvtn2 v0.4s, v2.2d
257; CHECK-SD-NEXT:    ret
258;
259; CHECK-GI-LABEL: fptrunc_v3f64_v3f32:
260; CHECK-GI:       // %bb.0: // %entry
261; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
262; CHECK-GI-NEXT:    // kill: def $d1 killed $d1 def $q1
263; CHECK-GI-NEXT:    fcvt s2, d2
264; CHECK-GI-NEXT:    mov v0.d[1], v1.d[0]
265; CHECK-GI-NEXT:    fcvtn v1.2s, v0.2d
266; CHECK-GI-NEXT:    mov v0.s[0], v1.s[0]
267; CHECK-GI-NEXT:    mov v0.s[1], v1.s[1]
268; CHECK-GI-NEXT:    mov v0.s[2], v2.s[0]
269; CHECK-GI-NEXT:    ret
270entry:
271  %c = fptrunc <3 x double> %a to <3 x float>
272  ret <3 x float> %c
273}
274
275define <4 x float> @fptrunc_v4f64_v4f32(<4 x double> %a) {
276; CHECK-LABEL: fptrunc_v4f64_v4f32:
277; CHECK:       // %bb.0: // %entry
278; CHECK-NEXT:    fcvtn v0.2s, v0.2d
279; CHECK-NEXT:    fcvtn2 v0.4s, v1.2d
280; CHECK-NEXT:    ret
281entry:
282  %c = fptrunc <4 x double> %a to <4 x float>
283  ret <4 x float> %c
284}
285
286define <2 x half> @fptrunc_v2f64_v2f16(<2 x double> %a) {
287; CHECK-SD-LABEL: fptrunc_v2f64_v2f16:
288; CHECK-SD:       // %bb.0: // %entry
289; CHECK-SD-NEXT:    fcvtxn v0.2s, v0.2d
290; CHECK-SD-NEXT:    fcvtn v0.4h, v0.4s
291; CHECK-SD-NEXT:    ret
292;
293; CHECK-GI-LABEL: fptrunc_v2f64_v2f16:
294; CHECK-GI:       // %bb.0: // %entry
295; CHECK-GI-NEXT:    mov d1, v0.d[1]
296; CHECK-GI-NEXT:    fcvt h0, d0
297; CHECK-GI-NEXT:    fcvt h1, d1
298; CHECK-GI-NEXT:    mov v0.h[1], v1.h[0]
299; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 killed $q0
300; CHECK-GI-NEXT:    ret
301entry:
302  %c = fptrunc <2 x double> %a to <2 x half>
303  ret <2 x half> %c
304}
305
306define <3 x half> @fptrunc_v3f64_v3f16(<3 x double> %a) {
307; CHECK-SD-LABEL: fptrunc_v3f64_v3f16:
308; CHECK-SD:       // %bb.0: // %entry
309; CHECK-SD-NEXT:    fcvt h1, d1
310; CHECK-SD-NEXT:    fcvt h0, d0
311; CHECK-SD-NEXT:    mov v0.h[1], v1.h[0]
312; CHECK-SD-NEXT:    fcvt h1, d2
313; CHECK-SD-NEXT:    mov v0.h[2], v1.h[0]
314; CHECK-SD-NEXT:    // kill: def $d0 killed $d0 killed $q0
315; CHECK-SD-NEXT:    ret
316;
317; CHECK-GI-LABEL: fptrunc_v3f64_v3f16:
318; CHECK-GI:       // %bb.0: // %entry
319; CHECK-GI-NEXT:    fcvt h0, d0
320; CHECK-GI-NEXT:    fcvt h1, d1
321; CHECK-GI-NEXT:    fcvt h2, d2
322; CHECK-GI-NEXT:    mov v0.h[1], v1.h[0]
323; CHECK-GI-NEXT:    mov v0.h[2], v2.h[0]
324; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 killed $q0
325; CHECK-GI-NEXT:    ret
326entry:
327  %c = fptrunc <3 x double> %a to <3 x half>
328  ret <3 x half> %c
329}
330
331define <4 x half> @fptrunc_v4f64_v4f16(<4 x double> %a) {
332; CHECK-SD-LABEL: fptrunc_v4f64_v4f16:
333; CHECK-SD:       // %bb.0: // %entry
334; CHECK-SD-NEXT:    fcvtxn v0.2s, v0.2d
335; CHECK-SD-NEXT:    fcvtxn2 v0.4s, v1.2d
336; CHECK-SD-NEXT:    fcvtn v0.4h, v0.4s
337; CHECK-SD-NEXT:    ret
338;
339; CHECK-GI-LABEL: fptrunc_v4f64_v4f16:
340; CHECK-GI:       // %bb.0: // %entry
341; CHECK-GI-NEXT:    mov d2, v0.d[1]
342; CHECK-GI-NEXT:    fcvt h0, d0
343; CHECK-GI-NEXT:    mov d3, v1.d[1]
344; CHECK-GI-NEXT:    fcvt h1, d1
345; CHECK-GI-NEXT:    fcvt h2, d2
346; CHECK-GI-NEXT:    mov v0.h[1], v2.h[0]
347; CHECK-GI-NEXT:    fcvt h2, d3
348; CHECK-GI-NEXT:    mov v0.h[2], v1.h[0]
349; CHECK-GI-NEXT:    mov v0.h[3], v2.h[0]
350; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 killed $q0
351; CHECK-GI-NEXT:    ret
352entry:
353  %c = fptrunc <4 x double> %a to <4 x half>
354  ret <4 x half> %c
355}
356
357define <2 x half> @fptrunc_v2f32_v2f16(<2 x float> %a) {
358; CHECK-SD-LABEL: fptrunc_v2f32_v2f16:
359; CHECK-SD:       // %bb.0: // %entry
360; CHECK-SD-NEXT:    // kill: def $d0 killed $d0 def $q0
361; CHECK-SD-NEXT:    fcvtn v0.4h, v0.4s
362; CHECK-SD-NEXT:    ret
363;
364; CHECK-GI-LABEL: fptrunc_v2f32_v2f16:
365; CHECK-GI:       // %bb.0: // %entry
366; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
367; CHECK-GI-NEXT:    mov v1.s[0], v0.s[0]
368; CHECK-GI-NEXT:    mov v1.s[1], v0.s[1]
369; CHECK-GI-NEXT:    fcvtn v0.4h, v1.4s
370; CHECK-GI-NEXT:    ret
371entry:
372  %c = fptrunc <2 x float> %a to <2 x half>
373  ret <2 x half> %c
374}
375
376define <3 x half> @fptrunc_v3f32_v3f16(<3 x float> %a) {
377; CHECK-LABEL: fptrunc_v3f32_v3f16:
378; CHECK:       // %bb.0: // %entry
379; CHECK-NEXT:    fcvtn v0.4h, v0.4s
380; CHECK-NEXT:    ret
381entry:
382  %c = fptrunc <3 x float> %a to <3 x half>
383  ret <3 x half> %c
384}
385
386define <4 x half> @fptrunc_v4f32_v4f16(<4 x float> %a) {
387; CHECK-LABEL: fptrunc_v4f32_v4f16:
388; CHECK:       // %bb.0: // %entry
389; CHECK-NEXT:    fcvtn v0.4h, v0.4s
390; CHECK-NEXT:    ret
391entry:
392  %c = fptrunc <4 x float> %a to <4 x half>
393  ret <4 x half> %c
394}
395
396define <8 x half> @fptrunc_v8f32_v8f16(<8 x float> %a) {
397; CHECK-LABEL: fptrunc_v8f32_v8f16:
398; CHECK:       // %bb.0: // %entry
399; CHECK-NEXT:    fcvtn v0.4h, v0.4s
400; CHECK-NEXT:    fcvtn2 v0.8h, v1.4s
401; CHECK-NEXT:    ret
402entry:
403  %c = fptrunc <8 x float> %a to <8 x half>
404  ret <8 x half> %c
405}
406