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