xref: /llvm-project/llvm/test/CodeGen/AArch64/f16-instructions.ll (revision 61510b51c33464a6bc15e4cf5b1ee07e2e0ec1c9)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
2; RUN: llc < %s -mtriple aarch64-unknown-unknown | FileCheck %s --check-prefixes=CHECK,CHECK-CVT,CHECK-CVT-SD
3; RUN: llc < %s -mtriple aarch64-unknown-unknown -mattr=+fullfp16 | FileCheck %s --check-prefixes=CHECK,CHECK-FP16,CHECK-FP16-SD
4; RUN: llc < %s -mtriple aarch64-unknown-unknown -global-isel | FileCheck %s --check-prefixes=CHECK,CHECK-CVT,CHECK-CVT-GI
5; RUN: llc < %s -mtriple aarch64-unknown-unknown -mattr=+fullfp16 -global-isel | FileCheck %s --check-prefixes=CHECK,CHECK-FP16,CHECK-FP16-GI
6
7define half @test_fadd(half %a, half %b) #0 {
8; CHECK-CVT-SD-LABEL: test_fadd:
9; CHECK-CVT-SD:       // %bb.0:
10; CHECK-CVT-SD-NEXT:    fcvt s1, h1
11; CHECK-CVT-SD-NEXT:    fcvt s0, h0
12; CHECK-CVT-SD-NEXT:    fadd s0, s0, s1
13; CHECK-CVT-SD-NEXT:    fcvt h0, s0
14; CHECK-CVT-SD-NEXT:    ret
15;
16; CHECK-FP16-LABEL: test_fadd:
17; CHECK-FP16:       // %bb.0:
18; CHECK-FP16-NEXT:    fadd h0, h0, h1
19; CHECK-FP16-NEXT:    ret
20;
21; CHECK-CVT-GI-LABEL: test_fadd:
22; CHECK-CVT-GI:       // %bb.0:
23; CHECK-CVT-GI-NEXT:    fcvt s0, h0
24; CHECK-CVT-GI-NEXT:    fcvt s1, h1
25; CHECK-CVT-GI-NEXT:    fadd s0, s0, s1
26; CHECK-CVT-GI-NEXT:    fcvt h0, s0
27; CHECK-CVT-GI-NEXT:    ret
28  %r = fadd half %a, %b
29  ret half %r
30}
31
32define half @test_fsub(half %a, half %b) #0 {
33; CHECK-CVT-SD-LABEL: test_fsub:
34; CHECK-CVT-SD:       // %bb.0:
35; CHECK-CVT-SD-NEXT:    fcvt s1, h1
36; CHECK-CVT-SD-NEXT:    fcvt s0, h0
37; CHECK-CVT-SD-NEXT:    fsub s0, s0, s1
38; CHECK-CVT-SD-NEXT:    fcvt h0, s0
39; CHECK-CVT-SD-NEXT:    ret
40;
41; CHECK-FP16-LABEL: test_fsub:
42; CHECK-FP16:       // %bb.0:
43; CHECK-FP16-NEXT:    fsub h0, h0, h1
44; CHECK-FP16-NEXT:    ret
45;
46; CHECK-CVT-GI-LABEL: test_fsub:
47; CHECK-CVT-GI:       // %bb.0:
48; CHECK-CVT-GI-NEXT:    fcvt s0, h0
49; CHECK-CVT-GI-NEXT:    fcvt s1, h1
50; CHECK-CVT-GI-NEXT:    fsub s0, s0, s1
51; CHECK-CVT-GI-NEXT:    fcvt h0, s0
52; CHECK-CVT-GI-NEXT:    ret
53  %r = fsub half %a, %b
54  ret half %r
55}
56
57define half @test_fmul(half %a, half %b) #0 {
58; CHECK-CVT-SD-LABEL: test_fmul:
59; CHECK-CVT-SD:       // %bb.0:
60; CHECK-CVT-SD-NEXT:    fcvt s1, h1
61; CHECK-CVT-SD-NEXT:    fcvt s0, h0
62; CHECK-CVT-SD-NEXT:    fmul s0, s0, s1
63; CHECK-CVT-SD-NEXT:    fcvt h0, s0
64; CHECK-CVT-SD-NEXT:    ret
65;
66; CHECK-FP16-LABEL: test_fmul:
67; CHECK-FP16:       // %bb.0:
68; CHECK-FP16-NEXT:    fmul h0, h0, h1
69; CHECK-FP16-NEXT:    ret
70;
71; CHECK-CVT-GI-LABEL: test_fmul:
72; CHECK-CVT-GI:       // %bb.0:
73; CHECK-CVT-GI-NEXT:    fcvt s0, h0
74; CHECK-CVT-GI-NEXT:    fcvt s1, h1
75; CHECK-CVT-GI-NEXT:    fmul s0, s0, s1
76; CHECK-CVT-GI-NEXT:    fcvt h0, s0
77; CHECK-CVT-GI-NEXT:    ret
78  %r = fmul half %a, %b
79  ret half %r
80}
81
82define half @test_fmadd(half %a, half %b, half %c) #0 {
83; CHECK-CVT-SD-LABEL: test_fmadd:
84; CHECK-CVT-SD:       // %bb.0:
85; CHECK-CVT-SD-NEXT:    fcvt s1, h1
86; CHECK-CVT-SD-NEXT:    fcvt s0, h0
87; CHECK-CVT-SD-NEXT:    fmul s0, s0, s1
88; CHECK-CVT-SD-NEXT:    fcvt s1, h2
89; CHECK-CVT-SD-NEXT:    fcvt h0, s0
90; CHECK-CVT-SD-NEXT:    fcvt s0, h0
91; CHECK-CVT-SD-NEXT:    fadd s0, s0, s1
92; CHECK-CVT-SD-NEXT:    fcvt h0, s0
93; CHECK-CVT-SD-NEXT:    ret
94;
95; CHECK-FP16-LABEL: test_fmadd:
96; CHECK-FP16:       // %bb.0:
97; CHECK-FP16-NEXT:    fmadd h0, h0, h1, h2
98; CHECK-FP16-NEXT:    ret
99;
100; CHECK-CVT-GI-LABEL: test_fmadd:
101; CHECK-CVT-GI:       // %bb.0:
102; CHECK-CVT-GI-NEXT:    fcvt s0, h0
103; CHECK-CVT-GI-NEXT:    fcvt s1, h1
104; CHECK-CVT-GI-NEXT:    fmul s0, s0, s1
105; CHECK-CVT-GI-NEXT:    fcvt s1, h2
106; CHECK-CVT-GI-NEXT:    fcvt h0, s0
107; CHECK-CVT-GI-NEXT:    fcvt s0, h0
108; CHECK-CVT-GI-NEXT:    fadd s0, s0, s1
109; CHECK-CVT-GI-NEXT:    fcvt h0, s0
110; CHECK-CVT-GI-NEXT:    ret
111  %mul = fmul fast half %a, %b
112  %r = fadd fast half %mul, %c
113  ret half %r
114}
115
116define half @test_fdiv(half %a, half %b) #0 {
117; CHECK-CVT-SD-LABEL: test_fdiv:
118; CHECK-CVT-SD:       // %bb.0:
119; CHECK-CVT-SD-NEXT:    fcvt s1, h1
120; CHECK-CVT-SD-NEXT:    fcvt s0, h0
121; CHECK-CVT-SD-NEXT:    fdiv s0, s0, s1
122; CHECK-CVT-SD-NEXT:    fcvt h0, s0
123; CHECK-CVT-SD-NEXT:    ret
124;
125; CHECK-FP16-LABEL: test_fdiv:
126; CHECK-FP16:       // %bb.0:
127; CHECK-FP16-NEXT:    fdiv h0, h0, h1
128; CHECK-FP16-NEXT:    ret
129;
130; CHECK-CVT-GI-LABEL: test_fdiv:
131; CHECK-CVT-GI:       // %bb.0:
132; CHECK-CVT-GI-NEXT:    fcvt s0, h0
133; CHECK-CVT-GI-NEXT:    fcvt s1, h1
134; CHECK-CVT-GI-NEXT:    fdiv s0, s0, s1
135; CHECK-CVT-GI-NEXT:    fcvt h0, s0
136; CHECK-CVT-GI-NEXT:    ret
137  %r = fdiv half %a, %b
138  ret half %r
139}
140
141define half @test_frem(half %a, half %b) #0 {
142; CHECK-LABEL: test_frem:
143; CHECK:       // %bb.0:
144; CHECK-NEXT:    str x30, [sp, #-16]! // 8-byte Folded Spill
145; CHECK-NEXT:    fcvt s0, h0
146; CHECK-NEXT:    fcvt s1, h1
147; CHECK-NEXT:    bl fmodf
148; CHECK-NEXT:    fcvt h0, s0
149; CHECK-NEXT:    ldr x30, [sp], #16 // 8-byte Folded Reload
150; CHECK-NEXT:    ret
151  %r = frem half %a, %b
152  ret half %r
153}
154
155define void @test_store(half %a, ptr %b) #0 {
156; CHECK-LABEL: test_store:
157; CHECK:       // %bb.0:
158; CHECK-NEXT:    str h0, [x0]
159; CHECK-NEXT:    ret
160  store half %a, ptr %b
161  ret void
162}
163
164define half @test_load(ptr %a) #0 {
165; CHECK-LABEL: test_load:
166; CHECK:       // %bb.0:
167; CHECK-NEXT:    ldr h0, [x0]
168; CHECK-NEXT:    ret
169  %r = load half, ptr %a
170  ret half %r
171}
172
173declare half @test_callee(half %a, half %b) #0
174
175define half @test_call(half %a, half %b) #0 {
176; CHECK-LABEL: test_call:
177; CHECK:       // %bb.0:
178; CHECK-NEXT:    str x30, [sp, #-16]! // 8-byte Folded Spill
179; CHECK-NEXT:    bl test_callee
180; CHECK-NEXT:    ldr x30, [sp], #16 // 8-byte Folded Reload
181; CHECK-NEXT:    ret
182  %r = call half @test_callee(half %a, half %b)
183  ret half %r
184}
185
186define half @test_call_flipped(half %a, half %b) #0 {
187; CHECK-LABEL: test_call_flipped:
188; CHECK:       // %bb.0:
189; CHECK-NEXT:    str x30, [sp, #-16]! // 8-byte Folded Spill
190; CHECK-NEXT:    fmov s2, s0
191; CHECK-NEXT:    fmov s0, s1
192; CHECK-NEXT:    fmov s1, s2
193; CHECK-NEXT:    bl test_callee
194; CHECK-NEXT:    ldr x30, [sp], #16 // 8-byte Folded Reload
195; CHECK-NEXT:    ret
196  %r = call half @test_callee(half %b, half %a)
197  ret half %r
198}
199
200define half @test_tailcall_flipped(half %a, half %b) #0 {
201; CHECK-LABEL: test_tailcall_flipped:
202; CHECK:       // %bb.0:
203; CHECK-NEXT:    fmov s2, s0
204; CHECK-NEXT:    fmov s0, s1
205; CHECK-NEXT:    fmov s1, s2
206; CHECK-NEXT:    b test_callee
207  %r = tail call half @test_callee(half %b, half %a)
208  ret half %r
209}
210
211define half @test_select(half %a, half %b, i1 zeroext %c) #0 {
212; CHECK-CVT-SD-LABEL: test_select:
213; CHECK-CVT-SD:       // %bb.0:
214; CHECK-CVT-SD-NEXT:    // kill: def $h0 killed $h0 def $s0
215; CHECK-CVT-SD-NEXT:    cmp w0, #0
216; CHECK-CVT-SD-NEXT:    // kill: def $h1 killed $h1 def $s1
217; CHECK-CVT-SD-NEXT:    fcsel s0, s0, s1, ne
218; CHECK-CVT-SD-NEXT:    // kill: def $h0 killed $h0 killed $s0
219; CHECK-CVT-SD-NEXT:    ret
220;
221; CHECK-FP16-SD-LABEL: test_select:
222; CHECK-FP16-SD:       // %bb.0:
223; CHECK-FP16-SD-NEXT:    cmp w0, #0
224; CHECK-FP16-SD-NEXT:    fcsel h0, h0, h1, ne
225; CHECK-FP16-SD-NEXT:    ret
226;
227; CHECK-CVT-GI-LABEL: test_select:
228; CHECK-CVT-GI:       // %bb.0:
229; CHECK-CVT-GI-NEXT:    // kill: def $h0 killed $h0 def $s0
230; CHECK-CVT-GI-NEXT:    // kill: def $h1 killed $h1 def $s1
231; CHECK-CVT-GI-NEXT:    fmov w8, s0
232; CHECK-CVT-GI-NEXT:    fmov w9, s1
233; CHECK-CVT-GI-NEXT:    tst w0, #0x1
234; CHECK-CVT-GI-NEXT:    csel w8, w8, w9, ne
235; CHECK-CVT-GI-NEXT:    fmov s0, w8
236; CHECK-CVT-GI-NEXT:    // kill: def $h0 killed $h0 killed $s0
237; CHECK-CVT-GI-NEXT:    ret
238;
239; CHECK-FP16-GI-LABEL: test_select:
240; CHECK-FP16-GI:       // %bb.0:
241; CHECK-FP16-GI-NEXT:    // kill: def $h0 killed $h0 def $s0
242; CHECK-FP16-GI-NEXT:    // kill: def $h1 killed $h1 def $s1
243; CHECK-FP16-GI-NEXT:    fmov w8, s0
244; CHECK-FP16-GI-NEXT:    fmov w9, s1
245; CHECK-FP16-GI-NEXT:    tst w0, #0x1
246; CHECK-FP16-GI-NEXT:    csel w8, w8, w9, ne
247; CHECK-FP16-GI-NEXT:    fmov s0, w8
248; CHECK-FP16-GI-NEXT:    // kill: def $h0 killed $h0 killed $s0
249; CHECK-FP16-GI-NEXT:    ret
250  %r = select i1 %c, half %a, half %b
251  ret half %r
252}
253
254define half @test_select_cc(half %a, half %b, half %c, half %d) #0 {
255; CHECK-CVT-SD-LABEL: test_select_cc:
256; CHECK-CVT-SD:       // %bb.0:
257; CHECK-CVT-SD-NEXT:    fcvt s3, h3
258; CHECK-CVT-SD-NEXT:    fcvt s2, h2
259; CHECK-CVT-SD-NEXT:    // kill: def $h0 killed $h0 def $s0
260; CHECK-CVT-SD-NEXT:    // kill: def $h1 killed $h1 def $s1
261; CHECK-CVT-SD-NEXT:    fcmp s2, s3
262; CHECK-CVT-SD-NEXT:    fcsel s0, s0, s1, ne
263; CHECK-CVT-SD-NEXT:    // kill: def $h0 killed $h0 killed $s0
264; CHECK-CVT-SD-NEXT:    ret
265;
266; CHECK-FP16-SD-LABEL: test_select_cc:
267; CHECK-FP16-SD:       // %bb.0:
268; CHECK-FP16-SD-NEXT:    fcmp h2, h3
269; CHECK-FP16-SD-NEXT:    fcsel h0, h0, h1, ne
270; CHECK-FP16-SD-NEXT:    ret
271;
272; CHECK-CVT-GI-LABEL: test_select_cc:
273; CHECK-CVT-GI:       // %bb.0:
274; CHECK-CVT-GI-NEXT:    fcvt s2, h2
275; CHECK-CVT-GI-NEXT:    fcvt s3, h3
276; CHECK-CVT-GI-NEXT:    // kill: def $h0 killed $h0 def $s0
277; CHECK-CVT-GI-NEXT:    // kill: def $h1 killed $h1 def $s1
278; CHECK-CVT-GI-NEXT:    fmov w8, s0
279; CHECK-CVT-GI-NEXT:    fmov w9, s1
280; CHECK-CVT-GI-NEXT:    fcmp s2, s3
281; CHECK-CVT-GI-NEXT:    csel w8, w8, w9, ne
282; CHECK-CVT-GI-NEXT:    fmov s0, w8
283; CHECK-CVT-GI-NEXT:    // kill: def $h0 killed $h0 killed $s0
284; CHECK-CVT-GI-NEXT:    ret
285;
286; CHECK-FP16-GI-LABEL: test_select_cc:
287; CHECK-FP16-GI:       // %bb.0:
288; CHECK-FP16-GI-NEXT:    // kill: def $h0 killed $h0 def $s0
289; CHECK-FP16-GI-NEXT:    // kill: def $h1 killed $h1 def $s1
290; CHECK-FP16-GI-NEXT:    fcmp h2, h3
291; CHECK-FP16-GI-NEXT:    fmov w8, s0
292; CHECK-FP16-GI-NEXT:    fmov w9, s1
293; CHECK-FP16-GI-NEXT:    csel w8, w8, w9, ne
294; CHECK-FP16-GI-NEXT:    fmov s0, w8
295; CHECK-FP16-GI-NEXT:    // kill: def $h0 killed $h0 killed $s0
296; CHECK-FP16-GI-NEXT:    ret
297  %cc = fcmp une half %c, %d
298  %r = select i1 %cc, half %a, half %b
299  ret half %r
300}
301
302define float @test_select_cc_f32_f16(float %a, float %b, half %c, half %d) #0 {
303; CHECK-CVT-SD-LABEL: test_select_cc_f32_f16:
304; CHECK-CVT-SD:       // %bb.0:
305; CHECK-CVT-SD-NEXT:    fcvt s3, h3
306; CHECK-CVT-SD-NEXT:    fcvt s2, h2
307; CHECK-CVT-SD-NEXT:    fcmp s2, s3
308; CHECK-CVT-SD-NEXT:    fcsel s0, s0, s1, ne
309; CHECK-CVT-SD-NEXT:    ret
310;
311; CHECK-FP16-LABEL: test_select_cc_f32_f16:
312; CHECK-FP16:       // %bb.0:
313; CHECK-FP16-NEXT:    fcmp h2, h3
314; CHECK-FP16-NEXT:    fcsel s0, s0, s1, ne
315; CHECK-FP16-NEXT:    ret
316;
317; CHECK-CVT-GI-LABEL: test_select_cc_f32_f16:
318; CHECK-CVT-GI:       // %bb.0:
319; CHECK-CVT-GI-NEXT:    fcvt s2, h2
320; CHECK-CVT-GI-NEXT:    fcvt s3, h3
321; CHECK-CVT-GI-NEXT:    fcmp s2, s3
322; CHECK-CVT-GI-NEXT:    fcsel s0, s0, s1, ne
323; CHECK-CVT-GI-NEXT:    ret
324  %cc = fcmp une half %c, %d
325  %r = select i1 %cc, float %a, float %b
326  ret float %r
327}
328
329define half @test_select_cc_f16_f32(half %a, half %b, float %c, float %d) #0 {
330; CHECK-CVT-SD-LABEL: test_select_cc_f16_f32:
331; CHECK-CVT-SD:       // %bb.0:
332; CHECK-CVT-SD-NEXT:    fcmp s2, s3
333; CHECK-CVT-SD-NEXT:    // kill: def $h0 killed $h0 def $s0
334; CHECK-CVT-SD-NEXT:    // kill: def $h1 killed $h1 def $s1
335; CHECK-CVT-SD-NEXT:    fcsel s0, s0, s1, ne
336; CHECK-CVT-SD-NEXT:    // kill: def $h0 killed $h0 killed $s0
337; CHECK-CVT-SD-NEXT:    ret
338;
339; CHECK-FP16-SD-LABEL: test_select_cc_f16_f32:
340; CHECK-FP16-SD:       // %bb.0:
341; CHECK-FP16-SD-NEXT:    fcmp s2, s3
342; CHECK-FP16-SD-NEXT:    fcsel h0, h0, h1, ne
343; CHECK-FP16-SD-NEXT:    ret
344;
345; CHECK-CVT-GI-LABEL: test_select_cc_f16_f32:
346; CHECK-CVT-GI:       // %bb.0:
347; CHECK-CVT-GI-NEXT:    // kill: def $h0 killed $h0 def $s0
348; CHECK-CVT-GI-NEXT:    // kill: def $h1 killed $h1 def $s1
349; CHECK-CVT-GI-NEXT:    fcmp s2, s3
350; CHECK-CVT-GI-NEXT:    fmov w8, s0
351; CHECK-CVT-GI-NEXT:    fmov w9, s1
352; CHECK-CVT-GI-NEXT:    csel w8, w8, w9, ne
353; CHECK-CVT-GI-NEXT:    fmov s0, w8
354; CHECK-CVT-GI-NEXT:    // kill: def $h0 killed $h0 killed $s0
355; CHECK-CVT-GI-NEXT:    ret
356;
357; CHECK-FP16-GI-LABEL: test_select_cc_f16_f32:
358; CHECK-FP16-GI:       // %bb.0:
359; CHECK-FP16-GI-NEXT:    // kill: def $h0 killed $h0 def $s0
360; CHECK-FP16-GI-NEXT:    // kill: def $h1 killed $h1 def $s1
361; CHECK-FP16-GI-NEXT:    fcmp s2, s3
362; CHECK-FP16-GI-NEXT:    fmov w8, s0
363; CHECK-FP16-GI-NEXT:    fmov w9, s1
364; CHECK-FP16-GI-NEXT:    csel w8, w8, w9, ne
365; CHECK-FP16-GI-NEXT:    fmov s0, w8
366; CHECK-FP16-GI-NEXT:    // kill: def $h0 killed $h0 killed $s0
367; CHECK-FP16-GI-NEXT:    ret
368  %cc = fcmp une float %c, %d
369  %r = select i1 %cc, half %a, half %b
370  ret half %r
371}
372
373define i1 @test_fcmp_une(half %a, half %b) #0 {
374; CHECK-CVT-SD-LABEL: test_fcmp_une:
375; CHECK-CVT-SD:       // %bb.0:
376; CHECK-CVT-SD-NEXT:    fcvt s1, h1
377; CHECK-CVT-SD-NEXT:    fcvt s0, h0
378; CHECK-CVT-SD-NEXT:    fcmp s0, s1
379; CHECK-CVT-SD-NEXT:    cset w0, ne
380; CHECK-CVT-SD-NEXT:    ret
381;
382; CHECK-FP16-LABEL: test_fcmp_une:
383; CHECK-FP16:       // %bb.0:
384; CHECK-FP16-NEXT:    fcmp h0, h1
385; CHECK-FP16-NEXT:    cset w0, ne
386; CHECK-FP16-NEXT:    ret
387;
388; CHECK-CVT-GI-LABEL: test_fcmp_une:
389; CHECK-CVT-GI:       // %bb.0:
390; CHECK-CVT-GI-NEXT:    fcvt s0, h0
391; CHECK-CVT-GI-NEXT:    fcvt s1, h1
392; CHECK-CVT-GI-NEXT:    fcmp s0, s1
393; CHECK-CVT-GI-NEXT:    cset w0, ne
394; CHECK-CVT-GI-NEXT:    ret
395  %r = fcmp une half %a, %b
396  ret i1 %r
397}
398
399define i1 @test_fcmp_ueq(half %a, half %b) #0 {
400; CHECK-CVT-SD-LABEL: test_fcmp_ueq:
401; CHECK-CVT-SD:       // %bb.0:
402; CHECK-CVT-SD-NEXT:    fcvt s1, h1
403; CHECK-CVT-SD-NEXT:    fcvt s0, h0
404; CHECK-CVT-SD-NEXT:    fcmp s0, s1
405; CHECK-CVT-SD-NEXT:    cset w8, eq
406; CHECK-CVT-SD-NEXT:    csinc w0, w8, wzr, vc
407; CHECK-CVT-SD-NEXT:    ret
408;
409; CHECK-FP16-SD-LABEL: test_fcmp_ueq:
410; CHECK-FP16-SD:       // %bb.0:
411; CHECK-FP16-SD-NEXT:    fcmp h0, h1
412; CHECK-FP16-SD-NEXT:    cset w8, eq
413; CHECK-FP16-SD-NEXT:    csinc w0, w8, wzr, vc
414; CHECK-FP16-SD-NEXT:    ret
415;
416; CHECK-CVT-GI-LABEL: test_fcmp_ueq:
417; CHECK-CVT-GI:       // %bb.0:
418; CHECK-CVT-GI-NEXT:    fcvt s0, h0
419; CHECK-CVT-GI-NEXT:    fcvt s1, h1
420; CHECK-CVT-GI-NEXT:    fcmp s0, s1
421; CHECK-CVT-GI-NEXT:    cset w8, eq
422; CHECK-CVT-GI-NEXT:    cset w9, vs
423; CHECK-CVT-GI-NEXT:    orr w0, w8, w9
424; CHECK-CVT-GI-NEXT:    ret
425;
426; CHECK-FP16-GI-LABEL: test_fcmp_ueq:
427; CHECK-FP16-GI:       // %bb.0:
428; CHECK-FP16-GI-NEXT:    fcmp h0, h1
429; CHECK-FP16-GI-NEXT:    cset w8, eq
430; CHECK-FP16-GI-NEXT:    cset w9, vs
431; CHECK-FP16-GI-NEXT:    orr w0, w8, w9
432; CHECK-FP16-GI-NEXT:    ret
433  %r = fcmp ueq half %a, %b
434  ret i1 %r
435}
436
437define i1 @test_fcmp_ugt(half %a, half %b) #0 {
438; CHECK-CVT-SD-LABEL: test_fcmp_ugt:
439; CHECK-CVT-SD:       // %bb.0:
440; CHECK-CVT-SD-NEXT:    fcvt s1, h1
441; CHECK-CVT-SD-NEXT:    fcvt s0, h0
442; CHECK-CVT-SD-NEXT:    fcmp s0, s1
443; CHECK-CVT-SD-NEXT:    cset w0, hi
444; CHECK-CVT-SD-NEXT:    ret
445;
446; CHECK-FP16-LABEL: test_fcmp_ugt:
447; CHECK-FP16:       // %bb.0:
448; CHECK-FP16-NEXT:    fcmp h0, h1
449; CHECK-FP16-NEXT:    cset w0, hi
450; CHECK-FP16-NEXT:    ret
451;
452; CHECK-CVT-GI-LABEL: test_fcmp_ugt:
453; CHECK-CVT-GI:       // %bb.0:
454; CHECK-CVT-GI-NEXT:    fcvt s0, h0
455; CHECK-CVT-GI-NEXT:    fcvt s1, h1
456; CHECK-CVT-GI-NEXT:    fcmp s0, s1
457; CHECK-CVT-GI-NEXT:    cset w0, hi
458; CHECK-CVT-GI-NEXT:    ret
459  %r = fcmp ugt half %a, %b
460  ret i1 %r
461}
462
463define i1 @test_fcmp_uge(half %a, half %b) #0 {
464; CHECK-CVT-SD-LABEL: test_fcmp_uge:
465; CHECK-CVT-SD:       // %bb.0:
466; CHECK-CVT-SD-NEXT:    fcvt s1, h1
467; CHECK-CVT-SD-NEXT:    fcvt s0, h0
468; CHECK-CVT-SD-NEXT:    fcmp s0, s1
469; CHECK-CVT-SD-NEXT:    cset w0, pl
470; CHECK-CVT-SD-NEXT:    ret
471;
472; CHECK-FP16-LABEL: test_fcmp_uge:
473; CHECK-FP16:       // %bb.0:
474; CHECK-FP16-NEXT:    fcmp h0, h1
475; CHECK-FP16-NEXT:    cset w0, pl
476; CHECK-FP16-NEXT:    ret
477;
478; CHECK-CVT-GI-LABEL: test_fcmp_uge:
479; CHECK-CVT-GI:       // %bb.0:
480; CHECK-CVT-GI-NEXT:    fcvt s0, h0
481; CHECK-CVT-GI-NEXT:    fcvt s1, h1
482; CHECK-CVT-GI-NEXT:    fcmp s0, s1
483; CHECK-CVT-GI-NEXT:    cset w0, pl
484; CHECK-CVT-GI-NEXT:    ret
485  %r = fcmp uge half %a, %b
486  ret i1 %r
487}
488
489define i1 @test_fcmp_ult(half %a, half %b) #0 {
490; CHECK-CVT-SD-LABEL: test_fcmp_ult:
491; CHECK-CVT-SD:       // %bb.0:
492; CHECK-CVT-SD-NEXT:    fcvt s1, h1
493; CHECK-CVT-SD-NEXT:    fcvt s0, h0
494; CHECK-CVT-SD-NEXT:    fcmp s0, s1
495; CHECK-CVT-SD-NEXT:    cset w0, lt
496; CHECK-CVT-SD-NEXT:    ret
497;
498; CHECK-FP16-LABEL: test_fcmp_ult:
499; CHECK-FP16:       // %bb.0:
500; CHECK-FP16-NEXT:    fcmp h0, h1
501; CHECK-FP16-NEXT:    cset w0, lt
502; CHECK-FP16-NEXT:    ret
503;
504; CHECK-CVT-GI-LABEL: test_fcmp_ult:
505; CHECK-CVT-GI:       // %bb.0:
506; CHECK-CVT-GI-NEXT:    fcvt s0, h0
507; CHECK-CVT-GI-NEXT:    fcvt s1, h1
508; CHECK-CVT-GI-NEXT:    fcmp s0, s1
509; CHECK-CVT-GI-NEXT:    cset w0, lt
510; CHECK-CVT-GI-NEXT:    ret
511  %r = fcmp ult half %a, %b
512  ret i1 %r
513}
514
515define i1 @test_fcmp_ule(half %a, half %b) #0 {
516; CHECK-CVT-SD-LABEL: test_fcmp_ule:
517; CHECK-CVT-SD:       // %bb.0:
518; CHECK-CVT-SD-NEXT:    fcvt s1, h1
519; CHECK-CVT-SD-NEXT:    fcvt s0, h0
520; CHECK-CVT-SD-NEXT:    fcmp s0, s1
521; CHECK-CVT-SD-NEXT:    cset w0, le
522; CHECK-CVT-SD-NEXT:    ret
523;
524; CHECK-FP16-LABEL: test_fcmp_ule:
525; CHECK-FP16:       // %bb.0:
526; CHECK-FP16-NEXT:    fcmp h0, h1
527; CHECK-FP16-NEXT:    cset w0, le
528; CHECK-FP16-NEXT:    ret
529;
530; CHECK-CVT-GI-LABEL: test_fcmp_ule:
531; CHECK-CVT-GI:       // %bb.0:
532; CHECK-CVT-GI-NEXT:    fcvt s0, h0
533; CHECK-CVT-GI-NEXT:    fcvt s1, h1
534; CHECK-CVT-GI-NEXT:    fcmp s0, s1
535; CHECK-CVT-GI-NEXT:    cset w0, le
536; CHECK-CVT-GI-NEXT:    ret
537  %r = fcmp ule half %a, %b
538  ret i1 %r
539}
540
541define i1 @test_fcmp_uno(half %a, half %b) #0 {
542; CHECK-CVT-SD-LABEL: test_fcmp_uno:
543; CHECK-CVT-SD:       // %bb.0:
544; CHECK-CVT-SD-NEXT:    fcvt s1, h1
545; CHECK-CVT-SD-NEXT:    fcvt s0, h0
546; CHECK-CVT-SD-NEXT:    fcmp s0, s1
547; CHECK-CVT-SD-NEXT:    cset w0, vs
548; CHECK-CVT-SD-NEXT:    ret
549;
550; CHECK-FP16-LABEL: test_fcmp_uno:
551; CHECK-FP16:       // %bb.0:
552; CHECK-FP16-NEXT:    fcmp h0, h1
553; CHECK-FP16-NEXT:    cset w0, vs
554; CHECK-FP16-NEXT:    ret
555;
556; CHECK-CVT-GI-LABEL: test_fcmp_uno:
557; CHECK-CVT-GI:       // %bb.0:
558; CHECK-CVT-GI-NEXT:    fcvt s0, h0
559; CHECK-CVT-GI-NEXT:    fcvt s1, h1
560; CHECK-CVT-GI-NEXT:    fcmp s0, s1
561; CHECK-CVT-GI-NEXT:    cset w0, vs
562; CHECK-CVT-GI-NEXT:    ret
563  %r = fcmp uno half %a, %b
564  ret i1 %r
565}
566
567define i1 @test_fcmp_one(half %a, half %b) #0 {
568; CHECK-CVT-SD-LABEL: test_fcmp_one:
569; CHECK-CVT-SD:       // %bb.0:
570; CHECK-CVT-SD-NEXT:    fcvt s1, h1
571; CHECK-CVT-SD-NEXT:    fcvt s0, h0
572; CHECK-CVT-SD-NEXT:    fcmp s0, s1
573; CHECK-CVT-SD-NEXT:    cset w8, mi
574; CHECK-CVT-SD-NEXT:    csinc w0, w8, wzr, le
575; CHECK-CVT-SD-NEXT:    ret
576;
577; CHECK-FP16-SD-LABEL: test_fcmp_one:
578; CHECK-FP16-SD:       // %bb.0:
579; CHECK-FP16-SD-NEXT:    fcmp h0, h1
580; CHECK-FP16-SD-NEXT:    cset w8, mi
581; CHECK-FP16-SD-NEXT:    csinc w0, w8, wzr, le
582; CHECK-FP16-SD-NEXT:    ret
583;
584; CHECK-CVT-GI-LABEL: test_fcmp_one:
585; CHECK-CVT-GI:       // %bb.0:
586; CHECK-CVT-GI-NEXT:    fcvt s0, h0
587; CHECK-CVT-GI-NEXT:    fcvt s1, h1
588; CHECK-CVT-GI-NEXT:    fcmp s0, s1
589; CHECK-CVT-GI-NEXT:    cset w8, mi
590; CHECK-CVT-GI-NEXT:    cset w9, gt
591; CHECK-CVT-GI-NEXT:    orr w0, w8, w9
592; CHECK-CVT-GI-NEXT:    ret
593;
594; CHECK-FP16-GI-LABEL: test_fcmp_one:
595; CHECK-FP16-GI:       // %bb.0:
596; CHECK-FP16-GI-NEXT:    fcmp h0, h1
597; CHECK-FP16-GI-NEXT:    cset w8, mi
598; CHECK-FP16-GI-NEXT:    cset w9, gt
599; CHECK-FP16-GI-NEXT:    orr w0, w8, w9
600; CHECK-FP16-GI-NEXT:    ret
601  %r = fcmp one half %a, %b
602  ret i1 %r
603}
604
605define i1 @test_fcmp_oeq(half %a, half %b) #0 {
606; CHECK-CVT-SD-LABEL: test_fcmp_oeq:
607; CHECK-CVT-SD:       // %bb.0:
608; CHECK-CVT-SD-NEXT:    fcvt s1, h1
609; CHECK-CVT-SD-NEXT:    fcvt s0, h0
610; CHECK-CVT-SD-NEXT:    fcmp s0, s1
611; CHECK-CVT-SD-NEXT:    cset w0, eq
612; CHECK-CVT-SD-NEXT:    ret
613;
614; CHECK-FP16-LABEL: test_fcmp_oeq:
615; CHECK-FP16:       // %bb.0:
616; CHECK-FP16-NEXT:    fcmp h0, h1
617; CHECK-FP16-NEXT:    cset w0, eq
618; CHECK-FP16-NEXT:    ret
619;
620; CHECK-CVT-GI-LABEL: test_fcmp_oeq:
621; CHECK-CVT-GI:       // %bb.0:
622; CHECK-CVT-GI-NEXT:    fcvt s0, h0
623; CHECK-CVT-GI-NEXT:    fcvt s1, h1
624; CHECK-CVT-GI-NEXT:    fcmp s0, s1
625; CHECK-CVT-GI-NEXT:    cset w0, eq
626; CHECK-CVT-GI-NEXT:    ret
627  %r = fcmp oeq half %a, %b
628  ret i1 %r
629}
630
631define i1 @test_fcmp_ogt(half %a, half %b) #0 {
632; CHECK-CVT-SD-LABEL: test_fcmp_ogt:
633; CHECK-CVT-SD:       // %bb.0:
634; CHECK-CVT-SD-NEXT:    fcvt s1, h1
635; CHECK-CVT-SD-NEXT:    fcvt s0, h0
636; CHECK-CVT-SD-NEXT:    fcmp s0, s1
637; CHECK-CVT-SD-NEXT:    cset w0, gt
638; CHECK-CVT-SD-NEXT:    ret
639;
640; CHECK-FP16-LABEL: test_fcmp_ogt:
641; CHECK-FP16:       // %bb.0:
642; CHECK-FP16-NEXT:    fcmp h0, h1
643; CHECK-FP16-NEXT:    cset w0, gt
644; CHECK-FP16-NEXT:    ret
645;
646; CHECK-CVT-GI-LABEL: test_fcmp_ogt:
647; CHECK-CVT-GI:       // %bb.0:
648; CHECK-CVT-GI-NEXT:    fcvt s0, h0
649; CHECK-CVT-GI-NEXT:    fcvt s1, h1
650; CHECK-CVT-GI-NEXT:    fcmp s0, s1
651; CHECK-CVT-GI-NEXT:    cset w0, gt
652; CHECK-CVT-GI-NEXT:    ret
653  %r = fcmp ogt half %a, %b
654  ret i1 %r
655}
656
657define i1 @test_fcmp_oge(half %a, half %b) #0 {
658; CHECK-CVT-SD-LABEL: test_fcmp_oge:
659; CHECK-CVT-SD:       // %bb.0:
660; CHECK-CVT-SD-NEXT:    fcvt s1, h1
661; CHECK-CVT-SD-NEXT:    fcvt s0, h0
662; CHECK-CVT-SD-NEXT:    fcmp s0, s1
663; CHECK-CVT-SD-NEXT:    cset w0, ge
664; CHECK-CVT-SD-NEXT:    ret
665;
666; CHECK-FP16-LABEL: test_fcmp_oge:
667; CHECK-FP16:       // %bb.0:
668; CHECK-FP16-NEXT:    fcmp h0, h1
669; CHECK-FP16-NEXT:    cset w0, ge
670; CHECK-FP16-NEXT:    ret
671;
672; CHECK-CVT-GI-LABEL: test_fcmp_oge:
673; CHECK-CVT-GI:       // %bb.0:
674; CHECK-CVT-GI-NEXT:    fcvt s0, h0
675; CHECK-CVT-GI-NEXT:    fcvt s1, h1
676; CHECK-CVT-GI-NEXT:    fcmp s0, s1
677; CHECK-CVT-GI-NEXT:    cset w0, ge
678; CHECK-CVT-GI-NEXT:    ret
679  %r = fcmp oge half %a, %b
680  ret i1 %r
681}
682
683define i1 @test_fcmp_olt(half %a, half %b) #0 {
684; CHECK-CVT-SD-LABEL: test_fcmp_olt:
685; CHECK-CVT-SD:       // %bb.0:
686; CHECK-CVT-SD-NEXT:    fcvt s1, h1
687; CHECK-CVT-SD-NEXT:    fcvt s0, h0
688; CHECK-CVT-SD-NEXT:    fcmp s0, s1
689; CHECK-CVT-SD-NEXT:    cset w0, mi
690; CHECK-CVT-SD-NEXT:    ret
691;
692; CHECK-FP16-LABEL: test_fcmp_olt:
693; CHECK-FP16:       // %bb.0:
694; CHECK-FP16-NEXT:    fcmp h0, h1
695; CHECK-FP16-NEXT:    cset w0, mi
696; CHECK-FP16-NEXT:    ret
697;
698; CHECK-CVT-GI-LABEL: test_fcmp_olt:
699; CHECK-CVT-GI:       // %bb.0:
700; CHECK-CVT-GI-NEXT:    fcvt s0, h0
701; CHECK-CVT-GI-NEXT:    fcvt s1, h1
702; CHECK-CVT-GI-NEXT:    fcmp s0, s1
703; CHECK-CVT-GI-NEXT:    cset w0, mi
704; CHECK-CVT-GI-NEXT:    ret
705  %r = fcmp olt half %a, %b
706  ret i1 %r
707}
708
709define i1 @test_fcmp_ole(half %a, half %b) #0 {
710; CHECK-CVT-SD-LABEL: test_fcmp_ole:
711; CHECK-CVT-SD:       // %bb.0:
712; CHECK-CVT-SD-NEXT:    fcvt s1, h1
713; CHECK-CVT-SD-NEXT:    fcvt s0, h0
714; CHECK-CVT-SD-NEXT:    fcmp s0, s1
715; CHECK-CVT-SD-NEXT:    cset w0, ls
716; CHECK-CVT-SD-NEXT:    ret
717;
718; CHECK-FP16-LABEL: test_fcmp_ole:
719; CHECK-FP16:       // %bb.0:
720; CHECK-FP16-NEXT:    fcmp h0, h1
721; CHECK-FP16-NEXT:    cset w0, ls
722; CHECK-FP16-NEXT:    ret
723;
724; CHECK-CVT-GI-LABEL: test_fcmp_ole:
725; CHECK-CVT-GI:       // %bb.0:
726; CHECK-CVT-GI-NEXT:    fcvt s0, h0
727; CHECK-CVT-GI-NEXT:    fcvt s1, h1
728; CHECK-CVT-GI-NEXT:    fcmp s0, s1
729; CHECK-CVT-GI-NEXT:    cset w0, ls
730; CHECK-CVT-GI-NEXT:    ret
731  %r = fcmp ole half %a, %b
732  ret i1 %r
733}
734
735define i1 @test_fcmp_ord(half %a, half %b) #0 {
736; CHECK-CVT-SD-LABEL: test_fcmp_ord:
737; CHECK-CVT-SD:       // %bb.0:
738; CHECK-CVT-SD-NEXT:    fcvt s1, h1
739; CHECK-CVT-SD-NEXT:    fcvt s0, h0
740; CHECK-CVT-SD-NEXT:    fcmp s0, s1
741; CHECK-CVT-SD-NEXT:    cset w0, vc
742; CHECK-CVT-SD-NEXT:    ret
743;
744; CHECK-FP16-LABEL: test_fcmp_ord:
745; CHECK-FP16:       // %bb.0:
746; CHECK-FP16-NEXT:    fcmp h0, h1
747; CHECK-FP16-NEXT:    cset w0, vc
748; CHECK-FP16-NEXT:    ret
749;
750; CHECK-CVT-GI-LABEL: test_fcmp_ord:
751; CHECK-CVT-GI:       // %bb.0:
752; CHECK-CVT-GI-NEXT:    fcvt s0, h0
753; CHECK-CVT-GI-NEXT:    fcvt s1, h1
754; CHECK-CVT-GI-NEXT:    fcmp s0, s1
755; CHECK-CVT-GI-NEXT:    cset w0, vc
756; CHECK-CVT-GI-NEXT:    ret
757  %r = fcmp ord half %a, %b
758  ret i1 %r
759}
760
761define void @test_fccmp(half %in, ptr %out) {
762; CHECK-CVT-SD-LABEL: test_fccmp:
763; CHECK-CVT-SD:       // %bb.0:
764; CHECK-CVT-SD-NEXT:    // kill: def $h0 killed $h0 def $s0
765; CHECK-CVT-SD-NEXT:    fcvt s1, h0
766; CHECK-CVT-SD-NEXT:    fmov s2, #5.00000000
767; CHECK-CVT-SD-NEXT:    adrp x8, .LCPI29_0
768; CHECK-CVT-SD-NEXT:    fcmp s1, s2
769; CHECK-CVT-SD-NEXT:    fmov s2, #8.00000000
770; CHECK-CVT-SD-NEXT:    fccmp s1, s2, #4, mi
771; CHECK-CVT-SD-NEXT:    ldr h1, [x8, :lo12:.LCPI29_0]
772; CHECK-CVT-SD-NEXT:    fcsel s0, s0, s1, gt
773; CHECK-CVT-SD-NEXT:    str h0, [x0]
774; CHECK-CVT-SD-NEXT:    ret
775;
776; CHECK-FP16-SD-LABEL: test_fccmp:
777; CHECK-FP16-SD:       // %bb.0:
778; CHECK-FP16-SD-NEXT:    fmov h1, #5.00000000
779; CHECK-FP16-SD-NEXT:    fmov h2, #8.00000000
780; CHECK-FP16-SD-NEXT:    fcmp h0, h1
781; CHECK-FP16-SD-NEXT:    fccmp h0, h2, #4, mi
782; CHECK-FP16-SD-NEXT:    fcsel h0, h0, h1, gt
783; CHECK-FP16-SD-NEXT:    str h0, [x0]
784; CHECK-FP16-SD-NEXT:    ret
785;
786; CHECK-CVT-GI-LABEL: test_fccmp:
787; CHECK-CVT-GI:       // %bb.0:
788; CHECK-CVT-GI-NEXT:    mov w8, #17664 // =0x4500
789; CHECK-CVT-GI-NEXT:    mov w9, #18432 // =0x4800
790; CHECK-CVT-GI-NEXT:    // kill: def $h0 killed $h0 def $s0
791; CHECK-CVT-GI-NEXT:    fcvt s2, h0
792; CHECK-CVT-GI-NEXT:    fmov s1, w8
793; CHECK-CVT-GI-NEXT:    fmov s3, w9
794; CHECK-CVT-GI-NEXT:    fmov w9, s0
795; CHECK-CVT-GI-NEXT:    fcvt s1, h1
796; CHECK-CVT-GI-NEXT:    fcvt s3, h3
797; CHECK-CVT-GI-NEXT:    fcmp s2, s1
798; CHECK-CVT-GI-NEXT:    fccmp s2, s3, #4, mi
799; CHECK-CVT-GI-NEXT:    csel w8, w9, w8, gt
800; CHECK-CVT-GI-NEXT:    strh w8, [x0]
801; CHECK-CVT-GI-NEXT:    ret
802;
803; CHECK-FP16-GI-LABEL: test_fccmp:
804; CHECK-FP16-GI:       // %bb.0:
805; CHECK-FP16-GI-NEXT:    fmov h1, #5.00000000
806; CHECK-FP16-GI-NEXT:    // kill: def $h0 killed $h0 def $s0
807; CHECK-FP16-GI-NEXT:    fmov h2, #8.00000000
808; CHECK-FP16-GI-NEXT:    fmov w8, s0
809; CHECK-FP16-GI-NEXT:    fcmp h0, h1
810; CHECK-FP16-GI-NEXT:    fmov w9, s1
811; CHECK-FP16-GI-NEXT:    fccmp h0, h2, #4, mi
812; CHECK-FP16-GI-NEXT:    csel w8, w8, w9, gt
813; CHECK-FP16-GI-NEXT:    strh w8, [x0]
814; CHECK-FP16-GI-NEXT:    ret
815  %cmp1 = fcmp ogt half %in, 0xH4800
816  %cmp2 = fcmp olt half %in, 0xH4500
817  %cond = and i1 %cmp1, %cmp2
818  %result = select i1 %cond, half %in, half 0xH4500
819  store half %result, ptr %out
820  ret void
821}
822
823define void @test_br_cc(half %a, half %b, ptr %p1, ptr %p2) #0 {
824; CHECK-CVT-SD-LABEL: test_br_cc:
825; CHECK-CVT-SD:       // %bb.0: // %common.ret
826; CHECK-CVT-SD-NEXT:    fcvt s1, h1
827; CHECK-CVT-SD-NEXT:    fcvt s0, h0
828; CHECK-CVT-SD-NEXT:    fcmp s0, s1
829; CHECK-CVT-SD-NEXT:    csel x8, x0, x1, pl
830; CHECK-CVT-SD-NEXT:    str wzr, [x8]
831; CHECK-CVT-SD-NEXT:    ret
832;
833; CHECK-FP16-LABEL: test_br_cc:
834; CHECK-FP16:       // %bb.0: // %common.ret
835; CHECK-FP16-NEXT:    fcmp h0, h1
836; CHECK-FP16-NEXT:    csel x8, x0, x1, pl
837; CHECK-FP16-NEXT:    str wzr, [x8]
838; CHECK-FP16-NEXT:    ret
839;
840; CHECK-CVT-GI-LABEL: test_br_cc:
841; CHECK-CVT-GI:       // %bb.0: // %common.ret
842; CHECK-CVT-GI-NEXT:    fcvt s0, h0
843; CHECK-CVT-GI-NEXT:    fcvt s1, h1
844; CHECK-CVT-GI-NEXT:    fcmp s0, s1
845; CHECK-CVT-GI-NEXT:    csel x8, x0, x1, pl
846; CHECK-CVT-GI-NEXT:    str wzr, [x8]
847; CHECK-CVT-GI-NEXT:    ret
848  %c = fcmp uge half %a, %b
849  br i1 %c, label %then, label %else
850then:
851  store i32 0, ptr %p1
852  ret void
853else:
854  store i32 0, ptr %p2
855  ret void
856}
857
858define half @test_phi(ptr %p1) #0 {
859; CHECK-LABEL: test_phi:
860; CHECK:       // %bb.0: // %entry
861; CHECK-NEXT:    stp d9, d8, [sp, #-32]! // 16-byte Folded Spill
862; CHECK-NEXT:    ldr h9, [x0]
863; CHECK-NEXT:    stp x30, x19, [sp, #16] // 16-byte Folded Spill
864; CHECK-NEXT:    mov x19, x0
865; CHECK-NEXT:  .LBB31_1: // %loop
866; CHECK-NEXT:    // =>This Inner Loop Header: Depth=1
867; CHECK-NEXT:    fmov s8, s9
868; CHECK-NEXT:    ldr h9, [x19]
869; CHECK-NEXT:    mov x0, x19
870; CHECK-NEXT:    bl test_dummy
871; CHECK-NEXT:    tbnz w0, #0, .LBB31_1
872; CHECK-NEXT:  // %bb.2: // %return
873; CHECK-NEXT:    ldp x30, x19, [sp, #16] // 16-byte Folded Reload
874; CHECK-NEXT:    fmov s0, s8
875; CHECK-NEXT:    ldp d9, d8, [sp], #32 // 16-byte Folded Reload
876; CHECK-NEXT:    ret
877entry:
878  %a = load half, ptr %p1
879  br label %loop
880loop:
881  %r = phi half [%a, %entry], [%b, %loop]
882  %b = load half, ptr %p1
883  %c = call i1 @test_dummy(ptr %p1)
884  br i1 %c, label %loop, label %return
885return:
886  ret half %r
887}
888
889declare i1 @test_dummy(ptr %p1) #0
890
891define i32 @test_fptosi_i32(half %a) #0 {
892; CHECK-CVT-LABEL: test_fptosi_i32:
893; CHECK-CVT:       // %bb.0:
894; CHECK-CVT-NEXT:    fcvt s0, h0
895; CHECK-CVT-NEXT:    fcvtzs w0, s0
896; CHECK-CVT-NEXT:    ret
897;
898; CHECK-FP16-LABEL: test_fptosi_i32:
899; CHECK-FP16:       // %bb.0:
900; CHECK-FP16-NEXT:    fcvtzs w0, h0
901; CHECK-FP16-NEXT:    ret
902  %r = fptosi half %a to i32
903  ret i32 %r
904}
905
906define i64 @test_fptosi_i64(half %a) #0 {
907; CHECK-CVT-LABEL: test_fptosi_i64:
908; CHECK-CVT:       // %bb.0:
909; CHECK-CVT-NEXT:    fcvt s0, h0
910; CHECK-CVT-NEXT:    fcvtzs x0, s0
911; CHECK-CVT-NEXT:    ret
912;
913; CHECK-FP16-LABEL: test_fptosi_i64:
914; CHECK-FP16:       // %bb.0:
915; CHECK-FP16-NEXT:    fcvtzs x0, h0
916; CHECK-FP16-NEXT:    ret
917  %r = fptosi half %a to i64
918  ret i64 %r
919}
920
921define i32 @test_fptoui_i32(half %a) #0 {
922; CHECK-CVT-LABEL: test_fptoui_i32:
923; CHECK-CVT:       // %bb.0:
924; CHECK-CVT-NEXT:    fcvt s0, h0
925; CHECK-CVT-NEXT:    fcvtzu w0, s0
926; CHECK-CVT-NEXT:    ret
927;
928; CHECK-FP16-LABEL: test_fptoui_i32:
929; CHECK-FP16:       // %bb.0:
930; CHECK-FP16-NEXT:    fcvtzu w0, h0
931; CHECK-FP16-NEXT:    ret
932  %r = fptoui half %a to i32
933  ret i32 %r
934}
935
936define i64 @test_fptoui_i64(half %a) #0 {
937; CHECK-CVT-LABEL: test_fptoui_i64:
938; CHECK-CVT:       // %bb.0:
939; CHECK-CVT-NEXT:    fcvt s0, h0
940; CHECK-CVT-NEXT:    fcvtzu x0, s0
941; CHECK-CVT-NEXT:    ret
942;
943; CHECK-FP16-LABEL: test_fptoui_i64:
944; CHECK-FP16:       // %bb.0:
945; CHECK-FP16-NEXT:    fcvtzu x0, h0
946; CHECK-FP16-NEXT:    ret
947  %r = fptoui half %a to i64
948  ret i64 %r
949}
950
951define half @test_uitofp_i32(i32 %a) #0 {
952; CHECK-CVT-LABEL: test_uitofp_i32:
953; CHECK-CVT:       // %bb.0:
954; CHECK-CVT-NEXT:    ucvtf s0, w0
955; CHECK-CVT-NEXT:    fcvt h0, s0
956; CHECK-CVT-NEXT:    ret
957;
958; CHECK-FP16-LABEL: test_uitofp_i32:
959; CHECK-FP16:       // %bb.0:
960; CHECK-FP16-NEXT:    ucvtf h0, w0
961; CHECK-FP16-NEXT:    ret
962  %r = uitofp i32 %a to half
963  ret half %r
964}
965
966define half @test_uitofp_i64(i64 %a) #0 {
967; CHECK-CVT-LABEL: test_uitofp_i64:
968; CHECK-CVT:       // %bb.0:
969; CHECK-CVT-NEXT:    ucvtf s0, x0
970; CHECK-CVT-NEXT:    fcvt h0, s0
971; CHECK-CVT-NEXT:    ret
972;
973; CHECK-FP16-LABEL: test_uitofp_i64:
974; CHECK-FP16:       // %bb.0:
975; CHECK-FP16-NEXT:    ucvtf h0, x0
976; CHECK-FP16-NEXT:    ret
977  %r = uitofp i64 %a to half
978  ret half %r
979}
980
981define half @test_sitofp_i32(i32 %a) #0 {
982; CHECK-CVT-LABEL: test_sitofp_i32:
983; CHECK-CVT:       // %bb.0:
984; CHECK-CVT-NEXT:    scvtf s0, w0
985; CHECK-CVT-NEXT:    fcvt h0, s0
986; CHECK-CVT-NEXT:    ret
987;
988; CHECK-FP16-LABEL: test_sitofp_i32:
989; CHECK-FP16:       // %bb.0:
990; CHECK-FP16-NEXT:    scvtf h0, w0
991; CHECK-FP16-NEXT:    ret
992  %r = sitofp i32 %a to half
993  ret half %r
994}
995
996define half @test_sitofp_i64(i64 %a) #0 {
997; CHECK-CVT-LABEL: test_sitofp_i64:
998; CHECK-CVT:       // %bb.0:
999; CHECK-CVT-NEXT:    scvtf s0, x0
1000; CHECK-CVT-NEXT:    fcvt h0, s0
1001; CHECK-CVT-NEXT:    ret
1002;
1003; CHECK-FP16-LABEL: test_sitofp_i64:
1004; CHECK-FP16:       // %bb.0:
1005; CHECK-FP16-NEXT:    scvtf h0, x0
1006; CHECK-FP16-NEXT:    ret
1007  %r = sitofp i64 %a to half
1008  ret half %r
1009}
1010
1011define half @test_uitofp_i32_fadd(i32 %a, half %b) #0 {
1012; CHECK-CVT-LABEL: test_uitofp_i32_fadd:
1013; CHECK-CVT:       // %bb.0:
1014; CHECK-CVT-NEXT:    ucvtf s1, w0
1015; CHECK-CVT-NEXT:    fcvt s0, h0
1016; CHECK-CVT-NEXT:    fcvt h1, s1
1017; CHECK-CVT-NEXT:    fcvt s1, h1
1018; CHECK-CVT-NEXT:    fadd s0, s0, s1
1019; CHECK-CVT-NEXT:    fcvt h0, s0
1020; CHECK-CVT-NEXT:    ret
1021;
1022; CHECK-FP16-LABEL: test_uitofp_i32_fadd:
1023; CHECK-FP16:       // %bb.0:
1024; CHECK-FP16-NEXT:    ucvtf h1, w0
1025; CHECK-FP16-NEXT:    fadd h0, h0, h1
1026; CHECK-FP16-NEXT:    ret
1027  %c = uitofp i32 %a to half
1028  %r = fadd half %b, %c
1029  ret half %r
1030}
1031
1032define half @test_sitofp_i32_fadd(i32 %a, half %b) #0 {
1033; CHECK-CVT-LABEL: test_sitofp_i32_fadd:
1034; CHECK-CVT:       // %bb.0:
1035; CHECK-CVT-NEXT:    scvtf s1, w0
1036; CHECK-CVT-NEXT:    fcvt s0, h0
1037; CHECK-CVT-NEXT:    fcvt h1, s1
1038; CHECK-CVT-NEXT:    fcvt s1, h1
1039; CHECK-CVT-NEXT:    fadd s0, s0, s1
1040; CHECK-CVT-NEXT:    fcvt h0, s0
1041; CHECK-CVT-NEXT:    ret
1042;
1043; CHECK-FP16-LABEL: test_sitofp_i32_fadd:
1044; CHECK-FP16:       // %bb.0:
1045; CHECK-FP16-NEXT:    scvtf h1, w0
1046; CHECK-FP16-NEXT:    fadd h0, h0, h1
1047; CHECK-FP16-NEXT:    ret
1048  %c = sitofp i32 %a to half
1049  %r = fadd half %b, %c
1050  ret half %r
1051}
1052
1053define half @test_fptrunc_float(float %a) #0 {
1054; CHECK-LABEL: test_fptrunc_float:
1055; CHECK:       // %bb.0:
1056; CHECK-NEXT:    fcvt h0, s0
1057; CHECK-NEXT:    ret
1058  %r = fptrunc float %a to half
1059  ret half %r
1060}
1061
1062define half @test_fptrunc_double(double %a) #0 {
1063; CHECK-LABEL: test_fptrunc_double:
1064; CHECK:       // %bb.0:
1065; CHECK-NEXT:    fcvt h0, d0
1066; CHECK-NEXT:    ret
1067  %r = fptrunc double %a to half
1068  ret half %r
1069}
1070
1071define float @test_fpext_float(half %a) #0 {
1072; CHECK-LABEL: test_fpext_float:
1073; CHECK:       // %bb.0:
1074; CHECK-NEXT:    fcvt s0, h0
1075; CHECK-NEXT:    ret
1076  %r = fpext half %a to float
1077  ret float %r
1078}
1079
1080define double @test_fpext_double(half %a) #0 {
1081; CHECK-LABEL: test_fpext_double:
1082; CHECK:       // %bb.0:
1083; CHECK-NEXT:    fcvt d0, h0
1084; CHECK-NEXT:    ret
1085  %r = fpext half %a to double
1086  ret double %r
1087}
1088
1089define i16 @test_bitcast_halftoi16(half %a) #0 {
1090; CHECK-LABEL: test_bitcast_halftoi16:
1091; CHECK:       // %bb.0:
1092; CHECK-NEXT:    // kill: def $h0 killed $h0 def $s0
1093; CHECK-NEXT:    fmov w0, s0
1094; CHECK-NEXT:    ret
1095  %r = bitcast half %a to i16
1096  ret i16 %r
1097}
1098
1099define half @test_bitcast_i16tohalf(i16 %a) #0 {
1100; CHECK-LABEL: test_bitcast_i16tohalf:
1101; CHECK:       // %bb.0:
1102; CHECK-NEXT:    fmov s0, w0
1103; CHECK-NEXT:    // kill: def $h0 killed $h0 killed $s0
1104; CHECK-NEXT:    ret
1105  %r = bitcast i16 %a to half
1106  ret half %r
1107}
1108
1109declare half @llvm.sqrt.f16(half %a) #0
1110declare half @llvm.powi.f16.i32(half %a, i32 %b) #0
1111declare half @llvm.sin.f16(half %a) #0
1112declare half @llvm.cos.f16(half %a) #0
1113declare half @llvm.tan.f16(half %a) #0
1114declare half @llvm.asin.f16(half %a) #0
1115declare half @llvm.acos.f16(half %a) #0
1116declare half @llvm.atan.f16(half %a) #0
1117declare half @llvm.atan2.f16(half %a, half %b) #0
1118declare half @llvm.sinh.f16(half %a) #0
1119declare half @llvm.cosh.f16(half %a) #0
1120declare half @llvm.tanh.f16(half %a) #0
1121declare half @llvm.pow.f16(half %a, half %b) #0
1122declare half @llvm.exp.f16(half %a) #0
1123declare half @llvm.exp2.f16(half %a) #0
1124declare half @llvm.log.f16(half %a) #0
1125declare half @llvm.log10.f16(half %a) #0
1126declare half @llvm.log2.f16(half %a) #0
1127declare half @llvm.fma.f16(half %a, half %b, half %c) #0
1128declare half @llvm.fabs.f16(half %a) #0
1129declare half @llvm.minnum.f16(half %a, half %b) #0
1130declare half @llvm.maxnum.f16(half %a, half %b) #0
1131declare half @llvm.copysign.f16(half %a, half %b) #0
1132declare half @llvm.floor.f16(half %a) #0
1133declare half @llvm.ceil.f16(half %a) #0
1134declare half @llvm.trunc.f16(half %a) #0
1135declare half @llvm.rint.f16(half %a) #0
1136declare half @llvm.nearbyint.f16(half %a) #0
1137declare half @llvm.round.f16(half %a) #0
1138declare half @llvm.roundeven.f16(half %a) #0
1139declare half @llvm.fmuladd.f16(half %a, half %b, half %c) #0
1140
1141
1142define half @test_sqrt(half %a) #0 {
1143; CHECK-CVT-LABEL: test_sqrt:
1144; CHECK-CVT:       // %bb.0:
1145; CHECK-CVT-NEXT:    fcvt s0, h0
1146; CHECK-CVT-NEXT:    fsqrt s0, s0
1147; CHECK-CVT-NEXT:    fcvt h0, s0
1148; CHECK-CVT-NEXT:    ret
1149;
1150; CHECK-FP16-LABEL: test_sqrt:
1151; CHECK-FP16:       // %bb.0:
1152; CHECK-FP16-NEXT:    fsqrt h0, h0
1153; CHECK-FP16-NEXT:    ret
1154  %r = call half @llvm.sqrt.f16(half %a)
1155  ret half %r
1156}
1157
1158define half @test_powi(half %a, i32 %b) #0 {
1159; CHECK-LABEL: test_powi:
1160; CHECK:       // %bb.0:
1161; CHECK-NEXT:    str x30, [sp, #-16]! // 8-byte Folded Spill
1162; CHECK-NEXT:    fcvt s0, h0
1163; CHECK-NEXT:    bl __powisf2
1164; CHECK-NEXT:    fcvt h0, s0
1165; CHECK-NEXT:    ldr x30, [sp], #16 // 8-byte Folded Reload
1166; CHECK-NEXT:    ret
1167  %r = call half @llvm.powi.f16.i32(half %a, i32 %b)
1168  ret half %r
1169}
1170
1171
1172define half @test_sin(half %a) #0 {
1173; CHECK-LABEL: test_sin:
1174; CHECK:       // %bb.0:
1175; CHECK-NEXT:    str x30, [sp, #-16]! // 8-byte Folded Spill
1176; CHECK-NEXT:    fcvt s0, h0
1177; CHECK-NEXT:    bl sinf
1178; CHECK-NEXT:    fcvt h0, s0
1179; CHECK-NEXT:    ldr x30, [sp], #16 // 8-byte Folded Reload
1180; CHECK-NEXT:    ret
1181  %r = call half @llvm.sin.f16(half %a)
1182  ret half %r
1183}
1184
1185define half @test_cos(half %a) #0 {
1186; CHECK-LABEL: test_cos:
1187; CHECK:       // %bb.0:
1188; CHECK-NEXT:    str x30, [sp, #-16]! // 8-byte Folded Spill
1189; CHECK-NEXT:    fcvt s0, h0
1190; CHECK-NEXT:    bl cosf
1191; CHECK-NEXT:    fcvt h0, s0
1192; CHECK-NEXT:    ldr x30, [sp], #16 // 8-byte Folded Reload
1193; CHECK-NEXT:    ret
1194  %r = call half @llvm.cos.f16(half %a)
1195  ret half %r
1196}
1197
1198define half @test_tan(half %a) #0 {
1199; CHECK-LABEL: test_tan:
1200; CHECK:       // %bb.0:
1201; CHECK-NEXT:    str x30, [sp, #-16]! // 8-byte Folded Spill
1202; CHECK-NEXT:    fcvt s0, h0
1203; CHECK-NEXT:    bl tanf
1204; CHECK-NEXT:    fcvt h0, s0
1205; CHECK-NEXT:    ldr x30, [sp], #16 // 8-byte Folded Reload
1206; CHECK-NEXT:    ret
1207  %r = call half @llvm.tan.f16(half %a)
1208  ret half %r
1209}
1210
1211define half @test_acos(half %a) #0 {
1212; CHECK-LABEL: test_acos:
1213; CHECK:       // %bb.0:
1214; CHECK-NEXT:    str x30, [sp, #-16]! // 8-byte Folded Spill
1215; CHECK-NEXT:    fcvt s0, h0
1216; CHECK-NEXT:    bl acosf
1217; CHECK-NEXT:    fcvt h0, s0
1218; CHECK-NEXT:    ldr x30, [sp], #16 // 8-byte Folded Reload
1219; CHECK-NEXT:    ret
1220  %r = call half @llvm.acos.f16(half %a)
1221  ret half %r
1222}
1223
1224define half @test_asin(half %a) #0 {
1225; CHECK-LABEL: test_asin:
1226; CHECK:       // %bb.0:
1227; CHECK-NEXT:    str x30, [sp, #-16]! // 8-byte Folded Spill
1228; CHECK-NEXT:    fcvt s0, h0
1229; CHECK-NEXT:    bl asinf
1230; CHECK-NEXT:    fcvt h0, s0
1231; CHECK-NEXT:    ldr x30, [sp], #16 // 8-byte Folded Reload
1232; CHECK-NEXT:    ret
1233  %r = call half @llvm.asin.f16(half %a)
1234  ret half %r
1235}
1236
1237define half @test_atan(half %a) #0 {
1238; CHECK-LABEL: test_atan:
1239; CHECK:       // %bb.0:
1240; CHECK-NEXT:    str x30, [sp, #-16]! // 8-byte Folded Spill
1241; CHECK-NEXT:    fcvt s0, h0
1242; CHECK-NEXT:    bl atanf
1243; CHECK-NEXT:    fcvt h0, s0
1244; CHECK-NEXT:    ldr x30, [sp], #16 // 8-byte Folded Reload
1245; CHECK-NEXT:    ret
1246  %r = call half @llvm.atan.f16(half %a)
1247  ret half %r
1248}
1249
1250define half @test_atan2(half %a, half %b) #0 {
1251  %r = call half @llvm.atan2.f16(half %a, half %b)
1252  ret half %r
1253}
1254
1255define half @test_cosh(half %a) #0 {
1256; CHECK-LABEL: test_cosh:
1257; CHECK:       // %bb.0:
1258; CHECK-NEXT:    str x30, [sp, #-16]! // 8-byte Folded Spill
1259; CHECK-NEXT:    fcvt s0, h0
1260; CHECK-NEXT:    bl coshf
1261; CHECK-NEXT:    fcvt h0, s0
1262; CHECK-NEXT:    ldr x30, [sp], #16 // 8-byte Folded Reload
1263; CHECK-NEXT:    ret
1264  %r = call half @llvm.cosh.f16(half %a)
1265  ret half %r
1266}
1267
1268define half @test_sinh(half %a) #0 {
1269; CHECK-LABEL: test_sinh:
1270; CHECK:       // %bb.0:
1271; CHECK-NEXT:    str x30, [sp, #-16]! // 8-byte Folded Spill
1272; CHECK-NEXT:    fcvt s0, h0
1273; CHECK-NEXT:    bl sinhf
1274; CHECK-NEXT:    fcvt h0, s0
1275; CHECK-NEXT:    ldr x30, [sp], #16 // 8-byte Folded Reload
1276; CHECK-NEXT:    ret
1277  %r = call half @llvm.sinh.f16(half %a)
1278  ret half %r
1279}
1280
1281define half @test_tanh(half %a) #0 {
1282; CHECK-LABEL: test_tanh:
1283; CHECK:       // %bb.0:
1284; CHECK-NEXT:    str x30, [sp, #-16]! // 8-byte Folded Spill
1285; CHECK-NEXT:    fcvt s0, h0
1286; CHECK-NEXT:    bl tanhf
1287; CHECK-NEXT:    fcvt h0, s0
1288; CHECK-NEXT:    ldr x30, [sp], #16 // 8-byte Folded Reload
1289; CHECK-NEXT:    ret
1290  %r = call half @llvm.tanh.f16(half %a)
1291  ret half %r
1292}
1293
1294define half @test_pow(half %a, half %b) #0 {
1295; CHECK-LABEL: test_pow:
1296; CHECK:       // %bb.0:
1297; CHECK-NEXT:    str x30, [sp, #-16]! // 8-byte Folded Spill
1298; CHECK-NEXT:    fcvt s0, h0
1299; CHECK-NEXT:    fcvt s1, h1
1300; CHECK-NEXT:    bl powf
1301; CHECK-NEXT:    fcvt h0, s0
1302; CHECK-NEXT:    ldr x30, [sp], #16 // 8-byte Folded Reload
1303; CHECK-NEXT:    ret
1304  %r = call half @llvm.pow.f16(half %a, half %b)
1305  ret half %r
1306}
1307
1308define half @test_exp(half %a) #0 {
1309; CHECK-LABEL: test_exp:
1310; CHECK:       // %bb.0:
1311; CHECK-NEXT:    str x30, [sp, #-16]! // 8-byte Folded Spill
1312; CHECK-NEXT:    fcvt s0, h0
1313; CHECK-NEXT:    bl expf
1314; CHECK-NEXT:    fcvt h0, s0
1315; CHECK-NEXT:    ldr x30, [sp], #16 // 8-byte Folded Reload
1316; CHECK-NEXT:    ret
1317  %r = call half @llvm.exp.f16(half %a)
1318  ret half %r
1319}
1320
1321define half @test_exp2(half %a) #0 {
1322; CHECK-LABEL: test_exp2:
1323; CHECK:       // %bb.0:
1324; CHECK-NEXT:    str x30, [sp, #-16]! // 8-byte Folded Spill
1325; CHECK-NEXT:    fcvt s0, h0
1326; CHECK-NEXT:    bl exp2f
1327; CHECK-NEXT:    fcvt h0, s0
1328; CHECK-NEXT:    ldr x30, [sp], #16 // 8-byte Folded Reload
1329; CHECK-NEXT:    ret
1330  %r = call half @llvm.exp2.f16(half %a)
1331  ret half %r
1332}
1333
1334define half @test_log(half %a) #0 {
1335; CHECK-LABEL: test_log:
1336; CHECK:       // %bb.0:
1337; CHECK-NEXT:    str x30, [sp, #-16]! // 8-byte Folded Spill
1338; CHECK-NEXT:    fcvt s0, h0
1339; CHECK-NEXT:    bl logf
1340; CHECK-NEXT:    fcvt h0, s0
1341; CHECK-NEXT:    ldr x30, [sp], #16 // 8-byte Folded Reload
1342; CHECK-NEXT:    ret
1343  %r = call half @llvm.log.f16(half %a)
1344  ret half %r
1345}
1346
1347define half @test_log10(half %a) #0 {
1348; CHECK-LABEL: test_log10:
1349; CHECK:       // %bb.0:
1350; CHECK-NEXT:    str x30, [sp, #-16]! // 8-byte Folded Spill
1351; CHECK-NEXT:    fcvt s0, h0
1352; CHECK-NEXT:    bl log10f
1353; CHECK-NEXT:    fcvt h0, s0
1354; CHECK-NEXT:    ldr x30, [sp], #16 // 8-byte Folded Reload
1355; CHECK-NEXT:    ret
1356  %r = call half @llvm.log10.f16(half %a)
1357  ret half %r
1358}
1359
1360define half @test_log2(half %a) #0 {
1361; CHECK-LABEL: test_log2:
1362; CHECK:       // %bb.0:
1363; CHECK-NEXT:    str x30, [sp, #-16]! // 8-byte Folded Spill
1364; CHECK-NEXT:    fcvt s0, h0
1365; CHECK-NEXT:    bl log2f
1366; CHECK-NEXT:    fcvt h0, s0
1367; CHECK-NEXT:    ldr x30, [sp], #16 // 8-byte Folded Reload
1368; CHECK-NEXT:    ret
1369  %r = call half @llvm.log2.f16(half %a)
1370  ret half %r
1371}
1372
1373define half @test_fma(half %a, half %b, half %c) #0 {
1374; CHECK-CVT-SD-LABEL: test_fma:
1375; CHECK-CVT-SD:       // %bb.0:
1376; CHECK-CVT-SD-NEXT:    fcvt s2, h2
1377; CHECK-CVT-SD-NEXT:    fcvt s1, h1
1378; CHECK-CVT-SD-NEXT:    fcvt s0, h0
1379; CHECK-CVT-SD-NEXT:    fmadd s0, s0, s1, s2
1380; CHECK-CVT-SD-NEXT:    fcvt h0, s0
1381; CHECK-CVT-SD-NEXT:    ret
1382;
1383; CHECK-FP16-LABEL: test_fma:
1384; CHECK-FP16:       // %bb.0:
1385; CHECK-FP16-NEXT:    fmadd h0, h0, h1, h2
1386; CHECK-FP16-NEXT:    ret
1387;
1388; CHECK-CVT-GI-LABEL: test_fma:
1389; CHECK-CVT-GI:       // %bb.0:
1390; CHECK-CVT-GI-NEXT:    fcvt s0, h0
1391; CHECK-CVT-GI-NEXT:    fcvt s1, h1
1392; CHECK-CVT-GI-NEXT:    fcvt s2, h2
1393; CHECK-CVT-GI-NEXT:    fmadd s0, s0, s1, s2
1394; CHECK-CVT-GI-NEXT:    fcvt h0, s0
1395; CHECK-CVT-GI-NEXT:    ret
1396  %r = call half @llvm.fma.f16(half %a, half %b, half %c)
1397  ret half %r
1398}
1399
1400define half @test_fabs(half %a) #0 {
1401; CHECK-CVT-LABEL: test_fabs:
1402; CHECK-CVT:       // %bb.0:
1403; CHECK-CVT-NEXT:    // kill: def $h0 killed $h0 def $s0
1404; CHECK-CVT-NEXT:    fmov w8, s0
1405; CHECK-CVT-NEXT:    and w8, w8, #0x7fff
1406; CHECK-CVT-NEXT:    fmov s0, w8
1407; CHECK-CVT-NEXT:    // kill: def $h0 killed $h0 killed $s0
1408; CHECK-CVT-NEXT:    ret
1409;
1410; CHECK-FP16-LABEL: test_fabs:
1411; CHECK-FP16:       // %bb.0:
1412; CHECK-FP16-NEXT:    fabs h0, h0
1413; CHECK-FP16-NEXT:    ret
1414  %r = call half @llvm.fabs.f16(half %a)
1415  ret half %r
1416}
1417
1418define half @test_minnum(half %a, half %b) #0 {
1419; CHECK-CVT-SD-LABEL: test_minnum:
1420; CHECK-CVT-SD:       // %bb.0:
1421; CHECK-CVT-SD-NEXT:    fcvt s1, h1
1422; CHECK-CVT-SD-NEXT:    fcvt s0, h0
1423; CHECK-CVT-SD-NEXT:    fminnm s0, s0, s1
1424; CHECK-CVT-SD-NEXT:    fcvt h0, s0
1425; CHECK-CVT-SD-NEXT:    ret
1426;
1427; CHECK-FP16-LABEL: test_minnum:
1428; CHECK-FP16:       // %bb.0:
1429; CHECK-FP16-NEXT:    fminnm h0, h0, h1
1430; CHECK-FP16-NEXT:    ret
1431;
1432; CHECK-CVT-GI-LABEL: test_minnum:
1433; CHECK-CVT-GI:       // %bb.0:
1434; CHECK-CVT-GI-NEXT:    fcvt s0, h0
1435; CHECK-CVT-GI-NEXT:    fcvt s1, h1
1436; CHECK-CVT-GI-NEXT:    fminnm s0, s0, s1
1437; CHECK-CVT-GI-NEXT:    fcvt h0, s0
1438; CHECK-CVT-GI-NEXT:    ret
1439  %r = call half @llvm.minnum.f16(half %a, half %b)
1440  ret half %r
1441}
1442
1443define half @test_maxnum(half %a, half %b) #0 {
1444; CHECK-CVT-SD-LABEL: test_maxnum:
1445; CHECK-CVT-SD:       // %bb.0:
1446; CHECK-CVT-SD-NEXT:    fcvt s1, h1
1447; CHECK-CVT-SD-NEXT:    fcvt s0, h0
1448; CHECK-CVT-SD-NEXT:    fmaxnm s0, s0, s1
1449; CHECK-CVT-SD-NEXT:    fcvt h0, s0
1450; CHECK-CVT-SD-NEXT:    ret
1451;
1452; CHECK-FP16-LABEL: test_maxnum:
1453; CHECK-FP16:       // %bb.0:
1454; CHECK-FP16-NEXT:    fmaxnm h0, h0, h1
1455; CHECK-FP16-NEXT:    ret
1456;
1457; CHECK-CVT-GI-LABEL: test_maxnum:
1458; CHECK-CVT-GI:       // %bb.0:
1459; CHECK-CVT-GI-NEXT:    fcvt s0, h0
1460; CHECK-CVT-GI-NEXT:    fcvt s1, h1
1461; CHECK-CVT-GI-NEXT:    fmaxnm s0, s0, s1
1462; CHECK-CVT-GI-NEXT:    fcvt h0, s0
1463; CHECK-CVT-GI-NEXT:    ret
1464  %r = call half @llvm.maxnum.f16(half %a, half %b)
1465  ret half %r
1466}
1467
1468define half @test_copysign(half %a, half %b) #0 {
1469; CHECK-CVT-SD-LABEL: test_copysign:
1470; CHECK-CVT-SD:       // %bb.0:
1471; CHECK-CVT-SD-NEXT:    fcvt s1, h1
1472; CHECK-CVT-SD-NEXT:    fcvt s0, h0
1473; CHECK-CVT-SD-NEXT:    mvni v2.4s, #128, lsl #24
1474; CHECK-CVT-SD-NEXT:    bif v0.16b, v1.16b, v2.16b
1475; CHECK-CVT-SD-NEXT:    fcvt h0, s0
1476; CHECK-CVT-SD-NEXT:    ret
1477;
1478; CHECK-FP16-SD-LABEL: test_copysign:
1479; CHECK-FP16-SD:       // %bb.0:
1480; CHECK-FP16-SD-NEXT:    mvni v2.8h, #128, lsl #8
1481; CHECK-FP16-SD-NEXT:    // kill: def $h0 killed $h0 def $q0
1482; CHECK-FP16-SD-NEXT:    // kill: def $h1 killed $h1 def $q1
1483; CHECK-FP16-SD-NEXT:    bif v0.16b, v1.16b, v2.16b
1484; CHECK-FP16-SD-NEXT:    // kill: def $h0 killed $h0 killed $q0
1485; CHECK-FP16-SD-NEXT:    ret
1486;
1487; CHECK-CVT-GI-LABEL: test_copysign:
1488; CHECK-CVT-GI:       // %bb.0:
1489; CHECK-CVT-GI-NEXT:    mvni v2.4h, #128, lsl #8
1490; CHECK-CVT-GI-NEXT:    // kill: def $h0 killed $h0 def $d0
1491; CHECK-CVT-GI-NEXT:    // kill: def $h1 killed $h1 def $d1
1492; CHECK-CVT-GI-NEXT:    bif v0.8b, v1.8b, v2.8b
1493; CHECK-CVT-GI-NEXT:    // kill: def $h0 killed $h0 killed $d0
1494; CHECK-CVT-GI-NEXT:    ret
1495;
1496; CHECK-FP16-GI-LABEL: test_copysign:
1497; CHECK-FP16-GI:       // %bb.0:
1498; CHECK-FP16-GI-NEXT:    mvni v2.4h, #128, lsl #8
1499; CHECK-FP16-GI-NEXT:    // kill: def $h0 killed $h0 def $d0
1500; CHECK-FP16-GI-NEXT:    // kill: def $h1 killed $h1 def $d1
1501; CHECK-FP16-GI-NEXT:    bif v0.8b, v1.8b, v2.8b
1502; CHECK-FP16-GI-NEXT:    // kill: def $h0 killed $h0 killed $d0
1503; CHECK-FP16-GI-NEXT:    ret
1504  %r = call half @llvm.copysign.f16(half %a, half %b)
1505  ret half %r
1506}
1507
1508define half @test_copysign_f32(half %a, float %b) #0 {
1509; CHECK-CVT-SD-LABEL: test_copysign_f32:
1510; CHECK-CVT-SD:       // %bb.0:
1511; CHECK-CVT-SD-NEXT:    fcvt s0, h0
1512; CHECK-CVT-SD-NEXT:    mvni v2.4s, #128, lsl #24
1513; CHECK-CVT-SD-NEXT:    // kill: def $s1 killed $s1 def $q1
1514; CHECK-CVT-SD-NEXT:    bif v0.16b, v1.16b, v2.16b
1515; CHECK-CVT-SD-NEXT:    fcvt h0, s0
1516; CHECK-CVT-SD-NEXT:    ret
1517;
1518; CHECK-FP16-SD-LABEL: test_copysign_f32:
1519; CHECK-FP16-SD:       // %bb.0:
1520; CHECK-FP16-SD-NEXT:    fcvt h1, s1
1521; CHECK-FP16-SD-NEXT:    mvni v2.8h, #128, lsl #8
1522; CHECK-FP16-SD-NEXT:    // kill: def $h0 killed $h0 def $q0
1523; CHECK-FP16-SD-NEXT:    bif v0.16b, v1.16b, v2.16b
1524; CHECK-FP16-SD-NEXT:    // kill: def $h0 killed $h0 killed $q0
1525; CHECK-FP16-SD-NEXT:    ret
1526;
1527; CHECK-CVT-GI-LABEL: test_copysign_f32:
1528; CHECK-CVT-GI:       // %bb.0:
1529; CHECK-CVT-GI-NEXT:    fcvt h1, s1
1530; CHECK-CVT-GI-NEXT:    mvni v2.4h, #128, lsl #8
1531; CHECK-CVT-GI-NEXT:    // kill: def $h0 killed $h0 def $d0
1532; CHECK-CVT-GI-NEXT:    bif v0.8b, v1.8b, v2.8b
1533; CHECK-CVT-GI-NEXT:    // kill: def $h0 killed $h0 killed $d0
1534; CHECK-CVT-GI-NEXT:    ret
1535;
1536; CHECK-FP16-GI-LABEL: test_copysign_f32:
1537; CHECK-FP16-GI:       // %bb.0:
1538; CHECK-FP16-GI-NEXT:    fcvt h1, s1
1539; CHECK-FP16-GI-NEXT:    mvni v2.4h, #128, lsl #8
1540; CHECK-FP16-GI-NEXT:    // kill: def $h0 killed $h0 def $d0
1541; CHECK-FP16-GI-NEXT:    bif v0.8b, v1.8b, v2.8b
1542; CHECK-FP16-GI-NEXT:    // kill: def $h0 killed $h0 killed $d0
1543; CHECK-FP16-GI-NEXT:    ret
1544  %tb = fptrunc float %b to half
1545  %r = call half @llvm.copysign.f16(half %a, half %tb)
1546  ret half %r
1547}
1548
1549define half @test_copysign_f64(half %a, double %b) #0 {
1550; CHECK-CVT-SD-LABEL: test_copysign_f64:
1551; CHECK-CVT-SD:       // %bb.0:
1552; CHECK-CVT-SD-NEXT:    fcvt s1, d1
1553; CHECK-CVT-SD-NEXT:    fcvt s0, h0
1554; CHECK-CVT-SD-NEXT:    mvni v2.4s, #128, lsl #24
1555; CHECK-CVT-SD-NEXT:    bif v0.16b, v1.16b, v2.16b
1556; CHECK-CVT-SD-NEXT:    fcvt h0, s0
1557; CHECK-CVT-SD-NEXT:    ret
1558;
1559; CHECK-FP16-SD-LABEL: test_copysign_f64:
1560; CHECK-FP16-SD:       // %bb.0:
1561; CHECK-FP16-SD-NEXT:    fcvt h1, d1
1562; CHECK-FP16-SD-NEXT:    mvni v2.8h, #128, lsl #8
1563; CHECK-FP16-SD-NEXT:    // kill: def $h0 killed $h0 def $q0
1564; CHECK-FP16-SD-NEXT:    bif v0.16b, v1.16b, v2.16b
1565; CHECK-FP16-SD-NEXT:    // kill: def $h0 killed $h0 killed $q0
1566; CHECK-FP16-SD-NEXT:    ret
1567;
1568; CHECK-CVT-GI-LABEL: test_copysign_f64:
1569; CHECK-CVT-GI:       // %bb.0:
1570; CHECK-CVT-GI-NEXT:    fcvt h1, d1
1571; CHECK-CVT-GI-NEXT:    mvni v2.4h, #128, lsl #8
1572; CHECK-CVT-GI-NEXT:    // kill: def $h0 killed $h0 def $d0
1573; CHECK-CVT-GI-NEXT:    bif v0.8b, v1.8b, v2.8b
1574; CHECK-CVT-GI-NEXT:    // kill: def $h0 killed $h0 killed $d0
1575; CHECK-CVT-GI-NEXT:    ret
1576;
1577; CHECK-FP16-GI-LABEL: test_copysign_f64:
1578; CHECK-FP16-GI:       // %bb.0:
1579; CHECK-FP16-GI-NEXT:    fcvt h1, d1
1580; CHECK-FP16-GI-NEXT:    mvni v2.4h, #128, lsl #8
1581; CHECK-FP16-GI-NEXT:    // kill: def $h0 killed $h0 def $d0
1582; CHECK-FP16-GI-NEXT:    bif v0.8b, v1.8b, v2.8b
1583; CHECK-FP16-GI-NEXT:    // kill: def $h0 killed $h0 killed $d0
1584; CHECK-FP16-GI-NEXT:    ret
1585  %tb = fptrunc double %b to half
1586  %r = call half @llvm.copysign.f16(half %a, half %tb)
1587  ret half %r
1588}
1589
1590; Check that the FP promotion will use a truncating FP_ROUND, so we can fold
1591; away the (fpext (fp_round <result>)) here.
1592
1593define float @test_copysign_extended(half %a, half %b) #0 {
1594; CHECK-CVT-SD-LABEL: test_copysign_extended:
1595; CHECK-CVT-SD:       // %bb.0:
1596; CHECK-CVT-SD-NEXT:    fcvt s1, h1
1597; CHECK-CVT-SD-NEXT:    fcvt s0, h0
1598; CHECK-CVT-SD-NEXT:    mvni v2.4s, #128, lsl #24
1599; CHECK-CVT-SD-NEXT:    bif v0.16b, v1.16b, v2.16b
1600; CHECK-CVT-SD-NEXT:    // kill: def $s0 killed $s0 killed $q0
1601; CHECK-CVT-SD-NEXT:    ret
1602;
1603; CHECK-FP16-SD-LABEL: test_copysign_extended:
1604; CHECK-FP16-SD:       // %bb.0:
1605; CHECK-FP16-SD-NEXT:    mvni v2.8h, #128, lsl #8
1606; CHECK-FP16-SD-NEXT:    // kill: def $h0 killed $h0 def $q0
1607; CHECK-FP16-SD-NEXT:    // kill: def $h1 killed $h1 def $q1
1608; CHECK-FP16-SD-NEXT:    bif v0.16b, v1.16b, v2.16b
1609; CHECK-FP16-SD-NEXT:    fcvt s0, h0
1610; CHECK-FP16-SD-NEXT:    ret
1611;
1612; CHECK-CVT-GI-LABEL: test_copysign_extended:
1613; CHECK-CVT-GI:       // %bb.0:
1614; CHECK-CVT-GI-NEXT:    mvni v2.4h, #128, lsl #8
1615; CHECK-CVT-GI-NEXT:    // kill: def $h0 killed $h0 def $d0
1616; CHECK-CVT-GI-NEXT:    // kill: def $h1 killed $h1 def $d1
1617; CHECK-CVT-GI-NEXT:    bif v0.8b, v1.8b, v2.8b
1618; CHECK-CVT-GI-NEXT:    fcvt s0, h0
1619; CHECK-CVT-GI-NEXT:    ret
1620;
1621; CHECK-FP16-GI-LABEL: test_copysign_extended:
1622; CHECK-FP16-GI:       // %bb.0:
1623; CHECK-FP16-GI-NEXT:    mvni v2.4h, #128, lsl #8
1624; CHECK-FP16-GI-NEXT:    // kill: def $h0 killed $h0 def $d0
1625; CHECK-FP16-GI-NEXT:    // kill: def $h1 killed $h1 def $d1
1626; CHECK-FP16-GI-NEXT:    bif v0.8b, v1.8b, v2.8b
1627; CHECK-FP16-GI-NEXT:    fcvt s0, h0
1628; CHECK-FP16-GI-NEXT:    ret
1629  %r = call half @llvm.copysign.f16(half %a, half %b)
1630  %xr = fpext half %r to float
1631  ret float %xr
1632}
1633
1634define half @test_floor(half %a) #0 {
1635; CHECK-CVT-LABEL: test_floor:
1636; CHECK-CVT:       // %bb.0:
1637; CHECK-CVT-NEXT:    fcvt s0, h0
1638; CHECK-CVT-NEXT:    frintm s0, s0
1639; CHECK-CVT-NEXT:    fcvt h0, s0
1640; CHECK-CVT-NEXT:    ret
1641;
1642; CHECK-FP16-LABEL: test_floor:
1643; CHECK-FP16:       // %bb.0:
1644; CHECK-FP16-NEXT:    frintm h0, h0
1645; CHECK-FP16-NEXT:    ret
1646  %r = call half @llvm.floor.f16(half %a)
1647  ret half %r
1648}
1649
1650define half @test_ceil(half %a) #0 {
1651; CHECK-CVT-LABEL: test_ceil:
1652; CHECK-CVT:       // %bb.0:
1653; CHECK-CVT-NEXT:    fcvt s0, h0
1654; CHECK-CVT-NEXT:    frintp s0, s0
1655; CHECK-CVT-NEXT:    fcvt h0, s0
1656; CHECK-CVT-NEXT:    ret
1657;
1658; CHECK-FP16-LABEL: test_ceil:
1659; CHECK-FP16:       // %bb.0:
1660; CHECK-FP16-NEXT:    frintp h0, h0
1661; CHECK-FP16-NEXT:    ret
1662  %r = call half @llvm.ceil.f16(half %a)
1663  ret half %r
1664}
1665
1666define half @test_trunc(half %a) #0 {
1667; CHECK-CVT-LABEL: test_trunc:
1668; CHECK-CVT:       // %bb.0:
1669; CHECK-CVT-NEXT:    fcvt s0, h0
1670; CHECK-CVT-NEXT:    frintz s0, s0
1671; CHECK-CVT-NEXT:    fcvt h0, s0
1672; CHECK-CVT-NEXT:    ret
1673;
1674; CHECK-FP16-LABEL: test_trunc:
1675; CHECK-FP16:       // %bb.0:
1676; CHECK-FP16-NEXT:    frintz h0, h0
1677; CHECK-FP16-NEXT:    ret
1678  %r = call half @llvm.trunc.f16(half %a)
1679  ret half %r
1680}
1681
1682define half @test_rint(half %a) #0 {
1683; CHECK-CVT-LABEL: test_rint:
1684; CHECK-CVT:       // %bb.0:
1685; CHECK-CVT-NEXT:    fcvt s0, h0
1686; CHECK-CVT-NEXT:    frintx s0, s0
1687; CHECK-CVT-NEXT:    fcvt h0, s0
1688; CHECK-CVT-NEXT:    ret
1689;
1690; CHECK-FP16-LABEL: test_rint:
1691; CHECK-FP16:       // %bb.0:
1692; CHECK-FP16-NEXT:    frintx h0, h0
1693; CHECK-FP16-NEXT:    ret
1694  %r = call half @llvm.rint.f16(half %a)
1695  ret half %r
1696}
1697
1698define half @test_nearbyint(half %a) #0 {
1699; CHECK-CVT-LABEL: test_nearbyint:
1700; CHECK-CVT:       // %bb.0:
1701; CHECK-CVT-NEXT:    fcvt s0, h0
1702; CHECK-CVT-NEXT:    frinti s0, s0
1703; CHECK-CVT-NEXT:    fcvt h0, s0
1704; CHECK-CVT-NEXT:    ret
1705;
1706; CHECK-FP16-LABEL: test_nearbyint:
1707; CHECK-FP16:       // %bb.0:
1708; CHECK-FP16-NEXT:    frinti h0, h0
1709; CHECK-FP16-NEXT:    ret
1710  %r = call half @llvm.nearbyint.f16(half %a)
1711  ret half %r
1712}
1713
1714define half @test_round(half %a) #0 {
1715; CHECK-CVT-LABEL: test_round:
1716; CHECK-CVT:       // %bb.0:
1717; CHECK-CVT-NEXT:    fcvt s0, h0
1718; CHECK-CVT-NEXT:    frinta s0, s0
1719; CHECK-CVT-NEXT:    fcvt h0, s0
1720; CHECK-CVT-NEXT:    ret
1721;
1722; CHECK-FP16-LABEL: test_round:
1723; CHECK-FP16:       // %bb.0:
1724; CHECK-FP16-NEXT:    frinta h0, h0
1725; CHECK-FP16-NEXT:    ret
1726  %r = call half @llvm.round.f16(half %a)
1727  ret half %r
1728}
1729
1730define half @test_roundeven(half %a) #0 {
1731; CHECK-CVT-LABEL: test_roundeven:
1732; CHECK-CVT:       // %bb.0:
1733; CHECK-CVT-NEXT:    fcvt s0, h0
1734; CHECK-CVT-NEXT:    frintn s0, s0
1735; CHECK-CVT-NEXT:    fcvt h0, s0
1736; CHECK-CVT-NEXT:    ret
1737;
1738; CHECK-FP16-LABEL: test_roundeven:
1739; CHECK-FP16:       // %bb.0:
1740; CHECK-FP16-NEXT:    frintn h0, h0
1741; CHECK-FP16-NEXT:    ret
1742  %r = call half @llvm.roundeven.f16(half %a)
1743  ret half %r
1744}
1745
1746define half @test_fmuladd(half %a, half %b, half %c) #0 {
1747; CHECK-CVT-SD-LABEL: test_fmuladd:
1748; CHECK-CVT-SD:       // %bb.0:
1749; CHECK-CVT-SD-NEXT:    fcvt s1, h1
1750; CHECK-CVT-SD-NEXT:    fcvt s0, h0
1751; CHECK-CVT-SD-NEXT:    fmul s0, s0, s1
1752; CHECK-CVT-SD-NEXT:    fcvt s1, h2
1753; CHECK-CVT-SD-NEXT:    fcvt h0, s0
1754; CHECK-CVT-SD-NEXT:    fcvt s0, h0
1755; CHECK-CVT-SD-NEXT:    fadd s0, s0, s1
1756; CHECK-CVT-SD-NEXT:    fcvt h0, s0
1757; CHECK-CVT-SD-NEXT:    ret
1758;
1759; CHECK-FP16-LABEL: test_fmuladd:
1760; CHECK-FP16:       // %bb.0:
1761; CHECK-FP16-NEXT:    fmadd h0, h0, h1, h2
1762; CHECK-FP16-NEXT:    ret
1763;
1764; CHECK-CVT-GI-LABEL: test_fmuladd:
1765; CHECK-CVT-GI:       // %bb.0:
1766; CHECK-CVT-GI-NEXT:    fcvt s0, h0
1767; CHECK-CVT-GI-NEXT:    fcvt s1, h1
1768; CHECK-CVT-GI-NEXT:    fmul s0, s0, s1
1769; CHECK-CVT-GI-NEXT:    fcvt s1, h2
1770; CHECK-CVT-GI-NEXT:    fcvt h0, s0
1771; CHECK-CVT-GI-NEXT:    fcvt s0, h0
1772; CHECK-CVT-GI-NEXT:    fadd s0, s0, s1
1773; CHECK-CVT-GI-NEXT:    fcvt h0, s0
1774; CHECK-CVT-GI-NEXT:    ret
1775  %r = call half @llvm.fmuladd.f16(half %a, half %b, half %c)
1776  ret half %r
1777}
1778
1779attributes #0 = { nounwind }
1780