[InstCombine] Signed saturation patterns
[llvm-core.git] / test / CodeGen / AArch64 / f16-instructions.ll
blob1ed4bdec9fb9a19ca3bf544702e4b8d8ae7b1f34
1 ; RUN: llc < %s -mtriple aarch64-unknown-unknown -aarch64-neon-syntax=apple -asm-verbose=false -disable-post-ra -frame-pointer=all | FileCheck %s --check-prefix=CHECK-CVT --check-prefix=CHECK-COMMON
2 ; RUN: llc < %s -mtriple aarch64-unknown-unknown -mattr=+fullfp16 -aarch64-neon-syntax=apple -asm-verbose=false -disable-post-ra -frame-pointer=all | FileCheck %s --check-prefix=CHECK-COMMON --check-prefix=CHECK-FP16
4 ; RUN: llc < %s -mtriple aarch64-unknown-unknown -aarch64-neon-syntax=apple \
5 ; RUN: -asm-verbose=false -disable-post-ra -frame-pointer=all -global-isel \
6 ; RUN: -global-isel-abort=2 -pass-remarks-missed=gisel-* 2>&1 | FileCheck %s \
7 ; RUN: --check-prefixes=FALLBACK,GISEL-CVT,GISEL
9 ; RUN: llc < %s -mtriple aarch64-unknown-unknown -mattr=+fullfp16 \
10 ; RUN: -aarch64-neon-syntax=apple -asm-verbose=false -disable-post-ra \
11 ; RUN: -frame-pointer=all -global-isel -global-isel-abort=2 \
12 ; RUN: -pass-remarks-missed=gisel-* 2>&1 | FileCheck %s \
13 ; RUN: --check-prefixes=FALLBACK-FP16,GISEL-FP16,GISEL
15 target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
17 ; CHECK-CVT-LABEL: test_fadd:
18 ; CHECK-CVT-NEXT: fcvt s1, h1
19 ; CHECK-CVT-NEXT: fcvt s0, h0
20 ; CHECK-CVT-NEXT: fadd s0, s0, s1
21 ; CHECK-CVT-NEXT: fcvt h0, s0
22 ; CHECK-CVT-NEXT: ret
24 ; CHECK-FP16-LABEL: test_fadd:
25 ; CHECK-FP16-NEXT:  fadd h0, h0, h1
26 ; CHECK-FP16-NEXT:  ret
28 define half @test_fadd(half %a, half %b) #0 {
29   %r = fadd half %a, %b
30   ret half %r
33 ; CHECK-CVT-LABEL: test_fsub:
34 ; CHECK-CVT-NEXT: fcvt s1, h1
35 ; CHECK-CVT-NEXT: fcvt s0, h0
36 ; CHECK-CVT-NEXT: fsub s0, s0, s1
37 ; CHECK-CVT-NEXT: fcvt h0, s0
38 ; CHECK-CVT-NEXT: ret
40 ; CHECK-FP16-LABEL: test_fsub:
41 ; CHECK-FP16-NEXT: fsub h0, h0, h1
42 ; CHECK-FP16-NEXT: ret
44 define half @test_fsub(half %a, half %b) #0 {
45   %r = fsub half %a, %b
46   ret half %r
49 ; CHECK-CVT-LABEL: test_fmul:
50 ; CHECK-CVT-NEXT: fcvt s1, h1
51 ; CHECK-CVT-NEXT: fcvt s0, h0
52 ; CHECK-CVT-NEXT: fmul s0, s0, s1
53 ; CHECK-CVT-NEXT: fcvt h0, s0
54 ; CHECK-CVT-NEXT: ret
56 ; CHECK-FP16-LABEL: test_fmul:
57 ; CHECK-FP16-NEXT: fmul h0, h0, h1
58 ; CHECK-FP16-NEXT: ret
60 define half @test_fmul(half %a, half %b) #0 {
61   %r = fmul half %a, %b
62   ret half %r
65 ; CHECK-CVT-LABEL: test_fdiv:
66 ; CHECK-CVT-NEXT: fcvt s1, h1
67 ; CHECK-CVT-NEXT: fcvt s0, h0
68 ; CHECK-CVT-NEXT: fdiv s0, s0, s1
69 ; CHECK-CVT-NEXT: fcvt h0, s0
70 ; CHECK-CVT-NEXT: ret
72 ; CHECK-FP16-LABEL: test_fdiv:
73 ; CHECK-FP16-NEXT: fdiv h0, h0, h1
74 ; CHECK-FP16-NEXT: ret
76 define half @test_fdiv(half %a, half %b) #0 {
77   %r = fdiv half %a, %b
78   ret half %r
81 ; CHECK-COMMON-LABEL: test_frem:
82 ; CHECK-COMMON-NEXT: stp x29, x30, [sp, #-16]!
83 ; CHECK-COMMON-NEXT: mov  x29, sp
84 ; CHECK-COMMON-NEXT: fcvt s0, h0
85 ; CHECK-COMMON-NEXT: fcvt s1, h1
86 ; CHECK-COMMON-NEXT: bl {{_?}}fmodf
87 ; CHECK-COMMON-NEXT: fcvt h0, s0
88 ; CHECK-COMMON-NEXT: ldp x29, x30, [sp], #16
89 ; CHECK-COMMON-NEXT: ret
90 define half @test_frem(half %a, half %b) #0 {
91   %r = frem half %a, %b
92   ret half %r
95 ; CHECK-COMMON-LABEL: test_store:
96 ; CHECK-COMMON-NEXT: str  h0, [x0]
97 ; CHECK-COMMON-NEXT: ret
98 define void @test_store(half %a, half* %b) #0 {
99   store half %a, half* %b
100   ret void
103 ; CHECK-COMMON-LABEL: test_load:
104 ; CHECK-COMMON-NEXT: ldr  h0, [x0]
105 ; CHECK-COMMON-NEXT: ret
106 define half @test_load(half* %a) #0 {
107   %r = load half, half* %a
108   ret half %r
111 declare half @test_callee(half %a, half %b) #0
113 ; CHECK-COMMON-LABEL: test_call:
114 ; CHECK-COMMON-NEXT: stp x29, x30, [sp, #-16]!
115 ; CHECK-COMMON-NEXT: mov  x29, sp
116 ; CHECK-COMMON-NEXT: bl {{_?}}test_callee
117 ; CHECK-COMMON-NEXT: ldp x29, x30, [sp], #16
118 ; CHECK-COMMON-NEXT: ret
119 define half @test_call(half %a, half %b) #0 {
120   %r = call half @test_callee(half %a, half %b)
121   ret half %r
124 ; CHECK-COMMON-LABEL: test_call_flipped:
125 ; CHECK-COMMON-NEXT: stp x29, x30, [sp, #-16]!
126 ; CHECK-COMMON-NEXT: mov  x29, sp
127 ; CHECK-COMMON-NEXT: mov.16b  v2, v0
128 ; CHECK-COMMON-NEXT: mov.16b  v0, v1
129 ; CHECK-COMMON-NEXT: mov.16b  v1, v2
130 ; CHECK-COMMON-NEXT: bl {{_?}}test_callee
131 ; CHECK-COMMON-NEXT: ldp x29, x30, [sp], #16
132 ; CHECK-COMMON-NEXT: ret
133 define half @test_call_flipped(half %a, half %b) #0 {
134   %r = call half @test_callee(half %b, half %a)
135   ret half %r
138 ; CHECK-COMMON-LABEL: test_tailcall_flipped:
139 ; CHECK-COMMON-NEXT: mov.16b  v2, v0
140 ; CHECK-COMMON-NEXT: mov.16b  v0, v1
141 ; CHECK-COMMON-NEXT: mov.16b  v1, v2
142 ; CHECK-COMMON-NEXT: b {{_?}}test_callee
143 define half @test_tailcall_flipped(half %a, half %b) #0 {
144   %r = tail call half @test_callee(half %b, half %a)
145   ret half %r
148 ; CHECK-CVT-LABEL: test_select:
149 ; CHECK-CVT-NEXT: fcvt s1, h1
150 ; CHECK-CVT-NEXT: fcvt s0, h0
151 ; CHECK-CVT-NEXT: cmp  w0, #0
152 ; CHECK-CVT-NEXT: fcsel s0, s0, s1, ne
153 ; CHECK-CVT-NEXT: fcvt h0, s0
154 ; CHECK-CVT-NEXT: ret
156 ; CHECK-FP16-LABEL: test_select:
157 ; CHECK-FP16-NEXT: cmp w0, #0
158 ; CHECK-FP16-NEXT: fcsel h0, h0, h1, ne
159 ; CHECK-FP16-NEXT: ret
161 define half @test_select(half %a, half %b, i1 zeroext %c) #0 {
162   %r = select i1 %c, half %a, half %b
163   ret half %r
166 ; CHECK-CVT-LABEL: test_select_cc:
167 ; CHECK-CVT-DAG: fcvt s3, h3
168 ; CHECK-CVT-DAG: fcvt s2, h2
169 ; CHECK-CVT-DAG: fcvt s1, h1
170 ; CHECK-CVT-DAG: fcvt s0, h0
171 ; CHECK-CVT-DAG: fcmp s2, s3
172 ; CHECK-CVT-DAG: cset [[CC:w[0-9]+]], ne
173 ; CHECK-CVT-DAG: cmp [[CC]], #0
174 ; CHECK-CVT-NEXT: fcsel s0, s0, s1, ne
175 ; CHECK-CVT-NEXT: fcvt h0, s0
176 ; CHECK-CVT-NEXT: ret
178 ; CHECK-FP16-LABEL: test_select_cc:
179 ; CHECK-FP16-NEXT: fcmp h2, h3
180 ; CHECK-FP16-NEXT: fcsel h0, h0, h1, ne
181 ; CHECK-FP16-NEXT: ret
183 define half @test_select_cc(half %a, half %b, half %c, half %d) #0 {
184   %cc = fcmp une half %c, %d
185   %r = select i1 %cc, half %a, half %b
186   ret half %r
189 ; CHECK-CVT-LABEL: test_select_cc_f32_f16:
190 ; CHECK-CVT-DAG:   fcvt s2, h2
191 ; CHECK-CVT-DAG:   fcvt s3, h3
192 ; CHECK-CVT-NEXT:  fcmp s2, s3
193 ; CHECK-CVT-NEXT:  fcsel s0, s0, s1, ne
194 ; CHECK-CVT-NEXT:  ret
196 ; CHECK-FP16-LABEL: test_select_cc_f32_f16:
197 ; CHECK-FP16-NEXT: fcmp h2, h3
198 ; CHECK-FP16-NEXT: fcsel        s0, s0, s1, ne
199 ; CHECK-FP16-NEXT: ret
201 define float @test_select_cc_f32_f16(float %a, float %b, half %c, half %d) #0 {
202   %cc = fcmp une half %c, %d
203   %r = select i1 %cc, float %a, float %b
204   ret float %r
207 ; CHECK-CVT-LABEL: test_select_cc_f16_f32:
208 ; CHECK-CVT-DAG:  fcvt s0, h0
209 ; CHECK-CVT-DAG:  fcvt s1, h1
210 ; CHECK-CVT-DAG:  fcmp s2, s3
211 ; CHECK-CVT-DAG:  cset w8, ne
212 ; CHECK-CVT-NEXT: cmp w8, #0
213 ; CHECK-CVT-NEXT: fcsel s0, s0, s1, ne
214 ; CHECK-CVT-NEXT: fcvt h0, s0
215 ; CHECK-CVT-NEXT: ret
217 ; CHECK-FP16-LABEL: test_select_cc_f16_f32:
218 ; CHECK-FP16-NEXT: fcmp s2, s3
219 ; CHECK-FP16-NEXT: fcsel h0, h0, h1, ne
220 ; CHECK-FP16-NEXT: ret
222 define half @test_select_cc_f16_f32(half %a, half %b, float %c, float %d) #0 {
223   %cc = fcmp une float %c, %d
224   %r = select i1 %cc, half %a, half %b
225   ret half %r
228 ; CHECK-CVT-LABEL: test_fcmp_une:
229 ; CHECK-CVT-NEXT: fcvt s1, h1
230 ; CHECK-CVT-NEXT: fcvt s0, h0
231 ; CHECK-CVT-NEXT: fcmp s0, s1
232 ; CHECK-CVT-NEXT: cset  w0, ne
233 ; CHECK-CVT-NEXT: ret
235 ; CHECK-FP16-LABEL: test_fcmp_une:
236 ; CHECK-FP16-NEXT: fcmp h0, h1
237 ; CHECK-FP16-NEXT: cset w0, ne
238 ; CHECK-FP16-NEXT: ret
240 define i1 @test_fcmp_une(half %a, half %b) #0 {
241   %r = fcmp une half %a, %b
242   ret i1 %r
245 ; CHECK-CVT-LABEL: test_fcmp_ueq:
246 ; CHECK-CVT-NEXT: fcvt s1, h1
247 ; CHECK-CVT-NEXT: fcvt s0, h0
248 ; CHECK-CVT-NEXT: fcmp s0, s1
249 ; CHECK-CVT-NEXT: cset [[TRUE:w[0-9]+]], eq
250 ; CHECK-CVT-NEXT: csinc w0, [[TRUE]], wzr, vc
251 ; CHECK-CVT-NEXT: ret
253 ; CHECK-FP16-LABEL: test_fcmp_ueq:
254 ; CHECK-FP16-NEXT: fcmp h0, h1
255 ; CHECK-FP16-NEXT: cset [[TRUE:w[0-9]+]], eq
256 ; CHECK-FP16-NEXT: csinc w0, [[TRUE]], wzr, vc
257 ; CHECK-FP16-NEXT: ret
259 define i1 @test_fcmp_ueq(half %a, half %b) #0 {
260   %r = fcmp ueq half %a, %b
261   ret i1 %r
264 ; CHECK-CVT-LABEL: test_fcmp_ugt:
265 ; CHECK-CVT-NEXT: fcvt s1, h1
266 ; CHECK-CVT-NEXT: fcvt s0, h0
267 ; CHECK-CVT-NEXT: fcmp s0, s1
268 ; CHECK-CVT-NEXT: cset  w0, hi
269 ; CHECK-CVT-NEXT: ret
271 ; CHECK-FP16-LABEL: test_fcmp_ugt:
272 ; CHECK-FP16-NEXT: fcmp h0, h1
273 ; CHECK-FP16-NEXT: cset  w0, hi
274 ; CHECK-FP16-NEXT: ret
276 define i1 @test_fcmp_ugt(half %a, half %b) #0 {
277   %r = fcmp ugt half %a, %b
278   ret i1 %r
281 ; CHECK-CVT-LABEL: test_fcmp_uge:
282 ; CHECK-CVT-NEXT: fcvt s1, h1
283 ; CHECK-CVT-NEXT: fcvt s0, h0
284 ; CHECK-CVT-NEXT: fcmp s0, s1
285 ; CHECK-CVT-NEXT: cset  w0, pl
286 ; CHECK-CVT-NEXT: ret
288 ; CHECK-FP16-LABEL: test_fcmp_uge:
289 ; CHECK-FP16-NEXT: fcmp h0, h1
290 ; CHECK-FP16-NEXT: cset  w0, pl
291 ; CHECK-FP16-NEXT: ret
293 define i1 @test_fcmp_uge(half %a, half %b) #0 {
294   %r = fcmp uge half %a, %b
295   ret i1 %r
298 ; CHECK-CVT-LABEL: test_fcmp_ult:
299 ; CHECK-CVT-NEXT: fcvt s1, h1
300 ; CHECK-CVT-NEXT: fcvt s0, h0
301 ; CHECK-CVT-NEXT: fcmp s0, s1
302 ; CHECK-CVT-NEXT: cset  w0, lt
303 ; CHECK-CVT-NEXT: ret
305 ; CHECK-FP16-LABEL: test_fcmp_ult:
306 ; CHECK-FP16-NEXT: fcmp h0, h1
307 ; CHECK-FP16-NEXT: cset  w0, lt
308 ; CHECK-FP16-NEXT: ret
310 define i1 @test_fcmp_ult(half %a, half %b) #0 {
311   %r = fcmp ult half %a, %b
312   ret i1 %r
315 ; CHECK-CVT-LABEL: test_fcmp_ule:
316 ; CHECK-CVT-NEXT: fcvt s1, h1
317 ; CHECK-CVT-NEXT: fcvt s0, h0
318 ; CHECK-CVT-NEXT: fcmp s0, s1
319 ; CHECK-CVT-NEXT: cset  w0, le
320 ; CHECK-CVT-NEXT: ret
322 ; CHECK-FP16-LABEL: test_fcmp_ule:
323 ; CHECK-FP16-NEXT: fcmp h0, h1
324 ; CHECK-FP16-NEXT: cset  w0, le
325 ; CHECK-FP16-NEXT: ret
327 define i1 @test_fcmp_ule(half %a, half %b) #0 {
328   %r = fcmp ule half %a, %b
329   ret i1 %r
332 ; CHECK-CVT-LABEL: test_fcmp_uno:
333 ; CHECK-CVT-NEXT: fcvt s1, h1
334 ; CHECK-CVT-NEXT: fcvt s0, h0
335 ; CHECK-CVT-NEXT: fcmp s0, s1
336 ; CHECK-CVT-NEXT: cset  w0, vs
337 ; CHECK-CVT-NEXT: ret
339 ; CHECK-FP16-LABEL: test_fcmp_uno:
340 ; CHECK-FP16-NEXT: fcmp h0, h1
341 ; CHECK-FP16-NEXT: cset  w0, vs
342 ; CHECK-FP16-NEXT: ret
344 define i1 @test_fcmp_uno(half %a, half %b) #0 {
345   %r = fcmp uno half %a, %b
346   ret i1 %r
349 ; CHECK-CVT-LABEL: test_fcmp_one:
350 ; CHECK-CVT-NEXT: fcvt s1, h1
351 ; CHECK-CVT-NEXT: fcvt s0, h0
352 ; CHECK-CVT-NEXT: fcmp s0, s1
353 ; CHECK-CVT-NEXT: cset [[TRUE:w[0-9]+]], mi
354 ; CHECK-CVT-NEXT: csinc w0, [[TRUE]], wzr, le
355 ; CHECK-CVT-NEXT: ret
357 ; CHECK-FP16-LABEL: test_fcmp_one:
358 ; CHECK-FP16-NEXT: fcmp h0, h1
359 ; CHECK-FP16-NEXT: cset [[TRUE:w[0-9]+]], mi
360 ; CHECK-FP16-NEXT: csinc w0, [[TRUE]], wzr, le
361 ; CHECK-FP16-NEXT: ret
363 define i1 @test_fcmp_one(half %a, half %b) #0 {
364   %r = fcmp one half %a, %b
365   ret i1 %r
368 ; CHECK-CVT-LABEL: test_fcmp_oeq:
369 ; CHECK-CVT-NEXT: fcvt s1, h1
370 ; CHECK-CVT-NEXT: fcvt s0, h0
371 ; CHECK-CVT-NEXT: fcmp s0, s1
372 ; CHECK-CVT-NEXT: cset  w0, eq
373 ; CHECK-CVT-NEXT: ret
375 ; CHECK-FP16-LABEL: test_fcmp_oeq:
376 ; CHECK-FP16-NEXT: fcmp h0, h1
377 ; CHECK-FP16-NEXT: cset  w0, eq
378 ; CHECK-FP16-NEXT: ret
380 define i1 @test_fcmp_oeq(half %a, half %b) #0 {
381   %r = fcmp oeq half %a, %b
382   ret i1 %r
385 ; CHECK-CVT-LABEL: test_fcmp_ogt:
386 ; CHECK-CVT-NEXT: fcvt s1, h1
387 ; CHECK-CVT-NEXT: fcvt s0, h0
388 ; CHECK-CVT-NEXT: fcmp s0, s1
389 ; CHECK-CVT-NEXT: cset  w0, gt
390 ; CHECK-CVT-NEXT: ret
392 ; CHECK-FP16-LABEL: test_fcmp_ogt:
393 ; CHECK-FP16-NEXT: fcmp h0, h1
394 ; CHECK-FP16-NEXT: cset  w0, gt
395 ; CHECK-FP16-NEXT: ret
397 define i1 @test_fcmp_ogt(half %a, half %b) #0 {
398   %r = fcmp ogt half %a, %b
399   ret i1 %r
402 ; CHECK-CVT-LABEL: test_fcmp_oge:
403 ; CHECK-CVT-NEXT: fcvt s1, h1
404 ; CHECK-CVT-NEXT: fcvt s0, h0
405 ; CHECK-CVT-NEXT: fcmp s0, s1
406 ; CHECK-CVT-NEXT: cset  w0, ge
407 ; CHECK-CVT-NEXT: ret
409 ; CHECK-FP16-LABEL: test_fcmp_oge:
410 ; CHECK-FP16-NEXT: fcmp h0, h1
411 ; CHECK-FP16-NEXT: cset  w0, ge
412 ; CHECK-FP16-NEXT: ret
414 define i1 @test_fcmp_oge(half %a, half %b) #0 {
415   %r = fcmp oge half %a, %b
416   ret i1 %r
419 ; CHECK-CVT-LABEL: test_fcmp_olt:
420 ; CHECK-CVT-NEXT: fcvt s1, h1
421 ; CHECK-CVT-NEXT: fcvt s0, h0
422 ; CHECK-CVT-NEXT: fcmp s0, s1
423 ; CHECK-CVT-NEXT: cset  w0, mi
424 ; CHECK-CVT-NEXT: ret
426 ; CHECK-FP16-LABEL: test_fcmp_olt:
427 ; CHECK-FP16-NEXT: fcmp h0, h1
428 ; CHECK-FP16-NEXT: cset  w0, mi
429 ; CHECK-FP16-NEXT: ret
431 define i1 @test_fcmp_olt(half %a, half %b) #0 {
432   %r = fcmp olt half %a, %b
433   ret i1 %r
436 ; CHECK-CVT-LABEL: test_fcmp_ole:
437 ; CHECK-CVT-NEXT: fcvt s1, h1
438 ; CHECK-CVT-NEXT: fcvt s0, h0
439 ; CHECK-CVT-NEXT: fcmp s0, s1
440 ; CHECK-CVT-NEXT: cset  w0, ls
441 ; CHECK-CVT-NEXT: ret
443 ; CHECK-FP16-LABEL: test_fcmp_ole:
444 ; CHECK-FP16-NEXT: fcmp h0, h1
445 ; CHECK-FP16-NEXT: cset  w0, ls
446 ; CHECK-FP16-NEXT: ret
448 define i1 @test_fcmp_ole(half %a, half %b) #0 {
449   %r = fcmp ole half %a, %b
450   ret i1 %r
453 ; CHECK-CVT-LABEL: test_fcmp_ord:
454 ; CHECK-CVT-NEXT: fcvt s1, h1
455 ; CHECK-CVT-NEXT: fcvt s0, h0
456 ; CHECK-CVT-NEXT: fcmp s0, s1
457 ; CHECK-CVT-NEXT: cset  w0, vc
458 ; CHECK-CVT-NEXT: ret
460 ; CHECK-FP16-LABEL: test_fcmp_ord:
461 ; CHECK-FP16-NEXT: fcmp h0, h1
462 ; CHECK-FP16-NEXT: cset  w0, vc
463 ; CHECK-FP16-NEXT: ret
465 define i1 @test_fcmp_ord(half %a, half %b) #0 {
466   %r = fcmp ord half %a, %b
467   ret i1 %r
470 ; CHECK-COMMON-LABEL: test_fccmp:
471 ; CHECK-CVT:      fcvt  s0, h0
472 ; CHECK-CVT-NEXT: fmov  s1, #8.00000000
473 ; CHECK-CVT-NEXT: fmov  s2, #5.00000000
474 ; CHECK-CVT-NEXT: fcmp  s0, s1
475 ; CHECK-CVT-NEXT: cset  w8, gt
476 ; CHECK-CVT-NEXT: fcmp  s0, s2
477 ; CHECK-CVT-NEXT: cset  w9, mi
478 ; CHECK-CVT-NEXT: tst   w8, w9
479 ; CHECK-CVT-NEXT: fcsel s0, s0, s2, ne
480 ; CHECK-CVT-NEXT: fcvt  h0, s0
481 ; CHECK-CVT-NEXT: str   h0, [x0]
482 ; CHECK-CVT-NEXT: ret
483 ; CHECK-FP16:      fmov  h1, #5.00000000
484 ; CHECK-FP16-NEXT: fcmp  h0, h1
485 ; CHECK-FP16-NEXT: fmov  h2, #8.00000000
486 ; CHECK-FP16-NEXT: fccmp h0, h2, #4, mi
487 ; CHECK-FP16-NEXT: fcsel h0, h0, h1, gt
488 ; CHECK-FP16-NEXT: str   h0, [x0]
489 ; CHECK-FP16-NEXT: ret
491 define void @test_fccmp(half %in, half* %out) {
492   %cmp1 = fcmp ogt half %in, 0xH4800
493   %cmp2 = fcmp olt half %in, 0xH4500
494   %cond = and i1 %cmp1, %cmp2
495   %result = select i1 %cond, half %in, half 0xH4500
496   store half %result, half* %out
497   ret void
500 ; CHECK-CVT-LABEL: test_br_cc:
501 ; CHECK-CVT-NEXT: fcvt s1, h1
502 ; CHECK-CVT-NEXT: fcvt s0, h0
503 ; CHECK-CVT-NEXT: fcmp s0, s1
504 ; CHECK-CVT-NEXT: b.mi [[BRCC_ELSE:.?LBB[0-9_]+]]
505 ; CHECK-CVT-NEXT: str  wzr, [x0]
506 ; CHECK-CVT-NEXT: ret
507 ; CHECK-CVT-NEXT: [[BRCC_ELSE]]:
508 ; CHECK-CVT-NEXT: str  wzr, [x1]
509 ; CHECK-CVT-NEXT: ret
511 ; CHECK-FP16-LABEL: test_br_cc:
512 ; CHECK-FP16-NEXT: fcmp h0, h1
513 ; CHECK-FP16-NEXT: b.mi [[BRCC_ELSE:.?LBB[0-9_]+]]
514 ; CHECK-FP16-NEXT: str  wzr, [x0]
515 ; CHECK-FP16-NEXT: ret
516 ; CHECK-FP16-NEXT: [[BRCC_ELSE]]:
517 ; CHECK-FP16-NEXT: str  wzr, [x1]
518 ; CHECK-FP16-NEXT: ret
520 define void @test_br_cc(half %a, half %b, i32* %p1, i32* %p2) #0 {
521   %c = fcmp uge half %a, %b
522   br i1 %c, label %then, label %else
523 then:
524   store i32 0, i32* %p1
525   ret void
526 else:
527   store i32 0, i32* %p2
528   ret void
531 ; CHECK-COMMON-LABEL: test_phi:
532 ; CHECK-COMMON: mov  x[[PTR:[0-9]+]], x0
533 ; CHECK-COMMON: ldr  h[[AB:[0-9]+]], [x0]
534 ; CHECK-COMMON: [[LOOP:LBB[0-9_]+]]:
535 ; CHECK-COMMON: mov.16b  v[[R:[0-9]+]], v[[AB]]
536 ; CHECK-COMMON: ldr  h[[AB]], [x[[PTR]]]
537 ; CHECK-COMMON: mov  x0, x[[PTR]]
538 ; CHECK-COMMON: bl {{_?}}test_dummy
539 ; CHECK-COMMON: mov.16b  v0, v[[R]]
540 ; CHECK-COMMON: ret
541 define half @test_phi(half* %p1) #0 {
542 entry:
543   %a = load half, half* %p1
544   br label %loop
545 loop:
546   %r = phi half [%a, %entry], [%b, %loop]
547   %b = load half, half* %p1
548   %c = call i1 @test_dummy(half* %p1)
549   br i1 %c, label %loop, label %return
550 return:
551   ret half %r
554 declare i1 @test_dummy(half* %p1) #0
556 ; CHECK-CVT-LABEL: test_fptosi_i32:
557 ; CHECK-CVT-NEXT: fcvt s0, h0
558 ; CHECK-CVT-NEXT: fcvtzs w0, s0
559 ; CHECK-CVT-NEXT: ret
561 ; CHECK-FP16-LABEL: test_fptosi_i32:
562 ; CHECK-FP16-NEXT: fcvtzs w0, h0
563 ; CHECK-FP16-NEXT: ret
565 define i32 @test_fptosi_i32(half %a) #0 {
566   %r = fptosi half %a to i32
567   ret i32 %r
570 ; CHECK-CVT-LABEL: test_fptosi_i64:
571 ; CHECK-CVT-NEXT: fcvt s0, h0
572 ; CHECK-CVT-NEXT: fcvtzs x0, s0
573 ; CHECK-CVT-NEXT: ret
575 ; CHECK-FP16-LABEL: test_fptosi_i64:
576 ; CHECK-FP16-NEXT: fcvtzs x0, h0
577 ; CHECK-FP16-NEXT: ret
579 define i64 @test_fptosi_i64(half %a) #0 {
580   %r = fptosi half %a to i64
581   ret i64 %r
584 ; CHECK-CVT-LABEL: test_fptoui_i32:
585 ; CHECK-CVT-NEXT: fcvt s0, h0
586 ; CHECK-CVT-NEXT: fcvtzu w0, s0
587 ; CHECK-CVT-NEXT: ret
589 ; CHECK-FP16-LABEL: test_fptoui_i32:
590 ; CHECK-FP16-NEXT: fcvtzu w0, h0
591 ; CHECK-FP16-NEXT: ret
593 define i32 @test_fptoui_i32(half %a) #0 {
594   %r = fptoui half %a to i32
595   ret i32 %r
598 ; CHECK-CVT-LABEL: test_fptoui_i64:
599 ; CHECK-CVT-NEXT: fcvt s0, h0
600 ; CHECK-CVT-NEXT: fcvtzu x0, s0
601 ; CHECK-CVT-NEXT: ret
603 ; CHECK-FP16-LABEL: test_fptoui_i64:
604 ; CHECK-FP16-NEXT: fcvtzu x0, h0
605 ; CHECK-FP16-NEXT: ret
607 define i64 @test_fptoui_i64(half %a) #0 {
608   %r = fptoui half %a to i64
609   ret i64 %r
612 ; CHECK-CVT-LABEL: test_uitofp_i32:
613 ; CHECK-CVT-NEXT: ucvtf s0, w0
614 ; CHECK-CVT-NEXT: fcvt h0, s0
615 ; CHECK-CVT-NEXT: ret
617 ; CHECK-FP16-LABEL: test_uitofp_i32:
618 ; CHECK-FP16-NEXT: ucvtf h0, w0
619 ; CHECK-FP16-NEXT: ret
621 define half @test_uitofp_i32(i32 %a) #0 {
622   %r = uitofp i32 %a to half
623   ret half %r
626 ; CHECK-CVT-LABEL: test_uitofp_i64:
627 ; CHECK-CVT-NEXT: ucvtf s0, x0
628 ; CHECK-CVT-NEXT: fcvt h0, s0
629 ; CHECK-CVT-NEXT: ret
631 ; CHECK-FP16-LABEL: test_uitofp_i64:
632 ; CHECK-FP16-NEXT: ucvtf h0, x0
633 ; CHECK-FP16-NEXT: ret
635 define half @test_uitofp_i64(i64 %a) #0 {
636   %r = uitofp i64 %a to half
637   ret half %r
640 ; CHECK-CVT-LABEL: test_sitofp_i32:
641 ; CHECK-CVT-NEXT: scvtf s0, w0
642 ; CHECK-CVT-NEXT: fcvt h0, s0
643 ; CHECK-CVT-NEXT: ret
645 ; CHECK-FP16-LABEL: test_sitofp_i32:
646 ; CHECK-FP16-NEXT: scvtf h0, w0
647 ; CHECK-FP16-NEXT: ret
649 define half @test_sitofp_i32(i32 %a) #0 {
650   %r = sitofp i32 %a to half
651   ret half %r
654 ; CHECK-CVT-LABEL: test_sitofp_i64:
655 ; CHECK-CVT-NEXT: scvtf s0, x0
656 ; CHECK-CVT-NEXT: fcvt h0, s0
657 ; CHECK-CVT-NEXT: ret
659 ; CHECK-FP16-LABEL: test_sitofp_i64:
660 ; CHECK-FP16-NEXT: scvtf h0, x0
661 ; CHECK-FP16-NEXT: ret
662 define half @test_sitofp_i64(i64 %a) #0 {
663   %r = sitofp i64 %a to half
664   ret half %r
667 ; CHECK-CVT-LABEL: test_uitofp_i32_fadd:
668 ; CHECK-CVT-NEXT: ucvtf s1, w0
669 ; CHECK-CVT-NEXT: fcvt h1, s1
670 ; CHECK-CVT-NEXT: fcvt s0, h0
671 ; CHECK-CVT-NEXT: fcvt s1, h1
672 ; CHECK-CVT-NEXT: fadd s0, s0, s1
673 ; CHECK-CVT-NEXT: fcvt h0, s0
674 ; CHECK-CVT-NEXT: ret
676 ; CHECK-FP16-LABEL: test_uitofp_i32_fadd:
677 ; CHECK-FP16-NEXT: ucvtf h1, w0
678 ; CHECK-FP16-NEXT: fadd h0, h0, h1
679 ; CHECK-FP16-NEXT: ret
681 define half @test_uitofp_i32_fadd(i32 %a, half %b) #0 {
682   %c = uitofp i32 %a to half
683   %r = fadd half %b, %c
684   ret half %r
687 ; CHECK-CVT-LABEL: test_sitofp_i32_fadd:
688 ; CHECK-CVT-NEXT: scvtf s1, w0
689 ; CHECK-CVT-NEXT: fcvt h1, s1
690 ; CHECK-CVT-NEXT: fcvt s0, h0
691 ; CHECK-CVT-NEXT: fcvt s1, h1
692 ; CHECK-CVT-NEXT: fadd s0, s0, s1
693 ; CHECK-CVT-NEXT: fcvt h0, s0
694 ; CHECK-CVT-NEXT: ret
696 ; CHECK-FP16-LABEL: test_sitofp_i32_fadd:
697 ; CHECK-FP16-NEXT: scvtf h1, w0
698 ; CHECK-FP16-NEXT: fadd h0, h0, h1
699 ; CHECK-FP16-NEXT: ret
701 define half @test_sitofp_i32_fadd(i32 %a, half %b) #0 {
702   %c = sitofp i32 %a to half
703   %r = fadd half %b, %c
704   ret half %r
707 ; CHECK-COMMON-LABEL: test_fptrunc_float:
708 ; CHECK-COMMON-NEXT: fcvt h0, s0
709 ; CHECK-COMMON-NEXT: ret
711 define half @test_fptrunc_float(float %a) #0 {
712   %r = fptrunc float %a to half
713   ret half %r
716 ; CHECK-COMMON-LABEL: test_fptrunc_double:
717 ; CHECK-COMMON-NEXT: fcvt h0, d0
718 ; CHECK-COMMON-NEXT: ret
719 define half @test_fptrunc_double(double %a) #0 {
720   %r = fptrunc double %a to half
721   ret half %r
724 ; CHECK-COMMON-LABEL: test_fpext_float:
725 ; CHECK-COMMON-NEXT: fcvt s0, h0
726 ; CHECK-COMMON-NEXT: ret
727 define float @test_fpext_float(half %a) #0 {
728   %r = fpext half %a to float
729   ret float %r
732 ; CHECK-COMMON-LABEL: test_fpext_double:
733 ; CHECK-COMMON-NEXT: fcvt d0, h0
734 ; CHECK-COMMON-NEXT: ret
735 define double @test_fpext_double(half %a) #0 {
736   %r = fpext half %a to double
737   ret double %r
741 ; CHECK-COMMON-LABEL: test_bitcast_halftoi16:
742 ; CHECK-COMMON-NEXT: fmov w0, s0
743 ; CHECK-COMMON-NEXT: ret
744 define i16 @test_bitcast_halftoi16(half %a) #0 {
745   %r = bitcast half %a to i16
746   ret i16 %r
749 ; CHECK-COMMON-LABEL: test_bitcast_i16tohalf:
750 ; CHECK-COMMON-NEXT: fmov s0, w0
751 ; CHECK-COMMON-NEXT: ret
752 define half @test_bitcast_i16tohalf(i16 %a) #0 {
753   %r = bitcast i16 %a to half
754   ret half %r
758 declare half @llvm.sqrt.f16(half %a) #0
759 declare half @llvm.powi.f16(half %a, i32 %b) #0
760 declare half @llvm.sin.f16(half %a) #0
761 declare half @llvm.cos.f16(half %a) #0
762 declare half @llvm.pow.f16(half %a, half %b) #0
763 declare half @llvm.exp.f16(half %a) #0
764 declare half @llvm.exp2.f16(half %a) #0
765 declare half @llvm.log.f16(half %a) #0
766 declare half @llvm.log10.f16(half %a) #0
767 declare half @llvm.log2.f16(half %a) #0
768 declare half @llvm.fma.f16(half %a, half %b, half %c) #0
769 declare half @llvm.fabs.f16(half %a) #0
770 declare half @llvm.minnum.f16(half %a, half %b) #0
771 declare half @llvm.maxnum.f16(half %a, half %b) #0
772 declare half @llvm.copysign.f16(half %a, half %b) #0
773 declare half @llvm.floor.f16(half %a) #0
774 declare half @llvm.ceil.f16(half %a) #0
775 declare half @llvm.trunc.f16(half %a) #0
776 declare half @llvm.rint.f16(half %a) #0
777 declare half @llvm.nearbyint.f16(half %a) #0
778 declare half @llvm.round.f16(half %a) #0
779 declare half @llvm.fmuladd.f16(half %a, half %b, half %c) #0
780 declare half @llvm.aarch64.neon.frecpe.f16(half %a) #0
781 declare half @llvm.aarch64.neon.frecpx.f16(half %a) #0
782 declare half @llvm.aarch64.neon.frsqrte.f16(half %a) #0
784 ; FALLBACK-NOT: remark:{{.*}}test_sqrt
785 ; FALLBACK-FP16-NOT: remark:{{.*}}test_sqrt
787 ; CHECK-CVT-LABEL: test_sqrt:
788 ; CHECK-CVT-NEXT: fcvt s0, h0
789 ; CHECK-CVT-NEXT: fsqrt s0, s0
790 ; CHECK-CVT-NEXT: fcvt h0, s0
791 ; CHECK-CVT-NEXT: ret
793 ; CHECK-FP16-LABEL: test_sqrt:
794 ; CHECK-FP16-NEXT: fsqrt h0, h0
795 ; CHECK-FP16-NEXT: ret
797 ; GISEL-CVT-LABEL: test_sqrt:
798 ; GISEL-CVT-NEXT: fcvt s0, h0
799 ; GISEL-CVT-NEXT: fsqrt s0, s0
800 ; GISEL-CVT-NEXT: fcvt h0, s0
801 ; GISEL-CVT-NEXT: ret
803 ; GISEL-FP16-LABEL: test_sqrt:
804 ; GISEL-FP16-NEXT: fsqrt h0, h0
805 ; GISEL-FP16-NEXT: ret
807 define half @test_sqrt(half %a) #0 {
808   %r = call half @llvm.sqrt.f16(half %a)
809   ret half %r
812 ; CHECK-COMMON-LABEL: test_powi:
813 ; CHECK-COMMON-NEXT: stp x29, x30, [sp, #-16]!
814 ; CHECK-COMMON-NEXT: mov  x29, sp
815 ; CHECK-COMMON-NEXT: fcvt s0, h0
816 ; CHECK-COMMON-NEXT: bl {{_?}}__powisf2
817 ; CHECK-COMMON-NEXT: fcvt h0, s0
818 ; CHECK-COMMON-NEXT: ldp x29, x30, [sp], #16
819 ; CHECK-COMMON-NEXT: ret
820 define half @test_powi(half %a, i32 %b) #0 {
821   %r = call half @llvm.powi.f16(half %a, i32 %b)
822   ret half %r
825 ; FALLBACK-NOT: remark:{{.*}}test_sin
826 ; FALLBACK-FP16-NOT: remark:{{.*}}test_sin
828 ; CHECK-COMMON-LABEL: test_sin:
829 ; CHECK-COMMON-NEXT: stp x29, x30, [sp, #-16]!
830 ; CHECK-COMMON-NEXT: mov  x29, sp
831 ; CHECK-COMMON-NEXT: fcvt s0, h0
832 ; CHECK-COMMON-NEXT: bl {{_?}}sinf
833 ; CHECK-COMMON-NEXT: fcvt h0, s0
834 ; CHECK-COMMON-NEXT: ldp x29, x30, [sp], #16
835 ; CHECK-COMMON-NEXT: ret
837 ; GISEL-LABEL: test_sin:
838 ; GISEL-NEXT: stp x29, x30, [sp, #-16]!
839 ; GISEL-NEXT: mov  x29, sp
840 ; GISEL-NEXT: fcvt s0, h0
841 ; GISEL-NEXT: bl {{_?}}sinf
842 ; GISEL-NEXT: fcvt h0, s0
843 ; GISEL-NEXT: ldp x29, x30, [sp], #16
844 ; GISEL-NEXT: ret
845 define half @test_sin(half %a) #0 {
846   %r = call half @llvm.sin.f16(half %a)
847   ret half %r
850 ; FALLBACK-NOT: remark:{{.*}}test_cos
851 ; FALLBACK-FP16-NOT: remark:{{.*}}test_cos
853 ; CHECK-COMMON-LABEL: test_cos:
854 ; CHECK-COMMON-NEXT: stp x29, x30, [sp, #-16]!
855 ; CHECK-COMMON-NEXT: mov  x29, sp
856 ; CHECK-COMMON-NEXT: fcvt s0, h0
857 ; CHECK-COMMON-NEXT: bl {{_?}}cosf
858 ; CHECK-COMMON-NEXT: fcvt h0, s0
859 ; CHECK-COMMON-NEXT: ldp x29, x30, [sp], #16
860 ; CHECK-COMMON-NEXT: ret
862 ; GISEL-LABEL: test_cos:
863 ; GISEL-NEXT: stp x29, x30, [sp, #-16]!
864 ; GISEL-NEXT: mov  x29, sp
865 ; GISEL-NEXT: fcvt s0, h0
866 ; GISEL-NEXT: bl {{_?}}cosf
867 ; GISEL-NEXT: fcvt h0, s0
868 ; GISEL-NEXT: ldp x29, x30, [sp], #16
869 ; GISEL-NEXT: ret
870 define half @test_cos(half %a) #0 {
871   %r = call half @llvm.cos.f16(half %a)
872   ret half %r
875 ; CHECK-COMMON-LABEL: test_pow:
876 ; CHECK-COMMON-NEXT: stp x29, x30, [sp, #-16]!
877 ; CHECK-COMMON-NEXT: mov  x29, sp
878 ; CHECK-COMMON-NEXT: fcvt s0, h0
879 ; CHECK-COMMON-NEXT: fcvt s1, h1
880 ; CHECK-COMMON-NEXT: bl {{_?}}powf
881 ; CHECK-COMMON-NEXT: fcvt h0, s0
882 ; CHECK-COMMON-NEXT: ldp x29, x30, [sp], #16
883 ; CHECK-COMMON-NEXT: ret
884 define half @test_pow(half %a, half %b) #0 {
885   %r = call half @llvm.pow.f16(half %a, half %b)
886   ret half %r
889 ; FALLBACK-NOT: remark:{{.*}}test_exp
890 ; FALLBACK-FP16-NOT: remark:{{.*}}test_exp
892 ; CHECK-COMMON-LABEL: test_exp:
893 ; CHECK-COMMON-NEXT: stp x29, x30, [sp, #-16]!
894 ; CHECK-COMMON-NEXT: mov  x29, sp
895 ; CHECK-COMMON-NEXT: fcvt s0, h0
896 ; CHECK-COMMON-NEXT: bl {{_?}}expf
897 ; CHECK-COMMON-NEXT: fcvt h0, s0
898 ; CHECK-COMMON-NEXT: ldp x29, x30, [sp], #16
899 ; CHECK-COMMON-NEXT: ret
901 ; GISEL-LABEL: test_exp:
902 ; GISEL-NEXT: stp x29, x30, [sp, #-16]!
903 ; GISEL-NEXT: mov  x29, sp
904 ; GISEL-NEXT: fcvt s0, h0
905 ; GISEL-NEXT: bl {{_?}}expf
906 ; GISEL-NEXT: fcvt h0, s0
907 ; GISEL-NEXT: ldp x29, x30, [sp], #16
908 ; GISEL-NEXT: ret
909 define half @test_exp(half %a) #0 {
910   %r = call half @llvm.exp.f16(half %a)
911   ret half %r
914 ; CHECK-COMMON-LABEL: test_exp2:
915 ; CHECK-COMMON-NEXT: stp x29, x30, [sp, #-16]!
916 ; CHECK-COMMON-NEXT: mov  x29, sp
917 ; CHECK-COMMON-NEXT: fcvt s0, h0
918 ; CHECK-COMMON-NEXT: bl {{_?}}exp2f
919 ; CHECK-COMMON-NEXT: fcvt h0, s0
920 ; CHECK-COMMON-NEXT: ldp x29, x30, [sp], #16
921 ; CHECK-COMMON-NEXT: ret
923 ; GISEL-LABEL: test_exp2:
924 ; GISEL-NEXT: stp x29, x30, [sp, #-16]!
925 ; GISEL-NEXT: mov  x29, sp
926 ; GISEL-NEXT: fcvt s0, h0
927 ; GISEL-NEXT: bl {{_?}}exp2f
928 ; GISEL-NEXT: fcvt h0, s0
929 ; GISEL-NEXT: ldp x29, x30, [sp], #16
930 ; GISEL-NEXT: ret
931 define half @test_exp2(half %a) #0 {
932   %r = call half @llvm.exp2.f16(half %a)
933   ret half %r
936 ; FALLBACK-NOT: remark:{{.*}}test_log
937 ; FALLBACK-FP16-NOT: remark:{{.*}}test_log
939 ; CHECK-COMMON-LABEL: test_log:
940 ; CHECK-COMMON-NEXT: stp x29, x30, [sp, #-16]!
941 ; CHECK-COMMON-NEXT: mov  x29, sp
942 ; CHECK-COMMON-NEXT: fcvt s0, h0
943 ; CHECK-COMMON-NEXT: bl {{_?}}logf
944 ; CHECK-COMMON-NEXT: fcvt h0, s0
945 ; CHECK-COMMON-NEXT: ldp x29, x30, [sp], #16
946 ; CHECK-COMMON-NEXT: ret
948 ; GISEL-LABEL: test_log:
949 ; GISEL: stp x29, x30, [sp, #-16]!
950 ; GISEL-NEXT: mov  x29, sp
951 ; GISEL-NEXT: fcvt s0, h0
952 ; GISEL-NEXT: bl {{_?}}logf
953 ; GISEL-NEXT: fcvt h0, s0
954 ; GISEL-NEXT: ldp x29, x30, [sp], #16
955 ; GISEL-NEXT: ret
957 define half @test_log(half %a) #0 {
958   %r = call half @llvm.log.f16(half %a)
959   ret half %r
962 ; FALLBACK-NOT: remark:{{.*}}test_log10
963 ; FALLBACK-FP16-NOT: remark:{{.*}}test_log10
965 ; CHECK-COMMON-LABEL: test_log10:
966 ; CHECK-COMMON-NEXT: stp x29, x30, [sp, #-16]!
967 ; CHECK-COMMON-NEXT: mov  x29, sp
968 ; CHECK-COMMON-NEXT: fcvt s0, h0
969 ; CHECK-COMMON-NEXT: bl {{_?}}log10f
970 ; CHECK-COMMON-NEXT: fcvt h0, s0
971 ; CHECK-COMMON-NEXT: ldp x29, x30, [sp], #16
972 ; CHECK-COMMON-NEXT: ret
974 ; GISEL-LABEL: test_log10:
975 ; GISEL-NEXT: stp x29, x30, [sp, #-16]!
976 ; GISEL-NEXT: mov  x29, sp
977 ; GISEL-NEXT: fcvt s0, h0
978 ; GISEL-NEXT: bl {{_?}}log10f
979 ; GISEL-NEXT: fcvt h0, s0
980 ; GISEL-NEXT: ldp x29, x30, [sp], #16
981 ; GISEL-NEXT: ret
983 define half @test_log10(half %a) #0 {
984   %r = call half @llvm.log10.f16(half %a)
985   ret half %r
988 ; FALLBACK-NOT: remark:{{.*}}test_log2
989 ; FALLBACK-FP16-NOT: remark:{{.*}}test_log2
991 ; CHECK-COMMON-LABEL: test_log2:
992 ; CHECK-COMMON-NEXT: stp x29, x30, [sp, #-16]!
993 ; CHECK-COMMON-NEXT: mov  x29, sp
994 ; CHECK-COMMON-NEXT: fcvt s0, h0
995 ; CHECK-COMMON-NEXT: bl {{_?}}log2f
996 ; CHECK-COMMON-NEXT: fcvt h0, s0
997 ; CHECK-COMMON-NEXT: ldp x29, x30, [sp], #16
998 ; CHECK-COMMON-NEXT: ret
1000 ; GISEL-LABEL: test_log2:
1001 ; GISEL-NEXT: stp x29, x30, [sp, #-16]!
1002 ; GISEL-NEXT: mov  x29, sp
1003 ; GISEL-NEXT: fcvt s0, h0
1004 ; GISEL-NEXT: bl {{_?}}log2f
1005 ; GISEL-NEXT: fcvt h0, s0
1006 ; GISEL-NEXT: ldp x29, x30, [sp], #16
1007 ; GISEL-NEXT: ret
1009 define half @test_log2(half %a) #0 {
1010   %r = call half @llvm.log2.f16(half %a)
1011   ret half %r
1014 ; CHECK-CVT-LABEL: test_fma:
1015 ; CHECK-CVT-NEXT: fcvt s2, h2
1016 ; CHECK-CVT-NEXT: fcvt s1, h1
1017 ; CHECK-CVT-NEXT: fcvt s0, h0
1018 ; CHECK-CVT-NEXT: fmadd s0, s0, s1, s2
1019 ; CHECK-CVT-NEXT: fcvt h0, s0
1020 ; CHECK-CVT-NEXT: ret
1022 ; CHECK-FP16-LABEL: test_fma:
1023 ; CHECK-FP16-NEXT: fmadd h0, h0, h1, h2
1024 ; CHECK-FP16-NEXT: ret
1026 define half @test_fma(half %a, half %b, half %c) #0 {
1027   %r = call half @llvm.fma.f16(half %a, half %b, half %c)
1028   ret half %r
1031 ; CHECK-CVT-LABEL: test_fabs:
1032 ; CHECK-CVT-NEXT: fcvt s0, h0
1033 ; CHECK-CVT-NEXT: fabs s0, s0
1034 ; CHECK-CVT-NEXT: fcvt h0, s0
1035 ; CHECK-CVT-NEXT: ret
1037 ; CHECK-FP16-LABEL: test_fabs:
1038 ; CHECK-FP16-NEXT: fabs h0, h0
1039 ; CHECK-FP16-NEXT: ret
1041 ; FALLBACK-NOT: remark:{{.*}}test_fabs
1042 ; FALLBACK-FP16-NOT: remark:{{.*}}test_fabs
1044 ; GISEL-CVT-LABEL: test_fabs:
1045 ; GISEL-CVT-NEXT: fcvt s0, h0
1046 ; GISEL-CVT-NEXT: fabs s0, s0
1047 ; GISEL-CVT-NEXT: fcvt h0, s0
1048 ; GISEL-CVT-NEXT: ret
1050 ; GISEL-FP16-LABEL: test_fabs:
1051 ; GISEL-FP16-NEXT: fabs h0, h0
1052 ; GISEL-FP16-NEXT: ret
1054 define half @test_fabs(half %a) #0 {
1055   %r = call half @llvm.fabs.f16(half %a)
1056   ret half %r
1059 ; CHECK-CVT-LABEL: test_minnum:
1060 ; CHECK-CVT-NEXT: fcvt s1, h1
1061 ; CHECK-CVT-NEXT: fcvt s0, h0
1062 ; CHECK-CVT-NEXT: fminnm s0, s0, s1
1063 ; CHECK-CVT-NEXT: fcvt h0, s0
1064 ; CHECK-CVT-NEXT: ret
1066 ; CHECK-FP16-LABEL: test_minnum:
1067 ; CHECK-FP16-NEXT: fminnm h0, h0, h1
1068 ; CHECK-FP16-NEXT: ret
1070 define half @test_minnum(half %a, half %b) #0 {
1071   %r = call half @llvm.minnum.f16(half %a, half %b)
1072   ret half %r
1075 ; CHECK-CVT-LABEL: test_maxnum:
1076 ; CHECK-CVT-NEXT: fcvt s1, h1
1077 ; CHECK-CVT-NEXT: fcvt s0, h0
1078 ; CHECK-CVT-NEXT: fmaxnm s0, s0, s1
1079 ; CHECK-CVT-NEXT: fcvt h0, s0
1080 ; CHECK-CVT-NEXT: ret
1082 ; CHECK-FP16-LABEL: test_maxnum:
1083 ; CHECK-FP16-NEXT: fmaxnm h0, h0, h1
1084 ; CHECK-FP16-NEXT: ret
1086 define half @test_maxnum(half %a, half %b) #0 {
1087   %r = call half @llvm.maxnum.f16(half %a, half %b)
1088   ret half %r
1091 ; CHECK-CVT-LABEL: test_copysign:
1092 ; CHECK-CVT-NEXT: fcvt s1, h1
1093 ; CHECK-CVT-NEXT: fcvt s0, h0
1094 ; CHECK-CVT-NEXT: movi.4s v2, #128, lsl #24
1095 ; CHECK-CVT-NEXT: bit.16b v0, v1, v2
1096 ; CHECK-CVT-NEXT: fcvt h0, s0
1097 ; CHECK-CVT-NEXT: ret
1099 ; CHECK-FP16-LABEL: test_copysign:
1100 ; CHECK-FP16-NEXT: movi.8h v2, #128, lsl #8
1101 ; CHECK-FP16-NEXT: bit.16b  v0, v1, v2
1102 ; CHECK-FP16-NEXT: ret
1104 define half @test_copysign(half %a, half %b) #0 {
1105   %r = call half @llvm.copysign.f16(half %a, half %b)
1106   ret half %r
1109 ; CHECK-CVT-LABEL: test_copysign_f32:
1110 ; CHECK-CVT-NEXT: fcvt s0, h0
1111 ; CHECK-CVT-NEXT: movi.4s v2, #128, lsl #24
1112 ; CHECK-CVT-NEXT: bit.16b v0, v1, v2
1113 ; CHECK-CVT-NEXT: fcvt h0, s0
1114 ; CHECK-CVT-NEXT: ret
1116 ; CHECK-FP16-LABEL: test_copysign_f32:
1117 ; CHECK-FP16-NEXT: fcvt h1, s1
1118 ; CHECK-FP16-NEXT: movi.8h      v2, #128, lsl #8
1119 ; CHECK-FP16-NEXT: bit.16b v0, v1, v2
1120 ; CHECK-FP16-NEXT: ret
1122 define half @test_copysign_f32(half %a, float %b) #0 {
1123   %tb = fptrunc float %b to half
1124   %r = call half @llvm.copysign.f16(half %a, half %tb)
1125   ret half %r
1128 ; CHECK-CVT-LABEL: test_copysign_f64:
1129 ; CHECK-CVT-NEXT: fcvt s1, d1
1130 ; CHECK-CVT-NEXT: fcvt s0, h0
1131 ; CHECK-CVT-NEXT: movi.4s v2, #128, lsl #24
1132 ; CHECK-CVT-NEXT: bit.16b v0, v1, v2
1133 ; CHECK-CVT-NEXT: fcvt h0, s0
1134 ; CHECK-CVT-NEXT: ret
1136 ; CHECK-FP16-LABEL: test_copysign_f64:
1137 ; CHECK-FP16-NEXT: fcvt h1, d1
1138 ; CHECK-FP16-NEXT: movi.8h v2, #128, lsl #8
1139 ; CHECK-FP16-NEXT: bit.16b v0, v1, v2
1140 ; CHECK-FP16-NEXT: ret
1142 define half @test_copysign_f64(half %a, double %b) #0 {
1143   %tb = fptrunc double %b to half
1144   %r = call half @llvm.copysign.f16(half %a, half %tb)
1145   ret half %r
1148 ; Check that the FP promotion will use a truncating FP_ROUND, so we can fold
1149 ; away the (fpext (fp_round <result>)) here.
1151 ; CHECK-CVT-LABEL: test_copysign_extended:
1152 ; CHECK-CVT-NEXT: fcvt s1, h1
1153 ; CHECK-CVT-NEXT: fcvt s0, h0
1154 ; CHECK-CVT-NEXT: movi.4s v2, #128, lsl #24
1155 ; CHECK-CVT-NEXT: bit.16b v0, v1, v2
1156 ; CHECK-CVT-NEXT: ret
1158 ; CHECK-FP16-LABEL: test_copysign_extended:
1159 ; CHECK-FP16-NEXT: movi.8h v2, #128, lsl #8
1160 ; CHECK-FP16-NEXT: bit.16b v0, v1, v2
1161 ; CHECK-FP16-NEXT: fcvt s0, h0
1162 ; CHECK-FP16-NEXT: ret
1164 define float @test_copysign_extended(half %a, half %b) #0 {
1165   %r = call half @llvm.copysign.f16(half %a, half %b)
1166   %xr = fpext half %r to float
1167   ret float %xr
1170 ; CHECK-CVT-LABEL: test_floor:
1171 ; CHECK-CVT-NEXT: fcvt [[FLOAT32:s[0-9]+]], h0
1172 ; CHECK-CVT-NEXT: frintm [[INT32:s[0-9]+]], [[FLOAT32]]
1173 ; CHECK-CVT-NEXT: fcvt h0, [[INT32]]
1174 ; CHECK-CVT-NEXT: ret
1176 ; CHECK-FP16-LABEL: test_floor:
1177 ; CHECK-FP16-NEXT: frintm h0, h0
1178 ; CHECK-FP16-NEXT: ret
1180 ; FALLBACK-NOT: remark:{{.*}}test_floor
1181 ; FALLBACK-FP16-NOT: remark:{{.*}}test_floor
1183 ; GISEL-CVT-LABEL: test_floor:
1184 ; GISEL-CVT-NEXT: fcvt [[FLOAT32:s[0-9]+]], h0
1185 ; GISEL-CVT-NEXT: frintm [[INT32:s[0-9]+]], [[FLOAT32]]
1186 ; GISEL-CVT-NEXT: fcvt h0, [[INT32]]
1187 ; GISEL-CVT-NEXT: ret
1189 ; GISEL-FP16-LABEL: test_floor:
1190 ; GISEL-FP16-NEXT: frintm h0, h0
1191 ; GISEL-FP16-NEXT: ret
1193 define half @test_floor(half %a) #0 {
1194   %r = call half @llvm.floor.f16(half %a)
1195   ret half %r
1198 ; CHECK-CVT-LABEL: test_ceil:
1199 ; CHECK-CVT-NEXT: fcvt [[FLOAT32:s[0-9]+]], h0
1200 ; CHECK-CVT-NEXT: frintp [[INT32:s[0-9]+]], [[FLOAT32]]
1201 ; CHECK-CVT-NEXT: fcvt h0, [[INT32]]
1202 ; CHECK-CVT-NEXT: ret
1204 ; CHECK-FP16-LABEL: test_ceil:
1205 ; CHECK-FP16-NEXT: frintp h0, h0
1206 ; CHECK-FP16-NEXT: ret
1208 ; FALLBACK-NOT: remark:{{.*}}test_ceil
1209 ; FALLBACK-FP16-NOT: remark:{{.*}}test_ceil
1211 ; GISEL-CVT-LABEL: test_ceil:
1212 ; GISEL-CVT-NEXT: fcvt [[FLOAT32:s[0-9]+]], h0
1213 ; GISEL-CVT-NEXT: frintp [[INT32:s[0-9]+]], [[FLOAT32]]
1214 ; GISEL-CVT-NEXT: fcvt h0, [[INT32]]
1215 ; GISEL-CVT-NEXT: ret
1217 ; GISEL-FP16-LABEL: test_ceil:
1218 ; GISEL-FP16-NEXT: frintp h0, h0
1219 ; GISEL-FP16-NEXT: ret
1220 define half @test_ceil(half %a) #0 {
1221   %r = call half @llvm.ceil.f16(half %a)
1222   ret half %r
1225 ; CHECK-CVT-LABEL: test_trunc:
1226 ; CHECK-CVT-NEXT: fcvt [[FLOAT32:s[0-9]+]], h0
1227 ; CHECK-CVT-NEXT: frintz [[INT32:s[0-9]+]], [[FLOAT32]]
1228 ; CHECK-CVT-NEXT: fcvt h0, [[INT32]]
1229 ; CHECK-CVT-NEXT: ret
1231 ; CHECK-FP16-LABEL: test_trunc:
1232 ; CHECK-FP16-NEXT: frintz h0, h0
1233 ; CHECK-FP16-NEXT: ret
1235 define half @test_trunc(half %a) #0 {
1236   %r = call half @llvm.trunc.f16(half %a)
1237   ret half %r
1240 ; CHECK-CVT-LABEL: test_rint:
1241 ; CHECK-CVT-NEXT: fcvt s0, h0
1242 ; CHECK-CVT-NEXT: frintx s0, s0
1243 ; CHECK-CVT-NEXT: fcvt h0, s0
1244 ; CHECK-CVT-NEXT: ret
1246 ; CHECK-FP16-LABEL: test_rint:
1247 ; CHECK-FP16-NEXT: frintx h0, h0
1248 ; CHECK-FP16-NEXT: ret
1250 define half @test_rint(half %a) #0 {
1251   %r = call half @llvm.rint.f16(half %a)
1252   ret half %r
1255 ; CHECK-CVT-LABEL: test_nearbyint:
1256 ; CHECK-CVT-NEXT: fcvt s0, h0
1257 ; CHECK-CVT-NEXT: frinti s0, s0
1258 ; CHECK-CVT-NEXT: fcvt h0, s0
1259 ; CHECK-CVT-NEXT: ret
1261 ; CHECK-FP16-LABEL: test_nearbyint:
1262 ; CHECK-FP16-NEXT: frinti h0, h0
1263 ; CHECK-FP16-NEXT: ret
1265 define half @test_nearbyint(half %a) #0 {
1266   %r = call half @llvm.nearbyint.f16(half %a)
1267   ret half %r
1270 ; CHECK-CVT-LABEL: test_round:
1271 ; CHECK-CVT-NEXT: fcvt [[FLOAT32:s[0-9]+]], h0
1272 ; CHECK-CVT-NEXT: frinta [[INT32:s[0-9]+]], [[FLOAT32]]
1273 ; CHECK-CVT-NEXT: fcvt h0, [[INT32]]
1274 ; CHECK-CVT-NEXT: ret
1276 ; GISEL-CVT-LABEL: test_round:
1277 ; GISEL-CVT-NEXT: fcvt [[FLOAT32:s[0-9]+]], h0
1278 ; GISEL-CVT-NEXT: frinta [[INT32:s[0-9]+]], [[FLOAT32]]
1279 ; GISEL-CVT-NEXT: fcvt h0, [[INT32]]
1280 ; GISEL-CVT-NEXT: ret
1283 ; CHECK-FP16-LABEL: test_round:
1284 ; CHECK-FP16-NEXT: frinta h0, h0
1285 ; CHECK-FP16-NEXT: ret
1287 ; GISEL-FP16-LABEL: test_round:
1288 ; GISEL-FP16-NEXT: frinta h0, h0
1289 ; GISEL-FP16-NEXT: ret
1291 define half @test_round(half %a) #0 {
1292   %r = call half @llvm.round.f16(half %a)
1293   ret half %r
1296 ; CHECK-CVT-LABEL: test_fmuladd:
1297 ; CHECK-CVT-NEXT: fcvt s1, h1
1298 ; CHECK-CVT-NEXT: fcvt s0, h0
1299 ; CHECK-CVT-NEXT: fmul s0, s0, s1
1300 ; CHECK-CVT-NEXT: fcvt h0, s0
1301 ; CHECK-CVT-NEXT: fcvt s0, h0
1302 ; CHECK-CVT-NEXT: fcvt s1, h2
1303 ; CHECK-CVT-NEXT: fadd s0, s0, s1
1304 ; CHECK-CVT-NEXT: fcvt h0, s0
1305 ; CHECK-CVT-NEXT: ret
1307 ; CHECK-FP16-LABEL: test_fmuladd:
1308 ; CHECK-FP16-NEXT: fmul h0, h0, h1
1309 ; CHECK-FP16-NEXT: fadd h0, h0, h2
1310 ; CHECK-FP16-NEXT: ret
1312 define half @test_fmuladd(half %a, half %b, half %c) #0 {
1313   %r = call half @llvm.fmuladd.f16(half %a, half %b, half %c)
1314   ret half %r
1317 ; CHECK-FP16-LABEL: test_vrecpeh_f16:
1318 ; CHECK-FP16-NEXT: frecpe h0, h0
1319 ; CHECK-FP16-NEXT: ret
1321 define half @test_vrecpeh_f16(half %a) #0 {
1322   %r = call half @llvm.aarch64.neon.frecpe.f16(half %a)
1323   ret half %r
1326 ; CHECK-FP16-LABEL: test_vrecpxh_f16:
1327 ; CHECK-FP16-NEXT: frecpx h0, h0
1328 ; CHECK-FP16-NEXT: ret
1330 define half @test_vrecpxh_f16(half %a) #0 {
1331   %r = call half @llvm.aarch64.neon.frecpx.f16(half %a)
1332   ret half %r
1335 ; CHECK-FP16-LABEL: test_vrsqrteh_f16:
1336 ; CHECK-FP16-NEXT: frsqrte h0, h0
1337 ; CHECK-FP16-NEXT: ret
1339 define half @test_vrsqrteh_f16(half %a) #0 {
1340   %r = call half @llvm.aarch64.neon.frsqrte.f16(half %a)
1341   ret half %r
1344 attributes #0 = { nounwind }