xref: /llvm-project/llvm/test/CodeGen/ARM/fp16-fullfp16.ll (revision 7ad12a7c047a421400803eebae4cacc82b27be1d)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple armv8a-none-none-eabihf -mattr=fullfp16 -asm-verbose=false < %s | FileCheck %s
3
4define void @test_fadd(ptr %p, ptr %q) {
5; CHECK-LABEL: test_fadd:
6; CHECK:         vldr.16 s0, [r1]
7; CHECK-NEXT:    vldr.16 s2, [r0]
8; CHECK-NEXT:    vadd.f16 s0, s2, s0
9; CHECK-NEXT:    vstr.16 s0, [r0]
10; CHECK-NEXT:    bx lr
11  %a = load half, ptr %p, align 2
12  %b = load half, ptr %q, align 2
13  %r = fadd half %a, %b
14  store half %r, ptr %p
15  ret void
16}
17
18define void @test_fsub(ptr %p, ptr %q) {
19; CHECK-LABEL: test_fsub:
20; CHECK:         vldr.16 s0, [r1]
21; CHECK-NEXT:    vldr.16 s2, [r0]
22; CHECK-NEXT:    vsub.f16 s0, s2, s0
23; CHECK-NEXT:    vstr.16 s0, [r0]
24; CHECK-NEXT:    bx lr
25  %a = load half, ptr %p, align 2
26  %b = load half, ptr %q, align 2
27  %r = fsub half %a, %b
28  store half %r, ptr %p
29  ret void
30}
31
32define void @test_fmul(ptr %p, ptr %q) {
33; CHECK-LABEL: test_fmul:
34; CHECK:         vldr.16 s0, [r1]
35; CHECK-NEXT:    vldr.16 s2, [r0]
36; CHECK-NEXT:    vmul.f16 s0, s2, s0
37; CHECK-NEXT:    vstr.16 s0, [r0]
38; CHECK-NEXT:    bx lr
39  %a = load half, ptr %p, align 2
40  %b = load half, ptr %q, align 2
41  %r = fmul half %a, %b
42  store half %r, ptr %p
43  ret void
44}
45
46define void @test_fdiv(ptr %p, ptr %q) {
47; CHECK-LABEL: test_fdiv:
48; CHECK:         vldr.16 s0, [r1]
49; CHECK-NEXT:    vldr.16 s2, [r0]
50; CHECK-NEXT:    vdiv.f16 s0, s2, s0
51; CHECK-NEXT:    vstr.16 s0, [r0]
52; CHECK-NEXT:    bx lr
53  %a = load half, ptr %p, align 2
54  %b = load half, ptr %q, align 2
55  %r = fdiv half %a, %b
56  store half %r, ptr %p
57  ret void
58}
59
60define arm_aapcs_vfpcc void @test_frem(ptr %p, ptr %q) {
61; CHECK-LABEL: test_frem:
62; CHECK:         .save {r4, lr}
63; CHECK-NEXT:    push {r4, lr}
64; CHECK-NEXT:    vldr.16 s0, [r0]
65; CHECK-NEXT:    vldr.16 s2, [r1]
66; CHECK-NEXT:    mov r4, r0
67; CHECK-NEXT:    vcvtb.f32.f16 s0, s0
68; CHECK-NEXT:    vcvtb.f32.f16 s1, s2
69; CHECK-NEXT:    bl fmodf
70; CHECK-NEXT:    vcvtb.f16.f32 s0, s0
71; CHECK-NEXT:    vstr.16 s0, [r4]
72; CHECK-NEXT:    pop {r4, pc}
73  %a = load half, ptr %p, align 2
74  %b = load half, ptr %q, align 2
75  %r = frem half %a, %b
76  store half %r, ptr %p
77  ret void
78}
79
80define void @test_load_store(ptr %p, ptr %q) {
81; CHECK-LABEL: test_load_store:
82; CHECK:         vldr.16 s0, [r0]
83; CHECK-NEXT:    vstr.16 s0, [r1]
84; CHECK-NEXT:    bx lr
85  %a = load half, ptr %p, align 2
86  store half %a, ptr %q
87  ret void
88}
89
90define i32 @test_fptosi_i32(ptr %p) {
91; CHECK-LABEL: test_fptosi_i32:
92; CHECK:         vldr.16 s0, [r0]
93; CHECK-NEXT:    vcvt.s32.f16 s0, s0
94; CHECK-NEXT:    vmov r0, s0
95; CHECK-NEXT:    bx lr
96  %a = load half, ptr %p, align 2
97  %r = fptosi half %a to i32
98  ret i32 %r
99}
100
101; FIXME
102;define i64 @test_fptosi_i64(ptr %p) {
103;  %a = load half, ptr %p, align 2
104;  %r = fptosi half %a to i64
105;  ret i64 %r
106;}
107
108define i32 @test_fptoui_i32(ptr %p) {
109; CHECK-LABEL: test_fptoui_i32:
110; CHECK:         vldr.16 s0, [r0]
111; CHECK-NEXT:    vcvt.u32.f16 s0, s0
112; CHECK-NEXT:    vmov r0, s0
113; CHECK-NEXT:    bx lr
114  %a = load half, ptr %p, align 2
115  %r = fptoui half %a to i32
116  ret i32 %r
117}
118
119; FIXME
120;define i64 @test_fptoui_i64(ptr %p) {
121;  %a = load half, ptr %p, align 2
122;  %r = fptoui half %a to i64
123;  ret i64 %r
124;}
125
126define void @test_sitofp_i32(i32 %a, ptr %p) {
127; CHECK-LABEL: test_sitofp_i32:
128; CHECK:         vmov s0, r0
129; CHECK-NEXT:    vcvt.f16.s32 s0, s0
130; CHECK-NEXT:    vstr.16 s0, [r1]
131; CHECK-NEXT:    bx lr
132  %r = sitofp i32 %a to half
133  store half %r, ptr %p
134  ret void
135}
136
137define void @test_uitofp_i32(i32 %a, ptr %p) {
138; CHECK-LABEL: test_uitofp_i32:
139; CHECK:         vmov s0, r0
140; CHECK-NEXT:    vcvt.f16.u32 s0, s0
141; CHECK-NEXT:    vstr.16 s0, [r1]
142; CHECK-NEXT:    bx lr
143  %r = uitofp i32 %a to half
144  store half %r, ptr %p
145  ret void
146}
147
148; FIXME
149;define void @test_sitofp_i64(i64 %a, ptr %p) {
150;  %r = sitofp i64 %a to half
151;  store half %r, ptr %p
152;  ret void
153;}
154
155; FIXME
156;define void @test_uitofp_i64(i64 %a, ptr %p) {
157;  %r = uitofp i64 %a to half
158;  store half %r, ptr %p
159;  ret void
160;}
161
162define void @test_fptrunc_float(float %f, ptr %p) {
163; CHECK-LABEL: test_fptrunc_float:
164; CHECK:         vcvtb.f16.f32 s0, s0
165; CHECK-NEXT:    vstr.16 s0, [r0]
166; CHECK-NEXT:    bx lr
167  %a = fptrunc float %f to half
168  store half %a, ptr %p
169  ret void
170}
171
172define void @test_fptrunc_double(double %d, ptr %p) {
173; CHECK-LABEL: test_fptrunc_double:
174; CHECK:         vcvtb.f16.f64 s0, d0
175; CHECK-NEXT:    vstr.16 s0, [r0]
176; CHECK-NEXT:    bx lr
177  %a = fptrunc double %d to half
178  store half %a, ptr %p
179  ret void
180}
181
182define float @test_fpextend_float(ptr %p) {
183; CHECK-LABEL: test_fpextend_float:
184; CHECK:         vldr.16 s0, [r0]
185; CHECK-NEXT:    vcvtb.f32.f16 s0, s0
186; CHECK-NEXT:    bx lr
187  %a = load half, ptr %p, align 2
188  %r = fpext half %a to float
189  ret float %r
190}
191
192define double @test_fpextend_double(ptr %p) {
193; CHECK-LABEL: test_fpextend_double:
194; CHECK:         vldr.16 s0, [r0]
195; CHECK-NEXT:    vcvtb.f64.f16 d0, s0
196; CHECK-NEXT:    bx lr
197  %a = load half, ptr %p, align 2
198  %r = fpext half %a to double
199  ret double %r
200}
201
202define i16 @test_bitcast_halftoi16(ptr %p) {
203; CHECK-LABEL: test_bitcast_halftoi16:
204; CHECK:         ldrh r0, [r0]
205; CHECK-NEXT:    bx lr
206  %a = load half, ptr %p, align 2
207  %r = bitcast half %a to i16
208  ret i16 %r
209}
210
211define void @test_bitcast_i16tohalf(i16 %a, ptr %p) {
212; CHECK-LABEL: test_bitcast_i16tohalf:
213; CHECK:         strh r0, [r1]
214; CHECK-NEXT:    bx lr
215  %r = bitcast i16 %a to half
216  store half %r, ptr %p
217  ret void
218}
219
220define void @test_sqrt(ptr %p) {
221; CHECK-LABEL: test_sqrt:
222; CHECK:         vldr.16 s0, [r0]
223; CHECK-NEXT:    vsqrt.f16 s0, s0
224; CHECK-NEXT:    vstr.16 s0, [r0]
225; CHECK-NEXT:    bx lr
226  %a = load half, ptr %p, align 2
227  %r = call half @llvm.sqrt.f16(half %a)
228  store half %r, ptr %p
229  ret void
230}
231
232define void @test_fpowi(ptr %p, i32 %b) {
233; CHECK-LABEL: test_fpowi:
234; CHECK:         .save {r4, lr}
235; CHECK-NEXT:    push {r4, lr}
236; CHECK-NEXT:    vldr.16 s0, [r0]
237; CHECK-NEXT:    mov r4, r0
238; CHECK-NEXT:    mov r0, r1
239; CHECK-NEXT:    vcvtb.f32.f16 s0, s0
240; CHECK-NEXT:    bl __powisf2
241; CHECK-NEXT:    vcvtb.f16.f32 s0, s0
242; CHECK-NEXT:    vstr.16 s0, [r4]
243; CHECK-NEXT:    pop {r4, pc}
244  %a = load half, ptr %p, align 2
245  %r = call half @llvm.powi.f16.i32(half %a, i32 %b)
246  store half %r, ptr %p
247  ret void
248}
249
250define void @test_sin(ptr %p) {
251; CHECK-LABEL: test_sin:
252; CHECK:         .save {r4, lr}
253; CHECK-NEXT:    push {r4, lr}
254; CHECK-NEXT:    vldr.16 s0, [r0]
255; CHECK-NEXT:    mov r4, r0
256; CHECK-NEXT:    vcvtb.f32.f16 s0, s0
257; CHECK-NEXT:    bl sinf
258; CHECK-NEXT:    vcvtb.f16.f32 s0, s0
259; CHECK-NEXT:    vstr.16 s0, [r4]
260; CHECK-NEXT:    pop {r4, pc}
261  %a = load half, ptr %p, align 2
262  %r = call half @llvm.sin.f16(half %a)
263  store half %r, ptr %p
264  ret void
265}
266
267define void @test_cos(ptr %p) {
268; CHECK-LABEL: test_cos:
269; CHECK:         .save {r4, lr}
270; CHECK-NEXT:    push {r4, lr}
271; CHECK-NEXT:    vldr.16 s0, [r0]
272; CHECK-NEXT:    mov r4, r0
273; CHECK-NEXT:    vcvtb.f32.f16 s0, s0
274; CHECK-NEXT:    bl cosf
275; CHECK-NEXT:    vcvtb.f16.f32 s0, s0
276; CHECK-NEXT:    vstr.16 s0, [r4]
277; CHECK-NEXT:    pop {r4, pc}
278  %a = load half, ptr %p, align 2
279  %r = call half @llvm.cos.f16(half %a)
280  store half %r, ptr %p
281  ret void
282}
283
284define void @test_tan(ptr %p) {
285; CHECK-LABEL: test_tan:
286; CHECK:         .save {r4, lr}
287; CHECK-NEXT:    push {r4, lr}
288; CHECK-NEXT:    vldr.16 s0, [r0]
289; CHECK-NEXT:    mov r4, r0
290; CHECK-NEXT:    vcvtb.f32.f16 s0, s0
291; CHECK-NEXT:    bl tanf
292; CHECK-NEXT:    vcvtb.f16.f32 s0, s0
293; CHECK-NEXT:    vstr.16 s0, [r4]
294; CHECK-NEXT:    pop {r4, pc}
295  %a = load half, ptr %p, align 2
296  %r = call half @llvm.tan.f16(half %a)
297  store half %r, ptr %p
298  ret void
299}
300
301define void @test_pow(ptr %p, ptr %q) {
302; CHECK-LABEL: test_pow:
303; CHECK:         .save {r4, lr}
304; CHECK-NEXT:    push {r4, lr}
305; CHECK-NEXT:    vldr.16 s0, [r0]
306; CHECK-NEXT:    vldr.16 s2, [r1]
307; CHECK-NEXT:    mov r4, r0
308; CHECK-NEXT:    vcvtb.f32.f16 s0, s0
309; CHECK-NEXT:    vcvtb.f32.f16 s1, s2
310; CHECK-NEXT:    bl powf
311; CHECK-NEXT:    vcvtb.f16.f32 s0, s0
312; CHECK-NEXT:    vstr.16 s0, [r4]
313; CHECK-NEXT:    pop {r4, pc}
314  %a = load half, ptr %p, align 2
315  %b = load half, ptr %q, align 2
316  %r = call half @llvm.pow.f16(half %a, half %b)
317  store half %r, ptr %p
318  ret void
319}
320
321define void @test_exp(ptr %p) {
322; CHECK-LABEL: test_exp:
323; CHECK:         .save {r4, lr}
324; CHECK-NEXT:    push {r4, lr}
325; CHECK-NEXT:    vldr.16 s0, [r0]
326; CHECK-NEXT:    mov r4, r0
327; CHECK-NEXT:    vcvtb.f32.f16 s0, s0
328; CHECK-NEXT:    bl expf
329; CHECK-NEXT:    vcvtb.f16.f32 s0, s0
330; CHECK-NEXT:    vstr.16 s0, [r4]
331; CHECK-NEXT:    pop {r4, pc}
332  %a = load half, ptr %p, align 2
333  %r = call half @llvm.exp.f16(half %a)
334  store half %r, ptr %p
335  ret void
336}
337
338define void @test_exp2(ptr %p) {
339; CHECK-LABEL: test_exp2:
340; CHECK:         .save {r4, lr}
341; CHECK-NEXT:    push {r4, lr}
342; CHECK-NEXT:    vldr.16 s0, [r0]
343; CHECK-NEXT:    mov r4, r0
344; CHECK-NEXT:    vcvtb.f32.f16 s0, s0
345; CHECK-NEXT:    bl exp2f
346; CHECK-NEXT:    vcvtb.f16.f32 s0, s0
347; CHECK-NEXT:    vstr.16 s0, [r4]
348; CHECK-NEXT:    pop {r4, pc}
349  %a = load half, ptr %p, align 2
350  %r = call half @llvm.exp2.f16(half %a)
351  store half %r, ptr %p
352  ret void
353}
354
355define void @test_log(ptr %p) {
356; CHECK-LABEL: test_log:
357; CHECK:         .save {r4, lr}
358; CHECK-NEXT:    push {r4, lr}
359; CHECK-NEXT:    vldr.16 s0, [r0]
360; CHECK-NEXT:    mov r4, r0
361; CHECK-NEXT:    vcvtb.f32.f16 s0, s0
362; CHECK-NEXT:    bl logf
363; CHECK-NEXT:    vcvtb.f16.f32 s0, s0
364; CHECK-NEXT:    vstr.16 s0, [r4]
365; CHECK-NEXT:    pop {r4, pc}
366  %a = load half, ptr %p, align 2
367  %r = call half @llvm.log.f16(half %a)
368  store half %r, ptr %p
369  ret void
370}
371
372define void @test_log10(ptr %p) {
373; CHECK-LABEL: test_log10:
374; CHECK:         .save {r4, lr}
375; CHECK-NEXT:    push {r4, lr}
376; CHECK-NEXT:    vldr.16 s0, [r0]
377; CHECK-NEXT:    mov r4, r0
378; CHECK-NEXT:    vcvtb.f32.f16 s0, s0
379; CHECK-NEXT:    bl log10f
380; CHECK-NEXT:    vcvtb.f16.f32 s0, s0
381; CHECK-NEXT:    vstr.16 s0, [r4]
382; CHECK-NEXT:    pop {r4, pc}
383  %a = load half, ptr %p, align 2
384  %r = call half @llvm.log10.f16(half %a)
385  store half %r, ptr %p
386  ret void
387}
388
389define void @test_log2(ptr %p) {
390; CHECK-LABEL: test_log2:
391; CHECK:         .save {r4, lr}
392; CHECK-NEXT:    push {r4, lr}
393; CHECK-NEXT:    vldr.16 s0, [r0]
394; CHECK-NEXT:    mov r4, r0
395; CHECK-NEXT:    vcvtb.f32.f16 s0, s0
396; CHECK-NEXT:    bl log2f
397; CHECK-NEXT:    vcvtb.f16.f32 s0, s0
398; CHECK-NEXT:    vstr.16 s0, [r4]
399; CHECK-NEXT:    pop {r4, pc}
400  %a = load half, ptr %p, align 2
401  %r = call half @llvm.log2.f16(half %a)
402  store half %r, ptr %p
403  ret void
404}
405
406define void @test_fma(ptr %p, ptr %q, ptr %r) {
407; CHECK-LABEL: test_fma:
408; CHECK:         vldr.16 s0, [r1]
409; CHECK-NEXT:    vldr.16 s2, [r0]
410; CHECK-NEXT:    vldr.16 s4, [r2]
411; CHECK-NEXT:    vfma.f16 s4, s2, s0
412; CHECK-NEXT:    vstr.16 s4, [r0]
413; CHECK-NEXT:    bx lr
414  %a = load half, ptr %p, align 2
415  %b = load half, ptr %q, align 2
416  %c = load half, ptr %r, align 2
417  %v = call half @llvm.fma.f16(half %a, half %b, half %c)
418  store half %v, ptr %p
419  ret void
420}
421
422define void @test_fabs(ptr %p) {
423; CHECK-LABEL: test_fabs:
424; CHECK:         vldr.16 s0, [r0]
425; CHECK-NEXT:    vabs.f16 s0, s0
426; CHECK-NEXT:    vstr.16 s0, [r0]
427; CHECK-NEXT:    bx lr
428  %a = load half, ptr %p, align 2
429  %r = call half @llvm.fabs.f16(half %a)
430  store half %r, ptr %p
431  ret void
432}
433
434define void @test_minnum(ptr %p, ptr %q) {
435; CHECK-LABEL: test_minnum:
436; CHECK:         vldr.16 s0, [r1]
437; CHECK-NEXT:    vldr.16 s2, [r0]
438; CHECK-NEXT:    vminnm.f16 s0, s2, s0
439; CHECK-NEXT:    vstr.16 s0, [r0]
440; CHECK-NEXT:    bx lr
441  %a = load half, ptr %p, align 2
442  %b = load half, ptr %q, align 2
443  %r = call half @llvm.minnum.f16(half %a, half %b)
444  store half %r, ptr %p
445  ret void
446}
447
448define void @test_maxnum(ptr %p, ptr %q) {
449; CHECK-LABEL: test_maxnum:
450; CHECK:         vldr.16 s0, [r1]
451; CHECK-NEXT:    vldr.16 s2, [r0]
452; CHECK-NEXT:    vmaxnm.f16 s0, s2, s0
453; CHECK-NEXT:    vstr.16 s0, [r0]
454; CHECK-NEXT:    bx lr
455  %a = load half, ptr %p, align 2
456  %b = load half, ptr %q, align 2
457  %r = call half @llvm.maxnum.f16(half %a, half %b)
458  store half %r, ptr %p
459  ret void
460}
461
462define void @test_minimum(ptr %p) {
463; CHECK-LABEL: test_minimum:
464; CHECK:         vldr.16 s2, [r0]
465; CHECK-NEXT:    vmov.f16 s0, #1.000000e+00
466; CHECK-NEXT:    vcmp.f16 s2, s0
467; CHECK-NEXT:    vmrs APSR_nzcv, fpscr
468; CHECK-NEXT:    vselge.f16 s0, s0, s2
469; CHECK-NEXT:    vstr.16 s0, [r0]
470; CHECK-NEXT:    bx lr
471  %a = load half, ptr %p, align 2
472  %c = fcmp ult half %a, 1.0
473  %r = select i1 %c, half %a, half 1.0
474  store half %r, ptr %p
475  ret void
476}
477
478define void @test_maximum(ptr %p) {
479; CHECK-LABEL: test_maximum:
480; CHECK:         vldr.16 s2, [r0]
481; CHECK-NEXT:    vmov.f16 s0, #1.000000e+00
482; CHECK-NEXT:    vcmp.f16 s0, s2
483; CHECK-NEXT:    vmrs APSR_nzcv, fpscr
484; CHECK-NEXT:    vselge.f16 s0, s0, s2
485; CHECK-NEXT:    vstr.16 s0, [r0]
486; CHECK-NEXT:    bx lr
487  %a = load half, ptr %p, align 2
488  %c = fcmp ugt half %a, 1.0
489  %r = select i1 %c, half %a, half 1.0
490  store half %r, ptr %p
491  ret void
492}
493
494define void @test_copysign(ptr %p, ptr %q) {
495; CHECK-LABEL: test_copysign:
496; CHECK:         .pad #4
497; CHECK-NEXT:    sub sp, sp, #4
498; CHECK-NEXT:    vldr.16 s0, [r1]
499; CHECK-NEXT:    vstr.16 s0, [sp]
500; CHECK-NEXT:    vldr.16 s0, [r0]
501; CHECK-NEXT:    ldrb r1, [sp, #1]
502; CHECK-NEXT:    vabs.f16 s0, s0
503; CHECK-NEXT:    tst r1, #128
504; CHECK-NEXT:    vneg.f16 s2, s0
505; CHECK-NEXT:    vseleq.f16 s0, s0, s2
506; CHECK-NEXT:    vstr.16 s0, [r0]
507; CHECK-NEXT:    add sp, sp, #4
508; CHECK-NEXT:    bx lr
509  %a = load half, ptr %p, align 2
510  %b = load half, ptr %q, align 2
511  %r = call half @llvm.copysign.f16(half %a, half %b)
512  store half %r, ptr %p
513  ret void
514}
515
516define void @test_floor(ptr %p) {
517; CHECK-LABEL: test_floor:
518; CHECK:         vldr.16 s0, [r0]
519; CHECK-NEXT:    vrintm.f16 s0, s0
520; CHECK-NEXT:    vstr.16 s0, [r0]
521; CHECK-NEXT:    bx lr
522  %a = load half, ptr %p, align 2
523  %r = call half @llvm.floor.f16(half %a)
524  store half %r, ptr %p
525  ret void
526}
527
528define void @test_ceil(ptr %p) {
529; CHECK-LABEL: test_ceil:
530; CHECK:         vldr.16 s0, [r0]
531; CHECK-NEXT:    vrintp.f16 s0, s0
532; CHECK-NEXT:    vstr.16 s0, [r0]
533; CHECK-NEXT:    bx lr
534  %a = load half, ptr %p, align 2
535  %r = call half @llvm.ceil.f16(half %a)
536  store half %r, ptr %p
537  ret void
538}
539
540define void @test_trunc(ptr %p) {
541; CHECK-LABEL: test_trunc:
542; CHECK:         vldr.16 s0, [r0]
543; CHECK-NEXT:    vrintz.f16 s0, s0
544; CHECK-NEXT:    vstr.16 s0, [r0]
545; CHECK-NEXT:    bx lr
546  %a = load half, ptr %p, align 2
547  %r = call half @llvm.trunc.f16(half %a)
548  store half %r, ptr %p
549  ret void
550}
551
552define void @test_rint(ptr %p) {
553; CHECK-LABEL: test_rint:
554; CHECK:         vldr.16 s0, [r0]
555; CHECK-NEXT:    vrintx.f16 s0, s0
556; CHECK-NEXT:    vstr.16 s0, [r0]
557; CHECK-NEXT:    bx lr
558  %a = load half, ptr %p, align 2
559  %r = call half @llvm.rint.f16(half %a)
560  store half %r, ptr %p
561  ret void
562}
563
564define void @test_nearbyint(ptr %p) {
565; CHECK-LABEL: test_nearbyint:
566; CHECK:         vldr.16 s0, [r0]
567; CHECK-NEXT:    vrintr.f16 s0, s0
568; CHECK-NEXT:    vstr.16 s0, [r0]
569; CHECK-NEXT:    bx lr
570  %a = load half, ptr %p, align 2
571  %r = call half @llvm.nearbyint.f16(half %a)
572  store half %r, ptr %p
573  ret void
574}
575
576define void @test_round(ptr %p) {
577; CHECK-LABEL: test_round:
578; CHECK:         vldr.16 s0, [r0]
579; CHECK-NEXT:    vrinta.f16 s0, s0
580; CHECK-NEXT:    vstr.16 s0, [r0]
581; CHECK-NEXT:    bx lr
582  %a = load half, ptr %p, align 2
583  %r = call half @llvm.round.f16(half %a)
584  store half %r, ptr %p
585  ret void
586}
587
588define void @test_fmuladd(ptr %p, ptr %q, ptr %r) {
589; CHECK-LABEL: test_fmuladd:
590; CHECK:         vldr.16 s0, [r1]
591; CHECK-NEXT:    vldr.16 s2, [r0]
592; CHECK-NEXT:    vldr.16 s4, [r2]
593; CHECK-NEXT:    vfma.f16 s4, s2, s0
594; CHECK-NEXT:    vstr.16 s4, [r0]
595; CHECK-NEXT:    bx lr
596  %a = load half, ptr %p, align 2
597  %b = load half, ptr %q, align 2
598  %c = load half, ptr %r, align 2
599  %v = call half @llvm.fmuladd.f16(half %a, half %b, half %c)
600  store half %v, ptr %p
601  ret void
602}
603
604declare half @llvm.sqrt.f16(half %a)
605declare half @llvm.powi.f16.i32(half %a, i32 %b)
606declare half @llvm.sin.f16(half %a)
607declare half @llvm.cos.f16(half %a)
608declare half @llvm.tan.f16(half %a)
609declare half @llvm.pow.f16(half %a, half %b)
610declare half @llvm.exp.f16(half %a)
611declare half @llvm.exp2.f16(half %a)
612declare half @llvm.log.f16(half %a)
613declare half @llvm.log10.f16(half %a)
614declare half @llvm.log2.f16(half %a)
615declare half @llvm.fma.f16(half %a, half %b, half %c)
616declare half @llvm.fabs.f16(half %a)
617declare half @llvm.minnum.f16(half %a, half %b)
618declare half @llvm.maxnum.f16(half %a, half %b)
619declare half @llvm.copysign.f16(half %a, half %b)
620declare half @llvm.floor.f16(half %a)
621declare half @llvm.ceil.f16(half %a)
622declare half @llvm.trunc.f16(half %a)
623declare half @llvm.rint.f16(half %a)
624declare half @llvm.nearbyint.f16(half %a)
625declare half @llvm.round.f16(half %a)
626declare half @llvm.fmuladd.f16(half %a, half %b, half %c)
627