[ARM] More MVE compare vector splat combines for ANDs
[llvm-complete.git] / test / CodeGen / ARM / fp16-promote.ll
blobf382144cf95fcb5bf88c3193a0cbf3b5470c8883
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(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
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
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
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
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
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
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(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
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
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(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
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: vcmpe.f32
206 ; CHECK-NOVFP: bl __aeabi_fcmplt
207 ; CHECK-FP16: vmrs APSR_nzcv, fpscr
208 ; CHECK-VFP: strmi
209 ; CHECK-VFP: strpl
210 ; CHECK-NOVFP: strne
211 ; CHECK-NOVFP: streq
212 define void @test_br_cc(half* %p, half* %q, i32* %p1, i32* %p2) #0 {
213   %a = load half, half* %p, align 2
214   %b = load half, half* %q, align 2
215   %c = fcmp uge half %a, %b
216   br i1 %c, label %then, label %else
217 then:
218   store i32 0, i32* %p1
219   ret void
220 else:
221   store i32 0, i32* %p2
222   ret void
225 declare i1 @test_dummy(half* %p) #0
226 ; CHECK-ALL-LABEL: test_phi:
227 ; CHECK-FP16: vcvtb.f32.f16
228 ; CHECK-FP16: [[LOOP:.LBB[1-9_]+]]:
229 ; CHECK-FP16: vcvtb.f32.f16
230 ; CHECK-FP16: bl      test_dummy
231 ; CHECK-FP16: bne     [[LOOP]]
232 ; CHECK-FP16: vcvtb.f16.f32
233 ; CHECK-LIBCALL-VFP: bl __aeabi_h2f
234 ; CHECK-LIBCALL: [[LOOP:.LBB[1-9_]+]]:
235 ; CHECK-LIBCALL-VFP: bl __aeabi_h2f
236 ; CHECK-LIBCALL: bl test_dummy
237 ; CHECK-LIBCALL: bne     [[LOOP]]
238 ; CHECK-LIBCALL-VFP: bl __aeabi_f2h
239 define void @test_phi(half* %p) #0 {
240 entry:
241   %a = load half, half* %p
242   br label %loop
243 loop:
244   %r = phi half [%a, %entry], [%b, %loop]
245   %b = load half, half* %p
246   %c = call i1 @test_dummy(half* %p)
247   br i1 %c, label %loop, label %return
248 return:
249   store half %r, half* %p
250   ret void
253 ; CHECK-ALL-LABEL: test_fptosi_i32:
254 ; CHECK-FP16: vcvtb.f32.f16
255 ; CHECK-LIBCALL: bl __aeabi_h2f
256 ; CHECK-VFP: vcvt.s32.f32
257 ; CHECK-NOVFP: bl __aeabi_f2iz
258 define i32 @test_fptosi_i32(half* %p) #0 {
259   %a = load half, half* %p, align 2
260   %r = fptosi half %a to i32
261   ret i32 %r
264 ; CHECK-ALL-LABEL: test_fptosi_i64:
265 ; CHECK-FP16: vcvtb.f32.f16
266 ; CHECK-LIBCALL: bl __aeabi_h2f
267 ; CHECK-ALL: bl __aeabi_f2lz
268 define i64 @test_fptosi_i64(half* %p) #0 {
269   %a = load half, half* %p, align 2
270   %r = fptosi half %a to i64
271   ret i64 %r
274 ; CHECK-ALL-LABEL: test_fptoui_i32:
275 ; CHECK-FP16: vcvtb.f32.f16
276 ; CHECK-LIBCALL: bl __aeabi_h2f
277 ; CHECK-VFP: vcvt.u32.f32
278 ; CHECK-NOVFP: bl __aeabi_f2uiz
279 define i32 @test_fptoui_i32(half* %p) #0 {
280   %a = load half, half* %p, align 2
281   %r = fptoui half %a to i32
282   ret i32 %r
285 ; CHECK-ALL-LABEL: test_fptoui_i64:
286 ; CHECK-FP16: vcvtb.f32.f16
287 ; CHECK-LIBCALL: bl __aeabi_h2f
288 ; CHECK-ALL: bl __aeabi_f2ulz
289 define i64 @test_fptoui_i64(half* %p) #0 {
290   %a = load half, half* %p, align 2
291   %r = fptoui half %a to i64
292   ret i64 %r
295 ; CHECK-ALL-LABEL: test_sitofp_i32:
296 ; CHECK-VFP: vcvt.f32.s32
297 ; CHECK-NOVFP: bl __aeabi_i2f
298 ; CHECK-FP16: vcvtb.f16.f32
299 ; CHECK-LIBCALL: bl __aeabi_f2h
300 define void @test_sitofp_i32(i32 %a, half* %p) #0 {
301   %r = sitofp i32 %a to half
302   store half %r, half* %p
303   ret void
306 ; CHECK-ALL-LABEL: test_uitofp_i32:
307 ; CHECK-VFP: vcvt.f32.u32
308 ; CHECK-NOVFP: bl __aeabi_ui2f
309 ; CHECK-FP16: vcvtb.f16.f32
310 ; CHECK-LIBCALL: bl __aeabi_f2h
311 define void @test_uitofp_i32(i32 %a, half* %p) #0 {
312   %r = uitofp i32 %a to half
313   store half %r, half* %p
314   ret void
317 ; CHECK-ALL-LABEL: test_sitofp_i64:
318 ; CHECK-ALL: bl __aeabi_l2f
319 ; CHECK-FP16: vcvtb.f16.f32
320 ; CHECK-LIBCALL: bl __aeabi_f2h
321 define void @test_sitofp_i64(i64 %a, half* %p) #0 {
322   %r = sitofp i64 %a to half
323   store half %r, half* %p
324   ret void
327 ; CHECK-ALL-LABEL: test_uitofp_i64:
328 ; CHECK-ALL: bl __aeabi_ul2f
329 ; CHECK-FP16: vcvtb.f16.f32
330 ; CHECK-LIBCALL: bl __aeabi_f2h
331 define void @test_uitofp_i64(i64 %a, half* %p) #0 {
332   %r = uitofp i64 %a to half
333   store half %r, half* %p
334   ret void
337 ; CHECK-FP16-LABEL: test_fptrunc_float:
338 ; CHECK-FP16: vcvtb.f16.f32
339 ; CHECK-LIBCALL-LABEL: test_fptrunc_float:
340 ; CHECK-LIBCALL: bl __aeabi_f2h
341 define void @test_fptrunc_float(float %f, half* %p) #0 {
342   %a = fptrunc float %f to half
343   store half %a, half* %p
344   ret void
347 ; CHECK-FP16-LABEL: test_fptrunc_double:
348 ; CHECK-FP16: bl __aeabi_d2h
349 ; CHECK-LIBCALL-LABEL: test_fptrunc_double:
350 ; CHECK-LIBCALL: bl __aeabi_d2h
351 define void @test_fptrunc_double(double %d, half* %p) #0 {
352   %a = fptrunc double %d to half
353   store half %a, half* %p
354   ret void
357 ; CHECK-FP16-LABEL: test_fpextend_float:
358 ; CHECK-FP16: vcvtb.f32.f16
359 ; CHECK-LIBCALL-LABEL: test_fpextend_float:
360 ; CHECK-LIBCALL: bl __aeabi_h2f
361 define float @test_fpextend_float(half* %p) {
362   %a = load half, half* %p, align 2
363   %r = fpext half %a to float
364   ret float %r
367 ; CHECK-FP16-LABEL: test_fpextend_double:
368 ; CHECK-FP16: vcvtb.f32.f16
369 ; CHECK-LIBCALL-LABEL: test_fpextend_double:
370 ; CHECK-LIBCALL: bl __aeabi_h2f
371 ; CHECK-VFP: vcvt.f64.f32
372 ; CHECK-NOVFP: bl __aeabi_f2d
373 define double @test_fpextend_double(half* %p) {
374   %a = load half, half* %p, align 2
375   %r = fpext half %a to double
376   ret double %r
379 ; CHECK-ALL-LABEL: test_bitcast_halftoi16:
380 ; CHECK-ALL-NEXT: .fnstart
381 ; CHECK-ALL-NEXT: ldrh r0, [r0]
382 ; CHECK-ALL-NEXT: bx lr
383 define i16 @test_bitcast_halftoi16(half* %p) #0 {
384   %a = load half, half* %p, align 2
385   %r = bitcast half %a to i16
386   ret i16 %r
389 ; CHECK-ALL-LABEL: test_bitcast_i16tohalf:
390 ; CHECK-ALL-NEXT: .fnstart
391 ; CHECK-ALL-NEXT: strh r0, [r1]
392 ; CHECK-ALL-NEXT: bx lr
393 define void @test_bitcast_i16tohalf(i16 %a, half* %p) #0 {
394   %r = bitcast i16 %a to half
395   store half %r, half* %p
396   ret void
399 declare half @llvm.sqrt.f16(half %a) #0
400 declare half @llvm.powi.f16(half %a, i32 %b) #0
401 declare half @llvm.sin.f16(half %a) #0
402 declare half @llvm.cos.f16(half %a) #0
403 declare half @llvm.pow.f16(half %a, half %b) #0
404 declare half @llvm.exp.f16(half %a) #0
405 declare half @llvm.exp2.f16(half %a) #0
406 declare half @llvm.log.f16(half %a) #0
407 declare half @llvm.log10.f16(half %a) #0
408 declare half @llvm.log2.f16(half %a) #0
409 declare half @llvm.fma.f16(half %a, half %b, half %c) #0
410 declare half @llvm.fabs.f16(half %a) #0
411 declare half @llvm.minnum.f16(half %a, half %b) #0
412 declare half @llvm.maxnum.f16(half %a, half %b) #0
413 declare half @llvm.copysign.f16(half %a, half %b) #0
414 declare half @llvm.floor.f16(half %a) #0
415 declare half @llvm.ceil.f16(half %a) #0
416 declare half @llvm.trunc.f16(half %a) #0
417 declare half @llvm.rint.f16(half %a) #0
418 declare half @llvm.nearbyint.f16(half %a) #0
419 declare half @llvm.round.f16(half %a) #0
420 declare half @llvm.fmuladd.f16(half %a, half %b, half %c) #0
422 ; CHECK-ALL-LABEL: test_sqrt:
423 ; CHECK-FP16: vcvtb.f32.f16
424 ; CHECK-FP16: vsqrt.f32
425 ; CHECK-FP16: vcvtb.f16.f32
426 ; CHECK-LIBCALL: bl __aeabi_h2f
427 ; CHECK-VFP-LIBCALL: vsqrt.f32
428 ; CHECK-NOVFP: bl sqrtf
429 ; CHECK-LIBCALL: bl __aeabi_f2h
430 define void @test_sqrt(half* %p) #0 {
431   %a = load half, half* %p, align 2
432   %r = call half @llvm.sqrt.f16(half %a)
433   store half %r, half* %p
434   ret void
437 ; CHECK-FP16-LABEL: test_fpowi:
438 ; CHECK-FP16: vcvtb.f32.f16
439 ; CHECK-FP16: bl __powisf2
440 ; CHECK-FP16: vcvtb.f16.f32
441 ; CHECK-LIBCALL-LABEL: test_fpowi:
442 ; CHECK-LIBCALL: bl __aeabi_h2f
443 ; CHECK-LIBCALL: bl __powisf2
444 ; CHECK-LIBCALL: bl __aeabi_f2h
445 define void @test_fpowi(half* %p, i32 %b) #0 {
446   %a = load half, half* %p, align 2
447   %r = call half @llvm.powi.f16(half %a, i32 %b)
448   store half %r, half* %p
449   ret void
452 ; CHECK-FP16-LABEL: test_sin:
453 ; CHECK-FP16: vcvtb.f32.f16
454 ; CHECK-FP16: bl sinf
455 ; CHECK-FP16: vcvtb.f16.f32
456 ; CHECK-LIBCALL-LABEL: test_sin:
457 ; CHECK-LIBCALL: bl __aeabi_h2f
458 ; CHECK-LIBCALL: bl sinf
459 ; CHECK-LIBCALL: bl __aeabi_f2h
460 define void @test_sin(half* %p) #0 {
461   %a = load half, half* %p, align 2
462   %r = call half @llvm.sin.f16(half %a)
463   store half %r, half* %p
464   ret void
467 ; CHECK-FP16-LABEL: test_cos:
468 ; CHECK-FP16: vcvtb.f32.f16
469 ; CHECK-FP16: bl cosf
470 ; CHECK-FP16: vcvtb.f16.f32
471 ; CHECK-LIBCALL-LABEL: test_cos:
472 ; CHECK-LIBCALL: bl __aeabi_h2f
473 ; CHECK-LIBCALL: bl cosf
474 ; CHECK-LIBCALL: bl __aeabi_f2h
475 define void @test_cos(half* %p) #0 {
476   %a = load half, half* %p, align 2
477   %r = call half @llvm.cos.f16(half %a)
478   store half %r, half* %p
479   ret void
482 ; CHECK-FP16-LABEL: test_pow:
483 ; CHECK-FP16: vcvtb.f32.f16
484 ; CHECK-FP16: vcvtb.f32.f16
485 ; CHECK-FP16: bl powf
486 ; CHECK-FP16: vcvtb.f16.f32
487 ; CHECK-LIBCALL-LABEL: test_pow:
488 ; CHECK-LIBCALL: bl __aeabi_h2f
489 ; CHECK-LIBCALL: bl __aeabi_h2f
490 ; CHECK-LIBCALL: bl powf
491 ; CHECK-LIBCALL: bl __aeabi_f2h
492 define void @test_pow(half* %p, half* %q) #0 {
493   %a = load half, half* %p, align 2
494   %b = load half, half* %q, align 2
495   %r = call half @llvm.pow.f16(half %a, half %b)
496   store half %r, half* %p
497   ret void
500 ; CHECK-FP16-LABEL: test_exp:
501 ; CHECK-FP16: vcvtb.f32.f16
502 ; CHECK-FP16: bl expf
503 ; CHECK-FP16: vcvtb.f16.f32
504 ; CHECK-LIBCALL-LABEL: test_exp:
505 ; CHECK-LIBCALL: bl __aeabi_h2f
506 ; CHECK-LIBCALL: bl expf
507 ; CHECK-LIBCALL: bl __aeabi_f2h
508 define void @test_exp(half* %p) #0 {
509   %a = load half, half* %p, align 2
510   %r = call half @llvm.exp.f16(half %a)
511   store half %r, half* %p
512   ret void
515 ; CHECK-FP16-LABEL: test_exp2:
516 ; CHECK-FP16: vcvtb.f32.f16
517 ; CHECK-FP16: bl exp2f
518 ; CHECK-FP16: vcvtb.f16.f32
519 ; CHECK-LIBCALL-LABEL: test_exp2:
520 ; CHECK-LIBCALL: bl __aeabi_h2f
521 ; CHECK-LIBCALL: bl exp2f
522 ; CHECK-LIBCALL: bl __aeabi_f2h
523 define void @test_exp2(half* %p) #0 {
524   %a = load half, half* %p, align 2
525   %r = call half @llvm.exp2.f16(half %a)
526   store half %r, half* %p
527   ret void
530 ; CHECK-FP16-LABEL: test_log:
531 ; CHECK-FP16: vcvtb.f32.f16
532 ; CHECK-FP16: bl logf
533 ; CHECK-FP16: vcvtb.f16.f32
534 ; CHECK-LIBCALL-LABEL: test_log:
535 ; CHECK-LIBCALL: bl __aeabi_h2f
536 ; CHECK-LIBCALL: bl logf
537 ; CHECK-LIBCALL: bl __aeabi_f2h
538 define void @test_log(half* %p) #0 {
539   %a = load half, half* %p, align 2
540   %r = call half @llvm.log.f16(half %a)
541   store half %r, half* %p
542   ret void
545 ; CHECK-FP16-LABEL: test_log10:
546 ; CHECK-FP16: vcvtb.f32.f16
547 ; CHECK-FP16: bl log10f
548 ; CHECK-FP16: vcvtb.f16.f32
549 ; CHECK-LIBCALL-LABEL: test_log10:
550 ; CHECK-LIBCALL: bl __aeabi_h2f
551 ; CHECK-LIBCALL: bl log10f
552 ; CHECK-LIBCALL: bl __aeabi_f2h
553 define void @test_log10(half* %p) #0 {
554   %a = load half, half* %p, align 2
555   %r = call half @llvm.log10.f16(half %a)
556   store half %r, half* %p
557   ret void
560 ; CHECK-FP16-LABEL: test_log2:
561 ; CHECK-FP16: vcvtb.f32.f16
562 ; CHECK-FP16: bl log2f
563 ; CHECK-FP16: vcvtb.f16.f32
564 ; CHECK-LIBCALL-LABEL: test_log2:
565 ; CHECK-LIBCALL: bl __aeabi_h2f
566 ; CHECK-LIBCALL: bl log2f
567 ; CHECK-LIBCALL: bl __aeabi_f2h
568 define void @test_log2(half* %p) #0 {
569   %a = load half, half* %p, align 2
570   %r = call half @llvm.log2.f16(half %a)
571   store half %r, half* %p
572   ret void
575 ; CHECK-FP16-LABEL: test_fma:
576 ; CHECK-FP16: vcvtb.f32.f16
577 ; CHECK-FP16: vcvtb.f32.f16
578 ; CHECK-FP16: vcvtb.f32.f16
579 ; CHECK-FP16: bl fmaf
580 ; CHECK-FP16: vcvtb.f16.f32
581 ; CHECK-LIBCALL-LABEL: test_fma:
582 ; CHECK-LIBCALL: bl __aeabi_h2f
583 ; CHECK-LIBCALL: bl __aeabi_h2f
584 ; CHECK-LIBCALL: bl __aeabi_h2f
585 ; CHECK-LIBCALL: bl fmaf
586 ; CHECK-LIBCALL: bl __aeabi_f2h
587 define void @test_fma(half* %p, half* %q, half* %r) #0 {
588   %a = load half, half* %p, align 2
589   %b = load half, half* %q, align 2
590   %c = load half, half* %r, align 2
591   %v = call half @llvm.fma.f16(half %a, half %b, half %c)
592   store half %v, half* %p
593   ret void
596 ; CHECK-FP16-LABEL: test_fabs:
597 ; CHECK-FP16: vcvtb.f32.f16
598 ; CHECK-FP16: vabs.f32
599 ; CHECK-FP16: vcvtb.f16.f32
600 ; CHECK-LIBCALL-LABEL: test_fabs:
601 ; CHECK-LIBCALL: bl __aeabi_h2f
602 ; CHECK-LIBCALL: bic
603 ; CHECK-LIBCALL: bl __aeabi_f2h
604 define void @test_fabs(half* %p) {
605   %a = load half, half* %p, align 2
606   %r = call half @llvm.fabs.f16(half %a)
607   store half %r, half* %p
608   ret void
611 ; CHECK-FP16-LABEL: test_minnum:
612 ; CHECK-FP16: vcvtb.f32.f16
613 ; CHECK-FP16: vcvtb.f32.f16
614 ; CHECK-FP16: bl fminf
615 ; CHECK-FP16: vcvtb.f16.f32
616 ; CHECK-LIBCALL-LABEL: test_minnum:
617 ; CHECK-LIBCALL: bl __aeabi_h2f
618 ; CHECK-LIBCALL: bl __aeabi_h2f
619 ; CHECK-LIBCALL: bl fminf
620 ; CHECK-LIBCALL: bl __aeabi_f2h
621 define void @test_minnum(half* %p, half* %q) #0 {
622   %a = load half, half* %p, align 2
623   %b = load half, half* %q, align 2
624   %r = call half @llvm.minnum.f16(half %a, half %b)
625   store half %r, half* %p
626   ret void
629 ; CHECK-FP16-LABEL: test_maxnum:
630 ; CHECK-FP16: vcvtb.f32.f16
631 ; CHECK-FP16: vcvtb.f32.f16
632 ; CHECK-FP16: bl fmaxf
633 ; CHECK-FP16: vcvtb.f16.f32
634 ; CHECK-LIBCALL-LABEL: test_maxnum:
635 ; CHECK-LIBCALL: bl __aeabi_h2f
636 ; CHECK-LIBCALL: bl __aeabi_h2f
637 ; CHECK-LIBCALL: bl fmaxf
638 ; CHECK-LIBCALL: bl __aeabi_f2h
639 define void @test_maxnum(half* %p, half* %q) #0 {
640   %a = load half, half* %p, align 2
641   %b = load half, half* %q, align 2
642   %r = call half @llvm.maxnum.f16(half %a, half %b)
643   store half %r, half* %p
644   ret void
647 ; CHECK-ALL-LABEL: test_minimum:
648 ; CHECK-FP16: vmov.f32 s0, #1.000000e+00
649 ; CHECK-FP16: vcvtb.f32.f16
650 ; CHECK-LIBCALL: bl __aeabi_h2f
651 ; CHECK-LIBCALL-VFP: vmov.f32 s{{[0-9]+}}, #1.000000e+00
652 ; CHECK-NOVFP: mov r{{[0-9]+}}, #1065353216
653 ; CHECK-VFP: vmin.f32
654 ; CHECK-NOVFP: bl __aeabi_fcmpge
655 ; CHECK-FP16: vcvtb.f16.f32
656 ; CHECK-LIBCALL: bl __aeabi_f2h
657 define void @test_minimum(half* %p) #0 {
658   %a = load half, half* %p, align 2
659   %c = fcmp ult half %a, 1.0
660   %r = select i1 %c, half %a, half 1.0
661   store half %r, half* %p
662   ret void
665 ; CHECK-ALL-LABEL: test_maximum:
666 ; CHECK-FP16: vmov.f32 s0, #1.000000e+00
667 ; CHECK-FP16: vcvtb.f32.f16
668 ; CHECK-LIBCALL: bl __aeabi_h2f
669 ; CHECK-LIBCALL-VFP: vmov.f32 s0, #1.000000e+00
670 ; CHECK-NOVFP: mov r{{[0-9]+}}, #1065353216
671 ; CHECK-VFP: vmax.f32
672 ; CHECK-NOVFP: bl __aeabi_fcmple
673 ; CHECK-FP16: vcvtb.f16.f32
674 ; CHECK-LIBCALL: bl __aeabi_f2h
675 define void @test_maximum(half* %p) #0 {
676   %a = load half, half* %p, align 2
677   %c = fcmp ugt half %a, 1.0
678   %r = select i1 %c, half %a, half 1.0
679   store half %r, half* %p
680   ret void
683 ; CHECK-FP16-LABEL: test_copysign:
684 ; CHECK-FP16: vcvtb.f32.f16
685 ; CHECK-FP16: vcvtb.f32.f16
686 ; CHECK-FP16: vbsl
687 ; CHECK-FP16: vcvtb.f16.f32
688 ; CHECK-LIBCALL-LABEL: test_copysign:
689 ; CHECK-LIBCALL: bl __aeabi_h2f
690 ; CHECK-LIBCALL: bl __aeabi_h2f
691 ; CHECK-VFP-LIBCALL: vbsl
692 ; CHECK-NOVFP: and
693 ; CHECK-NOVFP: bic
694 ; CHECK-NOVFP: orr
695 ; CHECK-LIBCALL: bl __aeabi_f2h
696 define void @test_copysign(half* %p, half* %q) #0 {
697   %a = load half, half* %p, align 2
698   %b = load half, half* %q, align 2
699   %r = call half @llvm.copysign.f16(half %a, half %b)
700   store half %r, half* %p
701   ret void
704 ; CHECK-FP16-LABEL: test_floor:
705 ; CHECK-FP16: vcvtb.f32.f16
706 ; CHECK-FP16: bl floorf
707 ; CHECK-FP16: vcvtb.f16.f32
708 ; CHECK-LIBCALL-LABEL: test_floor:
709 ; CHECK-LIBCALL: bl __aeabi_h2f
710 ; CHECK-LIBCALL: bl floorf
711 ; CHECK-LIBCALL: bl __aeabi_f2h
712 define void @test_floor(half* %p) {
713   %a = load half, half* %p, align 2
714   %r = call half @llvm.floor.f16(half %a)
715   store half %r, half* %p
716   ret void
719 ; CHECK-FP16-LABEL: test_ceil:
720 ; CHECK-FP16: vcvtb.f32.f16
721 ; CHECK-FP16: bl ceilf
722 ; CHECK-FP16: vcvtb.f16.f32
723 ; CHECK-LIBCALL-LABEL: test_ceil:
724 ; CHECK-LIBCALL: bl __aeabi_h2f
725 ; CHECK-LIBCALL: bl ceilf
726 ; CHECK-LIBCALL: bl __aeabi_f2h
727 define void @test_ceil(half* %p) {
728   %a = load half, half* %p, align 2
729   %r = call half @llvm.ceil.f16(half %a)
730   store half %r, half* %p
731   ret void
734 ; CHECK-FP16-LABEL: test_trunc:
735 ; CHECK-FP16: vcvtb.f32.f16
736 ; CHECK-FP16: bl truncf
737 ; CHECK-FP16: vcvtb.f16.f32
738 ; CHECK-LIBCALL-LABEL: test_trunc:
739 ; CHECK-LIBCALL: bl __aeabi_h2f
740 ; CHECK-LIBCALL: bl truncf
741 ; CHECK-LIBCALL: bl __aeabi_f2h
742 define void @test_trunc(half* %p) {
743   %a = load half, half* %p, align 2
744   %r = call half @llvm.trunc.f16(half %a)
745   store half %r, half* %p
746   ret void
749 ; CHECK-FP16-LABEL: test_rint:
750 ; CHECK-FP16: vcvtb.f32.f16
751 ; CHECK-FP16: bl rintf
752 ; CHECK-FP16: vcvtb.f16.f32
753 ; CHECK-LIBCALL-LABEL: test_rint:
754 ; CHECK-LIBCALL: bl __aeabi_h2f
755 ; CHECK-LIBCALL: bl rintf
756 ; CHECK-LIBCALL: bl __aeabi_f2h
757 define void @test_rint(half* %p) {
758   %a = load half, half* %p, align 2
759   %r = call half @llvm.rint.f16(half %a)
760   store half %r, half* %p
761   ret void
764 ; CHECK-FP16-LABEL: test_nearbyint:
765 ; CHECK-FP16: vcvtb.f32.f16
766 ; CHECK-FP16: bl nearbyintf
767 ; CHECK-FP16: vcvtb.f16.f32
768 ; CHECK-LIBCALL-LABEL: test_nearbyint:
769 ; CHECK-LIBCALL: bl __aeabi_h2f
770 ; CHECK-LIBCALL: bl nearbyintf
771 ; CHECK-LIBCALL: bl __aeabi_f2h
772 define void @test_nearbyint(half* %p) {
773   %a = load half, half* %p, align 2
774   %r = call half @llvm.nearbyint.f16(half %a)
775   store half %r, half* %p
776   ret void
779 ; CHECK-FP16-LABEL: test_round:
780 ; CHECK-FP16: vcvtb.f32.f16
781 ; CHECK-FP16: bl roundf
782 ; CHECK-FP16: vcvtb.f16.f32
783 ; CHECK-LIBCALL-LABEL: test_round:
784 ; CHECK-LIBCALL: bl __aeabi_h2f
785 ; CHECK-LIBCALL: bl roundf
786 ; CHECK-LIBCALL: bl __aeabi_f2h
787 define void @test_round(half* %p) {
788   %a = load half, half* %p, align 2
789   %r = call half @llvm.round.f16(half %a)
790   store half %r, half* %p
791   ret void
794 ; CHECK-FP16-LABEL: test_fmuladd:
795 ; CHECK-FP16: vcvtb.f32.f16
796 ; CHECK-FP16: vcvtb.f32.f16
797 ; CHECK-FP16: vcvtb.f32.f16
798 ; CHECK-FP16: vmla.f32
799 ; CHECK-FP16: vcvtb.f16.f32
800 ; CHECK-LIBCALL-LABEL: test_fmuladd:
801 ; CHECK-LIBCALL: bl __aeabi_h2f
802 ; CHECK-LIBCALL: bl __aeabi_h2f
803 ; CHECK-LIBCALL: bl __aeabi_h2f
804 ; CHECK-VFP-LIBCALL: vmla.f32
805 ; CHECK-NOVFP: bl __aeabi_fmul
806 ; CHECK-LIBCALL: bl __aeabi_f2h
807 define void @test_fmuladd(half* %p, half* %q, half* %r) #0 {
808   %a = load half, half* %p, align 2
809   %b = load half, half* %q, align 2
810   %c = load half, half* %r, align 2
811   %v = call half @llvm.fmuladd.f16(half %a, half %b, half %c)
812   store half %v, half* %p
813   ret void
816 ; f16 vectors are not legal in the backend.  Vector elements are not assigned
817 ; to the register, but are stored in the stack instead.  Hence insertelement
818 ; and extractelement have these extra loads and stores.
820 ; CHECK-ALL-LABEL: test_insertelement:
821 ; CHECK-ALL: sub sp, sp, #8
823 ; CHECK-VFP:    and     
824 ; CHECK-VFP:    mov     
825 ; CHECK-VFP:    ldrd    
826 ; CHECK-VFP:    orr     
827 ; CHECK-VFP:    ldrh    
828 ; CHECK-VFP:    stm     
829 ; CHECK-VFP:    strh    
830 ; CHECK-VFP:    ldm     
831 ; CHECK-VFP:    stm     
833 ; CHECK-NOVFP: ldrh
834 ; CHECK-NOVFP: ldrh
835 ; CHECK-NOVFP: ldrh
836 ; CHECK-NOVFP: ldrh
837 ; CHECK-NOVFP-DAG: strh
838 ; CHECK-NOVFP-DAG: strh
839 ; CHECK-NOVFP-DAG: mov
840 ; CHECK-NOVFP-DAG: ldrh
841 ; CHECK-NOVFP-DAG: orr
842 ; CHECK-NOVFP-DAG: strh
843 ; CHECK-NOVFP-DAG: strh
844 ; CHECK-NOVFP-DAG: strh
845 ; CHECK-NOVFP-DAG: ldrh
846 ; CHECK-NOVFP-DAG: ldrh
847 ; CHECK-NOVFP-DAG: ldrh
848 ; CHECK-NOVFP-DAG: strh
849 ; CHECK-NOVFP-DAG: strh
850 ; CHECK-NOVFP-DAG: strh
851 ; CHECK-NOVFP-DAG: strh
853 ; CHECK-ALL: add sp, sp, #8
854 define void @test_insertelement(half* %p, <4 x half>* %q, i32 %i) #0 {
855   %a = load half, half* %p, align 2
856   %b = load <4 x half>, <4 x half>* %q, align 8
857   %c = insertelement <4 x half> %b, half %a, i32 %i
858   store <4 x half> %c, <4 x half>* %q
859   ret void
862 ; CHECK-ALL-LABEL: test_extractelement:
863 ; CHECK-VFP: push {{{.*}}, lr}
864 ; CHECK-VFP: sub sp, sp, #8
865 ; CHECK-VFP: ldrd
866 ; CHECK-VFP: mov
867 ; CHECK-VFP: orr
868 ; CHECK-VFP: ldrh
869 ; CHECK-VFP: strh
870 ; CHECK-VFP: add sp, sp, #8
871 ; CHECK-VFP: pop {{{.*}}, pc}
872 ; CHECK-NOVFP: ldrh
873 ; CHECK-NOVFP: strh
874 ; CHECK-NOVFP: ldrh
875 ; CHECK-NOVFP: strh
876 ; CHECK-NOVFP: ldrh
877 ; CHECK-NOVFP: strh
878 ; CHECK-NOVFP: ldrh
879 ; CHECK-NOVFP: strh
880 ; CHECK-NOVFP: ldrh
881 define void @test_extractelement(half* %p, <4 x half>* %q, i32 %i) #0 {
882   %a = load <4 x half>, <4 x half>* %q, align 8
883   %b = extractelement <4 x half> %a, i32 %i
884   store half %b, half* %p
885   ret void
888 ; test struct operations
890 %struct.dummy = type { i32, half }
892 ; CHECK-ALL-LABEL: test_insertvalue:
893 ; CHECK-ALL-DAG: ldr
894 ; CHECK-ALL-DAG: ldrh
895 ; CHECK-ALL-DAG: strh
896 ; CHECK-ALL-DAG: str
897 define void @test_insertvalue(%struct.dummy* %p, half* %q) {
898   %a = load %struct.dummy, %struct.dummy* %p
899   %b = load half, half* %q
900   %c = insertvalue %struct.dummy %a, half %b, 1
901   store %struct.dummy %c, %struct.dummy* %p
902   ret void
905 ; CHECK-ALL-LABEL: test_extractvalue:
906 ; CHECK-ALL: .fnstart
907 ; CHECK-ALL: ldrh
908 ; CHECK-ALL: strh
909 define void @test_extractvalue(%struct.dummy* %p, half* %q) {
910   %a = load %struct.dummy, %struct.dummy* %p
911   %b = extractvalue %struct.dummy %a, 1
912   store half %b, half* %q
913   ret void
916 ; CHECK-ALL-LABEL: test_struct_return:
917 ; CHECK-FP16: vcvtb.f32.f16
918 ; CHECK-VFP-LIBCALL: bl __aeabi_h2f
919 ; CHECK-NOVFP-DAG: ldr
920 ; CHECK-NOVFP-DAG: ldrh
921 define %struct.dummy @test_struct_return(%struct.dummy* %p) {
922   %a = load %struct.dummy, %struct.dummy* %p
923   ret %struct.dummy %a
926 ; CHECK-ALL-LABEL: test_struct_arg:
927 ; CHECK-ALL-NEXT: .fnstart
928 ; CHECK-NOVFP-NEXT: mov r0, r1
929 ; CHECK-ALL-NEXT: bx lr
930 define half @test_struct_arg(%struct.dummy %p) {
931   %a = extractvalue %struct.dummy %p, 1
932   ret half %a
935 ; CHECK-LABEL: test_uitofp_i32_fadd:
936 ; CHECK-VFP-DAG: vcvt.f32.u32
937 ; CHECK-NOVFP-DAG: bl __aeabi_ui2f
939 ; CHECK-FP16-DAG: vcvtb.f16.f32
940 ; CHECK-FP16-DAG: vcvtb.f32.f16
941 ; CHECK-LIBCALL-DAG: bl __aeabi_h2f
942 ; CHECK-LIBCALL-DAG: bl __aeabi_h2f
944 ; CHECK-VFP-DAG: vadd.f32
945 ; CHECK-NOVFP-DAG: bl __aeabi_fadd
947 ; CHECK-FP16-DAG: vcvtb.f16.f32
948 ; CHECK-LIBCALL-DAG: bl __aeabi_f2h
949 define half @test_uitofp_i32_fadd(i32 %a, half %b) #0 {
950   %c = uitofp i32 %a to half
951   %r = fadd half %b, %c
952   ret half %r
955 ; CHECK-LABEL: test_sitofp_i32_fadd:
956 ; CHECK-VFP-DAG: vcvt.f32.s32
957 ; CHECK-NOVFP-DAG: bl __aeabi_i2f
959 ; CHECK-FP16-DAG: vcvtb.f16.f32
960 ; CHECK-FP16-DAG: vcvtb.f32.f16
961 ; CHECK-LIBCALL-DAG: bl __aeabi_h2f
962 ; CHECK-LIBCALL-DAG: bl __aeabi_h2f
964 ; CHECK-VFP-DAG: vadd.f32
965 ; CHECK-NOVFP-DAG: bl __aeabi_fadd
967 ; CHECK-FP16-DAG: vcvtb.f16.f32
968 ; CHECK-LIBCALL-DAG: bl __aeabi_f2h
969 define half @test_sitofp_i32_fadd(i32 %a, half %b) #0 {
970   %c = sitofp i32 %a to half
971   %r = fadd half %b, %c
972   ret half %r
975 attributes #0 = { nounwind }