• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
5target 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"
6target 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
17define 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
34define 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
51define 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
68define 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
84define 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]+}}]
96define 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
105declare 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}
113define 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}
130define 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
144define 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]+}}]
156define 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}}
175define 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}}
191define 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
210define 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
215then:
216  store i32 0, i32* %p1
217  ret void
218else:
219  store i32 0, i32* %p2
220  ret void
221}
222
223declare 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
237define void @test_phi(half* %p) #0 {
238entry:
239  %a = load half, half* %p
240  br label %loop
241loop:
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
246return:
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
256define 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
266define 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
277define 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
287define 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
298define 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
309define 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
319define 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
329define 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
339define 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
349define 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
359define 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
371define 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
381define 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
391define 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
397declare half @llvm.sqrt.f16(half %a) #0
398declare half @llvm.powi.f16(half %a, i32 %b) #0
399declare half @llvm.sin.f16(half %a) #0
400declare half @llvm.cos.f16(half %a) #0
401declare half @llvm.pow.f16(half %a, half %b) #0
402declare half @llvm.exp.f16(half %a) #0
403declare half @llvm.exp2.f16(half %a) #0
404declare half @llvm.log.f16(half %a) #0
405declare half @llvm.log10.f16(half %a) #0
406declare half @llvm.log2.f16(half %a) #0
407declare half @llvm.fma.f16(half %a, half %b, half %c) #0
408declare half @llvm.fabs.f16(half %a) #0
409declare half @llvm.minnum.f16(half %a, half %b) #0
410declare half @llvm.maxnum.f16(half %a, half %b) #0
411declare half @llvm.copysign.f16(half %a, half %b) #0
412declare half @llvm.floor.f16(half %a) #0
413declare half @llvm.ceil.f16(half %a) #0
414declare half @llvm.trunc.f16(half %a) #0
415declare half @llvm.rint.f16(half %a) #0
416declare half @llvm.nearbyint.f16(half %a) #0
417declare half @llvm.round.f16(half %a) #0
418declare 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
428define 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
443define 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
458define 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
473define 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
490define 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
506define 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
521define 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
536define 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
551define 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
566define 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
585define 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
602define 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
619define 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
637define 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
654define 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
671define 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
692define 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
708define 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
723define 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
738define 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
753define 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
768define 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
783define 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
803define 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: add
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
839define 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: add
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
872define 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
888define 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
900define 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
912define %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
921define 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
940define 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
960define 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
966attributes #0 = { nounwind }
967