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