[NFC][Py Reformat] Reformat python files in llvm
[llvm-project.git] / llvm / test / CodeGen / ARM / fp16-promote.ll
blobab8282c5aa12017d060e9090fc04c53853668c28
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
13 ; CHECK-VFP: vadd.f32
14 ; CHECK-NOVFP: bl __aeabi_fadd
15 ; CHECK-FP16: vcvtb.f16.f32
16 ; CHECK-LIBCALL: bl __aeabi_f2h
17 define void @test_fadd(ptr %p, ptr %q) #0 {
18   %a = load half, ptr %p, align 2
19   %b = load half, ptr %q, align 2
20   %r = fadd half %a, %b
21   store half %r, ptr %p
22   ret void
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
30 ; CHECK-VFP: vsub.f32
31 ; CHECK-NOVFP: bl __aeabi_fsub
32 ; CHECK-FP16: vcvtb.f16.f32
33 ; CHECK-LIBCALL: bl __aeabi_f2h
34 define void @test_fsub(ptr %p, ptr %q) #0 {
35   %a = load half, ptr %p, align 2
36   %b = load half, ptr %q, align 2
37   %r = fsub half %a, %b
38   store half %r, ptr %p
39   ret void
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
47 ; CHECK-VFP: vmul.f32
48 ; CHECK-NOVFP: bl __aeabi_fmul
49 ; CHECK-FP16: vcvtb.f16.f32
50 ; CHECK-LIBCALL: bl __aeabi_f2h
51 define void @test_fmul(ptr %p, ptr %q) #0 {
52   %a = load half, ptr %p, align 2
53   %b = load half, ptr %q, align 2
54   %r = fmul half %a, %b
55   store half %r, ptr %p
56   ret void
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
64 ; CHECK-VFP: vdiv.f32
65 ; CHECK-NOVFP: bl __aeabi_fdiv
66 ; CHECK-FP16: vcvtb.f16.f32
67 ; CHECK-LIBCALL: bl __aeabi_f2h
68 define void @test_fdiv(ptr %p, ptr %q) #0 {
69   %a = load half, ptr %p, align 2
70   %b = load half, ptr %q, align 2
71   %r = fdiv half %a, %b
72   store half %r, ptr %p
73   ret void
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(ptr %p, ptr %q) #0 {
85   %a = load half, ptr %p, align 2
86   %b = load half, ptr %q, align 2
87   %r = frem half %a, %b
88   store half %r, ptr %p
89   ret void
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(ptr %p, ptr %q) #0 {
97   %a = load half, ptr %p, align 2
98   store half %a, ptr %q
99   ret void
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)
115   ret half %r
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)
132   ret half %r
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)
146   ret half %r
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(ptr %p, ptr %q, i1 zeroext %c) #0 {
157   %a = load half, ptr %p, align 2
158   %b = load half, ptr %q, align 2
159   %r = select i1 %c, half %a, half %b
160   store half %r, ptr %p
161   ret void
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(ptr %p, ptr %q) #0 {
178   %a = load half, ptr %p, align 2
179   %b = load half, ptr %q, align 2
180   %r = fcmp une half %a, %b
181   ret i1 %r
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(ptr %p, ptr %q) #0 {
194   %a = load half, ptr %p, align 2
195   %b = load half, ptr %q, align 2
196   %r = fcmp ueq half %a, %b
197   ret i1 %r
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
208 ; CHECK-VFP: movmi
209 ; CHECK-VFP: str
210 ; CHECK-NOVFP: str
211 define void @test_br_cc(ptr %p, ptr %q, ptr %p1, ptr %p2) #0 {
212   %a = load half, ptr %p, align 2
213   %b = load half, ptr %q, align 2
214   %c = fcmp uge half %a, %b
215   br i1 %c, label %then, label %else
216 then:
217   store i32 0, ptr %p1
218   ret void
219 else:
220   store i32 0, ptr %p2
221   ret void
224 declare i1 @test_dummy(ptr %p) #0
225 ; CHECK-ALL-LABEL: test_phi:
226 ; CHECK-FP16: [[LOOP:.LBB[0-9_]+]]:
227 ; CHECK-FP16: bl      test_dummy
228 ; CHECK-FP16: bne     [[LOOP]]
229 ; CHECK-LIBCALL: [[LOOP:.LBB[0-9_]+]]:
230 ; CHECK-LIBCALL: bl test_dummy
231 ; CHECK-LIBCALL: bne     [[LOOP]]
232 define void @test_phi(ptr %p) #0 {
233 entry:
234   %a = load half, ptr %p
235   br label %loop
236 loop:
237   %r = phi half [%a, %entry], [%b, %loop]
238   %b = load half, ptr %p
239   %c = call i1 @test_dummy(ptr %p)
240   br i1 %c, label %loop, label %return
241 return:
242   store half %r, ptr %p
243   ret void
246 ; CHECK-ALL-LABEL: test_fptosi_i32:
247 ; CHECK-FP16: vcvtb.f32.f16
248 ; CHECK-LIBCALL: bl __aeabi_h2f
249 ; CHECK-VFP: vcvt.s32.f32
250 ; CHECK-NOVFP: bl __aeabi_f2iz
251 define i32 @test_fptosi_i32(ptr %p) #0 {
252   %a = load half, ptr %p, align 2
253   %r = fptosi half %a to i32
254   ret i32 %r
257 ; CHECK-ALL-LABEL: test_fptosi_i64:
258 ; CHECK-FP16: vcvtb.f32.f16
259 ; CHECK-LIBCALL: bl __aeabi_h2f
260 ; CHECK-ALL: bl __aeabi_f2lz
261 define i64 @test_fptosi_i64(ptr %p) #0 {
262   %a = load half, ptr %p, align 2
263   %r = fptosi half %a to i64
264   ret i64 %r
267 ; CHECK-ALL-LABEL: test_fptoui_i32:
268 ; CHECK-FP16: vcvtb.f32.f16
269 ; CHECK-LIBCALL: bl __aeabi_h2f
270 ; CHECK-VFP: vcvt.u32.f32
271 ; CHECK-NOVFP: bl __aeabi_f2uiz
272 define i32 @test_fptoui_i32(ptr %p) #0 {
273   %a = load half, ptr %p, align 2
274   %r = fptoui half %a to i32
275   ret i32 %r
278 ; CHECK-ALL-LABEL: test_fptoui_i64:
279 ; CHECK-FP16: vcvtb.f32.f16
280 ; CHECK-LIBCALL: bl __aeabi_h2f
281 ; CHECK-ALL: bl __aeabi_f2ulz
282 define i64 @test_fptoui_i64(ptr %p) #0 {
283   %a = load half, ptr %p, align 2
284   %r = fptoui half %a to i64
285   ret i64 %r
288 ; CHECK-ALL-LABEL: test_sitofp_i32:
289 ; CHECK-VFP: vcvt.f32.s32
290 ; CHECK-NOVFP: bl __aeabi_i2f
291 ; CHECK-FP16: vcvtb.f16.f32
292 ; CHECK-LIBCALL: bl __aeabi_f2h
293 define void @test_sitofp_i32(i32 %a, ptr %p) #0 {
294   %r = sitofp i32 %a to half
295   store half %r, ptr %p
296   ret void
299 ; CHECK-ALL-LABEL: test_uitofp_i32:
300 ; CHECK-VFP: vcvt.f32.u32
301 ; CHECK-NOVFP: bl __aeabi_ui2f
302 ; CHECK-FP16: vcvtb.f16.f32
303 ; CHECK-LIBCALL: bl __aeabi_f2h
304 define void @test_uitofp_i32(i32 %a, ptr %p) #0 {
305   %r = uitofp i32 %a to half
306   store half %r, ptr %p
307   ret void
310 ; CHECK-ALL-LABEL: test_sitofp_i64:
311 ; CHECK-ALL: bl __aeabi_l2f
312 ; CHECK-FP16: vcvtb.f16.f32
313 ; CHECK-LIBCALL: bl __aeabi_f2h
314 define void @test_sitofp_i64(i64 %a, ptr %p) #0 {
315   %r = sitofp i64 %a to half
316   store half %r, ptr %p
317   ret void
320 ; CHECK-ALL-LABEL: test_uitofp_i64:
321 ; CHECK-ALL: bl __aeabi_ul2f
322 ; CHECK-FP16: vcvtb.f16.f32
323 ; CHECK-LIBCALL: bl __aeabi_f2h
324 define void @test_uitofp_i64(i64 %a, ptr %p) #0 {
325   %r = uitofp i64 %a to half
326   store half %r, ptr %p
327   ret void
330 ; CHECK-FP16-LABEL: test_fptrunc_float:
331 ; CHECK-FP16: vcvtb.f16.f32
332 ; CHECK-LIBCALL-LABEL: test_fptrunc_float:
333 ; CHECK-LIBCALL: bl __aeabi_f2h
334 define void @test_fptrunc_float(float %f, ptr %p) #0 {
335   %a = fptrunc float %f to half
336   store half %a, ptr %p
337   ret void
340 ; CHECK-FP16-LABEL: test_fptrunc_double:
341 ; CHECK-FP16: bl __aeabi_d2h
342 ; CHECK-LIBCALL-LABEL: test_fptrunc_double:
343 ; CHECK-LIBCALL: bl __aeabi_d2h
344 define void @test_fptrunc_double(double %d, ptr %p) #0 {
345   %a = fptrunc double %d to half
346   store half %a, ptr %p
347   ret void
350 ; CHECK-FP16-LABEL: test_fpextend_float:
351 ; CHECK-FP16: vcvtb.f32.f16
352 ; CHECK-LIBCALL-LABEL: test_fpextend_float:
353 ; CHECK-LIBCALL: bl __aeabi_h2f
354 define float @test_fpextend_float(ptr %p) {
355   %a = load half, ptr %p, align 2
356   %r = fpext half %a to float
357   ret float %r
360 ; CHECK-FP16-LABEL: test_fpextend_double:
361 ; CHECK-FP16: vcvtb.f32.f16
362 ; CHECK-LIBCALL-LABEL: test_fpextend_double:
363 ; CHECK-LIBCALL: bl __aeabi_h2f
364 ; CHECK-VFP: vcvt.f64.f32
365 ; CHECK-NOVFP: bl __aeabi_f2d
366 define double @test_fpextend_double(ptr %p) {
367   %a = load half, ptr %p, align 2
368   %r = fpext half %a to double
369   ret double %r
372 ; CHECK-ALL-LABEL: test_bitcast_halftoi16:
373 ; CHECK-ALL-NEXT: .fnstart
374 ; CHECK-ALL-NEXT: ldrh r0, [r0]
375 ; CHECK-ALL-NEXT: bx lr
376 define i16 @test_bitcast_halftoi16(ptr %p) #0 {
377   %a = load half, ptr %p, align 2
378   %r = bitcast half %a to i16
379   ret i16 %r
382 ; CHECK-ALL-LABEL: test_bitcast_i16tohalf:
383 ; CHECK-ALL-NEXT: .fnstart
384 ; CHECK-ALL-NEXT: strh r0, [r1]
385 ; CHECK-ALL-NEXT: bx lr
386 define void @test_bitcast_i16tohalf(i16 %a, ptr %p) #0 {
387   %r = bitcast i16 %a to half
388   store half %r, ptr %p
389   ret void
392 declare half @llvm.sqrt.f16(half %a) #0
393 declare half @llvm.powi.f16.i32(half %a, i32 %b) #0
394 declare half @llvm.sin.f16(half %a) #0
395 declare half @llvm.cos.f16(half %a) #0
396 declare half @llvm.pow.f16(half %a, half %b) #0
397 declare half @llvm.exp.f16(half %a) #0
398 declare half @llvm.exp2.f16(half %a) #0
399 declare half @llvm.log.f16(half %a) #0
400 declare half @llvm.log10.f16(half %a) #0
401 declare half @llvm.log2.f16(half %a) #0
402 declare half @llvm.fma.f16(half %a, half %b, half %c) #0
403 declare half @llvm.fabs.f16(half %a) #0
404 declare half @llvm.minnum.f16(half %a, half %b) #0
405 declare half @llvm.maxnum.f16(half %a, half %b) #0
406 declare half @llvm.copysign.f16(half %a, half %b) #0
407 declare half @llvm.floor.f16(half %a) #0
408 declare half @llvm.ceil.f16(half %a) #0
409 declare half @llvm.trunc.f16(half %a) #0
410 declare half @llvm.rint.f16(half %a) #0
411 declare half @llvm.nearbyint.f16(half %a) #0
412 declare half @llvm.round.f16(half %a) #0
413 declare half @llvm.fmuladd.f16(half %a, half %b, half %c) #0
415 ; CHECK-ALL-LABEL: test_sqrt:
416 ; CHECK-FP16: vcvtb.f32.f16
417 ; CHECK-FP16: vsqrt.f32
418 ; CHECK-FP16: vcvtb.f16.f32
419 ; CHECK-LIBCALL: bl __aeabi_h2f
420 ; CHECK-LIBCALL-VFP: vsqrt.f32
421 ; CHECK-NOVFP: bl sqrtf
422 ; CHECK-LIBCALL: bl __aeabi_f2h
423 define void @test_sqrt(ptr %p) #0 {
424   %a = load half, ptr %p, align 2
425   %r = call half @llvm.sqrt.f16(half %a)
426   store half %r, ptr %p
427   ret void
430 ; CHECK-FP16-LABEL: test_fpowi:
431 ; CHECK-FP16: vcvtb.f32.f16
432 ; CHECK-FP16: bl __powisf2
433 ; CHECK-FP16: vcvtb.f16.f32
434 ; CHECK-LIBCALL-LABEL: test_fpowi:
435 ; CHECK-LIBCALL: bl __aeabi_h2f
436 ; CHECK-LIBCALL: bl __powisf2
437 ; CHECK-LIBCALL: bl __aeabi_f2h
438 define void @test_fpowi(ptr %p, i32 %b) #0 {
439   %a = load half, ptr %p, align 2
440   %r = call half @llvm.powi.f16.i32(half %a, i32 %b)
441   store half %r, ptr %p
442   ret void
445 ; CHECK-FP16-LABEL: test_sin:
446 ; CHECK-FP16: vcvtb.f32.f16
447 ; CHECK-FP16: bl sinf
448 ; CHECK-FP16: vcvtb.f16.f32
449 ; CHECK-LIBCALL-LABEL: test_sin:
450 ; CHECK-LIBCALL: bl __aeabi_h2f
451 ; CHECK-LIBCALL: bl sinf
452 ; CHECK-LIBCALL: bl __aeabi_f2h
453 define void @test_sin(ptr %p) #0 {
454   %a = load half, ptr %p, align 2
455   %r = call half @llvm.sin.f16(half %a)
456   store half %r, ptr %p
457   ret void
460 ; CHECK-FP16-LABEL: test_cos:
461 ; CHECK-FP16: vcvtb.f32.f16
462 ; CHECK-FP16: bl cosf
463 ; CHECK-FP16: vcvtb.f16.f32
464 ; CHECK-LIBCALL-LABEL: test_cos:
465 ; CHECK-LIBCALL: bl __aeabi_h2f
466 ; CHECK-LIBCALL: bl cosf
467 ; CHECK-LIBCALL: bl __aeabi_f2h
468 define void @test_cos(ptr %p) #0 {
469   %a = load half, ptr %p, align 2
470   %r = call half @llvm.cos.f16(half %a)
471   store half %r, ptr %p
472   ret void
475 ; CHECK-FP16-LABEL: test_pow:
476 ; CHECK-FP16: vcvtb.f32.f16
477 ; CHECK-FP16: vcvtb.f32.f16
478 ; CHECK-FP16: bl powf
479 ; CHECK-FP16: vcvtb.f16.f32
480 ; CHECK-LIBCALL-LABEL: test_pow:
481 ; CHECK-LIBCALL: bl __aeabi_h2f
482 ; CHECK-LIBCALL: bl __aeabi_h2f
483 ; CHECK-LIBCALL: bl powf
484 ; CHECK-LIBCALL: bl __aeabi_f2h
485 define void @test_pow(ptr %p, ptr %q) #0 {
486   %a = load half, ptr %p, align 2
487   %b = load half, ptr %q, align 2
488   %r = call half @llvm.pow.f16(half %a, half %b)
489   store half %r, ptr %p
490   ret void
493 ; CHECK-FP16-LABEL: test_cbrt:
494 ; CHECK-FP16: vcvtb.f32.f16
495 ; CHECK-FP16: bl powf
496 ; CHECK-FP16: vcvtb.f16.f32
497 ; CHECK-LIBCALL-LABEL: test_cbrt:
498 ; CHECK-LIBCALL: bl __aeabi_h2f
499 ; CHECK-LIBCALL: bl powf
500 ; CHECK-LIBCALL: bl __aeabi_f2h
501 define void @test_cbrt(ptr %p) #0 {
502   %a = load half, ptr %p, align 2
503   %r = call half @llvm.pow.f16(half %a, half 0x3FD5540000000000)
504   store half %r, ptr %p
505   ret void
508 ; CHECK-FP16-LABEL: test_exp:
509 ; CHECK-FP16: vcvtb.f32.f16
510 ; CHECK-FP16: bl expf
511 ; CHECK-FP16: vcvtb.f16.f32
512 ; CHECK-LIBCALL-LABEL: test_exp:
513 ; CHECK-LIBCALL: bl __aeabi_h2f
514 ; CHECK-LIBCALL: bl expf
515 ; CHECK-LIBCALL: bl __aeabi_f2h
516 define void @test_exp(ptr %p) #0 {
517   %a = load half, ptr %p, align 2
518   %r = call half @llvm.exp.f16(half %a)
519   store half %r, ptr %p
520   ret void
523 ; CHECK-FP16-LABEL: test_exp2:
524 ; CHECK-FP16: vcvtb.f32.f16
525 ; CHECK-FP16: bl exp2f
526 ; CHECK-FP16: vcvtb.f16.f32
527 ; CHECK-LIBCALL-LABEL: test_exp2:
528 ; CHECK-LIBCALL: bl __aeabi_h2f
529 ; CHECK-LIBCALL: bl exp2f
530 ; CHECK-LIBCALL: bl __aeabi_f2h
531 define void @test_exp2(ptr %p) #0 {
532   %a = load half, ptr %p, align 2
533   %r = call half @llvm.exp2.f16(half %a)
534   store half %r, ptr %p
535   ret void
538 ; CHECK-FP16-LABEL: test_log:
539 ; CHECK-FP16: vcvtb.f32.f16
540 ; CHECK-FP16: bl logf
541 ; CHECK-FP16: vcvtb.f16.f32
542 ; CHECK-LIBCALL-LABEL: test_log:
543 ; CHECK-LIBCALL: bl __aeabi_h2f
544 ; CHECK-LIBCALL: bl logf
545 ; CHECK-LIBCALL: bl __aeabi_f2h
546 define void @test_log(ptr %p) #0 {
547   %a = load half, ptr %p, align 2
548   %r = call half @llvm.log.f16(half %a)
549   store half %r, ptr %p
550   ret void
553 ; CHECK-FP16-LABEL: test_log10:
554 ; CHECK-FP16: vcvtb.f32.f16
555 ; CHECK-FP16: bl log10f
556 ; CHECK-FP16: vcvtb.f16.f32
557 ; CHECK-LIBCALL-LABEL: test_log10:
558 ; CHECK-LIBCALL: bl __aeabi_h2f
559 ; CHECK-LIBCALL: bl log10f
560 ; CHECK-LIBCALL: bl __aeabi_f2h
561 define void @test_log10(ptr %p) #0 {
562   %a = load half, ptr %p, align 2
563   %r = call half @llvm.log10.f16(half %a)
564   store half %r, ptr %p
565   ret void
568 ; CHECK-FP16-LABEL: test_log2:
569 ; CHECK-FP16: vcvtb.f32.f16
570 ; CHECK-FP16: bl log2f
571 ; CHECK-FP16: vcvtb.f16.f32
572 ; CHECK-LIBCALL-LABEL: test_log2:
573 ; CHECK-LIBCALL: bl __aeabi_h2f
574 ; CHECK-LIBCALL: bl log2f
575 ; CHECK-LIBCALL: bl __aeabi_f2h
576 define void @test_log2(ptr %p) #0 {
577   %a = load half, ptr %p, align 2
578   %r = call half @llvm.log2.f16(half %a)
579   store half %r, ptr %p
580   ret void
583 ; CHECK-FP16-LABEL: test_fma:
584 ; CHECK-FP16: vcvtb.f32.f16
585 ; CHECK-FP16: vcvtb.f32.f16
586 ; CHECK-FP16: vcvtb.f32.f16
587 ; CHECK-FP16: bl fmaf
588 ; CHECK-FP16: vcvtb.f16.f32
589 ; CHECK-LIBCALL-LABEL: test_fma:
590 ; CHECK-LIBCALL: bl __aeabi_h2f
591 ; CHECK-LIBCALL: bl __aeabi_h2f
592 ; CHECK-LIBCALL: bl __aeabi_h2f
593 ; CHECK-LIBCALL: bl fmaf
594 ; CHECK-LIBCALL: bl __aeabi_f2h
595 define void @test_fma(ptr %p, ptr %q, ptr %r) #0 {
596   %a = load half, ptr %p, align 2
597   %b = load half, ptr %q, align 2
598   %c = load half, ptr %r, align 2
599   %v = call half @llvm.fma.f16(half %a, half %b, half %c)
600   store half %v, ptr %p
601   ret void
604 ; CHECK-FP16-LABEL: test_fabs:
605 ; CHECK-FP16: vcvtb.f32.f16
606 ; CHECK-FP16: vabs.f32
607 ; CHECK-FP16: vcvtb.f16.f32
608 ; CHECK-LIBCALL-LABEL: test_fabs:
609 ; CHECK-LIBCALL: bl __aeabi_h2f
610 ; CHECK-LIBCALL: bic
611 ; CHECK-LIBCALL: bl __aeabi_f2h
612 define void @test_fabs(ptr %p) {
613   %a = load half, ptr %p, align 2
614   %r = call half @llvm.fabs.f16(half %a)
615   store half %r, ptr %p
616   ret void
619 ; CHECK-FP16-LABEL: test_minnum:
620 ; CHECK-FP16: vcvtb.f32.f16
621 ; CHECK-FP16: vcvtb.f32.f16
622 ; CHECK-FP16: bl fminf
623 ; CHECK-FP16: vcvtb.f16.f32
624 ; CHECK-LIBCALL-LABEL: test_minnum:
625 ; CHECK-LIBCALL: bl __aeabi_h2f
626 ; CHECK-LIBCALL: bl __aeabi_h2f
627 ; CHECK-LIBCALL: bl fminf
628 ; CHECK-LIBCALL: bl __aeabi_f2h
629 define void @test_minnum(ptr %p, ptr %q) #0 {
630   %a = load half, ptr %p, align 2
631   %b = load half, ptr %q, align 2
632   %r = call half @llvm.minnum.f16(half %a, half %b)
633   store half %r, ptr %p
634   ret void
637 ; CHECK-FP16-LABEL: test_maxnum:
638 ; CHECK-FP16: vcvtb.f32.f16
639 ; CHECK-FP16: vcvtb.f32.f16
640 ; CHECK-FP16: bl fmaxf
641 ; CHECK-FP16: vcvtb.f16.f32
642 ; CHECK-LIBCALL-LABEL: test_maxnum:
643 ; CHECK-LIBCALL: bl __aeabi_h2f
644 ; CHECK-LIBCALL: bl __aeabi_h2f
645 ; CHECK-LIBCALL: bl fmaxf
646 ; CHECK-LIBCALL: bl __aeabi_f2h
647 define void @test_maxnum(ptr %p, ptr %q) #0 {
648   %a = load half, ptr %p, align 2
649   %b = load half, ptr %q, align 2
650   %r = call half @llvm.maxnum.f16(half %a, half %b)
651   store half %r, ptr %p
652   ret void
655 ; CHECK-ALL-LABEL: test_minimum:
656 ; CHECK-FP16: vmov.f32 s0, #1.000000e+00
657 ; CHECK-FP16: vcvtb.f32.f16
658 ; CHECK-LIBCALL: bl __aeabi_h2f
659 ; CHECK-LIBCALL-VFP: vmov.f32 s{{[0-9]+}}, #1.000000e+00
660 ; CHECK-NOVFP: mov r{{[0-9]+}}, #1065353216
661 ; CHECK-VFP: vcmp.f32
662 ; CHECK-VFP: vmrs
663 ; CHECK-VFP: vmovlt.f32
664 ; CHECK-NOVFP: bl __aeabi_fcmpge
665 ; CHECK-FP16: vcvtb.f16.f32
666 ; CHECK-LIBCALL: bl __aeabi_f2h
667 define void @test_minimum(ptr %p) #0 {
668   %a = load half, ptr %p, align 2
669   %c = fcmp ult half %a, 1.0
670   %r = select i1 %c, half %a, half 1.0
671   store half %r, ptr %p
672   ret void
675 ; CHECK-ALL-LABEL: test_maximum:
676 ; CHECK-FP16: vmov.f32 s0, #1.000000e+00
677 ; CHECK-FP16: vcvtb.f32.f16
678 ; CHECK-LIBCALL: bl __aeabi_h2f
679 ; CHECK-LIBCALL-VFP: vmov.f32 s0, #1.000000e+00
680 ; CHECK-NOVFP: mov r{{[0-9]+}}, #1065353216
681 ; CHECK-VFP: vcmp.f32
682 ; CHECK-VFP: vmrs
683 ; CHECK-VFP: vmovhi.f32
684 ; CHECK-NOVFP: bl __aeabi_fcmple
685 ; CHECK-FP16: vcvtb.f16.f32
686 ; CHECK-LIBCALL: bl __aeabi_f2h
687 define void @test_maximum(ptr %p) #0 {
688   %a = load half, ptr %p, align 2
689   %c = fcmp ugt half %a, 1.0
690   %r = select i1 %c, half %a, half 1.0
691   store half %r, ptr %p
692   ret void
695 ; CHECK-FP16-LABEL: test_copysign:
696 ; CHECK-FP16:         ldrh r2, [r0]
697 ; CHECK-FP16-NEXT:    vmov.i32 d16, #0x80000000
698 ; CHECK-FP16-NEXT:    ldrh r1, [r1]
699 ; CHECK-FP16-NEXT:    vmov s0, r2
700 ; CHECK-FP16-NEXT:    vmov s2, r1
701 ; CHECK-FP16-NEXT:    vcvtb.f32.f16 s0, s0
702 ; CHECK-FP16-NEXT:    vcvtb.f32.f16 s2, s2
703 ; CHECK-FP16-NEXT:    vbit d0, d1, d16
704 ; CHECK-FP16-NEXT:    vcvtb.f16.f32 s0, s0
705 ; CHECK-FP16-NEXT:    vmov r1, s0
706 ; CHECK-FP16-NEXT:    strh r1, [r0]
707 ; CHECK-FP16-NEXT:    bx lr
709 ; CHECK-LIBCALL-LABEL: test_copysign:
710 ; CHECK-LIBCALL-VFP:         .fnstart
711 ; CHECK-LIBCALL-VFP-NEXT:    .save {r4, r5, r11, lr}
712 ; CHECK-LIBCALL-VFP-NEXT:    push {r4, r5, r11, lr}
713 ; CHECK-LIBCALL-VFP-NEXT:    .vsave {d8, d9}
714 ; CHECK-LIBCALL-VFP-NEXT:    vpush {d8, d9}
715 ; CHECK-LIBCALL-VFP-NEXT:    mov r5, r0
716 ; CHECK-LIBCALL-VFP-NEXT:    ldrh r0, [r0]
717 ; CHECK-LIBCALL-VFP-NEXT:    mov r4, r1
718 ; CHECK-LIBCALL: bl __aeabi_h2f
719 ; CHECK-LIBCALL-VFP:         ldrh r1, [r4]
720 ; CHECK-LIBCALL-VFP-NEXT:    vmov s18, r0
721 ; CHECK-LIBCALL-VFP-NEXT:    vmov.i32 d8, #0x80000000
722 ; CHECK-LIBCALL-VFP-NEXT:    mov r0, r1
723 ; CHECK-LIBCALL: bl __aeabi_h2f
724 ; CHECK-LIBCALL-VFP:         vmov s0, r0
725 ; CHECK-LIBCALL-VFP-NEXT:    vbif d0, d9, d8
726 ; CHECK-LIBCALL-VFP-NEXT:    vmov r0, s0
727 ; CHECK-LIBCALL: bl __aeabi_f2h
728 ; CHECK-LIBCALL-VFP:         strh r0, [r5]
729 ; CHECK-LIBCALL-VFP-NEXT:    vpop {d8, d9}
730 ; CHECK-LIBCALL-VFP-NEXT:    pop {r4, r5, r11, pc}
731 ; CHECK-NOVFP: and
732 ; CHECK-NOVFP: bic
733 ; CHECK-NOVFP: orr
734 define void @test_copysign(ptr %p, ptr %q) #0 {
735   %a = load half, ptr %p, align 2
736   %b = load half, ptr %q, align 2
737   %r = call half @llvm.copysign.f16(half %a, half %b)
738   store half %r, ptr %p
739   ret void
742 ; CHECK-FP16-LABEL: test_floor:
743 ; CHECK-FP16: vcvtb.f32.f16
744 ; CHECK-FP16: bl floorf
745 ; CHECK-FP16: vcvtb.f16.f32
746 ; CHECK-LIBCALL-LABEL: test_floor:
747 ; CHECK-LIBCALL: bl __aeabi_h2f
748 ; CHECK-LIBCALL: bl floorf
749 ; CHECK-LIBCALL: bl __aeabi_f2h
750 define void @test_floor(ptr %p) {
751   %a = load half, ptr %p, align 2
752   %r = call half @llvm.floor.f16(half %a)
753   store half %r, ptr %p
754   ret void
757 ; CHECK-FP16-LABEL: test_ceil:
758 ; CHECK-FP16: vcvtb.f32.f16
759 ; CHECK-FP16: bl ceilf
760 ; CHECK-FP16: vcvtb.f16.f32
761 ; CHECK-LIBCALL-LABEL: test_ceil:
762 ; CHECK-LIBCALL: bl __aeabi_h2f
763 ; CHECK-LIBCALL: bl ceilf
764 ; CHECK-LIBCALL: bl __aeabi_f2h
765 define void @test_ceil(ptr %p) {
766   %a = load half, ptr %p, align 2
767   %r = call half @llvm.ceil.f16(half %a)
768   store half %r, ptr %p
769   ret void
772 ; CHECK-FP16-LABEL: test_trunc:
773 ; CHECK-FP16: vcvtb.f32.f16
774 ; CHECK-FP16: bl truncf
775 ; CHECK-FP16: vcvtb.f16.f32
776 ; CHECK-LIBCALL-LABEL: test_trunc:
777 ; CHECK-LIBCALL: bl __aeabi_h2f
778 ; CHECK-LIBCALL: bl truncf
779 ; CHECK-LIBCALL: bl __aeabi_f2h
780 define void @test_trunc(ptr %p) {
781   %a = load half, ptr %p, align 2
782   %r = call half @llvm.trunc.f16(half %a)
783   store half %r, ptr %p
784   ret void
787 ; CHECK-FP16-LABEL: test_rint:
788 ; CHECK-FP16: vcvtb.f32.f16
789 ; CHECK-FP16: bl rintf
790 ; CHECK-FP16: vcvtb.f16.f32
791 ; CHECK-LIBCALL-LABEL: test_rint:
792 ; CHECK-LIBCALL: bl __aeabi_h2f
793 ; CHECK-LIBCALL: bl rintf
794 ; CHECK-LIBCALL: bl __aeabi_f2h
795 define void @test_rint(ptr %p) {
796   %a = load half, ptr %p, align 2
797   %r = call half @llvm.rint.f16(half %a)
798   store half %r, ptr %p
799   ret void
802 ; CHECK-FP16-LABEL: test_nearbyint:
803 ; CHECK-FP16: vcvtb.f32.f16
804 ; CHECK-FP16: bl nearbyintf
805 ; CHECK-FP16: vcvtb.f16.f32
806 ; CHECK-LIBCALL-LABEL: test_nearbyint:
807 ; CHECK-LIBCALL: bl __aeabi_h2f
808 ; CHECK-LIBCALL: bl nearbyintf
809 ; CHECK-LIBCALL: bl __aeabi_f2h
810 define void @test_nearbyint(ptr %p) {
811   %a = load half, ptr %p, align 2
812   %r = call half @llvm.nearbyint.f16(half %a)
813   store half %r, ptr %p
814   ret void
817 ; CHECK-FP16-LABEL: test_round:
818 ; CHECK-FP16: vcvtb.f32.f16
819 ; CHECK-FP16: bl roundf
820 ; CHECK-FP16: vcvtb.f16.f32
821 ; CHECK-LIBCALL-LABEL: test_round:
822 ; CHECK-LIBCALL: bl __aeabi_h2f
823 ; CHECK-LIBCALL: bl roundf
824 ; CHECK-LIBCALL: bl __aeabi_f2h
825 define void @test_round(ptr %p) {
826   %a = load half, ptr %p, align 2
827   %r = call half @llvm.round.f16(half %a)
828   store half %r, ptr %p
829   ret void
832 ; CHECK-FP16-LABEL: test_fmuladd:
833 ; CHECK-FP16: vcvtb.f32.f16
834 ; CHECK-FP16: vcvtb.f32.f16
835 ; CHECK-FP16: vcvtb.f32.f16
836 ; CHECK-FP16: vmla.f32
837 ; CHECK-FP16: vcvtb.f16.f32
838 ; CHECK-LIBCALL-LABEL: test_fmuladd:
839 ; CHECK-LIBCALL: bl __aeabi_h2f
840 ; CHECK-LIBCALL: bl __aeabi_h2f
841 ; CHECK-LIBCALL: bl __aeabi_h2f
842 ; CHECK-LIBCALL-VFP: vmla.f32
843 ; CHECK-NOVFP: bl __aeabi_fmul
844 ; CHECK-LIBCALL: bl __aeabi_f2h
845 define void @test_fmuladd(ptr %p, ptr %q, ptr %r) #0 {
846   %a = load half, ptr %p, align 2
847   %b = load half, ptr %q, align 2
848   %c = load half, ptr %r, align 2
849   %v = call half @llvm.fmuladd.f16(half %a, half %b, half %c)
850   store half %v, ptr %p
851   ret void
854 ; f16 vectors are not legal in the backend.  Vector elements are not assigned
855 ; to the register, but are stored in the stack instead.  Hence insertelement
856 ; and extractelement have these extra loads and stores.
858 ; CHECK-ALL-LABEL: test_insertelement:
859 ; CHECK-ALL: sub sp, sp, #8
861 ; CHECK-VFP:    and     
862 ; CHECK-VFP:    mov     
863 ; CHECK-VFP:    ldrd    
864 ; CHECK-VFP:    orr     
865 ; CHECK-VFP:    ldrh    
866 ; CHECK-VFP:    stm     
867 ; CHECK-VFP:    strh    
868 ; CHECK-VFP:    ldm     
869 ; CHECK-VFP:    stm     
871 ; CHECK-NOVFP: ldrh
872 ; CHECK-NOVFP: ldrh
873 ; CHECK-NOVFP: ldrh
874 ; CHECK-NOVFP: ldrh
875 ; CHECK-NOVFP-DAG: strh
876 ; CHECK-NOVFP-DAG: strh
877 ; CHECK-NOVFP-DAG: mov
878 ; CHECK-NOVFP-DAG: ldrh
879 ; CHECK-NOVFP-DAG: orr
880 ; CHECK-NOVFP-DAG: strh
881 ; CHECK-NOVFP-DAG: strh
882 ; CHECK-NOVFP-DAG: strh
883 ; CHECK-NOVFP-DAG: ldrh
884 ; CHECK-NOVFP-DAG: ldrh
885 ; CHECK-NOVFP-DAG: ldrh
886 ; CHECK-NOVFP-DAG: strh
887 ; CHECK-NOVFP-DAG: strh
888 ; CHECK-NOVFP-DAG: strh
889 ; CHECK-NOVFP-DAG: strh
891 ; CHECK-ALL: add sp, sp, #8
892 define void @test_insertelement(ptr %p, ptr %q, i32 %i) #0 {
893   %a = load half, ptr %p, align 2
894   %b = load <4 x half>, ptr %q, align 8
895   %c = insertelement <4 x half> %b, half %a, i32 %i
896   store <4 x half> %c, ptr %q
897   ret void
900 ; CHECK-ALL-LABEL: test_extractelement:
901 ; CHECK-VFP: push {{{.*}}, lr}
902 ; CHECK-VFP: sub sp, sp, #8
903 ; CHECK-VFP: ldrd
904 ; CHECK-VFP: mov
905 ; CHECK-VFP: orr
906 ; CHECK-VFP: ldrh
907 ; CHECK-VFP: strh
908 ; CHECK-VFP: add sp, sp, #8
909 ; CHECK-VFP: pop {{{.*}}, pc}
910 ; CHECK-NOVFP: ldrh
911 ; CHECK-NOVFP: strh
912 ; CHECK-NOVFP: ldrh
913 ; CHECK-NOVFP: strh
914 ; CHECK-NOVFP: ldrh
915 ; CHECK-NOVFP: strh
916 ; CHECK-NOVFP: ldrh
917 ; CHECK-NOVFP: strh
918 ; CHECK-NOVFP: ldrh
919 define void @test_extractelement(ptr %p, ptr %q, i32 %i) #0 {
920   %a = load <4 x half>, ptr %q, align 8
921   %b = extractelement <4 x half> %a, i32 %i
922   store half %b, ptr %p
923   ret void
926 ; test struct operations
928 %struct.dummy = type { i32, half }
930 ; CHECK-ALL-LABEL: test_insertvalue:
931 ; CHECK-ALL-DAG: ldr
932 ; CHECK-ALL-DAG: ldrh
933 ; CHECK-ALL-DAG: strh
934 ; CHECK-ALL-DAG: str
935 define void @test_insertvalue(ptr %p, ptr %q) {
936   %a = load %struct.dummy, ptr %p
937   %b = load half, ptr %q
938   %c = insertvalue %struct.dummy %a, half %b, 1
939   store %struct.dummy %c, ptr %p
940   ret void
943 ; CHECK-ALL-LABEL: test_extractvalue:
944 ; CHECK-ALL: .fnstart
945 ; CHECK-ALL: ldrh
946 ; CHECK-ALL: strh
947 define void @test_extractvalue(ptr %p, ptr %q) {
948   %a = load %struct.dummy, ptr %p
949   %b = extractvalue %struct.dummy %a, 1
950   store half %b, ptr %q
951   ret void
954 ; CHECK-ALL-LABEL: test_struct_return:
955 ; CHECK-VFP-LIBCALL: bl __aeabi_h2f
956 ; CHECK-NOVFP-DAG: ldr
957 ; CHECK-NOVFP-DAG: ldrh
958 define %struct.dummy @test_struct_return(ptr %p) {
959   %a = load %struct.dummy, ptr %p
960   ret %struct.dummy %a
963 ; CHECK-ALL-LABEL: test_struct_arg:
964 ; CHECK-ALL-NEXT: .fnstart
965 ; CHECK-NOVFP-NEXT: mov r0, r1
966 ; CHECK-ALL-NEXT: bx lr
967 define half @test_struct_arg(%struct.dummy %p) {
968   %a = extractvalue %struct.dummy %p, 1
969   ret half %a
972 ; CHECK-LABEL: test_uitofp_i32_fadd:
973 ; CHECK-VFP-DAG: vcvt.f32.u32
974 ; CHECK-NOVFP-DAG: bl __aeabi_ui2f
976 ; CHECK-FP16-DAG: vcvtb.f16.f32
977 ; CHECK-FP16-DAG: vcvtb.f32.f16
978 ; CHECK-LIBCALL-DAG: bl __aeabi_h2f
979 ; CHECK-LIBCALL-DAG: bl __aeabi_h2f
981 ; CHECK-VFP-DAG: vadd.f32
982 ; CHECK-NOVFP-DAG: bl __aeabi_fadd
984 ; CHECK-FP16-DAG: vcvtb.f16.f32
985 ; CHECK-LIBCALL-DAG: bl __aeabi_f2h
986 define half @test_uitofp_i32_fadd(i32 %a, half %b) #0 {
987   %c = uitofp i32 %a to half
988   %r = fadd half %b, %c
989   ret half %r
992 ; CHECK-LABEL: test_sitofp_i32_fadd:
993 ; CHECK-VFP-DAG: vcvt.f32.s32
994 ; CHECK-NOVFP-DAG: bl __aeabi_i2f
996 ; CHECK-FP16-DAG: vcvtb.f16.f32
997 ; CHECK-FP16-DAG: vcvtb.f32.f16
998 ; CHECK-LIBCALL-DAG: bl __aeabi_h2f
999 ; CHECK-LIBCALL-DAG: bl __aeabi_h2f
1001 ; CHECK-VFP-DAG: vadd.f32
1002 ; CHECK-NOVFP-DAG: bl __aeabi_fadd
1004 ; CHECK-FP16-DAG: vcvtb.f16.f32
1005 ; CHECK-LIBCALL-DAG: bl __aeabi_f2h
1006 define half @test_sitofp_i32_fadd(i32 %a, half %b) #0 {
1007   %c = sitofp i32 %a to half
1008   %r = fadd half %b, %c
1009   ret half %r
1012 attributes #0 = { nounwind }