1 ; RUN: llc -asm-verbose=false < %s -mattr=+vfp3,+fp16 | FileCheck -allow-deprecated-dag-overlap %s -check-prefix=CHECK-FP16 --check-prefix=CHECK-VFP -check-prefix=CHECK-ALL
2 ; RUN: llc -asm-verbose=false < %s | FileCheck -allow-deprecated-dag-overlap %s -check-prefix=CHECK-LIBCALL --check-prefix=CHECK-VFP -check-prefix=CHECK-ALL --check-prefix=CHECK-LIBCALL-VFP
3 ; RUN: llc -asm-verbose=false < %s -mattr=-fpregs | FileCheck -allow-deprecated-dag-overlap %s --check-prefix=CHECK-LIBCALL -check-prefix=CHECK-NOVFP -check-prefix=CHECK-ALL
5 target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-n32"
6 target triple = "armv7---eabihf"
8 ; CHECK-ALL-LABEL: test_fadd:
9 ; CHECK-FP16: vcvtb.f32.f16
10 ; CHECK-FP16: vcvtb.f32.f16
11 ; CHECK-LIBCALL: bl __aeabi_h2f
12 ; CHECK-LIBCALL: bl __aeabi_h2f
14 ; CHECK-NOVFP: bl __aeabi_fadd
15 ; CHECK-FP16: vcvtb.f16.f32
16 ; CHECK-LIBCALL: bl __aeabi_f2h
17 define void @test_fadd(half* %p, half* %q) #0 {
18 %a = load half, half* %p, align 2
19 %b = load half, half* %q, align 2
21 store half %r, half* %p
25 ; CHECK-ALL-LABEL: test_fsub:
26 ; CHECK-FP16: vcvtb.f32.f16
27 ; CHECK-FP16: vcvtb.f32.f16
28 ; CHECK-LIBCALL: bl __aeabi_h2f
29 ; CHECK-LIBCALL: bl __aeabi_h2f
31 ; CHECK-NOVFP: bl __aeabi_fsub
32 ; CHECK-FP16: vcvtb.f16.f32
33 ; CHECK-LIBCALL: bl __aeabi_f2h
34 define void @test_fsub(half* %p, half* %q) #0 {
35 %a = load half, half* %p, align 2
36 %b = load half, half* %q, align 2
38 store half %r, half* %p
42 ; CHECK-ALL-LABEL: test_fmul:
43 ; CHECK-FP16: vcvtb.f32.f16
44 ; CHECK-FP16: vcvtb.f32.f16
45 ; CHECK-LIBCALL: bl __aeabi_h2f
46 ; CHECK-LIBCALL: bl __aeabi_h2f
48 ; CHECK-NOVFP: bl __aeabi_fmul
49 ; CHECK-FP16: vcvtb.f16.f32
50 ; CHECK-LIBCALL: bl __aeabi_f2h
51 define void @test_fmul(half* %p, half* %q) #0 {
52 %a = load half, half* %p, align 2
53 %b = load half, half* %q, align 2
55 store half %r, half* %p
59 ; CHECK-ALL-LABEL: test_fdiv:
60 ; CHECK-FP16: vcvtb.f32.f16
61 ; CHECK-FP16: vcvtb.f32.f16
62 ; CHECK-LIBCALL: bl __aeabi_h2f
63 ; CHECK-LIBCALL: bl __aeabi_h2f
65 ; CHECK-NOVFP: bl __aeabi_fdiv
66 ; CHECK-FP16: vcvtb.f16.f32
67 ; CHECK-LIBCALL: bl __aeabi_f2h
68 define void @test_fdiv(half* %p, half* %q) #0 {
69 %a = load half, half* %p, align 2
70 %b = load half, half* %q, align 2
72 store half %r, half* %p
76 ; CHECK-ALL-LABEL: test_frem:
77 ; CHECK-FP16: vcvtb.f32.f16
78 ; CHECK-FP16: vcvtb.f32.f16
79 ; CHECK-LIBCALL: bl __aeabi_h2f
80 ; CHECK-LIBCALL: bl __aeabi_h2f
81 ; CHECK-LIBCALL: bl fmodf
82 ; CHECK-FP16: vcvtb.f16.f32
83 ; CHECK-LIBCALL: bl __aeabi_f2h
84 define void @test_frem(half* %p, half* %q) #0 {
85 %a = load half, half* %p, align 2
86 %b = load half, half* %q, align 2
88 store half %r, half* %p
92 ; CHECK-ALL-LABEL: test_load_store:
93 ; CHECK-ALL-NEXT: .fnstart
94 ; CHECK-ALL: ldrh {{r[0-9]+}}, [{{r[0-9]+}}]
95 ; CHECK-ALL: strh {{r[0-9]+}}, [{{r[0-9]+}}]
96 define void @test_load_store(half* %p, half* %q) #0 {
97 %a = load half, half* %p, align 2
98 store half %a, half* %q
102 ; Testing only successfull compilation of function calls. In ARM ABI, half
103 ; args and returns are handled as f32.
105 declare half @test_callee(half %a, half %b) #0
107 ; CHECK-ALL-LABEL: test_call:
108 ; CHECK-ALL-NEXT: .fnstart
109 ; CHECK-ALL-NEXT: .save {r11, lr}
110 ; CHECK-ALL-NEXT: push {r11, lr}
111 ; CHECK-ALL-NEXT: bl test_callee
112 ; CHECK-ALL-NEXT: pop {r11, pc}
113 define half @test_call(half %a, half %b) #0 {
114 %r = call half @test_callee(half %a, half %b)
118 ; CHECK-ALL-LABEL: test_call_flipped:
119 ; CHECK-ALL-NEXT: .fnstart
120 ; CHECK-ALL-NEXT: .save {r11, lr}
121 ; CHECK-ALL-NEXT: push {r11, lr}
122 ; CHECK-VFP-NEXT: vmov.f32 s2, s0
123 ; CHECK-VFP-NEXT: vmov.f32 s0, s1
124 ; CHECK-VFP-NEXT: vmov.f32 s1, s2
125 ; CHECK-NOVFP-NEXT: mov r2, r0
126 ; CHECK-NOVFP-NEXT: mov r0, r1
127 ; CHECK-NOVFP-NEXT: mov r1, r2
128 ; CHECK-ALL-NEXT: bl test_callee
129 ; CHECK-ALL-NEXT: pop {r11, pc}
130 define half @test_call_flipped(half %a, half %b) #0 {
131 %r = call half @test_callee(half %b, half %a)
135 ; CHECK-ALL-LABEL: test_tailcall_flipped:
136 ; CHECK-ALL-NEXT: .fnstart
137 ; CHECK-VFP-NEXT: vmov.f32 s2, s0
138 ; CHECK-VFP-NEXT: vmov.f32 s0, s1
139 ; CHECK-VFP-NEXT: vmov.f32 s1, s2
140 ; CHECK-NOVFP-NEXT: mov r2, r0
141 ; CHECK-NOVFP-NEXT: mov r0, r1
142 ; CHECK-NOVFP-NEXT: mov r1, r2
143 ; CHECK-ALL-NEXT: b test_callee
144 define half @test_tailcall_flipped(half %a, half %b) #0 {
145 %r = tail call half @test_callee(half %b, half %a)
149 ; Optimizer picks %p or %q based on %c and only loads that value
150 ; No conversion is needed
151 ; CHECK-ALL-LABEL: test_select:
152 ; CHECK-ALL: cmp {{r[0-9]+}}, #0
153 ; CHECK-ALL: movne {{r[0-9]+}}, {{r[0-9]+}}
154 ; CHECK-ALL: ldrh {{r[0-9]+}}, [{{r[0-9]+}}]
155 ; CHECK-ALL: strh {{r[0-9]+}}, [{{r[0-9]+}}]
156 define void @test_select(half* %p, half* %q, i1 zeroext %c) #0 {
157 %a = load half, half* %p, align 2
158 %b = load half, half* %q, align 2
159 %r = select i1 %c, half %a, half %b
160 store half %r, half* %p
164 ; Test only two variants of fcmp. These get translated to f32 vcmp
165 ; instructions anyway.
166 ; CHECK-ALL-LABEL: test_fcmp_une:
167 ; CHECK-FP16: vcvtb.f32.f16
168 ; CHECK-FP16: vcvtb.f32.f16
169 ; CHECK-LIBCALL: bl __aeabi_h2f
170 ; CHECK-LIBCALL: bl __aeabi_h2f
171 ; CHECK-VFP: vcmp.f32
172 ; CHECK-NOVFP: bl __aeabi_fcmpeq
173 ; CHECK-VFP-NEXT: vmrs APSR_nzcv, fpscr
174 ; CHECK-VFP-NEXT: movwne
175 ; CHECK-NOVFP-NEXT: clz r0, r0
176 ; CHECK-NOVFP-NEXT: lsr r0, r0, #5
177 define i1 @test_fcmp_une(half* %p, half* %q) #0 {
178 %a = load half, half* %p, align 2
179 %b = load half, half* %q, align 2
180 %r = fcmp une half %a, %b
184 ; CHECK-ALL-LABEL: test_fcmp_ueq:
185 ; CHECK-FP16: vcvtb.f32.f16
186 ; CHECK-FP16: vcvtb.f32.f16
187 ; CHECK-LIBCALL: bl __aeabi_h2f
188 ; CHECK-LIBCALL: bl __aeabi_h2f
189 ; CHECK-VFP: vcmp.f32
190 ; CHECK-NOVFP: bl __aeabi_fcmpeq
191 ; CHECK-FP16: vmrs APSR_nzcv, fpscr
192 ; CHECK-LIBCALL: movw{{ne|eq}}
193 define i1 @test_fcmp_ueq(half* %p, half* %q) #0 {
194 %a = load half, half* %p, align 2
195 %b = load half, half* %q, align 2
196 %r = fcmp ueq half %a, %b
200 ; CHECK-ALL-LABEL: test_br_cc:
201 ; CHECK-FP16: vcvtb.f32.f16
202 ; CHECK-FP16: vcvtb.f32.f16
203 ; CHECK-LIBCALL: bl __aeabi_h2f
204 ; CHECK-LIBCALL: bl __aeabi_h2f
205 ; CHECK-VFP: vcmp.f32
206 ; CHECK-NOVFP: bl __aeabi_fcmplt
207 ; CHECK-FP16: vmrs APSR_nzcv, fpscr
211 define void @test_br_cc(half* %p, half* %q, i32* %p1, i32* %p2) #0 {
212 %a = load half, half* %p, align 2
213 %b = load half, half* %q, align 2
214 %c = fcmp uge half %a, %b
215 br i1 %c, label %then, label %else
217 store i32 0, i32* %p1
220 store i32 0, i32* %p2
224 declare i1 @test_dummy(half* %p) #0
225 ; CHECK-ALL-LABEL: test_phi:
226 ; CHECK-FP16: vcvtb.f32.f16
227 ; CHECK-FP16: [[LOOP:.LBB[1-9_]+]]:
228 ; CHECK-FP16: vcvtb.f32.f16
229 ; CHECK-FP16: bl test_dummy
230 ; CHECK-FP16: bne [[LOOP]]
231 ; CHECK-FP16: vcvtb.f16.f32
232 ; CHECK-LIBCALL-VFP: bl __aeabi_h2f
233 ; CHECK-LIBCALL: [[LOOP:.LBB[1-9_]+]]:
234 ; CHECK-LIBCALL-VFP: bl __aeabi_h2f
235 ; CHECK-LIBCALL: bl test_dummy
236 ; CHECK-LIBCALL: bne [[LOOP]]
237 ; CHECK-LIBCALL-VFP: bl __aeabi_f2h
238 define void @test_phi(half* %p) #0 {
240 %a = load half, half* %p
243 %r = phi half [%a, %entry], [%b, %loop]
244 %b = load half, half* %p
245 %c = call i1 @test_dummy(half* %p)
246 br i1 %c, label %loop, label %return
248 store half %r, half* %p
252 ; CHECK-ALL-LABEL: test_fptosi_i32:
253 ; CHECK-FP16: vcvtb.f32.f16
254 ; CHECK-LIBCALL: bl __aeabi_h2f
255 ; CHECK-VFP: vcvt.s32.f32
256 ; CHECK-NOVFP: bl __aeabi_f2iz
257 define i32 @test_fptosi_i32(half* %p) #0 {
258 %a = load half, half* %p, align 2
259 %r = fptosi half %a to i32
263 ; CHECK-ALL-LABEL: test_fptosi_i64:
264 ; CHECK-FP16: vcvtb.f32.f16
265 ; CHECK-LIBCALL: bl __aeabi_h2f
266 ; CHECK-ALL: bl __aeabi_f2lz
267 define i64 @test_fptosi_i64(half* %p) #0 {
268 %a = load half, half* %p, align 2
269 %r = fptosi half %a to i64
273 ; CHECK-ALL-LABEL: test_fptoui_i32:
274 ; CHECK-FP16: vcvtb.f32.f16
275 ; CHECK-LIBCALL: bl __aeabi_h2f
276 ; CHECK-VFP: vcvt.u32.f32
277 ; CHECK-NOVFP: bl __aeabi_f2uiz
278 define i32 @test_fptoui_i32(half* %p) #0 {
279 %a = load half, half* %p, align 2
280 %r = fptoui half %a to i32
284 ; CHECK-ALL-LABEL: test_fptoui_i64:
285 ; CHECK-FP16: vcvtb.f32.f16
286 ; CHECK-LIBCALL: bl __aeabi_h2f
287 ; CHECK-ALL: bl __aeabi_f2ulz
288 define i64 @test_fptoui_i64(half* %p) #0 {
289 %a = load half, half* %p, align 2
290 %r = fptoui half %a to i64
294 ; CHECK-ALL-LABEL: test_sitofp_i32:
295 ; CHECK-VFP: vcvt.f32.s32
296 ; CHECK-NOVFP: bl __aeabi_i2f
297 ; CHECK-FP16: vcvtb.f16.f32
298 ; CHECK-LIBCALL: bl __aeabi_f2h
299 define void @test_sitofp_i32(i32 %a, half* %p) #0 {
300 %r = sitofp i32 %a to half
301 store half %r, half* %p
305 ; CHECK-ALL-LABEL: test_uitofp_i32:
306 ; CHECK-VFP: vcvt.f32.u32
307 ; CHECK-NOVFP: bl __aeabi_ui2f
308 ; CHECK-FP16: vcvtb.f16.f32
309 ; CHECK-LIBCALL: bl __aeabi_f2h
310 define void @test_uitofp_i32(i32 %a, half* %p) #0 {
311 %r = uitofp i32 %a to half
312 store half %r, half* %p
316 ; CHECK-ALL-LABEL: test_sitofp_i64:
317 ; CHECK-ALL: bl __aeabi_l2f
318 ; CHECK-FP16: vcvtb.f16.f32
319 ; CHECK-LIBCALL: bl __aeabi_f2h
320 define void @test_sitofp_i64(i64 %a, half* %p) #0 {
321 %r = sitofp i64 %a to half
322 store half %r, half* %p
326 ; CHECK-ALL-LABEL: test_uitofp_i64:
327 ; CHECK-ALL: bl __aeabi_ul2f
328 ; CHECK-FP16: vcvtb.f16.f32
329 ; CHECK-LIBCALL: bl __aeabi_f2h
330 define void @test_uitofp_i64(i64 %a, half* %p) #0 {
331 %r = uitofp i64 %a to half
332 store half %r, half* %p
336 ; CHECK-FP16-LABEL: test_fptrunc_float:
337 ; CHECK-FP16: vcvtb.f16.f32
338 ; CHECK-LIBCALL-LABEL: test_fptrunc_float:
339 ; CHECK-LIBCALL: bl __aeabi_f2h
340 define void @test_fptrunc_float(float %f, half* %p) #0 {
341 %a = fptrunc float %f to half
342 store half %a, half* %p
346 ; CHECK-FP16-LABEL: test_fptrunc_double:
347 ; CHECK-FP16: bl __aeabi_d2h
348 ; CHECK-LIBCALL-LABEL: test_fptrunc_double:
349 ; CHECK-LIBCALL: bl __aeabi_d2h
350 define void @test_fptrunc_double(double %d, half* %p) #0 {
351 %a = fptrunc double %d to half
352 store half %a, half* %p
356 ; CHECK-FP16-LABEL: test_fpextend_float:
357 ; CHECK-FP16: vcvtb.f32.f16
358 ; CHECK-LIBCALL-LABEL: test_fpextend_float:
359 ; CHECK-LIBCALL: bl __aeabi_h2f
360 define float @test_fpextend_float(half* %p) {
361 %a = load half, half* %p, align 2
362 %r = fpext half %a to float
366 ; CHECK-FP16-LABEL: test_fpextend_double:
367 ; CHECK-FP16: vcvtb.f32.f16
368 ; CHECK-LIBCALL-LABEL: test_fpextend_double:
369 ; CHECK-LIBCALL: bl __aeabi_h2f
370 ; CHECK-VFP: vcvt.f64.f32
371 ; CHECK-NOVFP: bl __aeabi_f2d
372 define double @test_fpextend_double(half* %p) {
373 %a = load half, half* %p, align 2
374 %r = fpext half %a to double
378 ; CHECK-ALL-LABEL: test_bitcast_halftoi16:
379 ; CHECK-ALL-NEXT: .fnstart
380 ; CHECK-ALL-NEXT: ldrh r0, [r0]
381 ; CHECK-ALL-NEXT: bx lr
382 define i16 @test_bitcast_halftoi16(half* %p) #0 {
383 %a = load half, half* %p, align 2
384 %r = bitcast half %a to i16
388 ; CHECK-ALL-LABEL: test_bitcast_i16tohalf:
389 ; CHECK-ALL-NEXT: .fnstart
390 ; CHECK-ALL-NEXT: strh r0, [r1]
391 ; CHECK-ALL-NEXT: bx lr
392 define void @test_bitcast_i16tohalf(i16 %a, half* %p) #0 {
393 %r = bitcast i16 %a to half
394 store half %r, half* %p
398 declare half @llvm.sqrt.f16(half %a) #0
399 declare half @llvm.powi.f16.i32(half %a, i32 %b) #0
400 declare half @llvm.sin.f16(half %a) #0
401 declare half @llvm.cos.f16(half %a) #0
402 declare half @llvm.pow.f16(half %a, half %b) #0
403 declare half @llvm.exp.f16(half %a) #0
404 declare half @llvm.exp2.f16(half %a) #0
405 declare half @llvm.log.f16(half %a) #0
406 declare half @llvm.log10.f16(half %a) #0
407 declare half @llvm.log2.f16(half %a) #0
408 declare half @llvm.fma.f16(half %a, half %b, half %c) #0
409 declare half @llvm.fabs.f16(half %a) #0
410 declare half @llvm.minnum.f16(half %a, half %b) #0
411 declare half @llvm.maxnum.f16(half %a, half %b) #0
412 declare half @llvm.copysign.f16(half %a, half %b) #0
413 declare half @llvm.floor.f16(half %a) #0
414 declare half @llvm.ceil.f16(half %a) #0
415 declare half @llvm.trunc.f16(half %a) #0
416 declare half @llvm.rint.f16(half %a) #0
417 declare half @llvm.nearbyint.f16(half %a) #0
418 declare half @llvm.round.f16(half %a) #0
419 declare half @llvm.fmuladd.f16(half %a, half %b, half %c) #0
421 ; CHECK-ALL-LABEL: test_sqrt:
422 ; CHECK-FP16: vcvtb.f32.f16
423 ; CHECK-FP16: vsqrt.f32
424 ; CHECK-FP16: vcvtb.f16.f32
425 ; CHECK-LIBCALL: bl __aeabi_h2f
426 ; CHECK-LIBCALL-VFP: vsqrt.f32
427 ; CHECK-NOVFP: bl sqrtf
428 ; CHECK-LIBCALL: bl __aeabi_f2h
429 define void @test_sqrt(half* %p) #0 {
430 %a = load half, half* %p, align 2
431 %r = call half @llvm.sqrt.f16(half %a)
432 store half %r, half* %p
436 ; CHECK-FP16-LABEL: test_fpowi:
437 ; CHECK-FP16: vcvtb.f32.f16
438 ; CHECK-FP16: bl __powisf2
439 ; CHECK-FP16: vcvtb.f16.f32
440 ; CHECK-LIBCALL-LABEL: test_fpowi:
441 ; CHECK-LIBCALL: bl __aeabi_h2f
442 ; CHECK-LIBCALL: bl __powisf2
443 ; CHECK-LIBCALL: bl __aeabi_f2h
444 define void @test_fpowi(half* %p, i32 %b) #0 {
445 %a = load half, half* %p, align 2
446 %r = call half @llvm.powi.f16.i32(half %a, i32 %b)
447 store half %r, half* %p
451 ; CHECK-FP16-LABEL: test_sin:
452 ; CHECK-FP16: vcvtb.f32.f16
453 ; CHECK-FP16: bl sinf
454 ; CHECK-FP16: vcvtb.f16.f32
455 ; CHECK-LIBCALL-LABEL: test_sin:
456 ; CHECK-LIBCALL: bl __aeabi_h2f
457 ; CHECK-LIBCALL: bl sinf
458 ; CHECK-LIBCALL: bl __aeabi_f2h
459 define void @test_sin(half* %p) #0 {
460 %a = load half, half* %p, align 2
461 %r = call half @llvm.sin.f16(half %a)
462 store half %r, half* %p
466 ; CHECK-FP16-LABEL: test_cos:
467 ; CHECK-FP16: vcvtb.f32.f16
468 ; CHECK-FP16: bl cosf
469 ; CHECK-FP16: vcvtb.f16.f32
470 ; CHECK-LIBCALL-LABEL: test_cos:
471 ; CHECK-LIBCALL: bl __aeabi_h2f
472 ; CHECK-LIBCALL: bl cosf
473 ; CHECK-LIBCALL: bl __aeabi_f2h
474 define void @test_cos(half* %p) #0 {
475 %a = load half, half* %p, align 2
476 %r = call half @llvm.cos.f16(half %a)
477 store half %r, half* %p
481 ; CHECK-FP16-LABEL: test_pow:
482 ; CHECK-FP16: vcvtb.f32.f16
483 ; CHECK-FP16: vcvtb.f32.f16
484 ; CHECK-FP16: bl powf
485 ; CHECK-FP16: vcvtb.f16.f32
486 ; CHECK-LIBCALL-LABEL: test_pow:
487 ; CHECK-LIBCALL: bl __aeabi_h2f
488 ; CHECK-LIBCALL: bl __aeabi_h2f
489 ; CHECK-LIBCALL: bl powf
490 ; CHECK-LIBCALL: bl __aeabi_f2h
491 define void @test_pow(half* %p, half* %q) #0 {
492 %a = load half, half* %p, align 2
493 %b = load half, half* %q, align 2
494 %r = call half @llvm.pow.f16(half %a, half %b)
495 store half %r, half* %p
499 ; CHECK-FP16-LABEL: test_cbrt:
500 ; CHECK-FP16: vcvtb.f32.f16
501 ; CHECK-FP16: bl powf
502 ; CHECK-FP16: vcvtb.f16.f32
503 ; CHECK-LIBCALL-LABEL: test_cbrt:
504 ; CHECK-LIBCALL: bl __aeabi_h2f
505 ; CHECK-LIBCALL: bl powf
506 ; CHECK-LIBCALL: bl __aeabi_f2h
507 define void @test_cbrt(half* %p) #0 {
508 %a = load half, half* %p, align 2
509 %r = call half @llvm.pow.f16(half %a, half 0x3FD5540000000000)
510 store half %r, half* %p
514 ; CHECK-FP16-LABEL: test_exp:
515 ; CHECK-FP16: vcvtb.f32.f16
516 ; CHECK-FP16: bl expf
517 ; CHECK-FP16: vcvtb.f16.f32
518 ; CHECK-LIBCALL-LABEL: test_exp:
519 ; CHECK-LIBCALL: bl __aeabi_h2f
520 ; CHECK-LIBCALL: bl expf
521 ; CHECK-LIBCALL: bl __aeabi_f2h
522 define void @test_exp(half* %p) #0 {
523 %a = load half, half* %p, align 2
524 %r = call half @llvm.exp.f16(half %a)
525 store half %r, half* %p
529 ; CHECK-FP16-LABEL: test_exp2:
530 ; CHECK-FP16: vcvtb.f32.f16
531 ; CHECK-FP16: bl exp2f
532 ; CHECK-FP16: vcvtb.f16.f32
533 ; CHECK-LIBCALL-LABEL: test_exp2:
534 ; CHECK-LIBCALL: bl __aeabi_h2f
535 ; CHECK-LIBCALL: bl exp2f
536 ; CHECK-LIBCALL: bl __aeabi_f2h
537 define void @test_exp2(half* %p) #0 {
538 %a = load half, half* %p, align 2
539 %r = call half @llvm.exp2.f16(half %a)
540 store half %r, half* %p
544 ; CHECK-FP16-LABEL: test_log:
545 ; CHECK-FP16: vcvtb.f32.f16
546 ; CHECK-FP16: bl logf
547 ; CHECK-FP16: vcvtb.f16.f32
548 ; CHECK-LIBCALL-LABEL: test_log:
549 ; CHECK-LIBCALL: bl __aeabi_h2f
550 ; CHECK-LIBCALL: bl logf
551 ; CHECK-LIBCALL: bl __aeabi_f2h
552 define void @test_log(half* %p) #0 {
553 %a = load half, half* %p, align 2
554 %r = call half @llvm.log.f16(half %a)
555 store half %r, half* %p
559 ; CHECK-FP16-LABEL: test_log10:
560 ; CHECK-FP16: vcvtb.f32.f16
561 ; CHECK-FP16: bl log10f
562 ; CHECK-FP16: vcvtb.f16.f32
563 ; CHECK-LIBCALL-LABEL: test_log10:
564 ; CHECK-LIBCALL: bl __aeabi_h2f
565 ; CHECK-LIBCALL: bl log10f
566 ; CHECK-LIBCALL: bl __aeabi_f2h
567 define void @test_log10(half* %p) #0 {
568 %a = load half, half* %p, align 2
569 %r = call half @llvm.log10.f16(half %a)
570 store half %r, half* %p
574 ; CHECK-FP16-LABEL: test_log2:
575 ; CHECK-FP16: vcvtb.f32.f16
576 ; CHECK-FP16: bl log2f
577 ; CHECK-FP16: vcvtb.f16.f32
578 ; CHECK-LIBCALL-LABEL: test_log2:
579 ; CHECK-LIBCALL: bl __aeabi_h2f
580 ; CHECK-LIBCALL: bl log2f
581 ; CHECK-LIBCALL: bl __aeabi_f2h
582 define void @test_log2(half* %p) #0 {
583 %a = load half, half* %p, align 2
584 %r = call half @llvm.log2.f16(half %a)
585 store half %r, half* %p
589 ; CHECK-FP16-LABEL: test_fma:
590 ; CHECK-FP16: vcvtb.f32.f16
591 ; CHECK-FP16: vcvtb.f32.f16
592 ; CHECK-FP16: vcvtb.f32.f16
593 ; CHECK-FP16: bl fmaf
594 ; CHECK-FP16: vcvtb.f16.f32
595 ; CHECK-LIBCALL-LABEL: test_fma:
596 ; CHECK-LIBCALL: bl __aeabi_h2f
597 ; CHECK-LIBCALL: bl __aeabi_h2f
598 ; CHECK-LIBCALL: bl __aeabi_h2f
599 ; CHECK-LIBCALL: bl fmaf
600 ; CHECK-LIBCALL: bl __aeabi_f2h
601 define void @test_fma(half* %p, half* %q, half* %r) #0 {
602 %a = load half, half* %p, align 2
603 %b = load half, half* %q, align 2
604 %c = load half, half* %r, align 2
605 %v = call half @llvm.fma.f16(half %a, half %b, half %c)
606 store half %v, half* %p
610 ; CHECK-FP16-LABEL: test_fabs:
611 ; CHECK-FP16: vcvtb.f32.f16
612 ; CHECK-FP16: vabs.f32
613 ; CHECK-FP16: vcvtb.f16.f32
614 ; CHECK-LIBCALL-LABEL: test_fabs:
615 ; CHECK-LIBCALL: bl __aeabi_h2f
617 ; CHECK-LIBCALL: bl __aeabi_f2h
618 define void @test_fabs(half* %p) {
619 %a = load half, half* %p, align 2
620 %r = call half @llvm.fabs.f16(half %a)
621 store half %r, half* %p
625 ; CHECK-FP16-LABEL: test_minnum:
626 ; CHECK-FP16: vcvtb.f32.f16
627 ; CHECK-FP16: vcvtb.f32.f16
628 ; CHECK-FP16: bl fminf
629 ; CHECK-FP16: vcvtb.f16.f32
630 ; CHECK-LIBCALL-LABEL: test_minnum:
631 ; CHECK-LIBCALL: bl __aeabi_h2f
632 ; CHECK-LIBCALL: bl __aeabi_h2f
633 ; CHECK-LIBCALL: bl fminf
634 ; CHECK-LIBCALL: bl __aeabi_f2h
635 define void @test_minnum(half* %p, half* %q) #0 {
636 %a = load half, half* %p, align 2
637 %b = load half, half* %q, align 2
638 %r = call half @llvm.minnum.f16(half %a, half %b)
639 store half %r, half* %p
643 ; CHECK-FP16-LABEL: test_maxnum:
644 ; CHECK-FP16: vcvtb.f32.f16
645 ; CHECK-FP16: vcvtb.f32.f16
646 ; CHECK-FP16: bl fmaxf
647 ; CHECK-FP16: vcvtb.f16.f32
648 ; CHECK-LIBCALL-LABEL: test_maxnum:
649 ; CHECK-LIBCALL: bl __aeabi_h2f
650 ; CHECK-LIBCALL: bl __aeabi_h2f
651 ; CHECK-LIBCALL: bl fmaxf
652 ; CHECK-LIBCALL: bl __aeabi_f2h
653 define void @test_maxnum(half* %p, half* %q) #0 {
654 %a = load half, half* %p, align 2
655 %b = load half, half* %q, align 2
656 %r = call half @llvm.maxnum.f16(half %a, half %b)
657 store half %r, half* %p
661 ; CHECK-ALL-LABEL: test_minimum:
662 ; CHECK-FP16: vmov.f32 s0, #1.000000e+00
663 ; CHECK-FP16: vcvtb.f32.f16
664 ; CHECK-LIBCALL: bl __aeabi_h2f
665 ; CHECK-LIBCALL-VFP: vmov.f32 s{{[0-9]+}}, #1.000000e+00
666 ; CHECK-NOVFP: mov r{{[0-9]+}}, #1065353216
667 ; CHECK-VFP: vcmp.f32
669 ; CHECK-VFP: vmovlt.f32
670 ; CHECK-NOVFP: bl __aeabi_fcmpge
671 ; CHECK-FP16: vcvtb.f16.f32
672 ; CHECK-LIBCALL: bl __aeabi_f2h
673 define void @test_minimum(half* %p) #0 {
674 %a = load half, half* %p, align 2
675 %c = fcmp ult half %a, 1.0
676 %r = select i1 %c, half %a, half 1.0
677 store half %r, half* %p
681 ; CHECK-ALL-LABEL: test_maximum:
682 ; CHECK-FP16: vmov.f32 s0, #1.000000e+00
683 ; CHECK-FP16: vcvtb.f32.f16
684 ; CHECK-LIBCALL: bl __aeabi_h2f
685 ; CHECK-LIBCALL-VFP: vmov.f32 s0, #1.000000e+00
686 ; CHECK-NOVFP: mov r{{[0-9]+}}, #1065353216
687 ; CHECK-VFP: vcmp.f32
689 ; CHECK-VFP: vmovhi.f32
690 ; CHECK-NOVFP: bl __aeabi_fcmple
691 ; CHECK-FP16: vcvtb.f16.f32
692 ; CHECK-LIBCALL: bl __aeabi_f2h
693 define void @test_maximum(half* %p) #0 {
694 %a = load half, half* %p, align 2
695 %c = fcmp ugt half %a, 1.0
696 %r = select i1 %c, half %a, half 1.0
697 store half %r, half* %p
701 ; CHECK-FP16-LABEL: test_copysign:
702 ; CHECK-FP16: ldrh r2, [r0]
703 ; CHECK-FP16-NEXT: vmov.i32 d16, #0x80000000
704 ; CHECK-FP16-NEXT: ldrh r1, [r1]
705 ; CHECK-FP16-NEXT: vmov s0, r2
706 ; CHECK-FP16-NEXT: vmov s2, r1
707 ; CHECK-FP16-NEXT: vcvtb.f32.f16 s0, s0
708 ; CHECK-FP16-NEXT: vcvtb.f32.f16 s2, s2
709 ; CHECK-FP16-NEXT: vbit d0, d1, d16
710 ; CHECK-FP16-NEXT: vcvtb.f16.f32 s0, s0
711 ; CHECK-FP16-NEXT: vmov r1, s0
712 ; CHECK-FP16-NEXT: strh r1, [r0]
713 ; CHECK-FP16-NEXT: bx lr
715 ; CHECK-LIBCALL-LABEL: test_copysign:
716 ; CHECK-LIBCALL-VFP: .fnstart
717 ; CHECK-LIBCALL-VFP-NEXT: .save {r4, r5, r11, lr}
718 ; CHECK-LIBCALL-VFP-NEXT: push {r4, r5, r11, lr}
719 ; CHECK-LIBCALL-VFP-NEXT: .vsave {d8, d9}
720 ; CHECK-LIBCALL-VFP-NEXT: vpush {d8, d9}
721 ; CHECK-LIBCALL-VFP-NEXT: mov r5, r0
722 ; CHECK-LIBCALL-VFP-NEXT: ldrh r0, [r0]
723 ; CHECK-LIBCALL-VFP-NEXT: mov r4, r1
724 ; CHECK-LIBCALL: bl __aeabi_h2f
725 ; CHECK-LIBCALL-VFP: ldrh r1, [r4]
726 ; CHECK-LIBCALL-VFP-NEXT: vmov s18, r0
727 ; CHECK-LIBCALL-VFP-NEXT: vmov.i32 d8, #0x80000000
728 ; CHECK-LIBCALL-VFP-NEXT: mov r0, r1
729 ; CHECK-LIBCALL: bl __aeabi_h2f
730 ; CHECK-LIBCALL-VFP: vmov s0, r0
731 ; CHECK-LIBCALL-VFP-NEXT: vbif d0, d9, d8
732 ; CHECK-LIBCALL-VFP-NEXT: vmov r0, s0
733 ; CHECK-LIBCALL: bl __aeabi_f2h
734 ; CHECK-LIBCALL-VFP: strh r0, [r5]
735 ; CHECK-LIBCALL-VFP-NEXT: vpop {d8, d9}
736 ; CHECK-LIBCALL-VFP-NEXT: pop {r4, r5, r11, pc}
740 define void @test_copysign(half* %p, half* %q) #0 {
741 %a = load half, half* %p, align 2
742 %b = load half, half* %q, align 2
743 %r = call half @llvm.copysign.f16(half %a, half %b)
744 store half %r, half* %p
748 ; CHECK-FP16-LABEL: test_floor:
749 ; CHECK-FP16: vcvtb.f32.f16
750 ; CHECK-FP16: bl floorf
751 ; CHECK-FP16: vcvtb.f16.f32
752 ; CHECK-LIBCALL-LABEL: test_floor:
753 ; CHECK-LIBCALL: bl __aeabi_h2f
754 ; CHECK-LIBCALL: bl floorf
755 ; CHECK-LIBCALL: bl __aeabi_f2h
756 define void @test_floor(half* %p) {
757 %a = load half, half* %p, align 2
758 %r = call half @llvm.floor.f16(half %a)
759 store half %r, half* %p
763 ; CHECK-FP16-LABEL: test_ceil:
764 ; CHECK-FP16: vcvtb.f32.f16
765 ; CHECK-FP16: bl ceilf
766 ; CHECK-FP16: vcvtb.f16.f32
767 ; CHECK-LIBCALL-LABEL: test_ceil:
768 ; CHECK-LIBCALL: bl __aeabi_h2f
769 ; CHECK-LIBCALL: bl ceilf
770 ; CHECK-LIBCALL: bl __aeabi_f2h
771 define void @test_ceil(half* %p) {
772 %a = load half, half* %p, align 2
773 %r = call half @llvm.ceil.f16(half %a)
774 store half %r, half* %p
778 ; CHECK-FP16-LABEL: test_trunc:
779 ; CHECK-FP16: vcvtb.f32.f16
780 ; CHECK-FP16: bl truncf
781 ; CHECK-FP16: vcvtb.f16.f32
782 ; CHECK-LIBCALL-LABEL: test_trunc:
783 ; CHECK-LIBCALL: bl __aeabi_h2f
784 ; CHECK-LIBCALL: bl truncf
785 ; CHECK-LIBCALL: bl __aeabi_f2h
786 define void @test_trunc(half* %p) {
787 %a = load half, half* %p, align 2
788 %r = call half @llvm.trunc.f16(half %a)
789 store half %r, half* %p
793 ; CHECK-FP16-LABEL: test_rint:
794 ; CHECK-FP16: vcvtb.f32.f16
795 ; CHECK-FP16: bl rintf
796 ; CHECK-FP16: vcvtb.f16.f32
797 ; CHECK-LIBCALL-LABEL: test_rint:
798 ; CHECK-LIBCALL: bl __aeabi_h2f
799 ; CHECK-LIBCALL: bl rintf
800 ; CHECK-LIBCALL: bl __aeabi_f2h
801 define void @test_rint(half* %p) {
802 %a = load half, half* %p, align 2
803 %r = call half @llvm.rint.f16(half %a)
804 store half %r, half* %p
808 ; CHECK-FP16-LABEL: test_nearbyint:
809 ; CHECK-FP16: vcvtb.f32.f16
810 ; CHECK-FP16: bl nearbyintf
811 ; CHECK-FP16: vcvtb.f16.f32
812 ; CHECK-LIBCALL-LABEL: test_nearbyint:
813 ; CHECK-LIBCALL: bl __aeabi_h2f
814 ; CHECK-LIBCALL: bl nearbyintf
815 ; CHECK-LIBCALL: bl __aeabi_f2h
816 define void @test_nearbyint(half* %p) {
817 %a = load half, half* %p, align 2
818 %r = call half @llvm.nearbyint.f16(half %a)
819 store half %r, half* %p
823 ; CHECK-FP16-LABEL: test_round:
824 ; CHECK-FP16: vcvtb.f32.f16
825 ; CHECK-FP16: bl roundf
826 ; CHECK-FP16: vcvtb.f16.f32
827 ; CHECK-LIBCALL-LABEL: test_round:
828 ; CHECK-LIBCALL: bl __aeabi_h2f
829 ; CHECK-LIBCALL: bl roundf
830 ; CHECK-LIBCALL: bl __aeabi_f2h
831 define void @test_round(half* %p) {
832 %a = load half, half* %p, align 2
833 %r = call half @llvm.round.f16(half %a)
834 store half %r, half* %p
838 ; CHECK-FP16-LABEL: test_fmuladd:
839 ; CHECK-FP16: vcvtb.f32.f16
840 ; CHECK-FP16: vcvtb.f32.f16
841 ; CHECK-FP16: vcvtb.f32.f16
842 ; CHECK-FP16: vmla.f32
843 ; CHECK-FP16: vcvtb.f16.f32
844 ; CHECK-LIBCALL-LABEL: test_fmuladd:
845 ; CHECK-LIBCALL: bl __aeabi_h2f
846 ; CHECK-LIBCALL: bl __aeabi_h2f
847 ; CHECK-LIBCALL: bl __aeabi_h2f
848 ; CHECK-LIBCALL-VFP: vmla.f32
849 ; CHECK-NOVFP: bl __aeabi_fmul
850 ; CHECK-LIBCALL: bl __aeabi_f2h
851 define void @test_fmuladd(half* %p, half* %q, half* %r) #0 {
852 %a = load half, half* %p, align 2
853 %b = load half, half* %q, align 2
854 %c = load half, half* %r, align 2
855 %v = call half @llvm.fmuladd.f16(half %a, half %b, half %c)
856 store half %v, half* %p
860 ; f16 vectors are not legal in the backend. Vector elements are not assigned
861 ; to the register, but are stored in the stack instead. Hence insertelement
862 ; and extractelement have these extra loads and stores.
864 ; CHECK-ALL-LABEL: test_insertelement:
865 ; CHECK-ALL: sub sp, sp, #8
881 ; CHECK-NOVFP-DAG: strh
882 ; CHECK-NOVFP-DAG: strh
883 ; CHECK-NOVFP-DAG: mov
884 ; CHECK-NOVFP-DAG: ldrh
885 ; CHECK-NOVFP-DAG: orr
886 ; CHECK-NOVFP-DAG: strh
887 ; CHECK-NOVFP-DAG: strh
888 ; CHECK-NOVFP-DAG: strh
889 ; CHECK-NOVFP-DAG: ldrh
890 ; CHECK-NOVFP-DAG: ldrh
891 ; CHECK-NOVFP-DAG: ldrh
892 ; CHECK-NOVFP-DAG: strh
893 ; CHECK-NOVFP-DAG: strh
894 ; CHECK-NOVFP-DAG: strh
895 ; CHECK-NOVFP-DAG: strh
897 ; CHECK-ALL: add sp, sp, #8
898 define void @test_insertelement(half* %p, <4 x half>* %q, i32 %i) #0 {
899 %a = load half, half* %p, align 2
900 %b = load <4 x half>, <4 x half>* %q, align 8
901 %c = insertelement <4 x half> %b, half %a, i32 %i
902 store <4 x half> %c, <4 x half>* %q
906 ; CHECK-ALL-LABEL: test_extractelement:
907 ; CHECK-VFP: push {{{.*}}, lr}
908 ; CHECK-VFP: sub sp, sp, #8
914 ; CHECK-VFP: add sp, sp, #8
915 ; CHECK-VFP: pop {{{.*}}, pc}
925 define void @test_extractelement(half* %p, <4 x half>* %q, i32 %i) #0 {
926 %a = load <4 x half>, <4 x half>* %q, align 8
927 %b = extractelement <4 x half> %a, i32 %i
928 store half %b, half* %p
932 ; test struct operations
934 %struct.dummy = type { i32, half }
936 ; CHECK-ALL-LABEL: test_insertvalue:
938 ; CHECK-ALL-DAG: ldrh
939 ; CHECK-ALL-DAG: strh
941 define void @test_insertvalue(%struct.dummy* %p, half* %q) {
942 %a = load %struct.dummy, %struct.dummy* %p
943 %b = load half, half* %q
944 %c = insertvalue %struct.dummy %a, half %b, 1
945 store %struct.dummy %c, %struct.dummy* %p
949 ; CHECK-ALL-LABEL: test_extractvalue:
950 ; CHECK-ALL: .fnstart
953 define void @test_extractvalue(%struct.dummy* %p, half* %q) {
954 %a = load %struct.dummy, %struct.dummy* %p
955 %b = extractvalue %struct.dummy %a, 1
956 store half %b, half* %q
960 ; CHECK-ALL-LABEL: test_struct_return:
961 ; CHECK-VFP-LIBCALL: bl __aeabi_h2f
962 ; CHECK-NOVFP-DAG: ldr
963 ; CHECK-NOVFP-DAG: ldrh
964 define %struct.dummy @test_struct_return(%struct.dummy* %p) {
965 %a = load %struct.dummy, %struct.dummy* %p
969 ; CHECK-ALL-LABEL: test_struct_arg:
970 ; CHECK-ALL-NEXT: .fnstart
971 ; CHECK-NOVFP-NEXT: mov r0, r1
972 ; CHECK-ALL-NEXT: bx lr
973 define half @test_struct_arg(%struct.dummy %p) {
974 %a = extractvalue %struct.dummy %p, 1
978 ; CHECK-LABEL: test_uitofp_i32_fadd:
979 ; CHECK-VFP-DAG: vcvt.f32.u32
980 ; CHECK-NOVFP-DAG: bl __aeabi_ui2f
982 ; CHECK-FP16-DAG: vcvtb.f16.f32
983 ; CHECK-FP16-DAG: vcvtb.f32.f16
984 ; CHECK-LIBCALL-DAG: bl __aeabi_h2f
985 ; CHECK-LIBCALL-DAG: bl __aeabi_h2f
987 ; CHECK-VFP-DAG: vadd.f32
988 ; CHECK-NOVFP-DAG: bl __aeabi_fadd
990 ; CHECK-FP16-DAG: vcvtb.f16.f32
991 ; CHECK-LIBCALL-DAG: bl __aeabi_f2h
992 define half @test_uitofp_i32_fadd(i32 %a, half %b) #0 {
993 %c = uitofp i32 %a to half
994 %r = fadd half %b, %c
998 ; CHECK-LABEL: test_sitofp_i32_fadd:
999 ; CHECK-VFP-DAG: vcvt.f32.s32
1000 ; CHECK-NOVFP-DAG: bl __aeabi_i2f
1002 ; CHECK-FP16-DAG: vcvtb.f16.f32
1003 ; CHECK-FP16-DAG: vcvtb.f32.f16
1004 ; CHECK-LIBCALL-DAG: bl __aeabi_h2f
1005 ; CHECK-LIBCALL-DAG: bl __aeabi_h2f
1007 ; CHECK-VFP-DAG: vadd.f32
1008 ; CHECK-NOVFP-DAG: bl __aeabi_fadd
1010 ; CHECK-FP16-DAG: vcvtb.f16.f32
1011 ; CHECK-LIBCALL-DAG: bl __aeabi_f2h
1012 define half @test_sitofp_i32_fadd(i32 %a, half %b) #0 {
1013 %c = sitofp i32 %a to half
1014 %r = fadd half %b, %c
1018 attributes #0 = { nounwind }