]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/CodeGen/ARM/fp16-promote.ll
Vendor import of llvm release_40 branch r292009:
[FreeBSD/FreeBSD.git] / test / CodeGen / ARM / fp16-promote.ll
1 ; RUN: llc -asm-verbose=false < %s -mattr=+vfp3,+fp16 | FileCheck %s -check-prefix=CHECK-FP16  --check-prefix=CHECK-VFP -check-prefix=CHECK-ALL
2 ; RUN: llc -asm-verbose=false < %s | FileCheck %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=-vfp2 | FileCheck %s --check-prefix=CHECK-LIBCALL -check-prefix=CHECK-NOVFP -check-prefix=CHECK-ALL
4
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"
7
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(half* %p, half* %q) #0 {
18   %a = load half, half* %p, align 2
19   %b = load half, half* %q, align 2
20   %r = fadd half %a, %b
21   store half %r, half* %p
22   ret void
23 }
24
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(half* %p, half* %q) #0 {
35   %a = load half, half* %p, align 2
36   %b = load half, half* %q, align 2
37   %r = fsub half %a, %b
38   store half %r, half* %p
39   ret void
40 }
41
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(half* %p, half* %q) #0 {
52   %a = load half, half* %p, align 2
53   %b = load half, half* %q, align 2
54   %r = fmul half %a, %b
55   store half %r, half* %p
56   ret void
57 }
58
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(half* %p, half* %q) #0 {
69   %a = load half, half* %p, align 2
70   %b = load half, half* %q, align 2
71   %r = fdiv half %a, %b
72   store half %r, half* %p
73   ret void
74 }
75
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
87   %r = frem half %a, %b
88   store half %r, half* %p
89   ret void
90 }
91
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
99   ret void
100 }
101
102 ; Testing only successfull compilation of function calls.  In ARM ABI, half
103 ; args and returns are handled as f32.
104
105 declare half @test_callee(half %a, half %b) #0
106
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
116 }
117
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
133 }
134
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
147 }
148
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
161   ret void
162 }
163
164 ; Test only two variants of fcmp.  These get translated to f32 vcmpe
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: vcmpe.f32
172 ; CHECK-NOVFP: bl __aeabi_fcmpeq
173 ; CHECK-FP16: vmrs APSR_nzcv, fpscr
174 ; CHECK-ALL: movw{{ne|eq}}
175 define i1 @test_fcmp_une(half* %p, half* %q) #0 {
176   %a = load half, half* %p, align 2
177   %b = load half, half* %q, align 2
178   %r = fcmp une half %a, %b
179   ret i1 %r
180 }
181
182 ; CHECK-ALL-LABEL: test_fcmp_ueq:
183 ; CHECK-FP16: vcvtb.f32.f16
184 ; CHECK-FP16: vcvtb.f32.f16
185 ; CHECK-LIBCALL: bl __aeabi_h2f
186 ; CHECK-LIBCALL: bl __aeabi_h2f
187 ; CHECK-VFP: vcmpe.f32
188 ; CHECK-NOVFP: bl __aeabi_fcmpeq
189 ; CHECK-FP16: vmrs APSR_nzcv, fpscr
190 ; CHECK-LIBCALL: movw{{ne|eq}}
191 define i1 @test_fcmp_ueq(half* %p, half* %q) #0 {
192   %a = load half, half* %p, align 2
193   %b = load half, half* %q, align 2
194   %r = fcmp ueq half %a, %b
195   ret i1 %r
196 }
197
198 ; CHECK-ALL-LABEL: test_br_cc:
199 ; CHECK-FP16: vcvtb.f32.f16
200 ; CHECK-FP16: vcvtb.f32.f16
201 ; CHECK-LIBCALL: bl __aeabi_h2f
202 ; CHECK-LIBCALL: bl __aeabi_h2f
203 ; CHECK-VFP: vcmpe.f32
204 ; CHECK-NOVFP: bl __aeabi_fcmplt
205 ; CHECK-FP16: vmrs APSR_nzcv, fpscr
206 ; CHECK-VFP: strmi
207 ; CHECK-VFP: strpl
208 ; CHECK-NOVFP: strne
209 ; CHECK-NOVFP: streq
210 define void @test_br_cc(half* %p, half* %q, i32* %p1, i32* %p2) #0 {
211   %a = load half, half* %p, align 2
212   %b = load half, half* %q, align 2
213   %c = fcmp uge half %a, %b
214   br i1 %c, label %then, label %else
215 then:
216   store i32 0, i32* %p1
217   ret void
218 else:
219   store i32 0, i32* %p2
220   ret void
221 }
222
223 declare i1 @test_dummy(half* %p) #0
224 ; CHECK-ALL-LABEL: test_phi:
225 ; CHECK-FP16: vcvtb.f32.f16
226 ; CHECK-FP16: [[LOOP:.LBB[1-9_]+]]:
227 ; CHECK-FP16: vcvtb.f32.f16
228 ; CHECK-FP16: bl      test_dummy
229 ; CHECK-FP16: bne     [[LOOP]]
230 ; CHECK-FP16: vcvtb.f16.f32
231 ; CHECK-LIBCALL-VFP: bl __aeabi_h2f
232 ; CHECK-LIBCALL: [[LOOP:.LBB[1-9_]+]]:
233 ; CHECK-LIBCALL-VFP: bl __aeabi_h2f
234 ; CHECK-LIBCALL: bl test_dummy
235 ; CHECK-LIBCALL: bne     [[LOOP]]
236 ; CHECK-LIBCALL-VFP: bl __aeabi_f2h
237 define void @test_phi(half* %p) #0 {
238 entry:
239   %a = load half, half* %p
240   br label %loop
241 loop:
242   %r = phi half [%a, %entry], [%b, %loop]
243   %b = load half, half* %p
244   %c = call i1 @test_dummy(half* %p)
245   br i1 %c, label %loop, label %return
246 return:
247   store half %r, half* %p
248   ret void
249 }
250
251 ; CHECK-ALL-LABEL: test_fptosi_i32:
252 ; CHECK-FP16: vcvtb.f32.f16
253 ; CHECK-LIBCALL: bl __aeabi_h2f
254 ; CHECK-VFP: vcvt.s32.f32
255 ; CHECK-NOVFP: bl __aeabi_f2iz
256 define i32 @test_fptosi_i32(half* %p) #0 {
257   %a = load half, half* %p, align 2
258   %r = fptosi half %a to i32
259   ret i32 %r
260 }
261
262 ; CHECK-ALL-LABEL: test_fptosi_i64:
263 ; CHECK-FP16: vcvtb.f32.f16
264 ; CHECK-LIBCALL: bl __aeabi_h2f
265 ; CHECK-ALL: bl __aeabi_f2lz
266 define i64 @test_fptosi_i64(half* %p) #0 {
267   %a = load half, half* %p, align 2
268   %r = fptosi half %a to i64
269   ret i64 %r
270 }
271
272 ; CHECK-ALL-LABEL: test_fptoui_i32:
273 ; CHECK-FP16: vcvtb.f32.f16
274 ; CHECK-LIBCALL: bl __aeabi_h2f
275 ; CHECK-VFP: vcvt.u32.f32
276 ; CHECK-NOVFP: bl __aeabi_f2uiz
277 define i32 @test_fptoui_i32(half* %p) #0 {
278   %a = load half, half* %p, align 2
279   %r = fptoui half %a to i32
280   ret i32 %r
281 }
282
283 ; CHECK-ALL-LABEL: test_fptoui_i64:
284 ; CHECK-FP16: vcvtb.f32.f16
285 ; CHECK-LIBCALL: bl __aeabi_h2f
286 ; CHECK-ALL: bl __aeabi_f2ulz
287 define i64 @test_fptoui_i64(half* %p) #0 {
288   %a = load half, half* %p, align 2
289   %r = fptoui half %a to i64
290   ret i64 %r
291 }
292
293 ; CHECK-ALL-LABEL: test_sitofp_i32:
294 ; CHECK-VFP: vcvt.f32.s32
295 ; CHECK-NOVFP: bl __aeabi_i2f
296 ; CHECK-FP16: vcvtb.f16.f32
297 ; CHECK-LIBCALL: bl __aeabi_f2h
298 define void @test_sitofp_i32(i32 %a, half* %p) #0 {
299   %r = sitofp i32 %a to half
300   store half %r, half* %p
301   ret void
302 }
303
304 ; CHECK-ALL-LABEL: test_uitofp_i32:
305 ; CHECK-VFP: vcvt.f32.u32
306 ; CHECK-NOVFP: bl __aeabi_ui2f
307 ; CHECK-FP16: vcvtb.f16.f32
308 ; CHECK-LIBCALL: bl __aeabi_f2h
309 define void @test_uitofp_i32(i32 %a, half* %p) #0 {
310   %r = uitofp i32 %a to half
311   store half %r, half* %p
312   ret void
313 }
314
315 ; CHECK-ALL-LABEL: test_sitofp_i64:
316 ; CHECK-ALL: bl __aeabi_l2f
317 ; CHECK-FP16: vcvtb.f16.f32
318 ; CHECK-LIBCALL: bl __aeabi_f2h
319 define void @test_sitofp_i64(i64 %a, half* %p) #0 {
320   %r = sitofp i64 %a to half
321   store half %r, half* %p
322   ret void
323 }
324
325 ; CHECK-ALL-LABEL: test_uitofp_i64:
326 ; CHECK-ALL: bl __aeabi_ul2f
327 ; CHECK-FP16: vcvtb.f16.f32
328 ; CHECK-LIBCALL: bl __aeabi_f2h
329 define void @test_uitofp_i64(i64 %a, half* %p) #0 {
330   %r = uitofp i64 %a to half
331   store half %r, half* %p
332   ret void
333 }
334
335 ; CHECK-FP16-LABEL: test_fptrunc_float:
336 ; CHECK-FP16: vcvtb.f16.f32
337 ; CHECK-LIBCALL-LABEL: test_fptrunc_float:
338 ; CHECK-LIBCALL: bl __aeabi_f2h
339 define void @test_fptrunc_float(float %f, half* %p) #0 {
340   %a = fptrunc float %f to half
341   store half %a, half* %p
342   ret void
343 }
344
345 ; CHECK-FP16-LABEL: test_fptrunc_double:
346 ; CHECK-FP16: bl __aeabi_d2h
347 ; CHECK-LIBCALL-LABEL: test_fptrunc_double:
348 ; CHECK-LIBCALL: bl __aeabi_d2h
349 define void @test_fptrunc_double(double %d, half* %p) #0 {
350   %a = fptrunc double %d to half
351   store half %a, half* %p
352   ret void
353 }
354
355 ; CHECK-FP16-LABEL: test_fpextend_float:
356 ; CHECK-FP16: vcvtb.f32.f16
357 ; CHECK-LIBCALL-LABEL: test_fpextend_float:
358 ; CHECK-LIBCALL: bl __aeabi_h2f
359 define float @test_fpextend_float(half* %p) {
360   %a = load half, half* %p, align 2
361   %r = fpext half %a to float
362   ret float %r
363 }
364
365 ; CHECK-FP16-LABEL: test_fpextend_double:
366 ; CHECK-FP16: vcvtb.f32.f16
367 ; CHECK-LIBCALL-LABEL: test_fpextend_double:
368 ; CHECK-LIBCALL: bl __aeabi_h2f
369 ; CHECK-VFP: vcvt.f64.f32
370 ; CHECK-NOVFP: bl __aeabi_f2d
371 define double @test_fpextend_double(half* %p) {
372   %a = load half, half* %p, align 2
373   %r = fpext half %a to double
374   ret double %r
375 }
376
377 ; CHECK-ALL-LABEL: test_bitcast_halftoi16:
378 ; CHECK-ALL-NEXT: .fnstart
379 ; CHECK-ALL-NEXT: ldrh r0, [r0]
380 ; CHECK-ALL-NEXT: bx lr
381 define i16 @test_bitcast_halftoi16(half* %p) #0 {
382   %a = load half, half* %p, align 2
383   %r = bitcast half %a to i16
384   ret i16 %r
385 }
386
387 ; CHECK-ALL-LABEL: test_bitcast_i16tohalf:
388 ; CHECK-ALL-NEXT: .fnstart
389 ; CHECK-ALL-NEXT: strh r0, [r1]
390 ; CHECK-ALL-NEXT: bx lr
391 define void @test_bitcast_i16tohalf(i16 %a, half* %p) #0 {
392   %r = bitcast i16 %a to half
393   store half %r, half* %p
394   ret void
395 }
396
397 declare half @llvm.sqrt.f16(half %a) #0
398 declare half @llvm.powi.f16(half %a, i32 %b) #0
399 declare half @llvm.sin.f16(half %a) #0
400 declare half @llvm.cos.f16(half %a) #0
401 declare half @llvm.pow.f16(half %a, half %b) #0
402 declare half @llvm.exp.f16(half %a) #0
403 declare half @llvm.exp2.f16(half %a) #0
404 declare half @llvm.log.f16(half %a) #0
405 declare half @llvm.log10.f16(half %a) #0
406 declare half @llvm.log2.f16(half %a) #0
407 declare half @llvm.fma.f16(half %a, half %b, half %c) #0
408 declare half @llvm.fabs.f16(half %a) #0
409 declare half @llvm.minnum.f16(half %a, half %b) #0
410 declare half @llvm.maxnum.f16(half %a, half %b) #0
411 declare half @llvm.copysign.f16(half %a, half %b) #0
412 declare half @llvm.floor.f16(half %a) #0
413 declare half @llvm.ceil.f16(half %a) #0
414 declare half @llvm.trunc.f16(half %a) #0
415 declare half @llvm.rint.f16(half %a) #0
416 declare half @llvm.nearbyint.f16(half %a) #0
417 declare half @llvm.round.f16(half %a) #0
418 declare half @llvm.fmuladd.f16(half %a, half %b, half %c) #0
419
420 ; CHECK-ALL-LABEL: test_sqrt:
421 ; CHECK-FP16: vcvtb.f32.f16
422 ; CHECK-FP16: vsqrt.f32
423 ; CHECK-FP16: vcvtb.f16.f32
424 ; CHECK-LIBCALL: bl __aeabi_h2f
425 ; CHECK-VFP-LIBCALL: vsqrt.f32
426 ; CHECK-NOVFP: bl sqrtf
427 ; CHECK-LIBCALL: bl __aeabi_f2h
428 define void @test_sqrt(half* %p) #0 {
429   %a = load half, half* %p, align 2
430   %r = call half @llvm.sqrt.f16(half %a)
431   store half %r, half* %p
432   ret void
433 }
434
435 ; CHECK-FP16-LABEL: test_fpowi:
436 ; CHECK-FP16: vcvtb.f32.f16
437 ; CHECK-FP16: bl __powisf2
438 ; CHECK-FP16: vcvtb.f16.f32
439 ; CHECK-LIBCALL-LABEL: test_fpowi:
440 ; CHECK-LIBCALL: bl __aeabi_h2f
441 ; CHECK-LIBCALL: bl __powisf2
442 ; CHECK-LIBCALL: bl __aeabi_f2h
443 define void @test_fpowi(half* %p, i32 %b) #0 {
444   %a = load half, half* %p, align 2
445   %r = call half @llvm.powi.f16(half %a, i32 %b)
446   store half %r, half* %p
447   ret void
448 }
449
450 ; CHECK-FP16-LABEL: test_sin:
451 ; CHECK-FP16: vcvtb.f32.f16
452 ; CHECK-FP16: bl sinf
453 ; CHECK-FP16: vcvtb.f16.f32
454 ; CHECK-LIBCALL-LABEL: test_sin:
455 ; CHECK-LIBCALL: bl __aeabi_h2f
456 ; CHECK-LIBCALL: bl sinf
457 ; CHECK-LIBCALL: bl __aeabi_f2h
458 define void @test_sin(half* %p) #0 {
459   %a = load half, half* %p, align 2
460   %r = call half @llvm.sin.f16(half %a)
461   store half %r, half* %p
462   ret void
463 }
464
465 ; CHECK-FP16-LABEL: test_cos:
466 ; CHECK-FP16: vcvtb.f32.f16
467 ; CHECK-FP16: bl cosf
468 ; CHECK-FP16: vcvtb.f16.f32
469 ; CHECK-LIBCALL-LABEL: test_cos:
470 ; CHECK-LIBCALL: bl __aeabi_h2f
471 ; CHECK-LIBCALL: bl cosf
472 ; CHECK-LIBCALL: bl __aeabi_f2h
473 define void @test_cos(half* %p) #0 {
474   %a = load half, half* %p, align 2
475   %r = call half @llvm.cos.f16(half %a)
476   store half %r, half* %p
477   ret void
478 }
479
480 ; CHECK-FP16-LABEL: test_pow:
481 ; CHECK-FP16: vcvtb.f32.f16
482 ; CHECK-FP16: vcvtb.f32.f16
483 ; CHECK-FP16: bl powf
484 ; CHECK-FP16: vcvtb.f16.f32
485 ; CHECK-LIBCALL-LABEL: test_pow:
486 ; CHECK-LIBCALL: bl __aeabi_h2f
487 ; CHECK-LIBCALL: bl __aeabi_h2f
488 ; CHECK-LIBCALL: bl powf
489 ; CHECK-LIBCALL: bl __aeabi_f2h
490 define void @test_pow(half* %p, half* %q) #0 {
491   %a = load half, half* %p, align 2
492   %b = load half, half* %q, align 2
493   %r = call half @llvm.pow.f16(half %a, half %b)
494   store half %r, half* %p
495   ret void
496 }
497
498 ; CHECK-FP16-LABEL: test_exp:
499 ; CHECK-FP16: vcvtb.f32.f16
500 ; CHECK-FP16: bl expf
501 ; CHECK-FP16: vcvtb.f16.f32
502 ; CHECK-LIBCALL-LABEL: test_exp:
503 ; CHECK-LIBCALL: bl __aeabi_h2f
504 ; CHECK-LIBCALL: bl expf
505 ; CHECK-LIBCALL: bl __aeabi_f2h
506 define void @test_exp(half* %p) #0 {
507   %a = load half, half* %p, align 2
508   %r = call half @llvm.exp.f16(half %a)
509   store half %r, half* %p
510   ret void
511 }
512
513 ; CHECK-FP16-LABEL: test_exp2:
514 ; CHECK-FP16: vcvtb.f32.f16
515 ; CHECK-FP16: bl exp2f
516 ; CHECK-FP16: vcvtb.f16.f32
517 ; CHECK-LIBCALL-LABEL: test_exp2:
518 ; CHECK-LIBCALL: bl __aeabi_h2f
519 ; CHECK-LIBCALL: bl exp2f
520 ; CHECK-LIBCALL: bl __aeabi_f2h
521 define void @test_exp2(half* %p) #0 {
522   %a = load half, half* %p, align 2
523   %r = call half @llvm.exp2.f16(half %a)
524   store half %r, half* %p
525   ret void
526 }
527
528 ; CHECK-FP16-LABEL: test_log:
529 ; CHECK-FP16: vcvtb.f32.f16
530 ; CHECK-FP16: bl logf
531 ; CHECK-FP16: vcvtb.f16.f32
532 ; CHECK-LIBCALL-LABEL: test_log:
533 ; CHECK-LIBCALL: bl __aeabi_h2f
534 ; CHECK-LIBCALL: bl logf
535 ; CHECK-LIBCALL: bl __aeabi_f2h
536 define void @test_log(half* %p) #0 {
537   %a = load half, half* %p, align 2
538   %r = call half @llvm.log.f16(half %a)
539   store half %r, half* %p
540   ret void
541 }
542
543 ; CHECK-FP16-LABEL: test_log10:
544 ; CHECK-FP16: vcvtb.f32.f16
545 ; CHECK-FP16: bl log10f
546 ; CHECK-FP16: vcvtb.f16.f32
547 ; CHECK-LIBCALL-LABEL: test_log10:
548 ; CHECK-LIBCALL: bl __aeabi_h2f
549 ; CHECK-LIBCALL: bl log10f
550 ; CHECK-LIBCALL: bl __aeabi_f2h
551 define void @test_log10(half* %p) #0 {
552   %a = load half, half* %p, align 2
553   %r = call half @llvm.log10.f16(half %a)
554   store half %r, half* %p
555   ret void
556 }
557
558 ; CHECK-FP16-LABEL: test_log2:
559 ; CHECK-FP16: vcvtb.f32.f16
560 ; CHECK-FP16: bl log2f
561 ; CHECK-FP16: vcvtb.f16.f32
562 ; CHECK-LIBCALL-LABEL: test_log2:
563 ; CHECK-LIBCALL: bl __aeabi_h2f
564 ; CHECK-LIBCALL: bl log2f
565 ; CHECK-LIBCALL: bl __aeabi_f2h
566 define void @test_log2(half* %p) #0 {
567   %a = load half, half* %p, align 2
568   %r = call half @llvm.log2.f16(half %a)
569   store half %r, half* %p
570   ret void
571 }
572
573 ; CHECK-FP16-LABEL: test_fma:
574 ; CHECK-FP16: vcvtb.f32.f16
575 ; CHECK-FP16: vcvtb.f32.f16
576 ; CHECK-FP16: vcvtb.f32.f16
577 ; CHECK-FP16: bl fmaf
578 ; CHECK-FP16: vcvtb.f16.f32
579 ; CHECK-LIBCALL-LABEL: test_fma:
580 ; CHECK-LIBCALL: bl __aeabi_h2f
581 ; CHECK-LIBCALL: bl __aeabi_h2f
582 ; CHECK-LIBCALL: bl __aeabi_h2f
583 ; CHECK-LIBCALL: bl fmaf
584 ; CHECK-LIBCALL: bl __aeabi_f2h
585 define void @test_fma(half* %p, half* %q, half* %r) #0 {
586   %a = load half, half* %p, align 2
587   %b = load half, half* %q, align 2
588   %c = load half, half* %r, align 2
589   %v = call half @llvm.fma.f16(half %a, half %b, half %c)
590   store half %v, half* %p
591   ret void
592 }
593
594 ; CHECK-FP16-LABEL: test_fabs:
595 ; CHECK-FP16: vcvtb.f32.f16
596 ; CHECK-FP16: vabs.f32
597 ; CHECK-FP16: vcvtb.f16.f32
598 ; CHECK-LIBCALL-LABEL: test_fabs:
599 ; CHECK-LIBCALL: bl __aeabi_h2f
600 ; CHECK-LIBCALL: bfc
601 ; CHECK-LIBCALL: bl __aeabi_f2h
602 define void @test_fabs(half* %p) {
603   %a = load half, half* %p, align 2
604   %r = call half @llvm.fabs.f16(half %a)
605   store half %r, half* %p
606   ret void
607 }
608
609 ; CHECK-FP16-LABEL: test_minnum:
610 ; CHECK-FP16: vcvtb.f32.f16
611 ; CHECK-FP16: vcvtb.f32.f16
612 ; CHECK-FP16: bl fminf
613 ; CHECK-FP16: vcvtb.f16.f32
614 ; CHECK-LIBCALL-LABEL: test_minnum:
615 ; CHECK-LIBCALL: bl __aeabi_h2f
616 ; CHECK-LIBCALL: bl __aeabi_h2f
617 ; CHECK-LIBCALL: bl fminf
618 ; CHECK-LIBCALL: bl __aeabi_f2h
619 define void @test_minnum(half* %p, half* %q) #0 {
620   %a = load half, half* %p, align 2
621   %b = load half, half* %q, align 2
622   %r = call half @llvm.minnum.f16(half %a, half %b)
623   store half %r, half* %p
624   ret void
625 }
626
627 ; CHECK-FP16-LABEL: test_maxnum:
628 ; CHECK-FP16: vcvtb.f32.f16
629 ; CHECK-FP16: vcvtb.f32.f16
630 ; CHECK-FP16: bl fmaxf
631 ; CHECK-FP16: vcvtb.f16.f32
632 ; CHECK-LIBCALL-LABEL: test_maxnum:
633 ; CHECK-LIBCALL: bl __aeabi_h2f
634 ; CHECK-LIBCALL: bl __aeabi_h2f
635 ; CHECK-LIBCALL: bl fmaxf
636 ; CHECK-LIBCALL: bl __aeabi_f2h
637 define void @test_maxnum(half* %p, half* %q) #0 {
638   %a = load half, half* %p, align 2
639   %b = load half, half* %q, align 2
640   %r = call half @llvm.maxnum.f16(half %a, half %b)
641   store half %r, half* %p
642   ret void
643 }
644
645 ; CHECK-ALL-LABEL: test_minnan:
646 ; CHECK-FP16: vcvtb.f32.f16
647 ; CHECK-FP16: vcvtb.f32.f16
648 ; CHECK-LIBCALL: bl __aeabi_h2f
649 ; CHECK-LIBCALL: bl __aeabi_h2f
650 ; CHECK-VFP: vmin.f32
651 ; CHECK-NOVFP: bl __aeabi_fcmpge
652 ; CHECK-FP16: vcvtb.f16.f32
653 ; CHECK-LIBCALL: bl __aeabi_f2h
654 define void @test_minnan(half* %p) #0 {
655   %a = load half, half* %p, align 2
656   %c = fcmp ult half %a, 1.0
657   %r = select i1 %c, half %a, half 1.0
658   store half %r, half* %p
659   ret void
660 }
661
662 ; CHECK-ALL-LABEL: test_maxnan:
663 ; CHECK-FP16: vcvtb.f32.f16
664 ; CHECK-FP16: vcvtb.f32.f16
665 ; CHECK-LIBCALL: bl __aeabi_h2f
666 ; CHECK-LIBCALL: bl __aeabi_h2f
667 ; CHECK-VFP: vmax.f32
668 ; CHECK-NOVFP: bl __aeabi_fcmple
669 ; CHECK-FP16: vcvtb.f16.f32
670 ; CHECK-LIBCALL: bl __aeabi_f2h
671 define void @test_maxnan(half* %p) #0 {
672   %a = load half, half* %p, align 2
673   %c = fcmp ugt half %a, 1.0
674   %r = select i1 %c, half %a, half 1.0
675   store half %r, half* %p
676   ret void
677 }
678
679 ; CHECK-FP16-LABEL: test_copysign:
680 ; CHECK-FP16: vcvtb.f32.f16
681 ; CHECK-FP16: vcvtb.f32.f16
682 ; CHECK-FP16: vbsl
683 ; CHECK-FP16: vcvtb.f16.f32
684 ; CHECK-LIBCALL-LABEL: test_copysign:
685 ; CHECK-LIBCALL: bl __aeabi_h2f
686 ; CHECK-LIBCALL: bl __aeabi_h2f
687 ; CHECK-VFP-LIBCALL: vbsl
688 ; CHECK-NOVFP: bfc
689 ; CHECK-NOVFP: and
690 ; CHECK-NOVFP: orr
691 ; CHECK-LIBCALL: bl __aeabi_f2h
692 define void @test_copysign(half* %p, half* %q) #0 {
693   %a = load half, half* %p, align 2
694   %b = load half, half* %q, align 2
695   %r = call half @llvm.copysign.f16(half %a, half %b)
696   store half %r, half* %p
697   ret void
698 }
699
700 ; CHECK-FP16-LABEL: test_floor:
701 ; CHECK-FP16: vcvtb.f32.f16
702 ; CHECK-FP16: bl floorf
703 ; CHECK-FP16: vcvtb.f16.f32
704 ; CHECK-LIBCALL-LABEL: test_floor:
705 ; CHECK-LIBCALL: bl __aeabi_h2f
706 ; CHECK-LIBCALL: bl floorf
707 ; CHECK-LIBCALL: bl __aeabi_f2h
708 define void @test_floor(half* %p) {
709   %a = load half, half* %p, align 2
710   %r = call half @llvm.floor.f16(half %a)
711   store half %r, half* %p
712   ret void
713 }
714
715 ; CHECK-FP16-LABEL: test_ceil:
716 ; CHECK-FP16: vcvtb.f32.f16
717 ; CHECK-FP16: bl ceilf
718 ; CHECK-FP16: vcvtb.f16.f32
719 ; CHECK-LIBCALL-LABEL: test_ceil:
720 ; CHECK-LIBCALL: bl __aeabi_h2f
721 ; CHECK-LIBCALL: bl ceilf
722 ; CHECK-LIBCALL: bl __aeabi_f2h
723 define void @test_ceil(half* %p) {
724   %a = load half, half* %p, align 2
725   %r = call half @llvm.ceil.f16(half %a)
726   store half %r, half* %p
727   ret void
728 }
729
730 ; CHECK-FP16-LABEL: test_trunc:
731 ; CHECK-FP16: vcvtb.f32.f16
732 ; CHECK-FP16: bl truncf
733 ; CHECK-FP16: vcvtb.f16.f32
734 ; CHECK-LIBCALL-LABEL: test_trunc:
735 ; CHECK-LIBCALL: bl __aeabi_h2f
736 ; CHECK-LIBCALL: bl truncf
737 ; CHECK-LIBCALL: bl __aeabi_f2h
738 define void @test_trunc(half* %p) {
739   %a = load half, half* %p, align 2
740   %r = call half @llvm.trunc.f16(half %a)
741   store half %r, half* %p
742   ret void
743 }
744
745 ; CHECK-FP16-LABEL: test_rint:
746 ; CHECK-FP16: vcvtb.f32.f16
747 ; CHECK-FP16: bl rintf
748 ; CHECK-FP16: vcvtb.f16.f32
749 ; CHECK-LIBCALL-LABEL: test_rint:
750 ; CHECK-LIBCALL: bl __aeabi_h2f
751 ; CHECK-LIBCALL: bl rintf
752 ; CHECK-LIBCALL: bl __aeabi_f2h
753 define void @test_rint(half* %p) {
754   %a = load half, half* %p, align 2
755   %r = call half @llvm.rint.f16(half %a)
756   store half %r, half* %p
757   ret void
758 }
759
760 ; CHECK-FP16-LABEL: test_nearbyint:
761 ; CHECK-FP16: vcvtb.f32.f16
762 ; CHECK-FP16: bl nearbyintf
763 ; CHECK-FP16: vcvtb.f16.f32
764 ; CHECK-LIBCALL-LABEL: test_nearbyint:
765 ; CHECK-LIBCALL: bl __aeabi_h2f
766 ; CHECK-LIBCALL: bl nearbyintf
767 ; CHECK-LIBCALL: bl __aeabi_f2h
768 define void @test_nearbyint(half* %p) {
769   %a = load half, half* %p, align 2
770   %r = call half @llvm.nearbyint.f16(half %a)
771   store half %r, half* %p
772   ret void
773 }
774
775 ; CHECK-FP16-LABEL: test_round:
776 ; CHECK-FP16: vcvtb.f32.f16
777 ; CHECK-FP16: bl roundf
778 ; CHECK-FP16: vcvtb.f16.f32
779 ; CHECK-LIBCALL-LABEL: test_round:
780 ; CHECK-LIBCALL: bl __aeabi_h2f
781 ; CHECK-LIBCALL: bl roundf
782 ; CHECK-LIBCALL: bl __aeabi_f2h
783 define void @test_round(half* %p) {
784   %a = load half, half* %p, align 2
785   %r = call half @llvm.round.f16(half %a)
786   store half %r, half* %p
787   ret void
788 }
789
790 ; CHECK-FP16-LABEL: test_fmuladd:
791 ; CHECK-FP16: vcvtb.f32.f16
792 ; CHECK-FP16: vcvtb.f32.f16
793 ; CHECK-FP16: vcvtb.f32.f16
794 ; CHECK-FP16: vmla.f32
795 ; CHECK-FP16: vcvtb.f16.f32
796 ; CHECK-LIBCALL-LABEL: test_fmuladd:
797 ; CHECK-LIBCALL: bl __aeabi_h2f
798 ; CHECK-LIBCALL: bl __aeabi_h2f
799 ; CHECK-LIBCALL: bl __aeabi_h2f
800 ; CHECK-VFP-LIBCALL: vmla.f32
801 ; CHECK-NOVFP: bl __aeabi_fmul
802 ; CHECK-LIBCALL: bl __aeabi_f2h
803 define void @test_fmuladd(half* %p, half* %q, half* %r) #0 {
804   %a = load half, half* %p, align 2
805   %b = load half, half* %q, align 2
806   %c = load half, half* %r, align 2
807   %v = call half @llvm.fmuladd.f16(half %a, half %b, half %c)
808   store half %v, half* %p
809   ret void
810 }
811
812 ; f16 vectors are not legal in the backend.  Vector elements are not assigned
813 ; to the register, but are stored in the stack instead.  Hence insertelement
814 ; and extractelement have these extra loads and stores.
815
816 ; CHECK-ALL-LABEL: test_insertelement:
817 ; CHECK-ALL: sub sp, sp, #8
818 ; CHECK-ALL: ldrh
819 ; CHECK-ALL: strh
820 ; CHECK-ALL: ldrh
821 ; CHECK-ALL: strh
822 ; CHECK-ALL: ldrh
823 ; CHECK-ALL: strh
824 ; CHECK-ALL: ldrh
825 ; CHECK-ALL: strh
826 ; CHECK-ALL: mov
827 ; CHECK-ALL-DAG: ldrh
828 ; CHECK-ALL-DAG: orr
829 ; CHECK-ALL: strh
830 ; CHECK-ALL: ldrh
831 ; CHECK-ALL: strh
832 ; CHECK-ALL: ldrh
833 ; CHECK-ALL: strh
834 ; CHECK-ALL: ldrh
835 ; CHECK-ALL: strh
836 ; CHECK-ALL: ldrh
837 ; CHECK-ALL: strh
838 ; CHECK-ALL: add sp, sp, #8
839 define void @test_insertelement(half* %p, <4 x half>* %q, i32 %i) #0 {
840   %a = load half, half* %p, align 2
841   %b = load <4 x half>, <4 x half>* %q, align 8
842   %c = insertelement <4 x half> %b, half %a, i32 %i
843   store <4 x half> %c, <4 x half>* %q
844   ret void
845 }
846
847 ; CHECK-ALL-LABEL: test_extractelement:
848 ; CHECK-VFP: sub sp, sp, #8
849 ; CHECK-VFP: ldrh
850 ; CHECK-VFP: ldrh
851 ; CHECK-VFP: orr
852 ; CHECK-VFP: str
853 ; CHECK-VFP: ldrh
854 ; CHECK-VFP: ldrh
855 ; CHECK-VFP: orr
856 ; CHECK-VFP: str
857 ; CHECK-VFP: mov
858 ; CHECK-VFP: orr
859 ; CHECK-VFP: ldrh
860 ; CHECK-VFP: strh
861 ; CHECK-VFP: add sp, sp, #8
862 ; CHECK-VFP: bx lr
863 ; CHECK-NOVFP: ldrh
864 ; CHECK-NOVFP: strh
865 ; CHECK-NOVFP: ldrh
866 ; CHECK-NOVFP: strh
867 ; CHECK-NOVFP: ldrh
868 ; CHECK-NOVFP: strh
869 ; CHECK-NOVFP: ldrh
870 ; CHECK-NOVFP: strh
871 ; CHECK-NOVFP: ldrh
872 define void @test_extractelement(half* %p, <4 x half>* %q, i32 %i) #0 {
873   %a = load <4 x half>, <4 x half>* %q, align 8
874   %b = extractelement <4 x half> %a, i32 %i
875   store half %b, half* %p
876   ret void
877 }
878
879 ; test struct operations
880
881 %struct.dummy = type { i32, half }
882
883 ; CHECK-ALL-LABEL: test_insertvalue:
884 ; CHECK-ALL-DAG: ldr
885 ; CHECK-ALL-DAG: ldrh
886 ; CHECK-ALL-DAG: strh
887 ; CHECK-ALL-DAG: str
888 define void @test_insertvalue(%struct.dummy* %p, half* %q) {
889   %a = load %struct.dummy, %struct.dummy* %p
890   %b = load half, half* %q
891   %c = insertvalue %struct.dummy %a, half %b, 1
892   store %struct.dummy %c, %struct.dummy* %p
893   ret void
894 }
895
896 ; CHECK-ALL-LABEL: test_extractvalue:
897 ; CHECK-ALL: .fnstart
898 ; CHECK-ALL: ldrh
899 ; CHECK-ALL: strh
900 define void @test_extractvalue(%struct.dummy* %p, half* %q) {
901   %a = load %struct.dummy, %struct.dummy* %p
902   %b = extractvalue %struct.dummy %a, 1
903   store half %b, half* %q
904   ret void
905 }
906
907 ; CHECK-ALL-LABEL: test_struct_return:
908 ; CHECK-FP16: vcvtb.f32.f16
909 ; CHECK-VFP-LIBCALL: bl __aeabi_h2f
910 ; CHECK-NOVFP-DAG: ldr
911 ; CHECK-NOVFP-DAG: ldrh
912 define %struct.dummy @test_struct_return(%struct.dummy* %p) {
913   %a = load %struct.dummy, %struct.dummy* %p
914   ret %struct.dummy %a
915 }
916
917 ; CHECK-ALL-LABEL: test_struct_arg:
918 ; CHECK-ALL-NEXT: .fnstart
919 ; CHECK-NOVFP-NEXT: mov r0, r1
920 ; CHECK-ALL-NEXT: bx lr
921 define half @test_struct_arg(%struct.dummy %p) {
922   %a = extractvalue %struct.dummy %p, 1
923   ret half %a
924 }
925
926 ; CHECK-LABEL: test_uitofp_i32_fadd:
927 ; CHECK-VFP-DAG: vcvt.f32.u32
928 ; CHECK-NOVFP-DAG: bl __aeabi_ui2f
929
930 ; CHECK-FP16-DAG: vcvtb.f16.f32
931 ; CHECK-FP16-DAG: vcvtb.f32.f16
932 ; CHECK-LIBCALL-DAG: bl __aeabi_h2f
933 ; CHECK-LIBCALL-DAG: bl __aeabi_h2f
934
935 ; CHECK-VFP-DAG: vadd.f32
936 ; CHECK-NOVFP-DAG: bl __aeabi_fadd
937
938 ; CHECK-FP16-DAG: vcvtb.f16.f32
939 ; CHECK-LIBCALL-DAG: bl __aeabi_f2h
940 define half @test_uitofp_i32_fadd(i32 %a, half %b) #0 {
941   %c = uitofp i32 %a to half
942   %r = fadd half %b, %c
943   ret half %r
944 }
945
946 ; CHECK-LABEL: test_sitofp_i32_fadd:
947 ; CHECK-VFP-DAG: vcvt.f32.s32
948 ; CHECK-NOVFP-DAG: bl __aeabi_i2f
949
950 ; CHECK-FP16-DAG: vcvtb.f16.f32
951 ; CHECK-FP16-DAG: vcvtb.f32.f16
952 ; CHECK-LIBCALL-DAG: bl __aeabi_h2f
953 ; CHECK-LIBCALL-DAG: bl __aeabi_h2f
954
955 ; CHECK-VFP-DAG: vadd.f32
956 ; CHECK-NOVFP-DAG: bl __aeabi_fadd
957
958 ; CHECK-FP16-DAG: vcvtb.f16.f32
959 ; CHECK-LIBCALL-DAG: bl __aeabi_f2h
960 define half @test_sitofp_i32_fadd(i32 %a, half %b) #0 {
961   %c = sitofp i32 %a to half
962   %r = fadd half %b, %c
963   ret half %r
964 }
965
966 attributes #0 = { nounwind }