1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple aarch64-unknown-unknown -aarch64-neon-syntax=apple -asm-verbose=false -disable-post-ra -frame-pointer=non-leaf | FileCheck %s --check-prefix=CHECK-CVT --check-prefix=CHECK-COMMON
3; RUN: llc < %s -mtriple aarch64-unknown-unknown -mattr=+fullfp16 -aarch64-neon-syntax=apple -asm-verbose=false -disable-post-ra -frame-pointer=non-leaf | FileCheck %s --check-prefix=CHECK-COMMON --check-prefix=CHECK-FP16
4
5; RUN: llc < %s -mtriple aarch64-unknown-unknown -aarch64-neon-syntax=apple \
6; RUN: -asm-verbose=false -disable-post-ra -frame-pointer=non-leaf -global-isel \
7; RUN: -global-isel-abort=2 -pass-remarks-missed=gisel-* 2>&1 | FileCheck %s \
8; RUN: --check-prefixes=FALLBACK,GISEL-CVT,GISEL
9
10; RUN: llc < %s -mtriple aarch64-unknown-unknown -mattr=+fullfp16 \
11; RUN: -aarch64-neon-syntax=apple -asm-verbose=false -disable-post-ra \
12; RUN: -frame-pointer=non-leaf -global-isel -global-isel-abort=2 \
13; RUN: -pass-remarks-missed=gisel-* 2>&1 | FileCheck %s \
14; RUN: --check-prefixes=FALLBACK-FP16,GISEL-FP16,GISEL
15
16target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
17
18; CHECK-CVT-LABEL: test_fadd:
19; CHECK-CVT-NEXT: fcvt s1, h1
20; CHECK-CVT-NEXT: fcvt s0, h0
21; CHECK-CVT-NEXT: fadd s0, s0, s1
22; CHECK-CVT-NEXT: fcvt h0, s0
23; CHECK-CVT-NEXT: ret
24
25; CHECK-FP16-LABEL: test_fadd:
26; CHECK-FP16-NEXT:  fadd h0, h0, h1
27; CHECK-FP16-NEXT:  ret
28
29define half @test_fadd(half %a, half %b) #0 {
30  %r = fadd half %a, %b
31  ret half %r
32}
33
34; CHECK-CVT-LABEL: test_fsub:
35; CHECK-CVT-NEXT: fcvt s1, h1
36; CHECK-CVT-NEXT: fcvt s0, h0
37; CHECK-CVT-NEXT: fsub s0, s0, s1
38; CHECK-CVT-NEXT: fcvt h0, s0
39; CHECK-CVT-NEXT: ret
40
41; CHECK-FP16-LABEL: test_fsub:
42; CHECK-FP16-NEXT: fsub h0, h0, h1
43; CHECK-FP16-NEXT: ret
44
45define half @test_fsub(half %a, half %b) #0 {
46  %r = fsub half %a, %b
47  ret half %r
48}
49
50; CHECK-CVT-LABEL: test_fmul:
51; CHECK-CVT-NEXT: fcvt s1, h1
52; CHECK-CVT-NEXT: fcvt s0, h0
53; CHECK-CVT-NEXT: fmul s0, s0, s1
54; CHECK-CVT-NEXT: fcvt h0, s0
55; CHECK-CVT-NEXT: ret
56
57; CHECK-FP16-LABEL: test_fmul:
58; CHECK-FP16-NEXT: fmul h0, h0, h1
59; CHECK-FP16-NEXT: ret
60
61define half @test_fmul(half %a, half %b) #0 {
62  %r = fmul half %a, %b
63  ret half %r
64}
65
66; CHECK-CVT-LABEL: test_fmadd:
67; CHECK-CVT-NEXT: fcvt s1, h1
68; CHECK-CVT-NEXT: fcvt s0, h0
69; CHECK-CVT-NEXT: fmul s0, s0, s1
70; CHECK-CVT-NEXT: fcvt h0, s0
71; CHECK-CVT-NEXT: fcvt s0, h0
72; CHECK-CVT-NEXT: fcvt s1, h2
73; CHECK-CVT-NEXT: fadd s0, s0, s1
74; CHECK-CVT-NEXT: fcvt h0, s0
75; CHECK-CVT-NEXT: ret
76
77; CHECK-FP16-LABEL: test_fmadd:
78; CHECK-FP16-NEXT: fmadd h0, h0, h1, h2
79; CHECK-FP16-NEXT: ret
80
81define half @test_fmadd(half %a, half %b, half %c) #0 {
82  %mul = fmul fast half %a, %b
83  %r = fadd fast half %mul, %c
84  ret half %r
85}
86; CHECK-CVT-LABEL: test_fdiv:
87; CHECK-CVT-NEXT: fcvt s1, h1
88; CHECK-CVT-NEXT: fcvt s0, h0
89; CHECK-CVT-NEXT: fdiv s0, s0, s1
90; CHECK-CVT-NEXT: fcvt h0, s0
91; CHECK-CVT-NEXT: ret
92
93; CHECK-FP16-LABEL: test_fdiv:
94; CHECK-FP16-NEXT: fdiv	h0, h0, h1
95; CHECK-FP16-NEXT: ret
96
97define half @test_fdiv(half %a, half %b) #0 {
98  %r = fdiv half %a, %b
99  ret half %r
100}
101
102; CHECK-COMMON-LABEL: test_frem:
103; CHECK-COMMON-NEXT: stp x29, x30, [sp, #-16]!
104; CHECK-COMMON-NEXT: mov  x29, sp
105; CHECK-COMMON-NEXT: fcvt s0, h0
106; CHECK-COMMON-NEXT: fcvt s1, h1
107; CHECK-COMMON-NEXT: bl {{_?}}fmodf
108; CHECK-COMMON-NEXT: fcvt h0, s0
109; CHECK-COMMON-NEXT: ldp x29, x30, [sp], #16
110; CHECK-COMMON-NEXT: ret
111define half @test_frem(half %a, half %b) #0 {
112  %r = frem half %a, %b
113  ret half %r
114}
115
116; CHECK-COMMON-LABEL: test_store:
117; CHECK-COMMON-NEXT: str  h0, [x0]
118; CHECK-COMMON-NEXT: ret
119define void @test_store(half %a, half* %b) #0 {
120  store half %a, half* %b
121  ret void
122}
123
124; CHECK-COMMON-LABEL: test_load:
125; CHECK-COMMON-NEXT: ldr  h0, [x0]
126; CHECK-COMMON-NEXT: ret
127define half @test_load(half* %a) #0 {
128  %r = load half, half* %a
129  ret half %r
130}
131
132declare half @test_callee(half %a, half %b) #0
133
134; CHECK-COMMON-LABEL: test_call:
135; CHECK-COMMON-NEXT: stp x29, x30, [sp, #-16]!
136; CHECK-COMMON-NEXT: mov  x29, sp
137; CHECK-COMMON-NEXT: bl {{_?}}test_callee
138; CHECK-COMMON-NEXT: ldp x29, x30, [sp], #16
139; CHECK-COMMON-NEXT: ret
140define half @test_call(half %a, half %b) #0 {
141  %r = call half @test_callee(half %a, half %b)
142  ret half %r
143}
144
145; CHECK-COMMON-LABEL: test_call_flipped:
146; CHECK-COMMON-NEXT: stp x29, x30, [sp, #-16]!
147; CHECK-COMMON-NEXT: mov  x29, sp
148; CHECK-COMMON-NEXT: fmov  s2, s0
149; CHECK-COMMON-NEXT: fmov  s0, s1
150; CHECK-COMMON-NEXT: fmov  s1, s2
151; CHECK-COMMON-NEXT: bl {{_?}}test_callee
152; CHECK-COMMON-NEXT: ldp x29, x30, [sp], #16
153; CHECK-COMMON-NEXT: ret
154define half @test_call_flipped(half %a, half %b) #0 {
155  %r = call half @test_callee(half %b, half %a)
156  ret half %r
157}
158
159; CHECK-COMMON-LABEL: test_tailcall_flipped:
160; CHECK-COMMON-NEXT: fmov  s2, s0
161; CHECK-COMMON-NEXT: fmov  s0, s1
162; CHECK-COMMON-NEXT: fmov  s1, s2
163; CHECK-COMMON-NEXT: b {{_?}}test_callee
164define half @test_tailcall_flipped(half %a, half %b) #0 {
165  %r = tail call half @test_callee(half %b, half %a)
166  ret half %r
167}
168
169; CHECK-CVT-LABEL: test_select:
170; CHECK-CVT-NEXT: fcvt s1, h1
171; CHECK-CVT-NEXT: fcvt s0, h0
172; CHECK-CVT-NEXT: cmp  w0, #0
173; CHECK-CVT-NEXT: fcsel s0, s0, s1, ne
174; CHECK-CVT-NEXT: fcvt h0, s0
175; CHECK-CVT-NEXT: ret
176
177; CHECK-FP16-LABEL: test_select:
178; CHECK-FP16-NEXT: cmp w0, #0
179; CHECK-FP16-NEXT: fcsel h0, h0, h1, ne
180; CHECK-FP16-NEXT: ret
181
182define half @test_select(half %a, half %b, i1 zeroext %c) #0 {
183  %r = select i1 %c, half %a, half %b
184  ret half %r
185}
186
187; CHECK-CVT-LABEL: test_select_cc:
188; CHECK-CVT-DAG: fcvt s3, h3
189; CHECK-CVT-DAG: fcvt s2, h2
190; CHECK-CVT-DAG: fcvt s1, h1
191; CHECK-CVT-DAG: fcvt s0, h0
192; CHECK-CVT-DAG: fcmp s2, s3
193; CHECK-CVT-NEXT: fcsel s0, s0, s1, ne
194; CHECK-CVT-NEXT: fcvt h0, s0
195; CHECK-CVT-NEXT: ret
196
197; CHECK-FP16-LABEL: test_select_cc:
198; CHECK-FP16-NEXT: fcmp h2, h3
199; CHECK-FP16-NEXT: fcsel h0, h0, h1, ne
200; CHECK-FP16-NEXT: ret
201
202define half @test_select_cc(half %a, half %b, half %c, half %d) #0 {
203  %cc = fcmp une half %c, %d
204  %r = select i1 %cc, half %a, half %b
205  ret half %r
206}
207
208; CHECK-CVT-LABEL: test_select_cc_f32_f16:
209; CHECK-CVT-DAG:   fcvt s2, h2
210; CHECK-CVT-DAG:   fcvt s3, h3
211; CHECK-CVT-NEXT:  fcmp s2, s3
212; CHECK-CVT-NEXT:  fcsel s0, s0, s1, ne
213; CHECK-CVT-NEXT:  ret
214
215; CHECK-FP16-LABEL: test_select_cc_f32_f16:
216; CHECK-FP16-NEXT: fcmp	h2, h3
217; CHECK-FP16-NEXT: fcsel	s0, s0, s1, ne
218; CHECK-FP16-NEXT: ret
219
220define float @test_select_cc_f32_f16(float %a, float %b, half %c, half %d) #0 {
221  %cc = fcmp une half %c, %d
222  %r = select i1 %cc, float %a, float %b
223  ret float %r
224}
225
226; CHECK-CVT-LABEL: test_select_cc_f16_f32:
227; CHECK-CVT-DAG:  fcvt s0, h0
228; CHECK-CVT-DAG:  fcvt s1, h1
229; CHECK-CVT-DAG:  fcmp s2, s3
230; CHECK-CVT-NEXT: fcsel s0, s0, s1, ne
231; CHECK-CVT-NEXT: fcvt h0, s0
232; CHECK-CVT-NEXT: ret
233
234; CHECK-FP16-LABEL: test_select_cc_f16_f32:
235; CHECK-FP16-NEXT: fcmp	s2, s3
236; CHECK-FP16-NEXT: fcsel h0, h0, h1, ne
237; CHECK-FP16-NEXT: ret
238
239define half @test_select_cc_f16_f32(half %a, half %b, float %c, float %d) #0 {
240  %cc = fcmp une float %c, %d
241  %r = select i1 %cc, half %a, half %b
242  ret half %r
243}
244
245; CHECK-CVT-LABEL: test_fcmp_une:
246; CHECK-CVT-NEXT: fcvt s1, h1
247; CHECK-CVT-NEXT: fcvt s0, h0
248; CHECK-CVT-NEXT: fcmp s0, s1
249; CHECK-CVT-NEXT: cset  w0, ne
250; CHECK-CVT-NEXT: ret
251
252; CHECK-FP16-LABEL: test_fcmp_une:
253; CHECK-FP16-NEXT: fcmp	h0, h1
254; CHECK-FP16-NEXT: cset w0, ne
255; CHECK-FP16-NEXT: ret
256
257define i1 @test_fcmp_une(half %a, half %b) #0 {
258  %r = fcmp une half %a, %b
259  ret i1 %r
260}
261
262; CHECK-CVT-LABEL: test_fcmp_ueq:
263; CHECK-CVT-NEXT: fcvt s1, h1
264; CHECK-CVT-NEXT: fcvt s0, h0
265; CHECK-CVT-NEXT: fcmp s0, s1
266; CHECK-CVT-NEXT: cset [[TRUE:w[0-9]+]], eq
267; CHECK-CVT-NEXT: csinc w0, [[TRUE]], wzr, vc
268; CHECK-CVT-NEXT: ret
269
270; CHECK-FP16-LABEL: test_fcmp_ueq:
271; CHECK-FP16-NEXT: fcmp	h0, h1
272; CHECK-FP16-NEXT: cset [[TRUE:w[0-9]+]], eq
273; CHECK-FP16-NEXT: csinc w0, [[TRUE]], wzr, vc
274; CHECK-FP16-NEXT: ret
275
276define i1 @test_fcmp_ueq(half %a, half %b) #0 {
277  %r = fcmp ueq half %a, %b
278  ret i1 %r
279}
280
281; CHECK-CVT-LABEL: test_fcmp_ugt:
282; CHECK-CVT-NEXT: fcvt s1, h1
283; CHECK-CVT-NEXT: fcvt s0, h0
284; CHECK-CVT-NEXT: fcmp s0, s1
285; CHECK-CVT-NEXT: cset  w0, hi
286; CHECK-CVT-NEXT: ret
287
288; CHECK-FP16-LABEL: test_fcmp_ugt:
289; CHECK-FP16-NEXT: fcmp h0, h1
290; CHECK-FP16-NEXT: cset  w0, hi
291; CHECK-FP16-NEXT: ret
292
293define i1 @test_fcmp_ugt(half %a, half %b) #0 {
294  %r = fcmp ugt half %a, %b
295  ret i1 %r
296}
297
298; CHECK-CVT-LABEL: test_fcmp_uge:
299; CHECK-CVT-NEXT: fcvt s1, h1
300; CHECK-CVT-NEXT: fcvt s0, h0
301; CHECK-CVT-NEXT: fcmp s0, s1
302; CHECK-CVT-NEXT: cset  w0, pl
303; CHECK-CVT-NEXT: ret
304
305; CHECK-FP16-LABEL: test_fcmp_uge:
306; CHECK-FP16-NEXT: fcmp h0, h1
307; CHECK-FP16-NEXT: cset  w0, pl
308; CHECK-FP16-NEXT: ret
309
310define i1 @test_fcmp_uge(half %a, half %b) #0 {
311  %r = fcmp uge half %a, %b
312  ret i1 %r
313}
314
315; CHECK-CVT-LABEL: test_fcmp_ult:
316; CHECK-CVT-NEXT: fcvt s1, h1
317; CHECK-CVT-NEXT: fcvt s0, h0
318; CHECK-CVT-NEXT: fcmp s0, s1
319; CHECK-CVT-NEXT: cset  w0, lt
320; CHECK-CVT-NEXT: ret
321
322; CHECK-FP16-LABEL: test_fcmp_ult:
323; CHECK-FP16-NEXT: fcmp h0, h1
324; CHECK-FP16-NEXT: cset  w0, lt
325; CHECK-FP16-NEXT: ret
326
327define i1 @test_fcmp_ult(half %a, half %b) #0 {
328  %r = fcmp ult half %a, %b
329  ret i1 %r
330}
331
332; CHECK-CVT-LABEL: test_fcmp_ule:
333; CHECK-CVT-NEXT: fcvt s1, h1
334; CHECK-CVT-NEXT: fcvt s0, h0
335; CHECK-CVT-NEXT: fcmp s0, s1
336; CHECK-CVT-NEXT: cset  w0, le
337; CHECK-CVT-NEXT: ret
338
339; CHECK-FP16-LABEL: test_fcmp_ule:
340; CHECK-FP16-NEXT: fcmp h0, h1
341; CHECK-FP16-NEXT: cset  w0, le
342; CHECK-FP16-NEXT: ret
343
344define i1 @test_fcmp_ule(half %a, half %b) #0 {
345  %r = fcmp ule half %a, %b
346  ret i1 %r
347}
348
349; CHECK-CVT-LABEL: test_fcmp_uno:
350; CHECK-CVT-NEXT: fcvt s1, h1
351; CHECK-CVT-NEXT: fcvt s0, h0
352; CHECK-CVT-NEXT: fcmp s0, s1
353; CHECK-CVT-NEXT: cset  w0, vs
354; CHECK-CVT-NEXT: ret
355
356; CHECK-FP16-LABEL: test_fcmp_uno:
357; CHECK-FP16-NEXT: fcmp h0, h1
358; CHECK-FP16-NEXT: cset  w0, vs
359; CHECK-FP16-NEXT: ret
360
361define i1 @test_fcmp_uno(half %a, half %b) #0 {
362  %r = fcmp uno half %a, %b
363  ret i1 %r
364}
365
366; CHECK-CVT-LABEL: test_fcmp_one:
367; CHECK-CVT-NEXT: fcvt s1, h1
368; CHECK-CVT-NEXT: fcvt s0, h0
369; CHECK-CVT-NEXT: fcmp s0, s1
370; CHECK-CVT-NEXT: cset [[TRUE:w[0-9]+]], mi
371; CHECK-CVT-NEXT: csinc w0, [[TRUE]], wzr, le
372; CHECK-CVT-NEXT: ret
373
374; CHECK-FP16-LABEL: test_fcmp_one:
375; CHECK-FP16-NEXT: fcmp h0, h1
376; CHECK-FP16-NEXT: cset [[TRUE:w[0-9]+]], mi
377; CHECK-FP16-NEXT: csinc w0, [[TRUE]], wzr, le
378; CHECK-FP16-NEXT: ret
379
380define i1 @test_fcmp_one(half %a, half %b) #0 {
381  %r = fcmp one half %a, %b
382  ret i1 %r
383}
384
385; CHECK-CVT-LABEL: test_fcmp_oeq:
386; CHECK-CVT-NEXT: fcvt s1, h1
387; CHECK-CVT-NEXT: fcvt s0, h0
388; CHECK-CVT-NEXT: fcmp s0, s1
389; CHECK-CVT-NEXT: cset  w0, eq
390; CHECK-CVT-NEXT: ret
391
392; CHECK-FP16-LABEL: test_fcmp_oeq:
393; CHECK-FP16-NEXT: fcmp h0, h1
394; CHECK-FP16-NEXT: cset  w0, eq
395; CHECK-FP16-NEXT: ret
396
397define i1 @test_fcmp_oeq(half %a, half %b) #0 {
398  %r = fcmp oeq half %a, %b
399  ret i1 %r
400}
401
402; CHECK-CVT-LABEL: test_fcmp_ogt:
403; CHECK-CVT-NEXT: fcvt s1, h1
404; CHECK-CVT-NEXT: fcvt s0, h0
405; CHECK-CVT-NEXT: fcmp s0, s1
406; CHECK-CVT-NEXT: cset  w0, gt
407; CHECK-CVT-NEXT: ret
408
409; CHECK-FP16-LABEL: test_fcmp_ogt:
410; CHECK-FP16-NEXT: fcmp h0, h1
411; CHECK-FP16-NEXT: cset  w0, gt
412; CHECK-FP16-NEXT: ret
413
414define i1 @test_fcmp_ogt(half %a, half %b) #0 {
415  %r = fcmp ogt half %a, %b
416  ret i1 %r
417}
418
419; CHECK-CVT-LABEL: test_fcmp_oge:
420; CHECK-CVT-NEXT: fcvt s1, h1
421; CHECK-CVT-NEXT: fcvt s0, h0
422; CHECK-CVT-NEXT: fcmp s0, s1
423; CHECK-CVT-NEXT: cset  w0, ge
424; CHECK-CVT-NEXT: ret
425
426; CHECK-FP16-LABEL: test_fcmp_oge:
427; CHECK-FP16-NEXT: fcmp h0, h1
428; CHECK-FP16-NEXT: cset  w0, ge
429; CHECK-FP16-NEXT: ret
430
431define i1 @test_fcmp_oge(half %a, half %b) #0 {
432  %r = fcmp oge half %a, %b
433  ret i1 %r
434}
435
436; CHECK-CVT-LABEL: test_fcmp_olt:
437; CHECK-CVT-NEXT: fcvt s1, h1
438; CHECK-CVT-NEXT: fcvt s0, h0
439; CHECK-CVT-NEXT: fcmp s0, s1
440; CHECK-CVT-NEXT: cset  w0, mi
441; CHECK-CVT-NEXT: ret
442
443; CHECK-FP16-LABEL: test_fcmp_olt:
444; CHECK-FP16-NEXT: fcmp h0, h1
445; CHECK-FP16-NEXT: cset  w0, mi
446; CHECK-FP16-NEXT: ret
447
448define i1 @test_fcmp_olt(half %a, half %b) #0 {
449  %r = fcmp olt half %a, %b
450  ret i1 %r
451}
452
453; CHECK-CVT-LABEL: test_fcmp_ole:
454; CHECK-CVT-NEXT: fcvt s1, h1
455; CHECK-CVT-NEXT: fcvt s0, h0
456; CHECK-CVT-NEXT: fcmp s0, s1
457; CHECK-CVT-NEXT: cset  w0, ls
458; CHECK-CVT-NEXT: ret
459
460; CHECK-FP16-LABEL: test_fcmp_ole:
461; CHECK-FP16-NEXT: fcmp h0, h1
462; CHECK-FP16-NEXT: cset  w0, ls
463; CHECK-FP16-NEXT: ret
464
465define i1 @test_fcmp_ole(half %a, half %b) #0 {
466  %r = fcmp ole half %a, %b
467  ret i1 %r
468}
469
470; CHECK-CVT-LABEL: test_fcmp_ord:
471; CHECK-CVT-NEXT: fcvt s1, h1
472; CHECK-CVT-NEXT: fcvt s0, h0
473; CHECK-CVT-NEXT: fcmp s0, s1
474; CHECK-CVT-NEXT: cset  w0, vc
475; CHECK-CVT-NEXT: ret
476
477; CHECK-FP16-LABEL: test_fcmp_ord:
478; CHECK-FP16-NEXT: fcmp h0, h1
479; CHECK-FP16-NEXT: cset  w0, vc
480; CHECK-FP16-NEXT: ret
481
482define i1 @test_fcmp_ord(half %a, half %b) #0 {
483  %r = fcmp ord half %a, %b
484  ret i1 %r
485}
486
487; CHECK-COMMON-LABEL: test_fccmp:
488; CHECK-CVT:      fcvt  s0, h0
489; CHECK-CVT-NEXT: fmov  s1, #8.00000000
490; CHECK-CVT-NEXT: fcmp  s0, s1
491; CHECK-CVT-NEXT: fmov  s1, #5.00000000
492; CHECK-CVT-NEXT: cset  w8, gt
493; CHECK-CVT-NEXT: fcmp  s0, s1
494; CHECK-CVT-NEXT: cset  w9, mi
495; CHECK-CVT-NEXT: tst   w8, w9
496; CHECK-CVT-NEXT: fcsel s0, s0, s1, ne
497; CHECK-CVT-NEXT: fcvt  h0, s0
498; CHECK-CVT-NEXT: str   h0, [x0]
499; CHECK-CVT-NEXT: ret
500; CHECK-FP16:      fmov  h1, #5.00000000
501; CHECK-FP16-NEXT: fcmp  h0, h1
502; CHECK-FP16-NEXT: fmov  h2, #8.00000000
503; CHECK-FP16-NEXT: fccmp h0, h2, #4, mi
504; CHECK-FP16-NEXT: fcsel h0, h0, h1, gt
505; CHECK-FP16-NEXT: str   h0, [x0]
506; CHECK-FP16-NEXT: ret
507
508define void @test_fccmp(half %in, half* %out) {
509  %cmp1 = fcmp ogt half %in, 0xH4800
510  %cmp2 = fcmp olt half %in, 0xH4500
511  %cond = and i1 %cmp1, %cmp2
512  %result = select i1 %cond, half %in, half 0xH4500
513  store half %result, half* %out
514  ret void
515}
516
517; CHECK-CVT-LABEL: test_br_cc:
518; CHECK-CVT-NEXT: fcvt s1, h1
519; CHECK-CVT-NEXT: fcvt s0, h0
520; CHECK-CVT-NEXT: fcmp s0, s1
521; CHECK-CVT-NEXT: csel x8, x0, x1, pl
522; CHECK-CVT-NEXT: str wzr, [x8]
523; CHECK-CVT-NEXT: ret
524
525; CHECK-FP16-LABEL: test_br_cc:
526; CHECK-FP16-NEXT: fcmp h0, h1
527; CHECK-FP16-NEXT: csel x8, x0, x1, pl
528; CHECK-FP16-NEXT: str wzr, [x8]
529; CHECK-FP16-NEXT: ret
530
531define void @test_br_cc(half %a, half %b, i32* %p1, i32* %p2) #0 {
532  %c = fcmp uge half %a, %b
533  br i1 %c, label %then, label %else
534then:
535  store i32 0, i32* %p1
536  ret void
537else:
538  store i32 0, i32* %p2
539  ret void
540}
541
542; CHECK-COMMON-LABEL: test_phi:
543; CHECK-COMMON: mov  x[[PTR:[0-9]+]], x0
544; CHECK-COMMON: ldr  h[[AB:[0-9]+]], [x0]
545; CHECK-COMMON: [[LOOP:LBB[0-9_]+]]:
546; CHECK-COMMON: fmov  s[[R:[0-9]+]], s[[AB]]
547; CHECK-COMMON: ldr  h[[AB]], [x[[PTR]]]
548; CHECK-COMMON: mov  x0, x[[PTR]]
549; CHECK-COMMON: bl {{_?}}test_dummy
550; CHECK-COMMON: fmov  s0, s[[R]]
551; CHECK-COMMON: ret
552define half @test_phi(half* %p1) #0 {
553entry:
554  %a = load half, half* %p1
555  br label %loop
556loop:
557  %r = phi half [%a, %entry], [%b, %loop]
558  %b = load half, half* %p1
559  %c = call i1 @test_dummy(half* %p1)
560  br i1 %c, label %loop, label %return
561return:
562  ret half %r
563}
564
565declare i1 @test_dummy(half* %p1) #0
566
567; CHECK-CVT-LABEL: test_fptosi_i32:
568; CHECK-CVT-NEXT: fcvt s0, h0
569; CHECK-CVT-NEXT: fcvtzs w0, s0
570; CHECK-CVT-NEXT: ret
571
572; CHECK-FP16-LABEL: test_fptosi_i32:
573; CHECK-FP16-NEXT: fcvtzs w0, h0
574; CHECK-FP16-NEXT: ret
575
576define i32 @test_fptosi_i32(half %a) #0 {
577  %r = fptosi half %a to i32
578  ret i32 %r
579}
580
581; CHECK-CVT-LABEL: test_fptosi_i64:
582; CHECK-CVT-NEXT: fcvt s0, h0
583; CHECK-CVT-NEXT: fcvtzs x0, s0
584; CHECK-CVT-NEXT: ret
585
586; CHECK-FP16-LABEL: test_fptosi_i64:
587; CHECK-FP16-NEXT: fcvtzs x0, h0
588; CHECK-FP16-NEXT: ret
589
590define i64 @test_fptosi_i64(half %a) #0 {
591  %r = fptosi half %a to i64
592  ret i64 %r
593}
594
595; CHECK-CVT-LABEL: test_fptoui_i32:
596; CHECK-CVT-NEXT: fcvt s0, h0
597; CHECK-CVT-NEXT: fcvtzu w0, s0
598; CHECK-CVT-NEXT: ret
599
600; CHECK-FP16-LABEL: test_fptoui_i32:
601; CHECK-FP16-NEXT: fcvtzu w0, h0
602; CHECK-FP16-NEXT: ret
603
604define i32 @test_fptoui_i32(half %a) #0 {
605  %r = fptoui half %a to i32
606  ret i32 %r
607}
608
609; CHECK-CVT-LABEL: test_fptoui_i64:
610; CHECK-CVT-NEXT: fcvt s0, h0
611; CHECK-CVT-NEXT: fcvtzu x0, s0
612; CHECK-CVT-NEXT: ret
613
614; CHECK-FP16-LABEL: test_fptoui_i64:
615; CHECK-FP16-NEXT: fcvtzu x0, h0
616; CHECK-FP16-NEXT: ret
617
618define i64 @test_fptoui_i64(half %a) #0 {
619  %r = fptoui half %a to i64
620  ret i64 %r
621}
622
623; CHECK-CVT-LABEL: test_uitofp_i32:
624; CHECK-CVT-NEXT: ucvtf s0, w0
625; CHECK-CVT-NEXT: fcvt h0, s0
626; CHECK-CVT-NEXT: ret
627
628; CHECK-FP16-LABEL: test_uitofp_i32:
629; CHECK-FP16-NEXT: ucvtf h0, w0
630; CHECK-FP16-NEXT: ret
631
632define half @test_uitofp_i32(i32 %a) #0 {
633  %r = uitofp i32 %a to half
634  ret half %r
635}
636
637; CHECK-CVT-LABEL: test_uitofp_i64:
638; CHECK-CVT-NEXT: ucvtf s0, x0
639; CHECK-CVT-NEXT: fcvt h0, s0
640; CHECK-CVT-NEXT: ret
641
642; CHECK-FP16-LABEL: test_uitofp_i64:
643; CHECK-FP16-NEXT: ucvtf h0, x0
644; CHECK-FP16-NEXT: ret
645
646define half @test_uitofp_i64(i64 %a) #0 {
647  %r = uitofp i64 %a to half
648  ret half %r
649}
650
651; CHECK-CVT-LABEL: test_sitofp_i32:
652; CHECK-CVT-NEXT: scvtf s0, w0
653; CHECK-CVT-NEXT: fcvt h0, s0
654; CHECK-CVT-NEXT: ret
655
656; CHECK-FP16-LABEL: test_sitofp_i32:
657; CHECK-FP16-NEXT: scvtf h0, w0
658; CHECK-FP16-NEXT: ret
659
660define half @test_sitofp_i32(i32 %a) #0 {
661  %r = sitofp i32 %a to half
662  ret half %r
663}
664
665; CHECK-CVT-LABEL: test_sitofp_i64:
666; CHECK-CVT-NEXT: scvtf s0, x0
667; CHECK-CVT-NEXT: fcvt h0, s0
668; CHECK-CVT-NEXT: ret
669
670; CHECK-FP16-LABEL: test_sitofp_i64:
671; CHECK-FP16-NEXT: scvtf h0, x0
672; CHECK-FP16-NEXT: ret
673define half @test_sitofp_i64(i64 %a) #0 {
674  %r = sitofp i64 %a to half
675  ret half %r
676}
677
678; CHECK-CVT-LABEL: test_uitofp_i32_fadd:
679; CHECK-CVT-NEXT: ucvtf s1, w0
680; CHECK-CVT-NEXT: fcvt h1, s1
681; CHECK-CVT-NEXT: fcvt s0, h0
682; CHECK-CVT-NEXT: fcvt s1, h1
683; CHECK-CVT-NEXT: fadd s0, s0, s1
684; CHECK-CVT-NEXT: fcvt h0, s0
685; CHECK-CVT-NEXT: ret
686
687; CHECK-FP16-LABEL: test_uitofp_i32_fadd:
688; CHECK-FP16-NEXT: ucvtf h1, w0
689; CHECK-FP16-NEXT: fadd h0, h0, h1
690; CHECK-FP16-NEXT: ret
691
692define half @test_uitofp_i32_fadd(i32 %a, half %b) #0 {
693  %c = uitofp i32 %a to half
694  %r = fadd half %b, %c
695  ret half %r
696}
697
698; CHECK-CVT-LABEL: test_sitofp_i32_fadd:
699; CHECK-CVT-NEXT: scvtf s1, w0
700; CHECK-CVT-NEXT: fcvt h1, s1
701; CHECK-CVT-NEXT: fcvt s0, h0
702; CHECK-CVT-NEXT: fcvt s1, h1
703; CHECK-CVT-NEXT: fadd s0, s0, s1
704; CHECK-CVT-NEXT: fcvt h0, s0
705; CHECK-CVT-NEXT: ret
706
707; CHECK-FP16-LABEL: test_sitofp_i32_fadd:
708; CHECK-FP16-NEXT: scvtf h1, w0
709; CHECK-FP16-NEXT: fadd h0, h0, h1
710; CHECK-FP16-NEXT: ret
711
712define half @test_sitofp_i32_fadd(i32 %a, half %b) #0 {
713  %c = sitofp i32 %a to half
714  %r = fadd half %b, %c
715  ret half %r
716}
717
718; CHECK-COMMON-LABEL: test_fptrunc_float:
719; CHECK-COMMON-NEXT: fcvt h0, s0
720; CHECK-COMMON-NEXT: ret
721
722define half @test_fptrunc_float(float %a) #0 {
723  %r = fptrunc float %a to half
724  ret half %r
725}
726
727; CHECK-COMMON-LABEL: test_fptrunc_double:
728; CHECK-COMMON-NEXT: fcvt h0, d0
729; CHECK-COMMON-NEXT: ret
730define half @test_fptrunc_double(double %a) #0 {
731  %r = fptrunc double %a to half
732  ret half %r
733}
734
735; CHECK-COMMON-LABEL: test_fpext_float:
736; CHECK-COMMON-NEXT: fcvt s0, h0
737; CHECK-COMMON-NEXT: ret
738define float @test_fpext_float(half %a) #0 {
739  %r = fpext half %a to float
740  ret float %r
741}
742
743; CHECK-COMMON-LABEL: test_fpext_double:
744; CHECK-COMMON-NEXT: fcvt d0, h0
745; CHECK-COMMON-NEXT: ret
746define double @test_fpext_double(half %a) #0 {
747  %r = fpext half %a to double
748  ret double %r
749}
750
751
752; CHECK-COMMON-LABEL: test_bitcast_halftoi16:
753; CHECK-COMMON-NEXT: fmov w0, s0
754; CHECK-COMMON-NEXT: ret
755define i16 @test_bitcast_halftoi16(half %a) #0 {
756  %r = bitcast half %a to i16
757  ret i16 %r
758}
759
760; CHECK-COMMON-LABEL: test_bitcast_i16tohalf:
761; CHECK-COMMON-NEXT: fmov s0, w0
762; CHECK-COMMON-NEXT: ret
763define half @test_bitcast_i16tohalf(i16 %a) #0 {
764  %r = bitcast i16 %a to half
765  ret half %r
766}
767
768
769declare half @llvm.sqrt.f16(half %a) #0
770declare half @llvm.powi.f16.i32(half %a, i32 %b) #0
771declare half @llvm.sin.f16(half %a) #0
772declare half @llvm.cos.f16(half %a) #0
773declare half @llvm.pow.f16(half %a, half %b) #0
774declare half @llvm.exp.f16(half %a) #0
775declare half @llvm.exp2.f16(half %a) #0
776declare half @llvm.log.f16(half %a) #0
777declare half @llvm.log10.f16(half %a) #0
778declare half @llvm.log2.f16(half %a) #0
779declare half @llvm.fma.f16(half %a, half %b, half %c) #0
780declare half @llvm.fabs.f16(half %a) #0
781declare half @llvm.minnum.f16(half %a, half %b) #0
782declare half @llvm.maxnum.f16(half %a, half %b) #0
783declare half @llvm.copysign.f16(half %a, half %b) #0
784declare half @llvm.floor.f16(half %a) #0
785declare half @llvm.ceil.f16(half %a) #0
786declare half @llvm.trunc.f16(half %a) #0
787declare half @llvm.rint.f16(half %a) #0
788declare half @llvm.nearbyint.f16(half %a) #0
789declare half @llvm.round.f16(half %a) #0
790declare half @llvm.roundeven.f16(half %a) #0
791declare half @llvm.fmuladd.f16(half %a, half %b, half %c) #0
792
793; FALLBACK-NOT: remark:{{.*}}test_sqrt
794; FALLBACK-FP16-NOT: remark:{{.*}}test_sqrt
795
796; CHECK-CVT-LABEL: test_sqrt:
797; CHECK-CVT-NEXT: fcvt s0, h0
798; CHECK-CVT-NEXT: fsqrt s0, s0
799; CHECK-CVT-NEXT: fcvt h0, s0
800; CHECK-CVT-NEXT: ret
801
802; CHECK-FP16-LABEL: test_sqrt:
803; CHECK-FP16-NEXT: fsqrt h0, h0
804; CHECK-FP16-NEXT: ret
805
806; GISEL-CVT-LABEL: test_sqrt:
807; GISEL-CVT-NEXT: fcvt s0, h0
808; GISEL-CVT-NEXT: fsqrt s0, s0
809; GISEL-CVT-NEXT: fcvt h0, s0
810; GISEL-CVT-NEXT: ret
811
812; GISEL-FP16-LABEL: test_sqrt:
813; GISEL-FP16-NEXT: fsqrt h0, h0
814; GISEL-FP16-NEXT: ret
815
816define half @test_sqrt(half %a) #0 {
817  %r = call half @llvm.sqrt.f16(half %a)
818  ret half %r
819}
820
821; CHECK-COMMON-LABEL: test_powi:
822; CHECK-COMMON-NEXT: stp x29, x30, [sp, #-16]!
823; CHECK-COMMON-NEXT: mov  x29, sp
824; CHECK-COMMON-NEXT: fcvt s0, h0
825; CHECK-COMMON-NEXT: bl {{_?}}__powisf2
826; CHECK-COMMON-NEXT: fcvt h0, s0
827; CHECK-COMMON-NEXT: ldp x29, x30, [sp], #16
828; CHECK-COMMON-NEXT: ret
829define half @test_powi(half %a, i32 %b) #0 {
830  %r = call half @llvm.powi.f16.i32(half %a, i32 %b)
831  ret half %r
832}
833
834; FALLBACK-NOT: remark:{{.*}}test_sin
835; FALLBACK-FP16-NOT: remark:{{.*}}test_sin
836
837; CHECK-COMMON-LABEL: test_sin:
838; CHECK-COMMON-NEXT: stp x29, x30, [sp, #-16]!
839; CHECK-COMMON-NEXT: mov  x29, sp
840; CHECK-COMMON-NEXT: fcvt s0, h0
841; CHECK-COMMON-NEXT: bl {{_?}}sinf
842; CHECK-COMMON-NEXT: fcvt h0, s0
843; CHECK-COMMON-NEXT: ldp x29, x30, [sp], #16
844; CHECK-COMMON-NEXT: ret
845
846; GISEL-LABEL: test_sin:
847; GISEL-NEXT: stp x29, x30, [sp, #-16]!
848; GISEL-NEXT: mov  x29, sp
849; GISEL-NEXT: fcvt s0, h0
850; GISEL-NEXT: bl {{_?}}sinf
851; GISEL-NEXT: fcvt h0, s0
852; GISEL-NEXT: ldp x29, x30, [sp], #16
853; GISEL-NEXT: ret
854define half @test_sin(half %a) #0 {
855  %r = call half @llvm.sin.f16(half %a)
856  ret half %r
857}
858
859; FALLBACK-NOT: remark:{{.*}}test_cos
860; FALLBACK-FP16-NOT: remark:{{.*}}test_cos
861
862; CHECK-COMMON-LABEL: test_cos:
863; CHECK-COMMON-NEXT: stp x29, x30, [sp, #-16]!
864; CHECK-COMMON-NEXT: mov  x29, sp
865; CHECK-COMMON-NEXT: fcvt s0, h0
866; CHECK-COMMON-NEXT: bl {{_?}}cosf
867; CHECK-COMMON-NEXT: fcvt h0, s0
868; CHECK-COMMON-NEXT: ldp x29, x30, [sp], #16
869; CHECK-COMMON-NEXT: ret
870
871; GISEL-LABEL: test_cos:
872; GISEL-NEXT: stp x29, x30, [sp, #-16]!
873; GISEL-NEXT: mov  x29, sp
874; GISEL-NEXT: fcvt s0, h0
875; GISEL-NEXT: bl {{_?}}cosf
876; GISEL-NEXT: fcvt h0, s0
877; GISEL-NEXT: ldp x29, x30, [sp], #16
878; GISEL-NEXT: ret
879define half @test_cos(half %a) #0 {
880  %r = call half @llvm.cos.f16(half %a)
881  ret half %r
882}
883
884; CHECK-COMMON-LABEL: test_pow:
885; CHECK-COMMON-NEXT: stp x29, x30, [sp, #-16]!
886; CHECK-COMMON-NEXT: mov  x29, sp
887; CHECK-COMMON-NEXT: fcvt s0, h0
888; CHECK-COMMON-NEXT: fcvt s1, h1
889; CHECK-COMMON-NEXT: bl {{_?}}powf
890; CHECK-COMMON-NEXT: fcvt h0, s0
891; CHECK-COMMON-NEXT: ldp x29, x30, [sp], #16
892; CHECK-COMMON-NEXT: ret
893define half @test_pow(half %a, half %b) #0 {
894  %r = call half @llvm.pow.f16(half %a, half %b)
895  ret half %r
896}
897
898; FALLBACK-NOT: remark:{{.*}}test_exp
899; FALLBACK-FP16-NOT: remark:{{.*}}test_exp
900
901; CHECK-COMMON-LABEL: test_exp:
902; CHECK-COMMON-NEXT: stp x29, x30, [sp, #-16]!
903; CHECK-COMMON-NEXT: mov  x29, sp
904; CHECK-COMMON-NEXT: fcvt s0, h0
905; CHECK-COMMON-NEXT: bl {{_?}}expf
906; CHECK-COMMON-NEXT: fcvt h0, s0
907; CHECK-COMMON-NEXT: ldp x29, x30, [sp], #16
908; CHECK-COMMON-NEXT: ret
909
910; GISEL-LABEL: test_exp:
911; GISEL-NEXT: stp x29, x30, [sp, #-16]!
912; GISEL-NEXT: mov  x29, sp
913; GISEL-NEXT: fcvt s0, h0
914; GISEL-NEXT: bl {{_?}}expf
915; GISEL-NEXT: fcvt h0, s0
916; GISEL-NEXT: ldp x29, x30, [sp], #16
917; GISEL-NEXT: ret
918define half @test_exp(half %a) #0 {
919  %r = call half @llvm.exp.f16(half %a)
920  ret half %r
921}
922
923; CHECK-COMMON-LABEL: test_exp2:
924; CHECK-COMMON-NEXT: stp x29, x30, [sp, #-16]!
925; CHECK-COMMON-NEXT: mov  x29, sp
926; CHECK-COMMON-NEXT: fcvt s0, h0
927; CHECK-COMMON-NEXT: bl {{_?}}exp2f
928; CHECK-COMMON-NEXT: fcvt h0, s0
929; CHECK-COMMON-NEXT: ldp x29, x30, [sp], #16
930; CHECK-COMMON-NEXT: ret
931
932; GISEL-LABEL: test_exp2:
933; GISEL-NEXT: stp x29, x30, [sp, #-16]!
934; GISEL-NEXT: mov  x29, sp
935; GISEL-NEXT: fcvt s0, h0
936; GISEL-NEXT: bl {{_?}}exp2f
937; GISEL-NEXT: fcvt h0, s0
938; GISEL-NEXT: ldp x29, x30, [sp], #16
939; GISEL-NEXT: ret
940define half @test_exp2(half %a) #0 {
941  %r = call half @llvm.exp2.f16(half %a)
942  ret half %r
943}
944
945; FALLBACK-NOT: remark:{{.*}}test_log
946; FALLBACK-FP16-NOT: remark:{{.*}}test_log
947
948; CHECK-COMMON-LABEL: test_log:
949; CHECK-COMMON-NEXT: stp x29, x30, [sp, #-16]!
950; CHECK-COMMON-NEXT: mov  x29, sp
951; CHECK-COMMON-NEXT: fcvt s0, h0
952; CHECK-COMMON-NEXT: bl {{_?}}logf
953; CHECK-COMMON-NEXT: fcvt h0, s0
954; CHECK-COMMON-NEXT: ldp x29, x30, [sp], #16
955; CHECK-COMMON-NEXT: ret
956
957; GISEL-LABEL: test_log:
958; GISEL: stp x29, x30, [sp, #-16]!
959; GISEL-NEXT: mov  x29, sp
960; GISEL-NEXT: fcvt s0, h0
961; GISEL-NEXT: bl {{_?}}logf
962; GISEL-NEXT: fcvt h0, s0
963; GISEL-NEXT: ldp x29, x30, [sp], #16
964; GISEL-NEXT: ret
965
966define half @test_log(half %a) #0 {
967  %r = call half @llvm.log.f16(half %a)
968  ret half %r
969}
970
971; FALLBACK-NOT: remark:{{.*}}test_log10
972; FALLBACK-FP16-NOT: remark:{{.*}}test_log10
973
974; CHECK-COMMON-LABEL: test_log10:
975; CHECK-COMMON-NEXT: stp x29, x30, [sp, #-16]!
976; CHECK-COMMON-NEXT: mov  x29, sp
977; CHECK-COMMON-NEXT: fcvt s0, h0
978; CHECK-COMMON-NEXT: bl {{_?}}log10f
979; CHECK-COMMON-NEXT: fcvt h0, s0
980; CHECK-COMMON-NEXT: ldp x29, x30, [sp], #16
981; CHECK-COMMON-NEXT: ret
982
983; GISEL-LABEL: test_log10:
984; GISEL-NEXT: stp x29, x30, [sp, #-16]!
985; GISEL-NEXT: mov  x29, sp
986; GISEL-NEXT: fcvt s0, h0
987; GISEL-NEXT: bl {{_?}}log10f
988; GISEL-NEXT: fcvt h0, s0
989; GISEL-NEXT: ldp x29, x30, [sp], #16
990; GISEL-NEXT: ret
991
992define half @test_log10(half %a) #0 {
993  %r = call half @llvm.log10.f16(half %a)
994  ret half %r
995}
996
997; FALLBACK-NOT: remark:{{.*}}test_log2
998; FALLBACK-FP16-NOT: remark:{{.*}}test_log2
999
1000; CHECK-COMMON-LABEL: test_log2:
1001; CHECK-COMMON-NEXT: stp x29, x30, [sp, #-16]!
1002; CHECK-COMMON-NEXT: mov  x29, sp
1003; CHECK-COMMON-NEXT: fcvt s0, h0
1004; CHECK-COMMON-NEXT: bl {{_?}}log2f
1005; CHECK-COMMON-NEXT: fcvt h0, s0
1006; CHECK-COMMON-NEXT: ldp x29, x30, [sp], #16
1007; CHECK-COMMON-NEXT: ret
1008
1009; GISEL-LABEL: test_log2:
1010; GISEL-NEXT: stp x29, x30, [sp, #-16]!
1011; GISEL-NEXT: mov  x29, sp
1012; GISEL-NEXT: fcvt s0, h0
1013; GISEL-NEXT: bl {{_?}}log2f
1014; GISEL-NEXT: fcvt h0, s0
1015; GISEL-NEXT: ldp x29, x30, [sp], #16
1016; GISEL-NEXT: ret
1017
1018define half @test_log2(half %a) #0 {
1019  %r = call half @llvm.log2.f16(half %a)
1020  ret half %r
1021}
1022
1023; CHECK-CVT-LABEL: test_fma:
1024; CHECK-CVT-NEXT: fcvt s2, h2
1025; CHECK-CVT-NEXT: fcvt s1, h1
1026; CHECK-CVT-NEXT: fcvt s0, h0
1027; CHECK-CVT-NEXT: fmadd s0, s0, s1, s2
1028; CHECK-CVT-NEXT: fcvt h0, s0
1029; CHECK-CVT-NEXT: ret
1030
1031; CHECK-FP16-LABEL: test_fma:
1032; CHECK-FP16-NEXT: fmadd h0, h0, h1, h2
1033; CHECK-FP16-NEXT: ret
1034
1035define half @test_fma(half %a, half %b, half %c) #0 {
1036  %r = call half @llvm.fma.f16(half %a, half %b, half %c)
1037  ret half %r
1038}
1039
1040; CHECK-CVT-LABEL: test_fabs:
1041; CHECK-CVT-NEXT: fcvt s0, h0
1042; CHECK-CVT-NEXT: fabs s0, s0
1043; CHECK-CVT-NEXT: fcvt h0, s0
1044; CHECK-CVT-NEXT: ret
1045
1046; CHECK-FP16-LABEL: test_fabs:
1047; CHECK-FP16-NEXT: fabs h0, h0
1048; CHECK-FP16-NEXT: ret
1049
1050; FALLBACK-NOT: remark:{{.*}}test_fabs
1051; FALLBACK-FP16-NOT: remark:{{.*}}test_fabs
1052
1053; GISEL-CVT-LABEL: test_fabs:
1054; GISEL-CVT-NEXT: fcvt s0, h0
1055; GISEL-CVT-NEXT: fabs s0, s0
1056; GISEL-CVT-NEXT: fcvt h0, s0
1057; GISEL-CVT-NEXT: ret
1058
1059; GISEL-FP16-LABEL: test_fabs:
1060; GISEL-FP16-NEXT: fabs h0, h0
1061; GISEL-FP16-NEXT: ret
1062
1063define half @test_fabs(half %a) #0 {
1064  %r = call half @llvm.fabs.f16(half %a)
1065  ret half %r
1066}
1067
1068; CHECK-CVT-LABEL: test_minnum:
1069; CHECK-CVT-NEXT: fcvt s1, h1
1070; CHECK-CVT-NEXT: fcvt s0, h0
1071; CHECK-CVT-NEXT: fminnm s0, s0, s1
1072; CHECK-CVT-NEXT: fcvt h0, s0
1073; CHECK-CVT-NEXT: ret
1074
1075; CHECK-FP16-LABEL: test_minnum:
1076; CHECK-FP16-NEXT: fminnm h0, h0, h1
1077; CHECK-FP16-NEXT: ret
1078
1079define half @test_minnum(half %a, half %b) #0 {
1080  %r = call half @llvm.minnum.f16(half %a, half %b)
1081  ret half %r
1082}
1083
1084; CHECK-CVT-LABEL: test_maxnum:
1085; CHECK-CVT-NEXT: fcvt s1, h1
1086; CHECK-CVT-NEXT: fcvt s0, h0
1087; CHECK-CVT-NEXT: fmaxnm s0, s0, s1
1088; CHECK-CVT-NEXT: fcvt h0, s0
1089; CHECK-CVT-NEXT: ret
1090
1091; CHECK-FP16-LABEL: test_maxnum:
1092; CHECK-FP16-NEXT: fmaxnm h0, h0, h1
1093; CHECK-FP16-NEXT: ret
1094
1095define half @test_maxnum(half %a, half %b) #0 {
1096  %r = call half @llvm.maxnum.f16(half %a, half %b)
1097  ret half %r
1098}
1099
1100; CHECK-CVT-LABEL: test_copysign:
1101; CHECK-CVT-NEXT: fcvt s1, h1
1102; CHECK-CVT-NEXT: fcvt s0, h0
1103; CHECK-CVT-NEXT: mvni.4s v2, #128, lsl #24
1104; CHECK-CVT-NEXT: bif.16b v0, v1, v2
1105; CHECK-CVT-NEXT: fcvt h0, s0
1106; CHECK-CVT-NEXT: ret
1107
1108; CHECK-FP16-LABEL: test_copysign:
1109; CHECK-FP16-NEXT: mvni.8h v2, #128, lsl #8
1110; CHECK-FP16-NEXT: bif.16b  v0, v1, v2
1111; CHECK-FP16-NEXT: ret
1112
1113define half @test_copysign(half %a, half %b) #0 {
1114  %r = call half @llvm.copysign.f16(half %a, half %b)
1115  ret half %r
1116}
1117
1118; CHECK-CVT-LABEL: test_copysign_f32:
1119; CHECK-CVT-NEXT: fcvt s0, h0
1120; CHECK-CVT-NEXT: mvni.4s v2, #128, lsl #24
1121; CHECK-CVT-NEXT: bif.16b v0, v1, v2
1122; CHECK-CVT-NEXT: fcvt h0, s0
1123; CHECK-CVT-NEXT: ret
1124
1125; CHECK-FP16-LABEL: test_copysign_f32:
1126; CHECK-FP16-NEXT: fcvt h1, s1
1127; CHECK-FP16-NEXT: mvni.8h	v2, #128, lsl #8
1128; CHECK-FP16-NEXT: bif.16b v0, v1, v2
1129; CHECK-FP16-NEXT: ret
1130
1131define half @test_copysign_f32(half %a, float %b) #0 {
1132  %tb = fptrunc float %b to half
1133  %r = call half @llvm.copysign.f16(half %a, half %tb)
1134  ret half %r
1135}
1136
1137; CHECK-CVT-LABEL: test_copysign_f64:
1138; CHECK-CVT-NEXT: fcvt s1, d1
1139; CHECK-CVT-NEXT: fcvt s0, h0
1140; CHECK-CVT-NEXT: mvni.4s v2, #128, lsl #24
1141; CHECK-CVT-NEXT: bif.16b v0, v1, v2
1142; CHECK-CVT-NEXT: fcvt h0, s0
1143; CHECK-CVT-NEXT: ret
1144
1145; CHECK-FP16-LABEL: test_copysign_f64:
1146; CHECK-FP16-NEXT: fcvt h1, d1
1147; CHECK-FP16-NEXT: mvni.8h v2, #128, lsl #8
1148; CHECK-FP16-NEXT: bif.16b v0, v1, v2
1149; CHECK-FP16-NEXT: ret
1150
1151define half @test_copysign_f64(half %a, double %b) #0 {
1152  %tb = fptrunc double %b to half
1153  %r = call half @llvm.copysign.f16(half %a, half %tb)
1154  ret half %r
1155}
1156
1157; Check that the FP promotion will use a truncating FP_ROUND, so we can fold
1158; away the (fpext (fp_round <result>)) here.
1159
1160; CHECK-CVT-LABEL: test_copysign_extended:
1161; CHECK-CVT-NEXT: fcvt s1, h1
1162; CHECK-CVT-NEXT: fcvt s0, h0
1163; CHECK-CVT-NEXT: mvni.4s v2, #128, lsl #24
1164; CHECK-CVT-NEXT: bif.16b v0, v1, v2
1165; CHECK-CVT-NEXT: ret
1166
1167; CHECK-FP16-LABEL: test_copysign_extended:
1168; CHECK-FP16-NEXT: mvni.8h v2, #128, lsl #8
1169; CHECK-FP16-NEXT: bif.16b v0, v1, v2
1170; CHECK-FP16-NEXT: fcvt s0, h0
1171; CHECK-FP16-NEXT: ret
1172
1173define float @test_copysign_extended(half %a, half %b) #0 {
1174  %r = call half @llvm.copysign.f16(half %a, half %b)
1175  %xr = fpext half %r to float
1176  ret float %xr
1177}
1178
1179; CHECK-CVT-LABEL: test_floor:
1180; CHECK-CVT-NEXT: fcvt [[FLOAT32:s[0-9]+]], h0
1181; CHECK-CVT-NEXT: frintm [[INT32:s[0-9]+]], [[FLOAT32]]
1182; CHECK-CVT-NEXT: fcvt h0, [[INT32]]
1183; CHECK-CVT-NEXT: ret
1184
1185; CHECK-FP16-LABEL: test_floor:
1186; CHECK-FP16-NEXT: frintm h0, h0
1187; CHECK-FP16-NEXT: ret
1188
1189; FALLBACK-NOT: remark:{{.*}}test_floor
1190; FALLBACK-FP16-NOT: remark:{{.*}}test_floor
1191
1192; GISEL-CVT-LABEL: test_floor:
1193; GISEL-CVT-NEXT: fcvt [[FLOAT32:s[0-9]+]], h0
1194; GISEL-CVT-NEXT: frintm [[INT32:s[0-9]+]], [[FLOAT32]]
1195; GISEL-CVT-NEXT: fcvt h0, [[INT32]]
1196; GISEL-CVT-NEXT: ret
1197
1198; GISEL-FP16-LABEL: test_floor:
1199; GISEL-FP16-NEXT: frintm h0, h0
1200; GISEL-FP16-NEXT: ret
1201
1202define half @test_floor(half %a) #0 {
1203  %r = call half @llvm.floor.f16(half %a)
1204  ret half %r
1205}
1206
1207; CHECK-CVT-LABEL: test_ceil:
1208; CHECK-CVT-NEXT: fcvt [[FLOAT32:s[0-9]+]], h0
1209; CHECK-CVT-NEXT: frintp [[INT32:s[0-9]+]], [[FLOAT32]]
1210; CHECK-CVT-NEXT: fcvt h0, [[INT32]]
1211; CHECK-CVT-NEXT: ret
1212
1213; CHECK-FP16-LABEL: test_ceil:
1214; CHECK-FP16-NEXT: frintp h0, h0
1215; CHECK-FP16-NEXT: ret
1216
1217; FALLBACK-NOT: remark:{{.*}}test_ceil
1218; FALLBACK-FP16-NOT: remark:{{.*}}test_ceil
1219
1220; GISEL-CVT-LABEL: test_ceil:
1221; GISEL-CVT-NEXT: fcvt [[FLOAT32:s[0-9]+]], h0
1222; GISEL-CVT-NEXT: frintp [[INT32:s[0-9]+]], [[FLOAT32]]
1223; GISEL-CVT-NEXT: fcvt h0, [[INT32]]
1224; GISEL-CVT-NEXT: ret
1225
1226; GISEL-FP16-LABEL: test_ceil:
1227; GISEL-FP16-NEXT: frintp h0, h0
1228; GISEL-FP16-NEXT: ret
1229define half @test_ceil(half %a) #0 {
1230  %r = call half @llvm.ceil.f16(half %a)
1231  ret half %r
1232}
1233
1234; CHECK-CVT-LABEL: test_trunc:
1235; CHECK-CVT-NEXT: fcvt [[FLOAT32:s[0-9]+]], h0
1236; CHECK-CVT-NEXT: frintz [[INT32:s[0-9]+]], [[FLOAT32]]
1237; CHECK-CVT-NEXT: fcvt h0, [[INT32]]
1238; CHECK-CVT-NEXT: ret
1239
1240; CHECK-FP16-LABEL: test_trunc:
1241; CHECK-FP16-NEXT: frintz h0, h0
1242; CHECK-FP16-NEXT: ret
1243
1244define half @test_trunc(half %a) #0 {
1245  %r = call half @llvm.trunc.f16(half %a)
1246  ret half %r
1247}
1248
1249; CHECK-CVT-LABEL: test_rint:
1250; CHECK-CVT-NEXT: fcvt s0, h0
1251; CHECK-CVT-NEXT: frintx s0, s0
1252; CHECK-CVT-NEXT: fcvt h0, s0
1253; CHECK-CVT-NEXT: ret
1254
1255; CHECK-FP16-LABEL: test_rint:
1256; CHECK-FP16-NEXT: frintx h0, h0
1257; CHECK-FP16-NEXT: ret
1258
1259define half @test_rint(half %a) #0 {
1260  %r = call half @llvm.rint.f16(half %a)
1261  ret half %r
1262}
1263
1264; CHECK-CVT-LABEL: test_nearbyint:
1265; CHECK-CVT-NEXT: fcvt s0, h0
1266; CHECK-CVT-NEXT: frinti s0, s0
1267; CHECK-CVT-NEXT: fcvt h0, s0
1268; CHECK-CVT-NEXT: ret
1269
1270; CHECK-FP16-LABEL: test_nearbyint:
1271; CHECK-FP16-NEXT: frinti h0, h0
1272; CHECK-FP16-NEXT: ret
1273
1274define half @test_nearbyint(half %a) #0 {
1275  %r = call half @llvm.nearbyint.f16(half %a)
1276  ret half %r
1277}
1278
1279; CHECK-CVT-LABEL: test_round:
1280; CHECK-CVT-NEXT: fcvt [[FLOAT32:s[0-9]+]], h0
1281; CHECK-CVT-NEXT: frinta [[INT32:s[0-9]+]], [[FLOAT32]]
1282; CHECK-CVT-NEXT: fcvt h0, [[INT32]]
1283; CHECK-CVT-NEXT: ret
1284
1285; GISEL-CVT-LABEL: test_round:
1286; GISEL-CVT-NEXT: fcvt [[FLOAT32:s[0-9]+]], h0
1287; GISEL-CVT-NEXT: frinta [[INT32:s[0-9]+]], [[FLOAT32]]
1288; GISEL-CVT-NEXT: fcvt h0, [[INT32]]
1289; GISEL-CVT-NEXT: ret
1290
1291
1292; CHECK-FP16-LABEL: test_round:
1293; CHECK-FP16-NEXT: frinta h0, h0
1294; CHECK-FP16-NEXT: ret
1295
1296; GISEL-FP16-LABEL: test_round:
1297; GISEL-FP16-NEXT: frinta h0, h0
1298; GISEL-FP16-NEXT: ret
1299
1300define half @test_round(half %a) #0 {
1301  %r = call half @llvm.round.f16(half %a)
1302  ret half %r
1303}
1304
1305; CHECK-CVT-LABEL: test_roundeven:
1306; CHECK-CVT-NEXT: fcvt [[FLOAT32:s[0-9]+]], h0
1307; CHECK-CVT-NEXT: frintn [[INT32:s[0-9]+]], [[FLOAT32]]
1308; CHECK-CVT-NEXT: fcvt h0, [[INT32]]
1309; CHECK-CVT-NEXT: ret
1310
1311; GISEL-CVT-LABEL: test_roundeven:
1312; GISEL-CVT-NEXT: fcvt [[FLOAT32:s[0-9]+]], h0
1313; GISEL-CVT-NEXT: frintn [[INT32:s[0-9]+]], [[FLOAT32]]
1314; GISEL-CVT-NEXT: fcvt h0, [[INT32]]
1315; GISEL-CVT-NEXT: ret
1316
1317
1318; CHECK-FP16-LABEL: test_roundeven:
1319; CHECK-FP16-NEXT: frintn h0, h0
1320; CHECK-FP16-NEXT: ret
1321
1322; GISEL-FP16-LABEL: test_roundeven:
1323; GISEL-FP16-NEXT: frintn h0, h0
1324; GISEL-FP16-NEXT: ret
1325
1326define half @test_roundeven(half %a) #0 {
1327  %r = call half @llvm.roundeven.f16(half %a)
1328  ret half %r
1329}
1330
1331; CHECK-CVT-LABEL: test_fmuladd:
1332; CHECK-CVT-NEXT: fcvt s1, h1
1333; CHECK-CVT-NEXT: fcvt s0, h0
1334; CHECK-CVT-NEXT: fmul s0, s0, s1
1335; CHECK-CVT-NEXT: fcvt h0, s0
1336; CHECK-CVT-NEXT: fcvt s0, h0
1337; CHECK-CVT-NEXT: fcvt s1, h2
1338; CHECK-CVT-NEXT: fadd s0, s0, s1
1339; CHECK-CVT-NEXT: fcvt h0, s0
1340; CHECK-CVT-NEXT: ret
1341
1342; CHECK-FP16-LABEL: test_fmuladd:
1343; CHECK-FP16-NEXT: fmadd h0, h0, h1, h2
1344; CHECK-FP16-NEXT: ret
1345
1346define half @test_fmuladd(half %a, half %b, half %c) #0 {
1347  %r = call half @llvm.fmuladd.f16(half %a, half %b, half %c)
1348  ret half %r
1349}
1350
1351attributes #0 = { nounwind }
1352