1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s -mtriple=aarch64 | FileCheck %s --check-prefixes=CHECK,CHECK-CVT
3 ; RUN: llc < %s -mtriple=aarch64 -mattr=+fullfp16 | FileCheck %s --check-prefixes=CHECK,CHECK-FP16
5 ; Round towards minus infinity (fcvtms).
7 define i32 @testmswbf(bfloat %a) {
8 ; CHECK-LABEL: testmswbf:
9 ; CHECK: // %bb.0: // %entry
10 ; CHECK-NEXT: // kill: def $h0 killed $h0 def $s0
11 ; CHECK-NEXT: fmov w9, s0
12 ; CHECK-NEXT: mov w8, #32767 // =0x7fff
13 ; CHECK-NEXT: lsl w9, w9, #16
14 ; CHECK-NEXT: fmov s0, w9
15 ; CHECK-NEXT: frintm s0, s0
16 ; CHECK-NEXT: fmov w9, s0
17 ; CHECK-NEXT: ubfx w10, w9, #16, #1
18 ; CHECK-NEXT: add w8, w9, w8
19 ; CHECK-NEXT: add w8, w10, w8
20 ; CHECK-NEXT: lsr w8, w8, #16
21 ; CHECK-NEXT: lsl w8, w8, #16
22 ; CHECK-NEXT: fmov s0, w8
23 ; CHECK-NEXT: fcvtzs w0, s0
26 %r = call bfloat @llvm.floor.bf16(bfloat %a) nounwind readnone
27 %i = call i32 @llvm.fptosi.sat.i32.bf16(bfloat %r)
31 define i64 @testmsxbf(bfloat %a) {
32 ; CHECK-LABEL: testmsxbf:
33 ; CHECK: // %bb.0: // %entry
34 ; CHECK-NEXT: // kill: def $h0 killed $h0 def $s0
35 ; CHECK-NEXT: fmov w9, s0
36 ; CHECK-NEXT: mov w8, #32767 // =0x7fff
37 ; CHECK-NEXT: lsl w9, w9, #16
38 ; CHECK-NEXT: fmov s0, w9
39 ; CHECK-NEXT: frintm s0, s0
40 ; CHECK-NEXT: fmov w9, s0
41 ; CHECK-NEXT: ubfx w10, w9, #16, #1
42 ; CHECK-NEXT: add w8, w9, w8
43 ; CHECK-NEXT: add w8, w10, w8
44 ; CHECK-NEXT: lsr w8, w8, #16
45 ; CHECK-NEXT: lsl w8, w8, #16
46 ; CHECK-NEXT: fmov s0, w8
47 ; CHECK-NEXT: fcvtzs x0, s0
50 %r = call bfloat @llvm.floor.bf16(bfloat %a) nounwind readnone
51 %i = call i64 @llvm.fptosi.sat.i64.bf16(bfloat %r)
55 define i32 @testmswh(half %a) {
56 ; CHECK-CVT-LABEL: testmswh:
57 ; CHECK-CVT: // %bb.0: // %entry
58 ; CHECK-CVT-NEXT: fcvt s0, h0
59 ; CHECK-CVT-NEXT: frintm s0, s0
60 ; CHECK-CVT-NEXT: fcvt h0, s0
61 ; CHECK-CVT-NEXT: fcvt s0, h0
62 ; CHECK-CVT-NEXT: fcvtzs w0, s0
65 ; CHECK-FP16-LABEL: testmswh:
66 ; CHECK-FP16: // %bb.0: // %entry
67 ; CHECK-FP16-NEXT: fcvtms w0, h0
68 ; CHECK-FP16-NEXT: ret
70 %r = call half @llvm.floor.f16(half %a) nounwind readnone
71 %i = call i32 @llvm.fptosi.sat.i32.f16(half %r)
75 define i64 @testmsxh(half %a) {
76 ; CHECK-CVT-LABEL: testmsxh:
77 ; CHECK-CVT: // %bb.0: // %entry
78 ; CHECK-CVT-NEXT: fcvt s0, h0
79 ; CHECK-CVT-NEXT: frintm s0, s0
80 ; CHECK-CVT-NEXT: fcvt h0, s0
81 ; CHECK-CVT-NEXT: fcvt s0, h0
82 ; CHECK-CVT-NEXT: fcvtzs x0, s0
85 ; CHECK-FP16-LABEL: testmsxh:
86 ; CHECK-FP16: // %bb.0: // %entry
87 ; CHECK-FP16-NEXT: fcvtms x0, h0
88 ; CHECK-FP16-NEXT: ret
90 %r = call half @llvm.floor.f16(half %a) nounwind readnone
91 %i = call i64 @llvm.fptosi.sat.i64.f16(half %r)
95 define i32 @testmsws(float %a) {
96 ; CHECK-LABEL: testmsws:
97 ; CHECK: // %bb.0: // %entry
98 ; CHECK-NEXT: fcvtms w0, s0
101 %r = call float @floorf(float %a) nounwind readnone
102 %i = call i32 @llvm.fptosi.sat.i32.f32(float %r)
106 define i64 @testmsxs(float %a) {
107 ; CHECK-LABEL: testmsxs:
108 ; CHECK: // %bb.0: // %entry
109 ; CHECK-NEXT: fcvtms x0, s0
112 %r = call float @floorf(float %a) nounwind readnone
113 %i = call i64 @llvm.fptosi.sat.i64.f32(float %r)
117 define i32 @testmswd(double %a) {
118 ; CHECK-LABEL: testmswd:
119 ; CHECK: // %bb.0: // %entry
120 ; CHECK-NEXT: fcvtms w0, d0
123 %r = call double @floor(double %a) nounwind readnone
124 %i = call i32 @llvm.fptosi.sat.i32.f64(double %r)
128 define i64 @testmsxd(double %a) {
129 ; CHECK-LABEL: testmsxd:
130 ; CHECK: // %bb.0: // %entry
131 ; CHECK-NEXT: fcvtms x0, d0
134 %r = call double @floor(double %a) nounwind readnone
135 %i = call i64 @llvm.fptosi.sat.i64.f64(double %r)
139 ; Round towards plus infinity (fcvtps).
141 define i32 @testpswbf(bfloat %a) {
142 ; CHECK-LABEL: testpswbf:
143 ; CHECK: // %bb.0: // %entry
144 ; CHECK-NEXT: // kill: def $h0 killed $h0 def $s0
145 ; CHECK-NEXT: fmov w9, s0
146 ; CHECK-NEXT: mov w8, #32767 // =0x7fff
147 ; CHECK-NEXT: lsl w9, w9, #16
148 ; CHECK-NEXT: fmov s0, w9
149 ; CHECK-NEXT: frintp s0, s0
150 ; CHECK-NEXT: fmov w9, s0
151 ; CHECK-NEXT: ubfx w10, w9, #16, #1
152 ; CHECK-NEXT: add w8, w9, w8
153 ; CHECK-NEXT: add w8, w10, w8
154 ; CHECK-NEXT: lsr w8, w8, #16
155 ; CHECK-NEXT: lsl w8, w8, #16
156 ; CHECK-NEXT: fmov s0, w8
157 ; CHECK-NEXT: fcvtzs w0, s0
160 %r = call bfloat @llvm.ceil.bf16(bfloat %a) nounwind readnone
161 %i = call i32 @llvm.fptosi.sat.i32.bf16(bfloat %r)
165 define i64 @testpsxbf(bfloat %a) {
166 ; CHECK-LABEL: testpsxbf:
167 ; CHECK: // %bb.0: // %entry
168 ; CHECK-NEXT: // kill: def $h0 killed $h0 def $s0
169 ; CHECK-NEXT: fmov w9, s0
170 ; CHECK-NEXT: mov w8, #32767 // =0x7fff
171 ; CHECK-NEXT: lsl w9, w9, #16
172 ; CHECK-NEXT: fmov s0, w9
173 ; CHECK-NEXT: frintp s0, s0
174 ; CHECK-NEXT: fmov w9, s0
175 ; CHECK-NEXT: ubfx w10, w9, #16, #1
176 ; CHECK-NEXT: add w8, w9, w8
177 ; CHECK-NEXT: add w8, w10, w8
178 ; CHECK-NEXT: lsr w8, w8, #16
179 ; CHECK-NEXT: lsl w8, w8, #16
180 ; CHECK-NEXT: fmov s0, w8
181 ; CHECK-NEXT: fcvtzs x0, s0
184 %r = call bfloat @llvm.ceil.bf16(bfloat %a) nounwind readnone
185 %i = call i64 @llvm.fptosi.sat.i64.bf16(bfloat %r)
189 define i32 @testpswh(half %a) {
190 ; CHECK-CVT-LABEL: testpswh:
191 ; CHECK-CVT: // %bb.0: // %entry
192 ; CHECK-CVT-NEXT: fcvt s0, h0
193 ; CHECK-CVT-NEXT: frintp s0, s0
194 ; CHECK-CVT-NEXT: fcvt h0, s0
195 ; CHECK-CVT-NEXT: fcvt s0, h0
196 ; CHECK-CVT-NEXT: fcvtzs w0, s0
197 ; CHECK-CVT-NEXT: ret
199 ; CHECK-FP16-LABEL: testpswh:
200 ; CHECK-FP16: // %bb.0: // %entry
201 ; CHECK-FP16-NEXT: fcvtps w0, h0
202 ; CHECK-FP16-NEXT: ret
204 %r = call half @llvm.ceil.f16(half %a) nounwind readnone
205 %i = call i32 @llvm.fptosi.sat.i32.f16(half %r)
209 define i64 @testpsxh(half %a) {
210 ; CHECK-CVT-LABEL: testpsxh:
211 ; CHECK-CVT: // %bb.0: // %entry
212 ; CHECK-CVT-NEXT: fcvt s0, h0
213 ; CHECK-CVT-NEXT: frintp s0, s0
214 ; CHECK-CVT-NEXT: fcvt h0, s0
215 ; CHECK-CVT-NEXT: fcvt s0, h0
216 ; CHECK-CVT-NEXT: fcvtzs x0, s0
217 ; CHECK-CVT-NEXT: ret
219 ; CHECK-FP16-LABEL: testpsxh:
220 ; CHECK-FP16: // %bb.0: // %entry
221 ; CHECK-FP16-NEXT: fcvtps x0, h0
222 ; CHECK-FP16-NEXT: ret
224 %r = call half @llvm.ceil.f16(half %a) nounwind readnone
225 %i = call i64 @llvm.fptosi.sat.i64.f16(half %r)
229 define i32 @testpsws(float %a) {
230 ; CHECK-LABEL: testpsws:
231 ; CHECK: // %bb.0: // %entry
232 ; CHECK-NEXT: fcvtps w0, s0
235 %r = call float @ceilf(float %a) nounwind readnone
236 %i = call i32 @llvm.fptosi.sat.i32.f32(float %r)
240 define i64 @testpsxs(float %a) {
241 ; CHECK-LABEL: testpsxs:
242 ; CHECK: // %bb.0: // %entry
243 ; CHECK-NEXT: fcvtps x0, s0
246 %r = call float @ceilf(float %a) nounwind readnone
247 %i = call i64 @llvm.fptosi.sat.i64.f32(float %r)
251 define i32 @testpswd(double %a) {
252 ; CHECK-LABEL: testpswd:
253 ; CHECK: // %bb.0: // %entry
254 ; CHECK-NEXT: fcvtps w0, d0
257 %r = call double @ceil(double %a) nounwind readnone
258 %i = call i32 @llvm.fptosi.sat.i32.f64(double %r)
262 define i64 @testpsxd(double %a) {
263 ; CHECK-LABEL: testpsxd:
264 ; CHECK: // %bb.0: // %entry
265 ; CHECK-NEXT: fcvtps x0, d0
268 %r = call double @ceil(double %a) nounwind readnone
269 %i = call i64 @llvm.fptosi.sat.i64.f64(double %r)
273 ; Round towards zero (fcvtzs).
275 define i32 @testzswh(half %a) {
276 ; CHECK-CVT-LABEL: testzswh:
277 ; CHECK-CVT: // %bb.0: // %entry
278 ; CHECK-CVT-NEXT: fcvt s0, h0
279 ; CHECK-CVT-NEXT: frintz s0, s0
280 ; CHECK-CVT-NEXT: fcvt h0, s0
281 ; CHECK-CVT-NEXT: fcvt s0, h0
282 ; CHECK-CVT-NEXT: fcvtzs w0, s0
283 ; CHECK-CVT-NEXT: ret
285 ; CHECK-FP16-LABEL: testzswh:
286 ; CHECK-FP16: // %bb.0: // %entry
287 ; CHECK-FP16-NEXT: fcvtzs w0, h0
288 ; CHECK-FP16-NEXT: ret
290 %r = call half @llvm.trunc.f16(half %a) nounwind readnone
291 %i = call i32 @llvm.fptosi.sat.i32.f16(half %r)
295 define i64 @testzsxh(half %a) {
296 ; CHECK-CVT-LABEL: testzsxh:
297 ; CHECK-CVT: // %bb.0: // %entry
298 ; CHECK-CVT-NEXT: fcvt s0, h0
299 ; CHECK-CVT-NEXT: frintz s0, s0
300 ; CHECK-CVT-NEXT: fcvt h0, s0
301 ; CHECK-CVT-NEXT: fcvt s0, h0
302 ; CHECK-CVT-NEXT: fcvtzs x0, s0
303 ; CHECK-CVT-NEXT: ret
305 ; CHECK-FP16-LABEL: testzsxh:
306 ; CHECK-FP16: // %bb.0: // %entry
307 ; CHECK-FP16-NEXT: fcvtzs x0, h0
308 ; CHECK-FP16-NEXT: ret
310 %r = call half @llvm.trunc.f16(half %a) nounwind readnone
311 %i = call i64 @llvm.fptosi.sat.i64.f16(half %r)
315 define i32 @testzsws(float %a) {
316 ; CHECK-LABEL: testzsws:
317 ; CHECK: // %bb.0: // %entry
318 ; CHECK-NEXT: fcvtzs w0, s0
321 %r = call float @truncf(float %a) nounwind readnone
322 %i = call i32 @llvm.fptosi.sat.i32.f32(float %r)
326 define i64 @testzsxs(float %a) {
327 ; CHECK-LABEL: testzsxs:
328 ; CHECK: // %bb.0: // %entry
329 ; CHECK-NEXT: fcvtzs x0, s0
332 %r = call float @truncf(float %a) nounwind readnone
333 %i = call i64 @llvm.fptosi.sat.i64.f32(float %r)
337 define i32 @testzswd(double %a) {
338 ; CHECK-LABEL: testzswd:
339 ; CHECK: // %bb.0: // %entry
340 ; CHECK-NEXT: fcvtzs w0, d0
343 %r = call double @trunc(double %a) nounwind readnone
344 %i = call i32 @llvm.fptosi.sat.i32.f64(double %r)
348 define i64 @testzsxd(double %a) {
349 ; CHECK-LABEL: testzsxd:
350 ; CHECK: // %bb.0: // %entry
351 ; CHECK-NEXT: fcvtzs x0, d0
354 %r = call double @trunc(double %a) nounwind readnone
355 %i = call i64 @llvm.fptosi.sat.i64.f64(double %r)
359 ; Round to nearest, ties away from zero (fcvtas).
361 define i32 @testaswh(half %a) {
362 ; CHECK-CVT-LABEL: testaswh:
363 ; CHECK-CVT: // %bb.0: // %entry
364 ; CHECK-CVT-NEXT: fcvt s0, h0
365 ; CHECK-CVT-NEXT: frinta s0, s0
366 ; CHECK-CVT-NEXT: fcvt h0, s0
367 ; CHECK-CVT-NEXT: fcvt s0, h0
368 ; CHECK-CVT-NEXT: fcvtzs w0, s0
369 ; CHECK-CVT-NEXT: ret
371 ; CHECK-FP16-LABEL: testaswh:
372 ; CHECK-FP16: // %bb.0: // %entry
373 ; CHECK-FP16-NEXT: fcvtas w0, h0
374 ; CHECK-FP16-NEXT: ret
376 %r = call half @llvm.round.f16(half %a) nounwind readnone
377 %i = call i32 @llvm.fptosi.sat.i32.f16(half %r)
381 define i64 @testasxh(half %a) {
382 ; CHECK-CVT-LABEL: testasxh:
383 ; CHECK-CVT: // %bb.0: // %entry
384 ; CHECK-CVT-NEXT: fcvt s0, h0
385 ; CHECK-CVT-NEXT: frinta s0, s0
386 ; CHECK-CVT-NEXT: fcvt h0, s0
387 ; CHECK-CVT-NEXT: fcvt s0, h0
388 ; CHECK-CVT-NEXT: fcvtzs x0, s0
389 ; CHECK-CVT-NEXT: ret
391 ; CHECK-FP16-LABEL: testasxh:
392 ; CHECK-FP16: // %bb.0: // %entry
393 ; CHECK-FP16-NEXT: fcvtas x0, h0
394 ; CHECK-FP16-NEXT: ret
396 %r = call half @llvm.round.f16(half %a) nounwind readnone
397 %i = call i64 @llvm.fptosi.sat.i64.f16(half %r)
401 define i32 @testasws(float %a) {
402 ; CHECK-LABEL: testasws:
403 ; CHECK: // %bb.0: // %entry
404 ; CHECK-NEXT: fcvtas w0, s0
407 %r = call float @roundf(float %a) nounwind readnone
408 %i = call i32 @llvm.fptosi.sat.i32.f32(float %r)
412 define i64 @testasxs(float %a) {
413 ; CHECK-LABEL: testasxs:
414 ; CHECK: // %bb.0: // %entry
415 ; CHECK-NEXT: fcvtas x0, s0
418 %r = call float @roundf(float %a) nounwind readnone
419 %i = call i64 @llvm.fptosi.sat.i64.f32(float %r)
423 define i32 @testaswd(double %a) {
424 ; CHECK-LABEL: testaswd:
425 ; CHECK: // %bb.0: // %entry
426 ; CHECK-NEXT: fcvtas w0, d0
429 %r = call double @round(double %a) nounwind readnone
430 %i = call i32 @llvm.fptosi.sat.i32.f64(double %r)
434 define i64 @testasxd(double %a) {
435 ; CHECK-LABEL: testasxd:
436 ; CHECK: // %bb.0: // %entry
437 ; CHECK-NEXT: fcvtas x0, d0
440 %r = call double @round(double %a) nounwind readnone
441 %i = call i64 @llvm.fptosi.sat.i64.f64(double %r)
445 declare i32 @llvm.fptosi.sat.i32.bf16 (bfloat)
446 declare i64 @llvm.fptosi.sat.i64.bf16 (bfloat)
447 declare i32 @llvm.fptosi.sat.i32.f16 (half)
448 declare i64 @llvm.fptosi.sat.i64.f16 (half)
449 declare i32 @llvm.fptosi.sat.i32.f32 (float)
450 declare i64 @llvm.fptosi.sat.i64.f32 (float)
451 declare i32 @llvm.fptosi.sat.i32.f64 (double)
452 declare i64 @llvm.fptosi.sat.i64.f64 (double)
454 declare bfloat @llvm.floor.bf16(bfloat) nounwind readnone
455 declare bfloat @llvm.ceil.bf16(bfloat) nounwind readnone
456 declare bfloat @llvm.trunc.bf16(bfloat) nounwind readnone
457 declare bfloat @llvm.round.bf16(bfloat) nounwind readnone
458 declare half @llvm.floor.f16(half) nounwind readnone
459 declare half @llvm.ceil.f16(half) nounwind readnone
460 declare half @llvm.trunc.f16(half) nounwind readnone
461 declare half @llvm.round.f16(half) nounwind readnone
462 declare float @floorf(float) nounwind readnone
463 declare float @ceilf(float) nounwind readnone
464 declare float @truncf(float) nounwind readnone
465 declare float @roundf(float) nounwind readnone
466 declare double @floor(double) nounwind readnone
467 declare double @ceil(double) nounwind readnone
468 declare double @trunc(double) nounwind readnone
469 declare double @round(double) nounwind readnone