xref: /llvm-project/llvm/test/CodeGen/RISCV/half-arith.ll (revision 9122c5235ec85ce0c0ad337e862b006e7b349d84)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple=riscv32 -mattr=+zfh -verify-machineinstrs \
3; RUN:   -target-abi ilp32f < %s | FileCheck -check-prefix=CHECKIZFH %s
4; RUN: llc -mtriple=riscv64 -mattr=+zfh -verify-machineinstrs \
5; RUN:   -target-abi lp64f < %s | FileCheck -check-prefix=CHECKIZFH %s
6; RUN: llc -mtriple=riscv32 -mattr=+zhinx -verify-machineinstrs \
7; RUN:   -target-abi ilp32 < %s | FileCheck -check-prefix=CHECKIZHINX %s
8; RUN: llc -mtriple=riscv64 -mattr=+zhinx -verify-machineinstrs \
9; RUN:   -target-abi lp64 < %s | FileCheck -check-prefix=CHECKIZHINX %s
10; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
11; RUN:   | FileCheck -check-prefix=RV32I %s
12; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
13; RUN:   | FileCheck -check-prefix=RV64I %s
14; RUN: llc -mtriple=riscv32 -mattr=+zfhmin -verify-machineinstrs \
15; RUN:   -target-abi ilp32f < %s | FileCheck -check-prefixes=CHECKIZFHMIN,RV32IZFHMIN %s
16; RUN: llc -mtriple=riscv64 -mattr=+zfhmin -verify-machineinstrs \
17; RUN:   -target-abi lp64f < %s | FileCheck --check-prefixes=CHECKIZFHMIN,RV64IZFHMIN %s
18; RUN: llc -mtriple=riscv32 -mattr=+zhinxmin -verify-machineinstrs \
19; RUN:   -target-abi ilp32 < %s | FileCheck --check-prefixes=CHECKIZHINXMIN,RV32IZHINXMIN %s
20; RUN: llc -mtriple=riscv64 -mattr=+zhinxmin -verify-machineinstrs \
21; RUN:   -target-abi lp64 < %s | FileCheck --check-prefixes=CHECKIZHINXMIN,RV64IZHINXMIN %s
22
23; These tests are each targeted at a particular RISC-V FPU instruction.
24; Compares and conversions can be found in half-fcmp.ll and half-convert.ll
25; respectively. Some other half-*.ll files in this folder exercise LLVM IR
26; instructions that don't directly match a RISC-V instruction.
27
28define half @fadd_h(half %a, half %b) nounwind {
29; CHECKIZFH-LABEL: fadd_h:
30; CHECKIZFH:       # %bb.0:
31; CHECKIZFH-NEXT:    fadd.h fa0, fa0, fa1
32; CHECKIZFH-NEXT:    ret
33;
34; CHECKIZHINX-LABEL: fadd_h:
35; CHECKIZHINX:       # %bb.0:
36; CHECKIZHINX-NEXT:    fadd.h a0, a0, a1
37; CHECKIZHINX-NEXT:    ret
38;
39; RV32I-LABEL: fadd_h:
40; RV32I:       # %bb.0:
41; RV32I-NEXT:    addi sp, sp, -16
42; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
43; RV32I-NEXT:    sw s0, 8(sp) # 4-byte Folded Spill
44; RV32I-NEXT:    sw s1, 4(sp) # 4-byte Folded Spill
45; RV32I-NEXT:    sw s2, 0(sp) # 4-byte Folded Spill
46; RV32I-NEXT:    mv s0, a1
47; RV32I-NEXT:    lui a1, 16
48; RV32I-NEXT:    addi s2, a1, -1
49; RV32I-NEXT:    and a0, a0, s2
50; RV32I-NEXT:    call __extendhfsf2
51; RV32I-NEXT:    mv s1, a0
52; RV32I-NEXT:    and a0, s0, s2
53; RV32I-NEXT:    call __extendhfsf2
54; RV32I-NEXT:    mv a1, a0
55; RV32I-NEXT:    mv a0, s1
56; RV32I-NEXT:    call __addsf3
57; RV32I-NEXT:    call __truncsfhf2
58; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
59; RV32I-NEXT:    lw s0, 8(sp) # 4-byte Folded Reload
60; RV32I-NEXT:    lw s1, 4(sp) # 4-byte Folded Reload
61; RV32I-NEXT:    lw s2, 0(sp) # 4-byte Folded Reload
62; RV32I-NEXT:    addi sp, sp, 16
63; RV32I-NEXT:    ret
64;
65; RV64I-LABEL: fadd_h:
66; RV64I:       # %bb.0:
67; RV64I-NEXT:    addi sp, sp, -32
68; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
69; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
70; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
71; RV64I-NEXT:    sd s2, 0(sp) # 8-byte Folded Spill
72; RV64I-NEXT:    mv s0, a1
73; RV64I-NEXT:    lui a1, 16
74; RV64I-NEXT:    addiw s2, a1, -1
75; RV64I-NEXT:    and a0, a0, s2
76; RV64I-NEXT:    call __extendhfsf2
77; RV64I-NEXT:    mv s1, a0
78; RV64I-NEXT:    and a0, s0, s2
79; RV64I-NEXT:    call __extendhfsf2
80; RV64I-NEXT:    mv a1, a0
81; RV64I-NEXT:    mv a0, s1
82; RV64I-NEXT:    call __addsf3
83; RV64I-NEXT:    call __truncsfhf2
84; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
85; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
86; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
87; RV64I-NEXT:    ld s2, 0(sp) # 8-byte Folded Reload
88; RV64I-NEXT:    addi sp, sp, 32
89; RV64I-NEXT:    ret
90;
91; CHECKIZFHMIN-LABEL: fadd_h:
92; CHECKIZFHMIN:       # %bb.0:
93; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa1
94; CHECKIZFHMIN-NEXT:    fcvt.s.h fa4, fa0
95; CHECKIZFHMIN-NEXT:    fadd.s fa5, fa4, fa5
96; CHECKIZFHMIN-NEXT:    fcvt.h.s fa0, fa5
97; CHECKIZFHMIN-NEXT:    ret
98;
99; CHECKIZHINXMIN-LABEL: fadd_h:
100; CHECKIZHINXMIN:       # %bb.0:
101; CHECKIZHINXMIN-NEXT:    fcvt.s.h a1, a1
102; CHECKIZHINXMIN-NEXT:    fcvt.s.h a0, a0
103; CHECKIZHINXMIN-NEXT:    fadd.s a0, a0, a1
104; CHECKIZHINXMIN-NEXT:    fcvt.h.s a0, a0
105; CHECKIZHINXMIN-NEXT:    ret
106  %1 = fadd half %a, %b
107  ret half %1
108}
109
110define half @fsub_h(half %a, half %b) nounwind {
111; CHECKIZFH-LABEL: fsub_h:
112; CHECKIZFH:       # %bb.0:
113; CHECKIZFH-NEXT:    fsub.h fa0, fa0, fa1
114; CHECKIZFH-NEXT:    ret
115;
116; CHECKIZHINX-LABEL: fsub_h:
117; CHECKIZHINX:       # %bb.0:
118; CHECKIZHINX-NEXT:    fsub.h a0, a0, a1
119; CHECKIZHINX-NEXT:    ret
120;
121; RV32I-LABEL: fsub_h:
122; RV32I:       # %bb.0:
123; RV32I-NEXT:    addi sp, sp, -16
124; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
125; RV32I-NEXT:    sw s0, 8(sp) # 4-byte Folded Spill
126; RV32I-NEXT:    sw s1, 4(sp) # 4-byte Folded Spill
127; RV32I-NEXT:    sw s2, 0(sp) # 4-byte Folded Spill
128; RV32I-NEXT:    mv s0, a1
129; RV32I-NEXT:    lui a1, 16
130; RV32I-NEXT:    addi s2, a1, -1
131; RV32I-NEXT:    and a0, a0, s2
132; RV32I-NEXT:    call __extendhfsf2
133; RV32I-NEXT:    mv s1, a0
134; RV32I-NEXT:    and a0, s0, s2
135; RV32I-NEXT:    call __extendhfsf2
136; RV32I-NEXT:    mv a1, a0
137; RV32I-NEXT:    mv a0, s1
138; RV32I-NEXT:    call __subsf3
139; RV32I-NEXT:    call __truncsfhf2
140; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
141; RV32I-NEXT:    lw s0, 8(sp) # 4-byte Folded Reload
142; RV32I-NEXT:    lw s1, 4(sp) # 4-byte Folded Reload
143; RV32I-NEXT:    lw s2, 0(sp) # 4-byte Folded Reload
144; RV32I-NEXT:    addi sp, sp, 16
145; RV32I-NEXT:    ret
146;
147; RV64I-LABEL: fsub_h:
148; RV64I:       # %bb.0:
149; RV64I-NEXT:    addi sp, sp, -32
150; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
151; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
152; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
153; RV64I-NEXT:    sd s2, 0(sp) # 8-byte Folded Spill
154; RV64I-NEXT:    mv s0, a1
155; RV64I-NEXT:    lui a1, 16
156; RV64I-NEXT:    addiw s2, a1, -1
157; RV64I-NEXT:    and a0, a0, s2
158; RV64I-NEXT:    call __extendhfsf2
159; RV64I-NEXT:    mv s1, a0
160; RV64I-NEXT:    and a0, s0, s2
161; RV64I-NEXT:    call __extendhfsf2
162; RV64I-NEXT:    mv a1, a0
163; RV64I-NEXT:    mv a0, s1
164; RV64I-NEXT:    call __subsf3
165; RV64I-NEXT:    call __truncsfhf2
166; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
167; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
168; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
169; RV64I-NEXT:    ld s2, 0(sp) # 8-byte Folded Reload
170; RV64I-NEXT:    addi sp, sp, 32
171; RV64I-NEXT:    ret
172;
173; CHECKIZFHMIN-LABEL: fsub_h:
174; CHECKIZFHMIN:       # %bb.0:
175; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa1
176; CHECKIZFHMIN-NEXT:    fcvt.s.h fa4, fa0
177; CHECKIZFHMIN-NEXT:    fsub.s fa5, fa4, fa5
178; CHECKIZFHMIN-NEXT:    fcvt.h.s fa0, fa5
179; CHECKIZFHMIN-NEXT:    ret
180;
181; CHECKIZHINXMIN-LABEL: fsub_h:
182; CHECKIZHINXMIN:       # %bb.0:
183; CHECKIZHINXMIN-NEXT:    fcvt.s.h a1, a1
184; CHECKIZHINXMIN-NEXT:    fcvt.s.h a0, a0
185; CHECKIZHINXMIN-NEXT:    fsub.s a0, a0, a1
186; CHECKIZHINXMIN-NEXT:    fcvt.h.s a0, a0
187; CHECKIZHINXMIN-NEXT:    ret
188  %1 = fsub half %a, %b
189  ret half %1
190}
191
192define half @fmul_h(half %a, half %b) nounwind {
193; CHECKIZFH-LABEL: fmul_h:
194; CHECKIZFH:       # %bb.0:
195; CHECKIZFH-NEXT:    fmul.h fa0, fa0, fa1
196; CHECKIZFH-NEXT:    ret
197;
198; CHECKIZHINX-LABEL: fmul_h:
199; CHECKIZHINX:       # %bb.0:
200; CHECKIZHINX-NEXT:    fmul.h a0, a0, a1
201; CHECKIZHINX-NEXT:    ret
202;
203; RV32I-LABEL: fmul_h:
204; RV32I:       # %bb.0:
205; RV32I-NEXT:    addi sp, sp, -16
206; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
207; RV32I-NEXT:    sw s0, 8(sp) # 4-byte Folded Spill
208; RV32I-NEXT:    sw s1, 4(sp) # 4-byte Folded Spill
209; RV32I-NEXT:    sw s2, 0(sp) # 4-byte Folded Spill
210; RV32I-NEXT:    mv s0, a1
211; RV32I-NEXT:    lui a1, 16
212; RV32I-NEXT:    addi s2, a1, -1
213; RV32I-NEXT:    and a0, a0, s2
214; RV32I-NEXT:    call __extendhfsf2
215; RV32I-NEXT:    mv s1, a0
216; RV32I-NEXT:    and a0, s0, s2
217; RV32I-NEXT:    call __extendhfsf2
218; RV32I-NEXT:    mv a1, a0
219; RV32I-NEXT:    mv a0, s1
220; RV32I-NEXT:    call __mulsf3
221; RV32I-NEXT:    call __truncsfhf2
222; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
223; RV32I-NEXT:    lw s0, 8(sp) # 4-byte Folded Reload
224; RV32I-NEXT:    lw s1, 4(sp) # 4-byte Folded Reload
225; RV32I-NEXT:    lw s2, 0(sp) # 4-byte Folded Reload
226; RV32I-NEXT:    addi sp, sp, 16
227; RV32I-NEXT:    ret
228;
229; RV64I-LABEL: fmul_h:
230; RV64I:       # %bb.0:
231; RV64I-NEXT:    addi sp, sp, -32
232; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
233; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
234; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
235; RV64I-NEXT:    sd s2, 0(sp) # 8-byte Folded Spill
236; RV64I-NEXT:    mv s0, a1
237; RV64I-NEXT:    lui a1, 16
238; RV64I-NEXT:    addiw s2, a1, -1
239; RV64I-NEXT:    and a0, a0, s2
240; RV64I-NEXT:    call __extendhfsf2
241; RV64I-NEXT:    mv s1, a0
242; RV64I-NEXT:    and a0, s0, s2
243; RV64I-NEXT:    call __extendhfsf2
244; RV64I-NEXT:    mv a1, a0
245; RV64I-NEXT:    mv a0, s1
246; RV64I-NEXT:    call __mulsf3
247; RV64I-NEXT:    call __truncsfhf2
248; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
249; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
250; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
251; RV64I-NEXT:    ld s2, 0(sp) # 8-byte Folded Reload
252; RV64I-NEXT:    addi sp, sp, 32
253; RV64I-NEXT:    ret
254;
255; CHECKIZFHMIN-LABEL: fmul_h:
256; CHECKIZFHMIN:       # %bb.0:
257; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa1
258; CHECKIZFHMIN-NEXT:    fcvt.s.h fa4, fa0
259; CHECKIZFHMIN-NEXT:    fmul.s fa5, fa4, fa5
260; CHECKIZFHMIN-NEXT:    fcvt.h.s fa0, fa5
261; CHECKIZFHMIN-NEXT:    ret
262;
263; CHECKIZHINXMIN-LABEL: fmul_h:
264; CHECKIZHINXMIN:       # %bb.0:
265; CHECKIZHINXMIN-NEXT:    fcvt.s.h a1, a1
266; CHECKIZHINXMIN-NEXT:    fcvt.s.h a0, a0
267; CHECKIZHINXMIN-NEXT:    fmul.s a0, a0, a1
268; CHECKIZHINXMIN-NEXT:    fcvt.h.s a0, a0
269; CHECKIZHINXMIN-NEXT:    ret
270  %1 = fmul half %a, %b
271  ret half %1
272}
273
274define half @fdiv_h(half %a, half %b) nounwind {
275; CHECKIZFH-LABEL: fdiv_h:
276; CHECKIZFH:       # %bb.0:
277; CHECKIZFH-NEXT:    fdiv.h fa0, fa0, fa1
278; CHECKIZFH-NEXT:    ret
279;
280; CHECKIZHINX-LABEL: fdiv_h:
281; CHECKIZHINX:       # %bb.0:
282; CHECKIZHINX-NEXT:    fdiv.h a0, a0, a1
283; CHECKIZHINX-NEXT:    ret
284;
285; RV32I-LABEL: fdiv_h:
286; RV32I:       # %bb.0:
287; RV32I-NEXT:    addi sp, sp, -16
288; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
289; RV32I-NEXT:    sw s0, 8(sp) # 4-byte Folded Spill
290; RV32I-NEXT:    sw s1, 4(sp) # 4-byte Folded Spill
291; RV32I-NEXT:    sw s2, 0(sp) # 4-byte Folded Spill
292; RV32I-NEXT:    mv s0, a1
293; RV32I-NEXT:    lui a1, 16
294; RV32I-NEXT:    addi s2, a1, -1
295; RV32I-NEXT:    and a0, a0, s2
296; RV32I-NEXT:    call __extendhfsf2
297; RV32I-NEXT:    mv s1, a0
298; RV32I-NEXT:    and a0, s0, s2
299; RV32I-NEXT:    call __extendhfsf2
300; RV32I-NEXT:    mv a1, a0
301; RV32I-NEXT:    mv a0, s1
302; RV32I-NEXT:    call __divsf3
303; RV32I-NEXT:    call __truncsfhf2
304; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
305; RV32I-NEXT:    lw s0, 8(sp) # 4-byte Folded Reload
306; RV32I-NEXT:    lw s1, 4(sp) # 4-byte Folded Reload
307; RV32I-NEXT:    lw s2, 0(sp) # 4-byte Folded Reload
308; RV32I-NEXT:    addi sp, sp, 16
309; RV32I-NEXT:    ret
310;
311; RV64I-LABEL: fdiv_h:
312; RV64I:       # %bb.0:
313; RV64I-NEXT:    addi sp, sp, -32
314; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
315; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
316; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
317; RV64I-NEXT:    sd s2, 0(sp) # 8-byte Folded Spill
318; RV64I-NEXT:    mv s0, a1
319; RV64I-NEXT:    lui a1, 16
320; RV64I-NEXT:    addiw s2, a1, -1
321; RV64I-NEXT:    and a0, a0, s2
322; RV64I-NEXT:    call __extendhfsf2
323; RV64I-NEXT:    mv s1, a0
324; RV64I-NEXT:    and a0, s0, s2
325; RV64I-NEXT:    call __extendhfsf2
326; RV64I-NEXT:    mv a1, a0
327; RV64I-NEXT:    mv a0, s1
328; RV64I-NEXT:    call __divsf3
329; RV64I-NEXT:    call __truncsfhf2
330; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
331; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
332; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
333; RV64I-NEXT:    ld s2, 0(sp) # 8-byte Folded Reload
334; RV64I-NEXT:    addi sp, sp, 32
335; RV64I-NEXT:    ret
336;
337; CHECKIZFHMIN-LABEL: fdiv_h:
338; CHECKIZFHMIN:       # %bb.0:
339; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa1
340; CHECKIZFHMIN-NEXT:    fcvt.s.h fa4, fa0
341; CHECKIZFHMIN-NEXT:    fdiv.s fa5, fa4, fa5
342; CHECKIZFHMIN-NEXT:    fcvt.h.s fa0, fa5
343; CHECKIZFHMIN-NEXT:    ret
344;
345; CHECKIZHINXMIN-LABEL: fdiv_h:
346; CHECKIZHINXMIN:       # %bb.0:
347; CHECKIZHINXMIN-NEXT:    fcvt.s.h a1, a1
348; CHECKIZHINXMIN-NEXT:    fcvt.s.h a0, a0
349; CHECKIZHINXMIN-NEXT:    fdiv.s a0, a0, a1
350; CHECKIZHINXMIN-NEXT:    fcvt.h.s a0, a0
351; CHECKIZHINXMIN-NEXT:    ret
352  %1 = fdiv half %a, %b
353  ret half %1
354}
355
356declare half @llvm.sqrt.f16(half)
357
358define half @fsqrt_h(half %a) nounwind {
359; CHECKIZFH-LABEL: fsqrt_h:
360; CHECKIZFH:       # %bb.0:
361; CHECKIZFH-NEXT:    fsqrt.h fa0, fa0
362; CHECKIZFH-NEXT:    ret
363;
364; CHECKIZHINX-LABEL: fsqrt_h:
365; CHECKIZHINX:       # %bb.0:
366; CHECKIZHINX-NEXT:    fsqrt.h a0, a0
367; CHECKIZHINX-NEXT:    ret
368;
369; RV32I-LABEL: fsqrt_h:
370; RV32I:       # %bb.0:
371; RV32I-NEXT:    addi sp, sp, -16
372; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
373; RV32I-NEXT:    slli a0, a0, 16
374; RV32I-NEXT:    srli a0, a0, 16
375; RV32I-NEXT:    call __extendhfsf2
376; RV32I-NEXT:    call sqrtf
377; RV32I-NEXT:    call __truncsfhf2
378; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
379; RV32I-NEXT:    addi sp, sp, 16
380; RV32I-NEXT:    ret
381;
382; RV64I-LABEL: fsqrt_h:
383; RV64I:       # %bb.0:
384; RV64I-NEXT:    addi sp, sp, -16
385; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
386; RV64I-NEXT:    slli a0, a0, 48
387; RV64I-NEXT:    srli a0, a0, 48
388; RV64I-NEXT:    call __extendhfsf2
389; RV64I-NEXT:    call sqrtf
390; RV64I-NEXT:    call __truncsfhf2
391; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
392; RV64I-NEXT:    addi sp, sp, 16
393; RV64I-NEXT:    ret
394;
395; CHECKIZFHMIN-LABEL: fsqrt_h:
396; CHECKIZFHMIN:       # %bb.0:
397; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa0
398; CHECKIZFHMIN-NEXT:    fsqrt.s fa5, fa5
399; CHECKIZFHMIN-NEXT:    fcvt.h.s fa0, fa5
400; CHECKIZFHMIN-NEXT:    ret
401;
402; CHECKIZHINXMIN-LABEL: fsqrt_h:
403; CHECKIZHINXMIN:       # %bb.0:
404; CHECKIZHINXMIN-NEXT:    fcvt.s.h a0, a0
405; CHECKIZHINXMIN-NEXT:    fsqrt.s a0, a0
406; CHECKIZHINXMIN-NEXT:    fcvt.h.s a0, a0
407; CHECKIZHINXMIN-NEXT:    ret
408  %1 = call half @llvm.sqrt.f16(half %a)
409  ret half %1
410}
411
412declare half @llvm.copysign.f16(half, half)
413
414define half @fsgnj_h(half %a, half %b) nounwind {
415; CHECKIZFH-LABEL: fsgnj_h:
416; CHECKIZFH:       # %bb.0:
417; CHECKIZFH-NEXT:    fsgnj.h fa0, fa0, fa1
418; CHECKIZFH-NEXT:    ret
419;
420; CHECKIZHINX-LABEL: fsgnj_h:
421; CHECKIZHINX:       # %bb.0:
422; CHECKIZHINX-NEXT:    fsgnj.h a0, a0, a1
423; CHECKIZHINX-NEXT:    ret
424;
425; RV32I-LABEL: fsgnj_h:
426; RV32I:       # %bb.0:
427; RV32I-NEXT:    lui a2, 1048568
428; RV32I-NEXT:    slli a0, a0, 17
429; RV32I-NEXT:    and a1, a1, a2
430; RV32I-NEXT:    srli a0, a0, 17
431; RV32I-NEXT:    or a0, a0, a1
432; RV32I-NEXT:    ret
433;
434; RV64I-LABEL: fsgnj_h:
435; RV64I:       # %bb.0:
436; RV64I-NEXT:    lui a2, 1048568
437; RV64I-NEXT:    slli a0, a0, 49
438; RV64I-NEXT:    and a1, a1, a2
439; RV64I-NEXT:    srli a0, a0, 49
440; RV64I-NEXT:    or a0, a0, a1
441; RV64I-NEXT:    ret
442;
443; RV32IZFHMIN-LABEL: fsgnj_h:
444; RV32IZFHMIN:       # %bb.0:
445; RV32IZFHMIN-NEXT:    fmv.x.h a0, fa1
446; RV32IZFHMIN-NEXT:    lui a1, 1048568
447; RV32IZFHMIN-NEXT:    and a0, a0, a1
448; RV32IZFHMIN-NEXT:    fmv.x.h a1, fa0
449; RV32IZFHMIN-NEXT:    slli a1, a1, 17
450; RV32IZFHMIN-NEXT:    srli a1, a1, 17
451; RV32IZFHMIN-NEXT:    or a0, a1, a0
452; RV32IZFHMIN-NEXT:    fmv.h.x fa0, a0
453; RV32IZFHMIN-NEXT:    ret
454;
455; RV64IZFHMIN-LABEL: fsgnj_h:
456; RV64IZFHMIN:       # %bb.0:
457; RV64IZFHMIN-NEXT:    fmv.x.h a0, fa1
458; RV64IZFHMIN-NEXT:    lui a1, 1048568
459; RV64IZFHMIN-NEXT:    and a0, a0, a1
460; RV64IZFHMIN-NEXT:    fmv.x.h a1, fa0
461; RV64IZFHMIN-NEXT:    slli a1, a1, 49
462; RV64IZFHMIN-NEXT:    srli a1, a1, 49
463; RV64IZFHMIN-NEXT:    or a0, a1, a0
464; RV64IZFHMIN-NEXT:    fmv.h.x fa0, a0
465; RV64IZFHMIN-NEXT:    ret
466;
467; RV32IZHINXMIN-LABEL: fsgnj_h:
468; RV32IZHINXMIN:       # %bb.0:
469; RV32IZHINXMIN-NEXT:    # kill: def $x11_h killed $x11_h def $x11
470; RV32IZHINXMIN-NEXT:    # kill: def $x10_h killed $x10_h def $x10
471; RV32IZHINXMIN-NEXT:    lui a2, 1048568
472; RV32IZHINXMIN-NEXT:    slli a0, a0, 17
473; RV32IZHINXMIN-NEXT:    and a1, a1, a2
474; RV32IZHINXMIN-NEXT:    srli a0, a0, 17
475; RV32IZHINXMIN-NEXT:    or a0, a0, a1
476; RV32IZHINXMIN-NEXT:    # kill: def $x10_h killed $x10_h killed $x10
477; RV32IZHINXMIN-NEXT:    ret
478;
479; RV64IZHINXMIN-LABEL: fsgnj_h:
480; RV64IZHINXMIN:       # %bb.0:
481; RV64IZHINXMIN-NEXT:    # kill: def $x11_h killed $x11_h def $x11
482; RV64IZHINXMIN-NEXT:    # kill: def $x10_h killed $x10_h def $x10
483; RV64IZHINXMIN-NEXT:    lui a2, 1048568
484; RV64IZHINXMIN-NEXT:    slli a0, a0, 49
485; RV64IZHINXMIN-NEXT:    and a1, a1, a2
486; RV64IZHINXMIN-NEXT:    srli a0, a0, 49
487; RV64IZHINXMIN-NEXT:    or a0, a0, a1
488; RV64IZHINXMIN-NEXT:    # kill: def $x10_h killed $x10_h killed $x10
489; RV64IZHINXMIN-NEXT:    ret
490  %1 = call half @llvm.copysign.f16(half %a, half %b)
491  ret half %1
492}
493
494; This function performs extra work to ensure that
495; DAGCombiner::visitBITCAST doesn't replace the fneg with an xor.
496define i32 @fneg_h(half %a, half %b) nounwind {
497; CHECKIZFH-LABEL: fneg_h:
498; CHECKIZFH:       # %bb.0:
499; CHECKIZFH-NEXT:    fadd.h fa5, fa0, fa0
500; CHECKIZFH-NEXT:    fneg.h fa4, fa5
501; CHECKIZFH-NEXT:    feq.h a0, fa5, fa4
502; CHECKIZFH-NEXT:    ret
503;
504; CHECKIZHINX-LABEL: fneg_h:
505; CHECKIZHINX:       # %bb.0:
506; CHECKIZHINX-NEXT:    fadd.h a0, a0, a0
507; CHECKIZHINX-NEXT:    fneg.h a1, a0
508; CHECKIZHINX-NEXT:    feq.h a0, a0, a1
509; CHECKIZHINX-NEXT:    ret
510;
511; RV32I-LABEL: fneg_h:
512; RV32I:       # %bb.0:
513; RV32I-NEXT:    addi sp, sp, -16
514; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
515; RV32I-NEXT:    sw s0, 8(sp) # 4-byte Folded Spill
516; RV32I-NEXT:    sw s1, 4(sp) # 4-byte Folded Spill
517; RV32I-NEXT:    lui a1, 16
518; RV32I-NEXT:    addi s1, a1, -1
519; RV32I-NEXT:    and a0, a0, s1
520; RV32I-NEXT:    call __extendhfsf2
521; RV32I-NEXT:    mv a1, a0
522; RV32I-NEXT:    call __addsf3
523; RV32I-NEXT:    call __truncsfhf2
524; RV32I-NEXT:    and a0, a0, s1
525; RV32I-NEXT:    call __extendhfsf2
526; RV32I-NEXT:    mv s0, a0
527; RV32I-NEXT:    lui a0, 524288
528; RV32I-NEXT:    xor a0, s0, a0
529; RV32I-NEXT:    call __truncsfhf2
530; RV32I-NEXT:    and a0, a0, s1
531; RV32I-NEXT:    call __extendhfsf2
532; RV32I-NEXT:    mv a1, a0
533; RV32I-NEXT:    mv a0, s0
534; RV32I-NEXT:    call __eqsf2
535; RV32I-NEXT:    seqz a0, a0
536; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
537; RV32I-NEXT:    lw s0, 8(sp) # 4-byte Folded Reload
538; RV32I-NEXT:    lw s1, 4(sp) # 4-byte Folded Reload
539; RV32I-NEXT:    addi sp, sp, 16
540; RV32I-NEXT:    ret
541;
542; RV64I-LABEL: fneg_h:
543; RV64I:       # %bb.0:
544; RV64I-NEXT:    addi sp, sp, -32
545; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
546; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
547; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
548; RV64I-NEXT:    lui a1, 16
549; RV64I-NEXT:    addiw s1, a1, -1
550; RV64I-NEXT:    and a0, a0, s1
551; RV64I-NEXT:    call __extendhfsf2
552; RV64I-NEXT:    mv a1, a0
553; RV64I-NEXT:    call __addsf3
554; RV64I-NEXT:    call __truncsfhf2
555; RV64I-NEXT:    and a0, a0, s1
556; RV64I-NEXT:    call __extendhfsf2
557; RV64I-NEXT:    mv s0, a0
558; RV64I-NEXT:    lui a0, 524288
559; RV64I-NEXT:    xor a0, s0, a0
560; RV64I-NEXT:    call __truncsfhf2
561; RV64I-NEXT:    and a0, a0, s1
562; RV64I-NEXT:    call __extendhfsf2
563; RV64I-NEXT:    mv a1, a0
564; RV64I-NEXT:    mv a0, s0
565; RV64I-NEXT:    call __eqsf2
566; RV64I-NEXT:    seqz a0, a0
567; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
568; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
569; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
570; RV64I-NEXT:    addi sp, sp, 32
571; RV64I-NEXT:    ret
572;
573; CHECKIZFHMIN-LABEL: fneg_h:
574; CHECKIZFHMIN:       # %bb.0:
575; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa0
576; CHECKIZFHMIN-NEXT:    lui a0, 1048568
577; CHECKIZFHMIN-NEXT:    fadd.s fa5, fa5, fa5
578; CHECKIZFHMIN-NEXT:    fcvt.h.s fa5, fa5
579; CHECKIZFHMIN-NEXT:    fmv.x.h a1, fa5
580; CHECKIZFHMIN-NEXT:    xor a0, a1, a0
581; CHECKIZFHMIN-NEXT:    fmv.h.x fa4, a0
582; CHECKIZFHMIN-NEXT:    fcvt.s.h fa4, fa4
583; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa5
584; CHECKIZFHMIN-NEXT:    feq.s a0, fa5, fa4
585; CHECKIZFHMIN-NEXT:    ret
586;
587; CHECKIZHINXMIN-LABEL: fneg_h:
588; CHECKIZHINXMIN:       # %bb.0:
589; CHECKIZHINXMIN-NEXT:    fcvt.s.h a0, a0
590; CHECKIZHINXMIN-NEXT:    lui a1, 1048568
591; CHECKIZHINXMIN-NEXT:    fadd.s a0, a0, a0
592; CHECKIZHINXMIN-NEXT:    fcvt.h.s a0, a0
593; CHECKIZHINXMIN-NEXT:    xor a1, a0, a1
594; CHECKIZHINXMIN-NEXT:    fcvt.s.h a1, a1
595; CHECKIZHINXMIN-NEXT:    fcvt.s.h a0, a0
596; CHECKIZHINXMIN-NEXT:    feq.s a0, a0, a1
597; CHECKIZHINXMIN-NEXT:    ret
598  %1 = fadd half %a, %a
599  %2 = fneg half %1
600  %3 = fcmp oeq half %1, %2
601  %4 = zext i1 %3 to i32
602  ret i32 %4
603}
604
605; This function performs extra work to ensure that
606; DAGCombiner::visitBITCAST doesn't replace the fneg with an xor.
607define half @fsgnjn_h(half %a, half %b) nounwind {
608; CHECKIZFH-LABEL: fsgnjn_h:
609; CHECKIZFH:       # %bb.0:
610; CHECKIZFH-NEXT:    fadd.h fa5, fa0, fa1
611; CHECKIZFH-NEXT:    fsgnjn.h fa0, fa0, fa5
612; CHECKIZFH-NEXT:    ret
613;
614; CHECKIZHINX-LABEL: fsgnjn_h:
615; CHECKIZHINX:       # %bb.0:
616; CHECKIZHINX-NEXT:    fadd.h a1, a0, a1
617; CHECKIZHINX-NEXT:    fsgnjn.h a0, a0, a1
618; CHECKIZHINX-NEXT:    ret
619;
620; RV32I-LABEL: fsgnjn_h:
621; RV32I:       # %bb.0:
622; RV32I-NEXT:    addi sp, sp, -32
623; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
624; RV32I-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
625; RV32I-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
626; RV32I-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
627; RV32I-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
628; RV32I-NEXT:    mv s0, a1
629; RV32I-NEXT:    mv s1, a0
630; RV32I-NEXT:    lui a0, 16
631; RV32I-NEXT:    addi s3, a0, -1
632; RV32I-NEXT:    and a0, s1, s3
633; RV32I-NEXT:    call __extendhfsf2
634; RV32I-NEXT:    mv s2, a0
635; RV32I-NEXT:    and a0, s0, s3
636; RV32I-NEXT:    call __extendhfsf2
637; RV32I-NEXT:    mv a1, a0
638; RV32I-NEXT:    mv a0, s2
639; RV32I-NEXT:    call __addsf3
640; RV32I-NEXT:    call __truncsfhf2
641; RV32I-NEXT:    and a0, a0, s3
642; RV32I-NEXT:    call __extendhfsf2
643; RV32I-NEXT:    lui a1, 524288
644; RV32I-NEXT:    xor a0, a0, a1
645; RV32I-NEXT:    call __truncsfhf2
646; RV32I-NEXT:    lui a1, 1048568
647; RV32I-NEXT:    slli s1, s1, 17
648; RV32I-NEXT:    and a0, a0, a1
649; RV32I-NEXT:    srli s1, s1, 17
650; RV32I-NEXT:    or a0, s1, a0
651; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
652; RV32I-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
653; RV32I-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
654; RV32I-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
655; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
656; RV32I-NEXT:    addi sp, sp, 32
657; RV32I-NEXT:    ret
658;
659; RV64I-LABEL: fsgnjn_h:
660; RV64I:       # %bb.0:
661; RV64I-NEXT:    addi sp, sp, -48
662; RV64I-NEXT:    sd ra, 40(sp) # 8-byte Folded Spill
663; RV64I-NEXT:    sd s0, 32(sp) # 8-byte Folded Spill
664; RV64I-NEXT:    sd s1, 24(sp) # 8-byte Folded Spill
665; RV64I-NEXT:    sd s2, 16(sp) # 8-byte Folded Spill
666; RV64I-NEXT:    sd s3, 8(sp) # 8-byte Folded Spill
667; RV64I-NEXT:    mv s0, a1
668; RV64I-NEXT:    mv s1, a0
669; RV64I-NEXT:    lui a0, 16
670; RV64I-NEXT:    addiw s3, a0, -1
671; RV64I-NEXT:    and a0, s1, s3
672; RV64I-NEXT:    call __extendhfsf2
673; RV64I-NEXT:    mv s2, a0
674; RV64I-NEXT:    and a0, s0, s3
675; RV64I-NEXT:    call __extendhfsf2
676; RV64I-NEXT:    mv a1, a0
677; RV64I-NEXT:    mv a0, s2
678; RV64I-NEXT:    call __addsf3
679; RV64I-NEXT:    call __truncsfhf2
680; RV64I-NEXT:    and a0, a0, s3
681; RV64I-NEXT:    call __extendhfsf2
682; RV64I-NEXT:    lui a1, 524288
683; RV64I-NEXT:    xor a0, a0, a1
684; RV64I-NEXT:    call __truncsfhf2
685; RV64I-NEXT:    lui a1, 1048568
686; RV64I-NEXT:    slli s1, s1, 49
687; RV64I-NEXT:    and a0, a0, a1
688; RV64I-NEXT:    srli s1, s1, 49
689; RV64I-NEXT:    or a0, s1, a0
690; RV64I-NEXT:    ld ra, 40(sp) # 8-byte Folded Reload
691; RV64I-NEXT:    ld s0, 32(sp) # 8-byte Folded Reload
692; RV64I-NEXT:    ld s1, 24(sp) # 8-byte Folded Reload
693; RV64I-NEXT:    ld s2, 16(sp) # 8-byte Folded Reload
694; RV64I-NEXT:    ld s3, 8(sp) # 8-byte Folded Reload
695; RV64I-NEXT:    addi sp, sp, 48
696; RV64I-NEXT:    ret
697;
698; RV32IZFHMIN-LABEL: fsgnjn_h:
699; RV32IZFHMIN:       # %bb.0:
700; RV32IZFHMIN-NEXT:    fcvt.s.h fa5, fa1
701; RV32IZFHMIN-NEXT:    fcvt.s.h fa4, fa0
702; RV32IZFHMIN-NEXT:    lui a0, 1048568
703; RV32IZFHMIN-NEXT:    fadd.s fa5, fa4, fa5
704; RV32IZFHMIN-NEXT:    fcvt.h.s fa5, fa5
705; RV32IZFHMIN-NEXT:    fmv.x.h a1, fa5
706; RV32IZFHMIN-NEXT:    not a1, a1
707; RV32IZFHMIN-NEXT:    and a0, a1, a0
708; RV32IZFHMIN-NEXT:    fmv.x.h a1, fa0
709; RV32IZFHMIN-NEXT:    slli a1, a1, 17
710; RV32IZFHMIN-NEXT:    srli a1, a1, 17
711; RV32IZFHMIN-NEXT:    or a0, a1, a0
712; RV32IZFHMIN-NEXT:    fmv.h.x fa0, a0
713; RV32IZFHMIN-NEXT:    ret
714;
715; RV64IZFHMIN-LABEL: fsgnjn_h:
716; RV64IZFHMIN:       # %bb.0:
717; RV64IZFHMIN-NEXT:    fcvt.s.h fa5, fa1
718; RV64IZFHMIN-NEXT:    fcvt.s.h fa4, fa0
719; RV64IZFHMIN-NEXT:    lui a0, 1048568
720; RV64IZFHMIN-NEXT:    fadd.s fa5, fa4, fa5
721; RV64IZFHMIN-NEXT:    fcvt.h.s fa5, fa5
722; RV64IZFHMIN-NEXT:    fmv.x.h a1, fa5
723; RV64IZFHMIN-NEXT:    not a1, a1
724; RV64IZFHMIN-NEXT:    and a0, a1, a0
725; RV64IZFHMIN-NEXT:    fmv.x.h a1, fa0
726; RV64IZFHMIN-NEXT:    slli a1, a1, 49
727; RV64IZFHMIN-NEXT:    srli a1, a1, 49
728; RV64IZFHMIN-NEXT:    or a0, a1, a0
729; RV64IZFHMIN-NEXT:    fmv.h.x fa0, a0
730; RV64IZFHMIN-NEXT:    ret
731;
732; RV32IZHINXMIN-LABEL: fsgnjn_h:
733; RV32IZHINXMIN:       # %bb.0:
734; RV32IZHINXMIN-NEXT:    # kill: def $x10_h killed $x10_h def $x10
735; RV32IZHINXMIN-NEXT:    fcvt.s.h a1, a1
736; RV32IZHINXMIN-NEXT:    fcvt.s.h a2, a0
737; RV32IZHINXMIN-NEXT:    fadd.s a1, a2, a1
738; RV32IZHINXMIN-NEXT:    lui a2, 1048568
739; RV32IZHINXMIN-NEXT:    slli a0, a0, 17
740; RV32IZHINXMIN-NEXT:    fcvt.h.s a1, a1
741; RV32IZHINXMIN-NEXT:    not a1, a1
742; RV32IZHINXMIN-NEXT:    and a1, a1, a2
743; RV32IZHINXMIN-NEXT:    srli a0, a0, 17
744; RV32IZHINXMIN-NEXT:    or a0, a0, a1
745; RV32IZHINXMIN-NEXT:    # kill: def $x10_h killed $x10_h killed $x10
746; RV32IZHINXMIN-NEXT:    ret
747;
748; RV64IZHINXMIN-LABEL: fsgnjn_h:
749; RV64IZHINXMIN:       # %bb.0:
750; RV64IZHINXMIN-NEXT:    # kill: def $x10_h killed $x10_h def $x10
751; RV64IZHINXMIN-NEXT:    fcvt.s.h a1, a1
752; RV64IZHINXMIN-NEXT:    fcvt.s.h a2, a0
753; RV64IZHINXMIN-NEXT:    fadd.s a1, a2, a1
754; RV64IZHINXMIN-NEXT:    lui a2, 1048568
755; RV64IZHINXMIN-NEXT:    slli a0, a0, 49
756; RV64IZHINXMIN-NEXT:    fcvt.h.s a1, a1
757; RV64IZHINXMIN-NEXT:    not a1, a1
758; RV64IZHINXMIN-NEXT:    and a1, a1, a2
759; RV64IZHINXMIN-NEXT:    srli a0, a0, 49
760; RV64IZHINXMIN-NEXT:    or a0, a0, a1
761; RV64IZHINXMIN-NEXT:    # kill: def $x10_h killed $x10_h killed $x10
762; RV64IZHINXMIN-NEXT:    ret
763  %1 = fadd half %a, %b
764  %2 = fneg half %1
765  %3 = call half @llvm.copysign.f16(half %a, half %2)
766  ret half %3
767}
768
769declare half @llvm.fabs.f16(half)
770
771; This function performs extra work to ensure that
772; DAGCombiner::visitBITCAST doesn't replace the fabs with an and.
773define half @fabs_h(half %a, half %b) nounwind {
774; CHECKIZFH-LABEL: fabs_h:
775; CHECKIZFH:       # %bb.0:
776; CHECKIZFH-NEXT:    fadd.h fa5, fa0, fa1
777; CHECKIZFH-NEXT:    fabs.h fa4, fa5
778; CHECKIZFH-NEXT:    fadd.h fa0, fa4, fa5
779; CHECKIZFH-NEXT:    ret
780;
781; CHECKIZHINX-LABEL: fabs_h:
782; CHECKIZHINX:       # %bb.0:
783; CHECKIZHINX-NEXT:    fadd.h a0, a0, a1
784; CHECKIZHINX-NEXT:    fabs.h a1, a0
785; CHECKIZHINX-NEXT:    fadd.h a0, a1, a0
786; CHECKIZHINX-NEXT:    ret
787;
788; RV32I-LABEL: fabs_h:
789; RV32I:       # %bb.0:
790; RV32I-NEXT:    addi sp, sp, -16
791; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
792; RV32I-NEXT:    sw s0, 8(sp) # 4-byte Folded Spill
793; RV32I-NEXT:    sw s1, 4(sp) # 4-byte Folded Spill
794; RV32I-NEXT:    sw s2, 0(sp) # 4-byte Folded Spill
795; RV32I-NEXT:    mv s0, a1
796; RV32I-NEXT:    lui a1, 16
797; RV32I-NEXT:    addi s2, a1, -1
798; RV32I-NEXT:    and a0, a0, s2
799; RV32I-NEXT:    call __extendhfsf2
800; RV32I-NEXT:    mv s1, a0
801; RV32I-NEXT:    and a0, s0, s2
802; RV32I-NEXT:    call __extendhfsf2
803; RV32I-NEXT:    mv a1, a0
804; RV32I-NEXT:    mv a0, s1
805; RV32I-NEXT:    call __addsf3
806; RV32I-NEXT:    call __truncsfhf2
807; RV32I-NEXT:    and a0, a0, s2
808; RV32I-NEXT:    call __extendhfsf2
809; RV32I-NEXT:    mv s0, a0
810; RV32I-NEXT:    slli a0, a0, 1
811; RV32I-NEXT:    srli a0, a0, 1
812; RV32I-NEXT:    call __truncsfhf2
813; RV32I-NEXT:    and a0, a0, s2
814; RV32I-NEXT:    call __extendhfsf2
815; RV32I-NEXT:    mv a1, s0
816; RV32I-NEXT:    call __addsf3
817; RV32I-NEXT:    call __truncsfhf2
818; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
819; RV32I-NEXT:    lw s0, 8(sp) # 4-byte Folded Reload
820; RV32I-NEXT:    lw s1, 4(sp) # 4-byte Folded Reload
821; RV32I-NEXT:    lw s2, 0(sp) # 4-byte Folded Reload
822; RV32I-NEXT:    addi sp, sp, 16
823; RV32I-NEXT:    ret
824;
825; RV64I-LABEL: fabs_h:
826; RV64I:       # %bb.0:
827; RV64I-NEXT:    addi sp, sp, -32
828; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
829; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
830; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
831; RV64I-NEXT:    sd s2, 0(sp) # 8-byte Folded Spill
832; RV64I-NEXT:    mv s0, a1
833; RV64I-NEXT:    lui a1, 16
834; RV64I-NEXT:    addiw s2, a1, -1
835; RV64I-NEXT:    and a0, a0, s2
836; RV64I-NEXT:    call __extendhfsf2
837; RV64I-NEXT:    mv s1, a0
838; RV64I-NEXT:    and a0, s0, s2
839; RV64I-NEXT:    call __extendhfsf2
840; RV64I-NEXT:    mv a1, a0
841; RV64I-NEXT:    mv a0, s1
842; RV64I-NEXT:    call __addsf3
843; RV64I-NEXT:    call __truncsfhf2
844; RV64I-NEXT:    and a0, a0, s2
845; RV64I-NEXT:    call __extendhfsf2
846; RV64I-NEXT:    mv s0, a0
847; RV64I-NEXT:    slli a0, a0, 33
848; RV64I-NEXT:    srli a0, a0, 33
849; RV64I-NEXT:    call __truncsfhf2
850; RV64I-NEXT:    and a0, a0, s2
851; RV64I-NEXT:    call __extendhfsf2
852; RV64I-NEXT:    mv a1, s0
853; RV64I-NEXT:    call __addsf3
854; RV64I-NEXT:    call __truncsfhf2
855; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
856; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
857; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
858; RV64I-NEXT:    ld s2, 0(sp) # 8-byte Folded Reload
859; RV64I-NEXT:    addi sp, sp, 32
860; RV64I-NEXT:    ret
861;
862; RV32IZFHMIN-LABEL: fabs_h:
863; RV32IZFHMIN:       # %bb.0:
864; RV32IZFHMIN-NEXT:    fcvt.s.h fa5, fa1
865; RV32IZFHMIN-NEXT:    fcvt.s.h fa4, fa0
866; RV32IZFHMIN-NEXT:    fadd.s fa5, fa4, fa5
867; RV32IZFHMIN-NEXT:    fcvt.h.s fa5, fa5
868; RV32IZFHMIN-NEXT:    fmv.x.h a0, fa5
869; RV32IZFHMIN-NEXT:    slli a0, a0, 17
870; RV32IZFHMIN-NEXT:    srli a0, a0, 17
871; RV32IZFHMIN-NEXT:    fmv.h.x fa4, a0
872; RV32IZFHMIN-NEXT:    fcvt.s.h fa5, fa5
873; RV32IZFHMIN-NEXT:    fcvt.s.h fa4, fa4
874; RV32IZFHMIN-NEXT:    fadd.s fa5, fa4, fa5
875; RV32IZFHMIN-NEXT:    fcvt.h.s fa0, fa5
876; RV32IZFHMIN-NEXT:    ret
877;
878; RV64IZFHMIN-LABEL: fabs_h:
879; RV64IZFHMIN:       # %bb.0:
880; RV64IZFHMIN-NEXT:    fcvt.s.h fa5, fa1
881; RV64IZFHMIN-NEXT:    fcvt.s.h fa4, fa0
882; RV64IZFHMIN-NEXT:    fadd.s fa5, fa4, fa5
883; RV64IZFHMIN-NEXT:    fcvt.h.s fa5, fa5
884; RV64IZFHMIN-NEXT:    fmv.x.h a0, fa5
885; RV64IZFHMIN-NEXT:    slli a0, a0, 49
886; RV64IZFHMIN-NEXT:    srli a0, a0, 49
887; RV64IZFHMIN-NEXT:    fmv.h.x fa4, a0
888; RV64IZFHMIN-NEXT:    fcvt.s.h fa5, fa5
889; RV64IZFHMIN-NEXT:    fcvt.s.h fa4, fa4
890; RV64IZFHMIN-NEXT:    fadd.s fa5, fa4, fa5
891; RV64IZFHMIN-NEXT:    fcvt.h.s fa0, fa5
892; RV64IZFHMIN-NEXT:    ret
893;
894; RV32IZHINXMIN-LABEL: fabs_h:
895; RV32IZHINXMIN:       # %bb.0:
896; RV32IZHINXMIN-NEXT:    fcvt.s.h a1, a1
897; RV32IZHINXMIN-NEXT:    fcvt.s.h a0, a0
898; RV32IZHINXMIN-NEXT:    fadd.s a0, a0, a1
899; RV32IZHINXMIN-NEXT:    fcvt.h.s a0, a0
900; RV32IZHINXMIN-NEXT:    slli a1, a0, 17
901; RV32IZHINXMIN-NEXT:    srli a1, a1, 17
902; RV32IZHINXMIN-NEXT:    fcvt.s.h a0, a0
903; RV32IZHINXMIN-NEXT:    fcvt.s.h a1, a1
904; RV32IZHINXMIN-NEXT:    fadd.s a0, a1, a0
905; RV32IZHINXMIN-NEXT:    fcvt.h.s a0, a0
906; RV32IZHINXMIN-NEXT:    ret
907;
908; RV64IZHINXMIN-LABEL: fabs_h:
909; RV64IZHINXMIN:       # %bb.0:
910; RV64IZHINXMIN-NEXT:    fcvt.s.h a1, a1
911; RV64IZHINXMIN-NEXT:    fcvt.s.h a0, a0
912; RV64IZHINXMIN-NEXT:    fadd.s a0, a0, a1
913; RV64IZHINXMIN-NEXT:    fcvt.h.s a0, a0
914; RV64IZHINXMIN-NEXT:    slli a1, a0, 49
915; RV64IZHINXMIN-NEXT:    srli a1, a1, 49
916; RV64IZHINXMIN-NEXT:    fcvt.s.h a0, a0
917; RV64IZHINXMIN-NEXT:    fcvt.s.h a1, a1
918; RV64IZHINXMIN-NEXT:    fadd.s a0, a1, a0
919; RV64IZHINXMIN-NEXT:    fcvt.h.s a0, a0
920; RV64IZHINXMIN-NEXT:    ret
921  %1 = fadd half %a, %b
922  %2 = call half @llvm.fabs.f16(half %1)
923  %3 = fadd half %2, %1
924  ret half %3
925}
926
927declare half @llvm.minnum.f16(half, half)
928
929define half @fmin_h(half %a, half %b) nounwind {
930; CHECKIZFH-LABEL: fmin_h:
931; CHECKIZFH:       # %bb.0:
932; CHECKIZFH-NEXT:    fmin.h fa0, fa0, fa1
933; CHECKIZFH-NEXT:    ret
934;
935; CHECKIZHINX-LABEL: fmin_h:
936; CHECKIZHINX:       # %bb.0:
937; CHECKIZHINX-NEXT:    fmin.h a0, a0, a1
938; CHECKIZHINX-NEXT:    ret
939;
940; RV32I-LABEL: fmin_h:
941; RV32I:       # %bb.0:
942; RV32I-NEXT:    addi sp, sp, -16
943; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
944; RV32I-NEXT:    sw s0, 8(sp) # 4-byte Folded Spill
945; RV32I-NEXT:    sw s1, 4(sp) # 4-byte Folded Spill
946; RV32I-NEXT:    sw s2, 0(sp) # 4-byte Folded Spill
947; RV32I-NEXT:    mv s0, a1
948; RV32I-NEXT:    lui a1, 16
949; RV32I-NEXT:    addi s2, a1, -1
950; RV32I-NEXT:    and a0, a0, s2
951; RV32I-NEXT:    call __extendhfsf2
952; RV32I-NEXT:    mv s1, a0
953; RV32I-NEXT:    and a0, s0, s2
954; RV32I-NEXT:    call __extendhfsf2
955; RV32I-NEXT:    mv a1, a0
956; RV32I-NEXT:    mv a0, s1
957; RV32I-NEXT:    call fminf
958; RV32I-NEXT:    call __truncsfhf2
959; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
960; RV32I-NEXT:    lw s0, 8(sp) # 4-byte Folded Reload
961; RV32I-NEXT:    lw s1, 4(sp) # 4-byte Folded Reload
962; RV32I-NEXT:    lw s2, 0(sp) # 4-byte Folded Reload
963; RV32I-NEXT:    addi sp, sp, 16
964; RV32I-NEXT:    ret
965;
966; RV64I-LABEL: fmin_h:
967; RV64I:       # %bb.0:
968; RV64I-NEXT:    addi sp, sp, -32
969; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
970; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
971; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
972; RV64I-NEXT:    sd s2, 0(sp) # 8-byte Folded Spill
973; RV64I-NEXT:    mv s0, a1
974; RV64I-NEXT:    lui a1, 16
975; RV64I-NEXT:    addiw s2, a1, -1
976; RV64I-NEXT:    and a0, a0, s2
977; RV64I-NEXT:    call __extendhfsf2
978; RV64I-NEXT:    mv s1, a0
979; RV64I-NEXT:    and a0, s0, s2
980; RV64I-NEXT:    call __extendhfsf2
981; RV64I-NEXT:    mv a1, a0
982; RV64I-NEXT:    mv a0, s1
983; RV64I-NEXT:    call fminf
984; RV64I-NEXT:    call __truncsfhf2
985; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
986; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
987; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
988; RV64I-NEXT:    ld s2, 0(sp) # 8-byte Folded Reload
989; RV64I-NEXT:    addi sp, sp, 32
990; RV64I-NEXT:    ret
991;
992; CHECKIZFHMIN-LABEL: fmin_h:
993; CHECKIZFHMIN:       # %bb.0:
994; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa1
995; CHECKIZFHMIN-NEXT:    fcvt.s.h fa4, fa0
996; CHECKIZFHMIN-NEXT:    fmin.s fa5, fa4, fa5
997; CHECKIZFHMIN-NEXT:    fcvt.h.s fa0, fa5
998; CHECKIZFHMIN-NEXT:    ret
999;
1000; CHECKIZHINXMIN-LABEL: fmin_h:
1001; CHECKIZHINXMIN:       # %bb.0:
1002; CHECKIZHINXMIN-NEXT:    fcvt.s.h a1, a1
1003; CHECKIZHINXMIN-NEXT:    fcvt.s.h a0, a0
1004; CHECKIZHINXMIN-NEXT:    fmin.s a0, a0, a1
1005; CHECKIZHINXMIN-NEXT:    fcvt.h.s a0, a0
1006; CHECKIZHINXMIN-NEXT:    ret
1007  %1 = call half @llvm.minnum.f16(half %a, half %b)
1008  ret half %1
1009}
1010
1011declare half @llvm.maxnum.f16(half, half)
1012
1013define half @fmax_h(half %a, half %b) nounwind {
1014; CHECKIZFH-LABEL: fmax_h:
1015; CHECKIZFH:       # %bb.0:
1016; CHECKIZFH-NEXT:    fmax.h fa0, fa0, fa1
1017; CHECKIZFH-NEXT:    ret
1018;
1019; CHECKIZHINX-LABEL: fmax_h:
1020; CHECKIZHINX:       # %bb.0:
1021; CHECKIZHINX-NEXT:    fmax.h a0, a0, a1
1022; CHECKIZHINX-NEXT:    ret
1023;
1024; RV32I-LABEL: fmax_h:
1025; RV32I:       # %bb.0:
1026; RV32I-NEXT:    addi sp, sp, -16
1027; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
1028; RV32I-NEXT:    sw s0, 8(sp) # 4-byte Folded Spill
1029; RV32I-NEXT:    sw s1, 4(sp) # 4-byte Folded Spill
1030; RV32I-NEXT:    sw s2, 0(sp) # 4-byte Folded Spill
1031; RV32I-NEXT:    mv s0, a1
1032; RV32I-NEXT:    lui a1, 16
1033; RV32I-NEXT:    addi s2, a1, -1
1034; RV32I-NEXT:    and a0, a0, s2
1035; RV32I-NEXT:    call __extendhfsf2
1036; RV32I-NEXT:    mv s1, a0
1037; RV32I-NEXT:    and a0, s0, s2
1038; RV32I-NEXT:    call __extendhfsf2
1039; RV32I-NEXT:    mv a1, a0
1040; RV32I-NEXT:    mv a0, s1
1041; RV32I-NEXT:    call fmaxf
1042; RV32I-NEXT:    call __truncsfhf2
1043; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
1044; RV32I-NEXT:    lw s0, 8(sp) # 4-byte Folded Reload
1045; RV32I-NEXT:    lw s1, 4(sp) # 4-byte Folded Reload
1046; RV32I-NEXT:    lw s2, 0(sp) # 4-byte Folded Reload
1047; RV32I-NEXT:    addi sp, sp, 16
1048; RV32I-NEXT:    ret
1049;
1050; RV64I-LABEL: fmax_h:
1051; RV64I:       # %bb.0:
1052; RV64I-NEXT:    addi sp, sp, -32
1053; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
1054; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
1055; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
1056; RV64I-NEXT:    sd s2, 0(sp) # 8-byte Folded Spill
1057; RV64I-NEXT:    mv s0, a1
1058; RV64I-NEXT:    lui a1, 16
1059; RV64I-NEXT:    addiw s2, a1, -1
1060; RV64I-NEXT:    and a0, a0, s2
1061; RV64I-NEXT:    call __extendhfsf2
1062; RV64I-NEXT:    mv s1, a0
1063; RV64I-NEXT:    and a0, s0, s2
1064; RV64I-NEXT:    call __extendhfsf2
1065; RV64I-NEXT:    mv a1, a0
1066; RV64I-NEXT:    mv a0, s1
1067; RV64I-NEXT:    call fmaxf
1068; RV64I-NEXT:    call __truncsfhf2
1069; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
1070; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
1071; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
1072; RV64I-NEXT:    ld s2, 0(sp) # 8-byte Folded Reload
1073; RV64I-NEXT:    addi sp, sp, 32
1074; RV64I-NEXT:    ret
1075;
1076; CHECKIZFHMIN-LABEL: fmax_h:
1077; CHECKIZFHMIN:       # %bb.0:
1078; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa1
1079; CHECKIZFHMIN-NEXT:    fcvt.s.h fa4, fa0
1080; CHECKIZFHMIN-NEXT:    fmax.s fa5, fa4, fa5
1081; CHECKIZFHMIN-NEXT:    fcvt.h.s fa0, fa5
1082; CHECKIZFHMIN-NEXT:    ret
1083;
1084; CHECKIZHINXMIN-LABEL: fmax_h:
1085; CHECKIZHINXMIN:       # %bb.0:
1086; CHECKIZHINXMIN-NEXT:    fcvt.s.h a1, a1
1087; CHECKIZHINXMIN-NEXT:    fcvt.s.h a0, a0
1088; CHECKIZHINXMIN-NEXT:    fmax.s a0, a0, a1
1089; CHECKIZHINXMIN-NEXT:    fcvt.h.s a0, a0
1090; CHECKIZHINXMIN-NEXT:    ret
1091  %1 = call half @llvm.maxnum.f16(half %a, half %b)
1092  ret half %1
1093}
1094
1095declare half @llvm.fma.f16(half, half, half)
1096
1097define half @fmadd_h(half %a, half %b, half %c) nounwind {
1098; CHECKIZFH-LABEL: fmadd_h:
1099; CHECKIZFH:       # %bb.0:
1100; CHECKIZFH-NEXT:    fmadd.h fa0, fa0, fa1, fa2
1101; CHECKIZFH-NEXT:    ret
1102;
1103; CHECKIZHINX-LABEL: fmadd_h:
1104; CHECKIZHINX:       # %bb.0:
1105; CHECKIZHINX-NEXT:    fmadd.h a0, a0, a1, a2
1106; CHECKIZHINX-NEXT:    ret
1107;
1108; RV32I-LABEL: fmadd_h:
1109; RV32I:       # %bb.0:
1110; RV32I-NEXT:    addi sp, sp, -32
1111; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
1112; RV32I-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
1113; RV32I-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
1114; RV32I-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
1115; RV32I-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
1116; RV32I-NEXT:    mv s0, a2
1117; RV32I-NEXT:    mv s1, a1
1118; RV32I-NEXT:    lui a1, 16
1119; RV32I-NEXT:    addi s3, a1, -1
1120; RV32I-NEXT:    and a0, a0, s3
1121; RV32I-NEXT:    call __extendhfsf2
1122; RV32I-NEXT:    mv s2, a0
1123; RV32I-NEXT:    and a0, s1, s3
1124; RV32I-NEXT:    call __extendhfsf2
1125; RV32I-NEXT:    mv s1, a0
1126; RV32I-NEXT:    and a0, s0, s3
1127; RV32I-NEXT:    call __extendhfsf2
1128; RV32I-NEXT:    mv a2, a0
1129; RV32I-NEXT:    mv a0, s2
1130; RV32I-NEXT:    mv a1, s1
1131; RV32I-NEXT:    call fmaf
1132; RV32I-NEXT:    call __truncsfhf2
1133; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
1134; RV32I-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
1135; RV32I-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
1136; RV32I-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
1137; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
1138; RV32I-NEXT:    addi sp, sp, 32
1139; RV32I-NEXT:    ret
1140;
1141; RV64I-LABEL: fmadd_h:
1142; RV64I:       # %bb.0:
1143; RV64I-NEXT:    addi sp, sp, -48
1144; RV64I-NEXT:    sd ra, 40(sp) # 8-byte Folded Spill
1145; RV64I-NEXT:    sd s0, 32(sp) # 8-byte Folded Spill
1146; RV64I-NEXT:    sd s1, 24(sp) # 8-byte Folded Spill
1147; RV64I-NEXT:    sd s2, 16(sp) # 8-byte Folded Spill
1148; RV64I-NEXT:    sd s3, 8(sp) # 8-byte Folded Spill
1149; RV64I-NEXT:    mv s0, a2
1150; RV64I-NEXT:    mv s1, a1
1151; RV64I-NEXT:    lui a1, 16
1152; RV64I-NEXT:    addiw s3, a1, -1
1153; RV64I-NEXT:    and a0, a0, s3
1154; RV64I-NEXT:    call __extendhfsf2
1155; RV64I-NEXT:    mv s2, a0
1156; RV64I-NEXT:    and a0, s1, s3
1157; RV64I-NEXT:    call __extendhfsf2
1158; RV64I-NEXT:    mv s1, a0
1159; RV64I-NEXT:    and a0, s0, s3
1160; RV64I-NEXT:    call __extendhfsf2
1161; RV64I-NEXT:    mv a2, a0
1162; RV64I-NEXT:    mv a0, s2
1163; RV64I-NEXT:    mv a1, s1
1164; RV64I-NEXT:    call fmaf
1165; RV64I-NEXT:    call __truncsfhf2
1166; RV64I-NEXT:    ld ra, 40(sp) # 8-byte Folded Reload
1167; RV64I-NEXT:    ld s0, 32(sp) # 8-byte Folded Reload
1168; RV64I-NEXT:    ld s1, 24(sp) # 8-byte Folded Reload
1169; RV64I-NEXT:    ld s2, 16(sp) # 8-byte Folded Reload
1170; RV64I-NEXT:    ld s3, 8(sp) # 8-byte Folded Reload
1171; RV64I-NEXT:    addi sp, sp, 48
1172; RV64I-NEXT:    ret
1173;
1174; CHECKIZFHMIN-LABEL: fmadd_h:
1175; CHECKIZFHMIN:       # %bb.0:
1176; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa2
1177; CHECKIZFHMIN-NEXT:    fcvt.s.h fa4, fa1
1178; CHECKIZFHMIN-NEXT:    fcvt.s.h fa3, fa0
1179; CHECKIZFHMIN-NEXT:    fmadd.s fa5, fa3, fa4, fa5
1180; CHECKIZFHMIN-NEXT:    fcvt.h.s fa0, fa5
1181; CHECKIZFHMIN-NEXT:    ret
1182;
1183; CHECKIZHINXMIN-LABEL: fmadd_h:
1184; CHECKIZHINXMIN:       # %bb.0:
1185; CHECKIZHINXMIN-NEXT:    fcvt.s.h a2, a2
1186; CHECKIZHINXMIN-NEXT:    fcvt.s.h a1, a1
1187; CHECKIZHINXMIN-NEXT:    fcvt.s.h a0, a0
1188; CHECKIZHINXMIN-NEXT:    fmadd.s a0, a0, a1, a2
1189; CHECKIZHINXMIN-NEXT:    fcvt.h.s a0, a0
1190; CHECKIZHINXMIN-NEXT:    ret
1191  %1 = call half @llvm.fma.f16(half %a, half %b, half %c)
1192  ret half %1
1193}
1194
1195define half @fmsub_h(half %a, half %b, half %c) nounwind {
1196; CHECKIZFH-LABEL: fmsub_h:
1197; CHECKIZFH:       # %bb.0:
1198; CHECKIZFH-NEXT:    fmv.h.x fa5, zero
1199; CHECKIZFH-NEXT:    fadd.h fa5, fa2, fa5
1200; CHECKIZFH-NEXT:    fmsub.h fa0, fa0, fa1, fa5
1201; CHECKIZFH-NEXT:    ret
1202;
1203; CHECKIZHINX-LABEL: fmsub_h:
1204; CHECKIZHINX:       # %bb.0:
1205; CHECKIZHINX-NEXT:    fadd.h a2, a2, zero
1206; CHECKIZHINX-NEXT:    fmsub.h a0, a0, a1, a2
1207; CHECKIZHINX-NEXT:    ret
1208;
1209; RV32I-LABEL: fmsub_h:
1210; RV32I:       # %bb.0:
1211; RV32I-NEXT:    addi sp, sp, -32
1212; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
1213; RV32I-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
1214; RV32I-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
1215; RV32I-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
1216; RV32I-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
1217; RV32I-NEXT:    mv s0, a1
1218; RV32I-NEXT:    mv s1, a0
1219; RV32I-NEXT:    lui a0, 16
1220; RV32I-NEXT:    addi s3, a0, -1
1221; RV32I-NEXT:    and a0, a2, s3
1222; RV32I-NEXT:    call __extendhfsf2
1223; RV32I-NEXT:    li a1, 0
1224; RV32I-NEXT:    call __addsf3
1225; RV32I-NEXT:    call __truncsfhf2
1226; RV32I-NEXT:    and a0, a0, s3
1227; RV32I-NEXT:    call __extendhfsf2
1228; RV32I-NEXT:    lui a1, 524288
1229; RV32I-NEXT:    xor a0, a0, a1
1230; RV32I-NEXT:    call __truncsfhf2
1231; RV32I-NEXT:    mv s2, a0
1232; RV32I-NEXT:    and a0, s1, s3
1233; RV32I-NEXT:    call __extendhfsf2
1234; RV32I-NEXT:    mv s1, a0
1235; RV32I-NEXT:    and a0, s0, s3
1236; RV32I-NEXT:    call __extendhfsf2
1237; RV32I-NEXT:    mv s0, a0
1238; RV32I-NEXT:    and a0, s2, s3
1239; RV32I-NEXT:    call __extendhfsf2
1240; RV32I-NEXT:    mv a2, a0
1241; RV32I-NEXT:    mv a0, s1
1242; RV32I-NEXT:    mv a1, s0
1243; RV32I-NEXT:    call fmaf
1244; RV32I-NEXT:    call __truncsfhf2
1245; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
1246; RV32I-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
1247; RV32I-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
1248; RV32I-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
1249; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
1250; RV32I-NEXT:    addi sp, sp, 32
1251; RV32I-NEXT:    ret
1252;
1253; RV64I-LABEL: fmsub_h:
1254; RV64I:       # %bb.0:
1255; RV64I-NEXT:    addi sp, sp, -48
1256; RV64I-NEXT:    sd ra, 40(sp) # 8-byte Folded Spill
1257; RV64I-NEXT:    sd s0, 32(sp) # 8-byte Folded Spill
1258; RV64I-NEXT:    sd s1, 24(sp) # 8-byte Folded Spill
1259; RV64I-NEXT:    sd s2, 16(sp) # 8-byte Folded Spill
1260; RV64I-NEXT:    sd s3, 8(sp) # 8-byte Folded Spill
1261; RV64I-NEXT:    mv s0, a1
1262; RV64I-NEXT:    mv s1, a0
1263; RV64I-NEXT:    lui a0, 16
1264; RV64I-NEXT:    addiw s3, a0, -1
1265; RV64I-NEXT:    and a0, a2, s3
1266; RV64I-NEXT:    call __extendhfsf2
1267; RV64I-NEXT:    li a1, 0
1268; RV64I-NEXT:    call __addsf3
1269; RV64I-NEXT:    call __truncsfhf2
1270; RV64I-NEXT:    and a0, a0, s3
1271; RV64I-NEXT:    call __extendhfsf2
1272; RV64I-NEXT:    lui a1, 524288
1273; RV64I-NEXT:    xor a0, a0, a1
1274; RV64I-NEXT:    call __truncsfhf2
1275; RV64I-NEXT:    mv s2, a0
1276; RV64I-NEXT:    and a0, s1, s3
1277; RV64I-NEXT:    call __extendhfsf2
1278; RV64I-NEXT:    mv s1, a0
1279; RV64I-NEXT:    and a0, s0, s3
1280; RV64I-NEXT:    call __extendhfsf2
1281; RV64I-NEXT:    mv s0, a0
1282; RV64I-NEXT:    and a0, s2, s3
1283; RV64I-NEXT:    call __extendhfsf2
1284; RV64I-NEXT:    mv a2, a0
1285; RV64I-NEXT:    mv a0, s1
1286; RV64I-NEXT:    mv a1, s0
1287; RV64I-NEXT:    call fmaf
1288; RV64I-NEXT:    call __truncsfhf2
1289; RV64I-NEXT:    ld ra, 40(sp) # 8-byte Folded Reload
1290; RV64I-NEXT:    ld s0, 32(sp) # 8-byte Folded Reload
1291; RV64I-NEXT:    ld s1, 24(sp) # 8-byte Folded Reload
1292; RV64I-NEXT:    ld s2, 16(sp) # 8-byte Folded Reload
1293; RV64I-NEXT:    ld s3, 8(sp) # 8-byte Folded Reload
1294; RV64I-NEXT:    addi sp, sp, 48
1295; RV64I-NEXT:    ret
1296;
1297; CHECKIZFHMIN-LABEL: fmsub_h:
1298; CHECKIZFHMIN:       # %bb.0:
1299; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa2
1300; CHECKIZFHMIN-NEXT:    fmv.w.x fa4, zero
1301; CHECKIZFHMIN-NEXT:    lui a0, 1048568
1302; CHECKIZFHMIN-NEXT:    fcvt.s.h fa3, fa1
1303; CHECKIZFHMIN-NEXT:    fadd.s fa5, fa5, fa4
1304; CHECKIZFHMIN-NEXT:    fcvt.h.s fa5, fa5
1305; CHECKIZFHMIN-NEXT:    fmv.x.h a1, fa5
1306; CHECKIZFHMIN-NEXT:    xor a0, a1, a0
1307; CHECKIZFHMIN-NEXT:    fmv.h.x fa5, a0
1308; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa5
1309; CHECKIZFHMIN-NEXT:    fcvt.s.h fa4, fa0
1310; CHECKIZFHMIN-NEXT:    fmadd.s fa5, fa4, fa3, fa5
1311; CHECKIZFHMIN-NEXT:    fcvt.h.s fa0, fa5
1312; CHECKIZFHMIN-NEXT:    ret
1313;
1314; CHECKIZHINXMIN-LABEL: fmsub_h:
1315; CHECKIZHINXMIN:       # %bb.0:
1316; CHECKIZHINXMIN-NEXT:    fcvt.s.h a2, a2
1317; CHECKIZHINXMIN-NEXT:    lui a3, 1048568
1318; CHECKIZHINXMIN-NEXT:    fcvt.s.h a1, a1
1319; CHECKIZHINXMIN-NEXT:    fadd.s a2, a2, zero
1320; CHECKIZHINXMIN-NEXT:    fcvt.h.s a2, a2
1321; CHECKIZHINXMIN-NEXT:    xor a2, a2, a3
1322; CHECKIZHINXMIN-NEXT:    fcvt.s.h a2, a2
1323; CHECKIZHINXMIN-NEXT:    fcvt.s.h a0, a0
1324; CHECKIZHINXMIN-NEXT:    fmadd.s a0, a0, a1, a2
1325; CHECKIZHINXMIN-NEXT:    fcvt.h.s a0, a0
1326; CHECKIZHINXMIN-NEXT:    ret
1327  %c_ = fadd half 0.0, %c ; avoid negation using xor
1328  %negc = fsub half -0.0, %c_
1329  %1 = call half @llvm.fma.f16(half %a, half %b, half %negc)
1330  ret half %1
1331}
1332
1333define half @fnmadd_h(half %a, half %b, half %c) nounwind {
1334; CHECKIZFH-LABEL: fnmadd_h:
1335; CHECKIZFH:       # %bb.0:
1336; CHECKIZFH-NEXT:    fmv.h.x fa5, zero
1337; CHECKIZFH-NEXT:    fadd.h fa4, fa0, fa5
1338; CHECKIZFH-NEXT:    fadd.h fa5, fa2, fa5
1339; CHECKIZFH-NEXT:    fnmadd.h fa0, fa4, fa1, fa5
1340; CHECKIZFH-NEXT:    ret
1341;
1342; CHECKIZHINX-LABEL: fnmadd_h:
1343; CHECKIZHINX:       # %bb.0:
1344; CHECKIZHINX-NEXT:    fadd.h a0, a0, zero
1345; CHECKIZHINX-NEXT:    fadd.h a2, a2, zero
1346; CHECKIZHINX-NEXT:    fnmadd.h a0, a0, a1, a2
1347; CHECKIZHINX-NEXT:    ret
1348;
1349; RV32I-LABEL: fnmadd_h:
1350; RV32I:       # %bb.0:
1351; RV32I-NEXT:    addi sp, sp, -32
1352; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
1353; RV32I-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
1354; RV32I-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
1355; RV32I-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
1356; RV32I-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
1357; RV32I-NEXT:    sw s4, 8(sp) # 4-byte Folded Spill
1358; RV32I-NEXT:    mv s1, a2
1359; RV32I-NEXT:    mv s0, a1
1360; RV32I-NEXT:    lui s3, 16
1361; RV32I-NEXT:    addi s3, s3, -1
1362; RV32I-NEXT:    and a0, a0, s3
1363; RV32I-NEXT:    call __extendhfsf2
1364; RV32I-NEXT:    li a1, 0
1365; RV32I-NEXT:    call __addsf3
1366; RV32I-NEXT:    call __truncsfhf2
1367; RV32I-NEXT:    mv s2, a0
1368; RV32I-NEXT:    and a0, s1, s3
1369; RV32I-NEXT:    call __extendhfsf2
1370; RV32I-NEXT:    li a1, 0
1371; RV32I-NEXT:    call __addsf3
1372; RV32I-NEXT:    call __truncsfhf2
1373; RV32I-NEXT:    mv s1, a0
1374; RV32I-NEXT:    and a0, s2, s3
1375; RV32I-NEXT:    call __extendhfsf2
1376; RV32I-NEXT:    lui s4, 524288
1377; RV32I-NEXT:    xor a0, a0, s4
1378; RV32I-NEXT:    call __truncsfhf2
1379; RV32I-NEXT:    mv s2, a0
1380; RV32I-NEXT:    and a0, s1, s3
1381; RV32I-NEXT:    call __extendhfsf2
1382; RV32I-NEXT:    xor a0, a0, s4
1383; RV32I-NEXT:    call __truncsfhf2
1384; RV32I-NEXT:    mv s1, a0
1385; RV32I-NEXT:    and a0, s0, s3
1386; RV32I-NEXT:    call __extendhfsf2
1387; RV32I-NEXT:    mv s0, a0
1388; RV32I-NEXT:    and a0, s2, s3
1389; RV32I-NEXT:    call __extendhfsf2
1390; RV32I-NEXT:    mv s2, a0
1391; RV32I-NEXT:    and a0, s1, s3
1392; RV32I-NEXT:    call __extendhfsf2
1393; RV32I-NEXT:    mv a2, a0
1394; RV32I-NEXT:    mv a0, s2
1395; RV32I-NEXT:    mv a1, s0
1396; RV32I-NEXT:    call fmaf
1397; RV32I-NEXT:    call __truncsfhf2
1398; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
1399; RV32I-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
1400; RV32I-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
1401; RV32I-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
1402; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
1403; RV32I-NEXT:    lw s4, 8(sp) # 4-byte Folded Reload
1404; RV32I-NEXT:    addi sp, sp, 32
1405; RV32I-NEXT:    ret
1406;
1407; RV64I-LABEL: fnmadd_h:
1408; RV64I:       # %bb.0:
1409; RV64I-NEXT:    addi sp, sp, -48
1410; RV64I-NEXT:    sd ra, 40(sp) # 8-byte Folded Spill
1411; RV64I-NEXT:    sd s0, 32(sp) # 8-byte Folded Spill
1412; RV64I-NEXT:    sd s1, 24(sp) # 8-byte Folded Spill
1413; RV64I-NEXT:    sd s2, 16(sp) # 8-byte Folded Spill
1414; RV64I-NEXT:    sd s3, 8(sp) # 8-byte Folded Spill
1415; RV64I-NEXT:    sd s4, 0(sp) # 8-byte Folded Spill
1416; RV64I-NEXT:    mv s1, a2
1417; RV64I-NEXT:    mv s0, a1
1418; RV64I-NEXT:    lui s3, 16
1419; RV64I-NEXT:    addiw s3, s3, -1
1420; RV64I-NEXT:    and a0, a0, s3
1421; RV64I-NEXT:    call __extendhfsf2
1422; RV64I-NEXT:    li a1, 0
1423; RV64I-NEXT:    call __addsf3
1424; RV64I-NEXT:    call __truncsfhf2
1425; RV64I-NEXT:    mv s2, a0
1426; RV64I-NEXT:    and a0, s1, s3
1427; RV64I-NEXT:    call __extendhfsf2
1428; RV64I-NEXT:    li a1, 0
1429; RV64I-NEXT:    call __addsf3
1430; RV64I-NEXT:    call __truncsfhf2
1431; RV64I-NEXT:    mv s1, a0
1432; RV64I-NEXT:    and a0, s2, s3
1433; RV64I-NEXT:    call __extendhfsf2
1434; RV64I-NEXT:    lui s4, 524288
1435; RV64I-NEXT:    xor a0, a0, s4
1436; RV64I-NEXT:    call __truncsfhf2
1437; RV64I-NEXT:    mv s2, a0
1438; RV64I-NEXT:    and a0, s1, s3
1439; RV64I-NEXT:    call __extendhfsf2
1440; RV64I-NEXT:    xor a0, a0, s4
1441; RV64I-NEXT:    call __truncsfhf2
1442; RV64I-NEXT:    mv s1, a0
1443; RV64I-NEXT:    and a0, s0, s3
1444; RV64I-NEXT:    call __extendhfsf2
1445; RV64I-NEXT:    mv s0, a0
1446; RV64I-NEXT:    and a0, s2, s3
1447; RV64I-NEXT:    call __extendhfsf2
1448; RV64I-NEXT:    mv s2, a0
1449; RV64I-NEXT:    and a0, s1, s3
1450; RV64I-NEXT:    call __extendhfsf2
1451; RV64I-NEXT:    mv a2, a0
1452; RV64I-NEXT:    mv a0, s2
1453; RV64I-NEXT:    mv a1, s0
1454; RV64I-NEXT:    call fmaf
1455; RV64I-NEXT:    call __truncsfhf2
1456; RV64I-NEXT:    ld ra, 40(sp) # 8-byte Folded Reload
1457; RV64I-NEXT:    ld s0, 32(sp) # 8-byte Folded Reload
1458; RV64I-NEXT:    ld s1, 24(sp) # 8-byte Folded Reload
1459; RV64I-NEXT:    ld s2, 16(sp) # 8-byte Folded Reload
1460; RV64I-NEXT:    ld s3, 8(sp) # 8-byte Folded Reload
1461; RV64I-NEXT:    ld s4, 0(sp) # 8-byte Folded Reload
1462; RV64I-NEXT:    addi sp, sp, 48
1463; RV64I-NEXT:    ret
1464;
1465; CHECKIZFHMIN-LABEL: fnmadd_h:
1466; CHECKIZFHMIN:       # %bb.0:
1467; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa0
1468; CHECKIZFHMIN-NEXT:    fmv.w.x fa4, zero
1469; CHECKIZFHMIN-NEXT:    fcvt.s.h fa3, fa2
1470; CHECKIZFHMIN-NEXT:    lui a0, 1048568
1471; CHECKIZFHMIN-NEXT:    fadd.s fa5, fa5, fa4
1472; CHECKIZFHMIN-NEXT:    fadd.s fa4, fa3, fa4
1473; CHECKIZFHMIN-NEXT:    fcvt.h.s fa5, fa5
1474; CHECKIZFHMIN-NEXT:    fcvt.h.s fa4, fa4
1475; CHECKIZFHMIN-NEXT:    fmv.x.h a1, fa5
1476; CHECKIZFHMIN-NEXT:    fmv.x.h a2, fa4
1477; CHECKIZFHMIN-NEXT:    xor a1, a1, a0
1478; CHECKIZFHMIN-NEXT:    xor a0, a2, a0
1479; CHECKIZFHMIN-NEXT:    fmv.h.x fa5, a1
1480; CHECKIZFHMIN-NEXT:    fmv.h.x fa4, a0
1481; CHECKIZFHMIN-NEXT:    fcvt.s.h fa4, fa4
1482; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa5
1483; CHECKIZFHMIN-NEXT:    fcvt.s.h fa3, fa1
1484; CHECKIZFHMIN-NEXT:    fmadd.s fa5, fa5, fa3, fa4
1485; CHECKIZFHMIN-NEXT:    fcvt.h.s fa0, fa5
1486; CHECKIZFHMIN-NEXT:    ret
1487;
1488; CHECKIZHINXMIN-LABEL: fnmadd_h:
1489; CHECKIZHINXMIN:       # %bb.0:
1490; CHECKIZHINXMIN-NEXT:    fcvt.s.h a0, a0
1491; CHECKIZHINXMIN-NEXT:    fcvt.s.h a2, a2
1492; CHECKIZHINXMIN-NEXT:    lui a3, 1048568
1493; CHECKIZHINXMIN-NEXT:    fadd.s a0, a0, zero
1494; CHECKIZHINXMIN-NEXT:    fadd.s a2, a2, zero
1495; CHECKIZHINXMIN-NEXT:    fcvt.h.s a0, a0
1496; CHECKIZHINXMIN-NEXT:    fcvt.h.s a2, a2
1497; CHECKIZHINXMIN-NEXT:    xor a0, a0, a3
1498; CHECKIZHINXMIN-NEXT:    xor a2, a2, a3
1499; CHECKIZHINXMIN-NEXT:    fcvt.s.h a2, a2
1500; CHECKIZHINXMIN-NEXT:    fcvt.s.h a0, a0
1501; CHECKIZHINXMIN-NEXT:    fcvt.s.h a1, a1
1502; CHECKIZHINXMIN-NEXT:    fmadd.s a0, a0, a1, a2
1503; CHECKIZHINXMIN-NEXT:    fcvt.h.s a0, a0
1504; CHECKIZHINXMIN-NEXT:    ret
1505  %a_ = fadd half 0.0, %a
1506  %c_ = fadd half 0.0, %c
1507  %nega = fsub half -0.0, %a_
1508  %negc = fsub half -0.0, %c_
1509  %1 = call half @llvm.fma.f16(half %nega, half %b, half %negc)
1510  ret half %1
1511}
1512
1513define half @fnmadd_h_2(half %a, half %b, half %c) nounwind {
1514; CHECKIZFH-LABEL: fnmadd_h_2:
1515; CHECKIZFH:       # %bb.0:
1516; CHECKIZFH-NEXT:    fmv.h.x fa5, zero
1517; CHECKIZFH-NEXT:    fadd.h fa4, fa1, fa5
1518; CHECKIZFH-NEXT:    fadd.h fa5, fa2, fa5
1519; CHECKIZFH-NEXT:    fnmadd.h fa0, fa4, fa0, fa5
1520; CHECKIZFH-NEXT:    ret
1521;
1522; CHECKIZHINX-LABEL: fnmadd_h_2:
1523; CHECKIZHINX:       # %bb.0:
1524; CHECKIZHINX-NEXT:    fadd.h a1, a1, zero
1525; CHECKIZHINX-NEXT:    fadd.h a2, a2, zero
1526; CHECKIZHINX-NEXT:    fnmadd.h a0, a1, a0, a2
1527; CHECKIZHINX-NEXT:    ret
1528;
1529; RV32I-LABEL: fnmadd_h_2:
1530; RV32I:       # %bb.0:
1531; RV32I-NEXT:    addi sp, sp, -32
1532; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
1533; RV32I-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
1534; RV32I-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
1535; RV32I-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
1536; RV32I-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
1537; RV32I-NEXT:    sw s4, 8(sp) # 4-byte Folded Spill
1538; RV32I-NEXT:    mv s1, a2
1539; RV32I-NEXT:    mv s0, a0
1540; RV32I-NEXT:    lui s3, 16
1541; RV32I-NEXT:    addi s3, s3, -1
1542; RV32I-NEXT:    and a0, a1, s3
1543; RV32I-NEXT:    call __extendhfsf2
1544; RV32I-NEXT:    li a1, 0
1545; RV32I-NEXT:    call __addsf3
1546; RV32I-NEXT:    call __truncsfhf2
1547; RV32I-NEXT:    mv s2, a0
1548; RV32I-NEXT:    and a0, s1, s3
1549; RV32I-NEXT:    call __extendhfsf2
1550; RV32I-NEXT:    li a1, 0
1551; RV32I-NEXT:    call __addsf3
1552; RV32I-NEXT:    call __truncsfhf2
1553; RV32I-NEXT:    mv s1, a0
1554; RV32I-NEXT:    and a0, s2, s3
1555; RV32I-NEXT:    call __extendhfsf2
1556; RV32I-NEXT:    lui s4, 524288
1557; RV32I-NEXT:    xor a0, a0, s4
1558; RV32I-NEXT:    call __truncsfhf2
1559; RV32I-NEXT:    mv s2, a0
1560; RV32I-NEXT:    and a0, s1, s3
1561; RV32I-NEXT:    call __extendhfsf2
1562; RV32I-NEXT:    xor a0, a0, s4
1563; RV32I-NEXT:    call __truncsfhf2
1564; RV32I-NEXT:    mv s1, a0
1565; RV32I-NEXT:    and a0, s0, s3
1566; RV32I-NEXT:    call __extendhfsf2
1567; RV32I-NEXT:    mv s0, a0
1568; RV32I-NEXT:    and a0, s2, s3
1569; RV32I-NEXT:    call __extendhfsf2
1570; RV32I-NEXT:    mv s2, a0
1571; RV32I-NEXT:    and a0, s1, s3
1572; RV32I-NEXT:    call __extendhfsf2
1573; RV32I-NEXT:    mv a2, a0
1574; RV32I-NEXT:    mv a0, s0
1575; RV32I-NEXT:    mv a1, s2
1576; RV32I-NEXT:    call fmaf
1577; RV32I-NEXT:    call __truncsfhf2
1578; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
1579; RV32I-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
1580; RV32I-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
1581; RV32I-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
1582; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
1583; RV32I-NEXT:    lw s4, 8(sp) # 4-byte Folded Reload
1584; RV32I-NEXT:    addi sp, sp, 32
1585; RV32I-NEXT:    ret
1586;
1587; RV64I-LABEL: fnmadd_h_2:
1588; RV64I:       # %bb.0:
1589; RV64I-NEXT:    addi sp, sp, -48
1590; RV64I-NEXT:    sd ra, 40(sp) # 8-byte Folded Spill
1591; RV64I-NEXT:    sd s0, 32(sp) # 8-byte Folded Spill
1592; RV64I-NEXT:    sd s1, 24(sp) # 8-byte Folded Spill
1593; RV64I-NEXT:    sd s2, 16(sp) # 8-byte Folded Spill
1594; RV64I-NEXT:    sd s3, 8(sp) # 8-byte Folded Spill
1595; RV64I-NEXT:    sd s4, 0(sp) # 8-byte Folded Spill
1596; RV64I-NEXT:    mv s1, a2
1597; RV64I-NEXT:    mv s0, a0
1598; RV64I-NEXT:    lui s3, 16
1599; RV64I-NEXT:    addiw s3, s3, -1
1600; RV64I-NEXT:    and a0, a1, s3
1601; RV64I-NEXT:    call __extendhfsf2
1602; RV64I-NEXT:    li a1, 0
1603; RV64I-NEXT:    call __addsf3
1604; RV64I-NEXT:    call __truncsfhf2
1605; RV64I-NEXT:    mv s2, a0
1606; RV64I-NEXT:    and a0, s1, s3
1607; RV64I-NEXT:    call __extendhfsf2
1608; RV64I-NEXT:    li a1, 0
1609; RV64I-NEXT:    call __addsf3
1610; RV64I-NEXT:    call __truncsfhf2
1611; RV64I-NEXT:    mv s1, a0
1612; RV64I-NEXT:    and a0, s2, s3
1613; RV64I-NEXT:    call __extendhfsf2
1614; RV64I-NEXT:    lui s4, 524288
1615; RV64I-NEXT:    xor a0, a0, s4
1616; RV64I-NEXT:    call __truncsfhf2
1617; RV64I-NEXT:    mv s2, a0
1618; RV64I-NEXT:    and a0, s1, s3
1619; RV64I-NEXT:    call __extendhfsf2
1620; RV64I-NEXT:    xor a0, a0, s4
1621; RV64I-NEXT:    call __truncsfhf2
1622; RV64I-NEXT:    mv s1, a0
1623; RV64I-NEXT:    and a0, s0, s3
1624; RV64I-NEXT:    call __extendhfsf2
1625; RV64I-NEXT:    mv s0, a0
1626; RV64I-NEXT:    and a0, s2, s3
1627; RV64I-NEXT:    call __extendhfsf2
1628; RV64I-NEXT:    mv s2, a0
1629; RV64I-NEXT:    and a0, s1, s3
1630; RV64I-NEXT:    call __extendhfsf2
1631; RV64I-NEXT:    mv a2, a0
1632; RV64I-NEXT:    mv a0, s0
1633; RV64I-NEXT:    mv a1, s2
1634; RV64I-NEXT:    call fmaf
1635; RV64I-NEXT:    call __truncsfhf2
1636; RV64I-NEXT:    ld ra, 40(sp) # 8-byte Folded Reload
1637; RV64I-NEXT:    ld s0, 32(sp) # 8-byte Folded Reload
1638; RV64I-NEXT:    ld s1, 24(sp) # 8-byte Folded Reload
1639; RV64I-NEXT:    ld s2, 16(sp) # 8-byte Folded Reload
1640; RV64I-NEXT:    ld s3, 8(sp) # 8-byte Folded Reload
1641; RV64I-NEXT:    ld s4, 0(sp) # 8-byte Folded Reload
1642; RV64I-NEXT:    addi sp, sp, 48
1643; RV64I-NEXT:    ret
1644;
1645; CHECKIZFHMIN-LABEL: fnmadd_h_2:
1646; CHECKIZFHMIN:       # %bb.0:
1647; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa1
1648; CHECKIZFHMIN-NEXT:    fmv.w.x fa4, zero
1649; CHECKIZFHMIN-NEXT:    fcvt.s.h fa3, fa2
1650; CHECKIZFHMIN-NEXT:    lui a0, 1048568
1651; CHECKIZFHMIN-NEXT:    fadd.s fa5, fa5, fa4
1652; CHECKIZFHMIN-NEXT:    fadd.s fa4, fa3, fa4
1653; CHECKIZFHMIN-NEXT:    fcvt.h.s fa5, fa5
1654; CHECKIZFHMIN-NEXT:    fcvt.h.s fa4, fa4
1655; CHECKIZFHMIN-NEXT:    fmv.x.h a1, fa5
1656; CHECKIZFHMIN-NEXT:    fmv.x.h a2, fa4
1657; CHECKIZFHMIN-NEXT:    xor a1, a1, a0
1658; CHECKIZFHMIN-NEXT:    xor a0, a2, a0
1659; CHECKIZFHMIN-NEXT:    fmv.h.x fa5, a1
1660; CHECKIZFHMIN-NEXT:    fmv.h.x fa4, a0
1661; CHECKIZFHMIN-NEXT:    fcvt.s.h fa4, fa4
1662; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa5
1663; CHECKIZFHMIN-NEXT:    fcvt.s.h fa3, fa0
1664; CHECKIZFHMIN-NEXT:    fmadd.s fa5, fa3, fa5, fa4
1665; CHECKIZFHMIN-NEXT:    fcvt.h.s fa0, fa5
1666; CHECKIZFHMIN-NEXT:    ret
1667;
1668; CHECKIZHINXMIN-LABEL: fnmadd_h_2:
1669; CHECKIZHINXMIN:       # %bb.0:
1670; CHECKIZHINXMIN-NEXT:    fcvt.s.h a1, a1
1671; CHECKIZHINXMIN-NEXT:    fcvt.s.h a2, a2
1672; CHECKIZHINXMIN-NEXT:    lui a3, 1048568
1673; CHECKIZHINXMIN-NEXT:    fadd.s a1, a1, zero
1674; CHECKIZHINXMIN-NEXT:    fadd.s a2, a2, zero
1675; CHECKIZHINXMIN-NEXT:    fcvt.h.s a1, a1
1676; CHECKIZHINXMIN-NEXT:    fcvt.h.s a2, a2
1677; CHECKIZHINXMIN-NEXT:    xor a1, a1, a3
1678; CHECKIZHINXMIN-NEXT:    xor a2, a2, a3
1679; CHECKIZHINXMIN-NEXT:    fcvt.s.h a2, a2
1680; CHECKIZHINXMIN-NEXT:    fcvt.s.h a1, a1
1681; CHECKIZHINXMIN-NEXT:    fcvt.s.h a0, a0
1682; CHECKIZHINXMIN-NEXT:    fmadd.s a0, a0, a1, a2
1683; CHECKIZHINXMIN-NEXT:    fcvt.h.s a0, a0
1684; CHECKIZHINXMIN-NEXT:    ret
1685  %b_ = fadd half 0.0, %b
1686  %c_ = fadd half 0.0, %c
1687  %negb = fsub half -0.0, %b_
1688  %negc = fsub half -0.0, %c_
1689  %1 = call half @llvm.fma.f16(half %a, half %negb, half %negc)
1690  ret half %1
1691}
1692
1693define half @fnmadd_h_3(half %a, half %b, half %c) nounwind {
1694; RV32IZFH-LABEL: fnmadd_h_3:
1695; RV32IZFH:       # %bb.0:
1696; RV32IZFH-NEXT:    fmadd.h ft0, fa0, fa1, fa2
1697; RV32IZFH-NEXT:    fneg.h fa0, ft0
1698; RV32IZFH-NEXT:    ret
1699;
1700; RV64IZFH-LABEL: fnmadd_h_3:
1701; RV64IZFH:       # %bb.0:
1702; RV64IZFH-NEXT:    fmadd.h ft0, fa0, fa1, fa2
1703; RV64IZFH-NEXT:    fneg.h fa0, ft0
1704; RV64IZFH-NEXT:    ret
1705;
1706; CHECKIZFH-LABEL: fnmadd_h_3:
1707; CHECKIZFH:       # %bb.0:
1708; CHECKIZFH-NEXT:    fmadd.h fa5, fa0, fa1, fa2
1709; CHECKIZFH-NEXT:    fneg.h fa0, fa5
1710; CHECKIZFH-NEXT:    ret
1711;
1712; CHECKIZHINX-LABEL: fnmadd_h_3:
1713; CHECKIZHINX:       # %bb.0:
1714; CHECKIZHINX-NEXT:    fmadd.h a0, a0, a1, a2
1715; CHECKIZHINX-NEXT:    fneg.h a0, a0
1716; CHECKIZHINX-NEXT:    ret
1717;
1718; RV32I-LABEL: fnmadd_h_3:
1719; RV32I:       # %bb.0:
1720; RV32I-NEXT:    addi sp, sp, -32
1721; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
1722; RV32I-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
1723; RV32I-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
1724; RV32I-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
1725; RV32I-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
1726; RV32I-NEXT:    mv s0, a2
1727; RV32I-NEXT:    mv s1, a1
1728; RV32I-NEXT:    lui a1, 16
1729; RV32I-NEXT:    addi s3, a1, -1
1730; RV32I-NEXT:    and a0, a0, s3
1731; RV32I-NEXT:    call __extendhfsf2
1732; RV32I-NEXT:    mv s2, a0
1733; RV32I-NEXT:    and a0, s1, s3
1734; RV32I-NEXT:    call __extendhfsf2
1735; RV32I-NEXT:    mv s1, a0
1736; RV32I-NEXT:    and a0, s0, s3
1737; RV32I-NEXT:    call __extendhfsf2
1738; RV32I-NEXT:    mv a2, a0
1739; RV32I-NEXT:    mv a0, s2
1740; RV32I-NEXT:    mv a1, s1
1741; RV32I-NEXT:    call fmaf
1742; RV32I-NEXT:    call __truncsfhf2
1743; RV32I-NEXT:    lui a1, 1048568
1744; RV32I-NEXT:    xor a0, a0, a1
1745; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
1746; RV32I-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
1747; RV32I-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
1748; RV32I-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
1749; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
1750; RV32I-NEXT:    addi sp, sp, 32
1751; RV32I-NEXT:    ret
1752;
1753; RV64I-LABEL: fnmadd_h_3:
1754; RV64I:       # %bb.0:
1755; RV64I-NEXT:    addi sp, sp, -48
1756; RV64I-NEXT:    sd ra, 40(sp) # 8-byte Folded Spill
1757; RV64I-NEXT:    sd s0, 32(sp) # 8-byte Folded Spill
1758; RV64I-NEXT:    sd s1, 24(sp) # 8-byte Folded Spill
1759; RV64I-NEXT:    sd s2, 16(sp) # 8-byte Folded Spill
1760; RV64I-NEXT:    sd s3, 8(sp) # 8-byte Folded Spill
1761; RV64I-NEXT:    mv s0, a2
1762; RV64I-NEXT:    mv s1, a1
1763; RV64I-NEXT:    lui a1, 16
1764; RV64I-NEXT:    addiw s3, a1, -1
1765; RV64I-NEXT:    and a0, a0, s3
1766; RV64I-NEXT:    call __extendhfsf2
1767; RV64I-NEXT:    mv s2, a0
1768; RV64I-NEXT:    and a0, s1, s3
1769; RV64I-NEXT:    call __extendhfsf2
1770; RV64I-NEXT:    mv s1, a0
1771; RV64I-NEXT:    and a0, s0, s3
1772; RV64I-NEXT:    call __extendhfsf2
1773; RV64I-NEXT:    mv a2, a0
1774; RV64I-NEXT:    mv a0, s2
1775; RV64I-NEXT:    mv a1, s1
1776; RV64I-NEXT:    call fmaf
1777; RV64I-NEXT:    call __truncsfhf2
1778; RV64I-NEXT:    lui a1, 1048568
1779; RV64I-NEXT:    xor a0, a0, a1
1780; RV64I-NEXT:    ld ra, 40(sp) # 8-byte Folded Reload
1781; RV64I-NEXT:    ld s0, 32(sp) # 8-byte Folded Reload
1782; RV64I-NEXT:    ld s1, 24(sp) # 8-byte Folded Reload
1783; RV64I-NEXT:    ld s2, 16(sp) # 8-byte Folded Reload
1784; RV64I-NEXT:    ld s3, 8(sp) # 8-byte Folded Reload
1785; RV64I-NEXT:    addi sp, sp, 48
1786; RV64I-NEXT:    ret
1787;
1788; CHECKIZFHMIN-LABEL: fnmadd_h_3:
1789; CHECKIZFHMIN:       # %bb.0:
1790; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa2
1791; CHECKIZFHMIN-NEXT:    fcvt.s.h fa4, fa1
1792; CHECKIZFHMIN-NEXT:    fcvt.s.h fa3, fa0
1793; CHECKIZFHMIN-NEXT:    fmadd.s fa5, fa3, fa4, fa5
1794; CHECKIZFHMIN-NEXT:    fcvt.h.s fa5, fa5
1795; CHECKIZFHMIN-NEXT:    fmv.x.h a0, fa5
1796; CHECKIZFHMIN-NEXT:    lui a1, 1048568
1797; CHECKIZFHMIN-NEXT:    xor a0, a0, a1
1798; CHECKIZFHMIN-NEXT:    fmv.h.x fa0, a0
1799; CHECKIZFHMIN-NEXT:    ret
1800;
1801; CHECKIZHINXMIN-LABEL: fnmadd_h_3:
1802; CHECKIZHINXMIN:       # %bb.0:
1803; CHECKIZHINXMIN-NEXT:    fcvt.s.h a2, a2
1804; CHECKIZHINXMIN-NEXT:    fcvt.s.h a1, a1
1805; CHECKIZHINXMIN-NEXT:    fcvt.s.h a0, a0
1806; CHECKIZHINXMIN-NEXT:    fmadd.s a0, a0, a1, a2
1807; CHECKIZHINXMIN-NEXT:    fcvt.h.s a0, a0
1808; CHECKIZHINXMIN-NEXT:    lui a1, 1048568
1809; CHECKIZHINXMIN-NEXT:    xor a0, a0, a1
1810; CHECKIZHINXMIN-NEXT:    # kill: def $x10_h killed $x10_h killed $x10
1811; CHECKIZHINXMIN-NEXT:    ret
1812  %1 = call half @llvm.fma.f16(half %a, half %b, half %c)
1813  %neg = fneg half %1
1814  ret half %neg
1815}
1816
1817
1818define half @fnmadd_nsz(half %a, half %b, half %c) nounwind {
1819; RV32IZFH-LABEL: fnmadd_nsz:
1820; RV32IZFH:       # %bb.0:
1821; RV32IZFH-NEXT:    fnmadd.h fa0, fa0, fa1, fa2
1822; RV32IZFH-NEXT:    ret
1823;
1824; RV64IZFH-LABEL: fnmadd_nsz:
1825; RV64IZFH:       # %bb.0:
1826; RV64IZFH-NEXT:    fnmadd.h fa0, fa0, fa1, fa2
1827; RV64IZFH-NEXT:    ret
1828;
1829; CHECKIZFH-LABEL: fnmadd_nsz:
1830; CHECKIZFH:       # %bb.0:
1831; CHECKIZFH-NEXT:    fnmadd.h fa0, fa0, fa1, fa2
1832; CHECKIZFH-NEXT:    ret
1833;
1834; CHECKIZHINX-LABEL: fnmadd_nsz:
1835; CHECKIZHINX:       # %bb.0:
1836; CHECKIZHINX-NEXT:    fnmadd.h a0, a0, a1, a2
1837; CHECKIZHINX-NEXT:    ret
1838;
1839; RV32I-LABEL: fnmadd_nsz:
1840; RV32I:       # %bb.0:
1841; RV32I-NEXT:    addi sp, sp, -32
1842; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
1843; RV32I-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
1844; RV32I-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
1845; RV32I-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
1846; RV32I-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
1847; RV32I-NEXT:    mv s0, a2
1848; RV32I-NEXT:    mv s1, a1
1849; RV32I-NEXT:    lui a1, 16
1850; RV32I-NEXT:    addi s3, a1, -1
1851; RV32I-NEXT:    and a0, a0, s3
1852; RV32I-NEXT:    call __extendhfsf2
1853; RV32I-NEXT:    mv s2, a0
1854; RV32I-NEXT:    and a0, s1, s3
1855; RV32I-NEXT:    call __extendhfsf2
1856; RV32I-NEXT:    mv s1, a0
1857; RV32I-NEXT:    and a0, s0, s3
1858; RV32I-NEXT:    call __extendhfsf2
1859; RV32I-NEXT:    mv a2, a0
1860; RV32I-NEXT:    mv a0, s2
1861; RV32I-NEXT:    mv a1, s1
1862; RV32I-NEXT:    call fmaf
1863; RV32I-NEXT:    call __truncsfhf2
1864; RV32I-NEXT:    lui a1, 1048568
1865; RV32I-NEXT:    xor a0, a0, a1
1866; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
1867; RV32I-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
1868; RV32I-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
1869; RV32I-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
1870; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
1871; RV32I-NEXT:    addi sp, sp, 32
1872; RV32I-NEXT:    ret
1873;
1874; RV64I-LABEL: fnmadd_nsz:
1875; RV64I:       # %bb.0:
1876; RV64I-NEXT:    addi sp, sp, -48
1877; RV64I-NEXT:    sd ra, 40(sp) # 8-byte Folded Spill
1878; RV64I-NEXT:    sd s0, 32(sp) # 8-byte Folded Spill
1879; RV64I-NEXT:    sd s1, 24(sp) # 8-byte Folded Spill
1880; RV64I-NEXT:    sd s2, 16(sp) # 8-byte Folded Spill
1881; RV64I-NEXT:    sd s3, 8(sp) # 8-byte Folded Spill
1882; RV64I-NEXT:    mv s0, a2
1883; RV64I-NEXT:    mv s1, a1
1884; RV64I-NEXT:    lui a1, 16
1885; RV64I-NEXT:    addiw s3, a1, -1
1886; RV64I-NEXT:    and a0, a0, s3
1887; RV64I-NEXT:    call __extendhfsf2
1888; RV64I-NEXT:    mv s2, a0
1889; RV64I-NEXT:    and a0, s1, s3
1890; RV64I-NEXT:    call __extendhfsf2
1891; RV64I-NEXT:    mv s1, a0
1892; RV64I-NEXT:    and a0, s0, s3
1893; RV64I-NEXT:    call __extendhfsf2
1894; RV64I-NEXT:    mv a2, a0
1895; RV64I-NEXT:    mv a0, s2
1896; RV64I-NEXT:    mv a1, s1
1897; RV64I-NEXT:    call fmaf
1898; RV64I-NEXT:    call __truncsfhf2
1899; RV64I-NEXT:    lui a1, 1048568
1900; RV64I-NEXT:    xor a0, a0, a1
1901; RV64I-NEXT:    ld ra, 40(sp) # 8-byte Folded Reload
1902; RV64I-NEXT:    ld s0, 32(sp) # 8-byte Folded Reload
1903; RV64I-NEXT:    ld s1, 24(sp) # 8-byte Folded Reload
1904; RV64I-NEXT:    ld s2, 16(sp) # 8-byte Folded Reload
1905; RV64I-NEXT:    ld s3, 8(sp) # 8-byte Folded Reload
1906; RV64I-NEXT:    addi sp, sp, 48
1907; RV64I-NEXT:    ret
1908;
1909; CHECKIZFHMIN-LABEL: fnmadd_nsz:
1910; CHECKIZFHMIN:       # %bb.0:
1911; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa2
1912; CHECKIZFHMIN-NEXT:    fcvt.s.h fa4, fa1
1913; CHECKIZFHMIN-NEXT:    fcvt.s.h fa3, fa0
1914; CHECKIZFHMIN-NEXT:    fmadd.s fa5, fa3, fa4, fa5
1915; CHECKIZFHMIN-NEXT:    fcvt.h.s fa5, fa5
1916; CHECKIZFHMIN-NEXT:    fmv.x.h a0, fa5
1917; CHECKIZFHMIN-NEXT:    lui a1, 1048568
1918; CHECKIZFHMIN-NEXT:    xor a0, a0, a1
1919; CHECKIZFHMIN-NEXT:    fmv.h.x fa0, a0
1920; CHECKIZFHMIN-NEXT:    ret
1921;
1922; CHECKIZHINXMIN-LABEL: fnmadd_nsz:
1923; CHECKIZHINXMIN:       # %bb.0:
1924; CHECKIZHINXMIN-NEXT:    fcvt.s.h a2, a2
1925; CHECKIZHINXMIN-NEXT:    fcvt.s.h a1, a1
1926; CHECKIZHINXMIN-NEXT:    fcvt.s.h a0, a0
1927; CHECKIZHINXMIN-NEXT:    fmadd.s a0, a0, a1, a2
1928; CHECKIZHINXMIN-NEXT:    fcvt.h.s a0, a0
1929; CHECKIZHINXMIN-NEXT:    lui a1, 1048568
1930; CHECKIZHINXMIN-NEXT:    xor a0, a0, a1
1931; CHECKIZHINXMIN-NEXT:    # kill: def $x10_h killed $x10_h killed $x10
1932; CHECKIZHINXMIN-NEXT:    ret
1933  %1 = call nsz half @llvm.fma.f16(half %a, half %b, half %c)
1934  %neg = fneg nsz half %1
1935  ret half %neg
1936}
1937
1938define half @fnmsub_h(half %a, half %b, half %c) nounwind {
1939; CHECKIZFH-LABEL: fnmsub_h:
1940; CHECKIZFH:       # %bb.0:
1941; CHECKIZFH-NEXT:    fmv.h.x fa5, zero
1942; CHECKIZFH-NEXT:    fadd.h fa5, fa0, fa5
1943; CHECKIZFH-NEXT:    fnmsub.h fa0, fa5, fa1, fa2
1944; CHECKIZFH-NEXT:    ret
1945;
1946; CHECKIZHINX-LABEL: fnmsub_h:
1947; CHECKIZHINX:       # %bb.0:
1948; CHECKIZHINX-NEXT:    fadd.h a0, a0, zero
1949; CHECKIZHINX-NEXT:    fnmsub.h a0, a0, a1, a2
1950; CHECKIZHINX-NEXT:    ret
1951;
1952; RV32I-LABEL: fnmsub_h:
1953; RV32I:       # %bb.0:
1954; RV32I-NEXT:    addi sp, sp, -32
1955; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
1956; RV32I-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
1957; RV32I-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
1958; RV32I-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
1959; RV32I-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
1960; RV32I-NEXT:    mv s0, a2
1961; RV32I-NEXT:    mv s1, a1
1962; RV32I-NEXT:    lui a1, 16
1963; RV32I-NEXT:    addi s3, a1, -1
1964; RV32I-NEXT:    and a0, a0, s3
1965; RV32I-NEXT:    call __extendhfsf2
1966; RV32I-NEXT:    li a1, 0
1967; RV32I-NEXT:    call __addsf3
1968; RV32I-NEXT:    call __truncsfhf2
1969; RV32I-NEXT:    and a0, a0, s3
1970; RV32I-NEXT:    call __extendhfsf2
1971; RV32I-NEXT:    lui a1, 524288
1972; RV32I-NEXT:    xor a0, a0, a1
1973; RV32I-NEXT:    call __truncsfhf2
1974; RV32I-NEXT:    mv s2, a0
1975; RV32I-NEXT:    and a0, s1, s3
1976; RV32I-NEXT:    call __extendhfsf2
1977; RV32I-NEXT:    mv s1, a0
1978; RV32I-NEXT:    and a0, s0, s3
1979; RV32I-NEXT:    call __extendhfsf2
1980; RV32I-NEXT:    mv s0, a0
1981; RV32I-NEXT:    and a0, s2, s3
1982; RV32I-NEXT:    call __extendhfsf2
1983; RV32I-NEXT:    mv a1, s1
1984; RV32I-NEXT:    mv a2, s0
1985; RV32I-NEXT:    call fmaf
1986; RV32I-NEXT:    call __truncsfhf2
1987; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
1988; RV32I-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
1989; RV32I-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
1990; RV32I-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
1991; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
1992; RV32I-NEXT:    addi sp, sp, 32
1993; RV32I-NEXT:    ret
1994;
1995; RV64I-LABEL: fnmsub_h:
1996; RV64I:       # %bb.0:
1997; RV64I-NEXT:    addi sp, sp, -48
1998; RV64I-NEXT:    sd ra, 40(sp) # 8-byte Folded Spill
1999; RV64I-NEXT:    sd s0, 32(sp) # 8-byte Folded Spill
2000; RV64I-NEXT:    sd s1, 24(sp) # 8-byte Folded Spill
2001; RV64I-NEXT:    sd s2, 16(sp) # 8-byte Folded Spill
2002; RV64I-NEXT:    sd s3, 8(sp) # 8-byte Folded Spill
2003; RV64I-NEXT:    mv s0, a2
2004; RV64I-NEXT:    mv s1, a1
2005; RV64I-NEXT:    lui a1, 16
2006; RV64I-NEXT:    addiw s3, a1, -1
2007; RV64I-NEXT:    and a0, a0, s3
2008; RV64I-NEXT:    call __extendhfsf2
2009; RV64I-NEXT:    li a1, 0
2010; RV64I-NEXT:    call __addsf3
2011; RV64I-NEXT:    call __truncsfhf2
2012; RV64I-NEXT:    and a0, a0, s3
2013; RV64I-NEXT:    call __extendhfsf2
2014; RV64I-NEXT:    lui a1, 524288
2015; RV64I-NEXT:    xor a0, a0, a1
2016; RV64I-NEXT:    call __truncsfhf2
2017; RV64I-NEXT:    mv s2, a0
2018; RV64I-NEXT:    and a0, s1, s3
2019; RV64I-NEXT:    call __extendhfsf2
2020; RV64I-NEXT:    mv s1, a0
2021; RV64I-NEXT:    and a0, s0, s3
2022; RV64I-NEXT:    call __extendhfsf2
2023; RV64I-NEXT:    mv s0, a0
2024; RV64I-NEXT:    and a0, s2, s3
2025; RV64I-NEXT:    call __extendhfsf2
2026; RV64I-NEXT:    mv a1, s1
2027; RV64I-NEXT:    mv a2, s0
2028; RV64I-NEXT:    call fmaf
2029; RV64I-NEXT:    call __truncsfhf2
2030; RV64I-NEXT:    ld ra, 40(sp) # 8-byte Folded Reload
2031; RV64I-NEXT:    ld s0, 32(sp) # 8-byte Folded Reload
2032; RV64I-NEXT:    ld s1, 24(sp) # 8-byte Folded Reload
2033; RV64I-NEXT:    ld s2, 16(sp) # 8-byte Folded Reload
2034; RV64I-NEXT:    ld s3, 8(sp) # 8-byte Folded Reload
2035; RV64I-NEXT:    addi sp, sp, 48
2036; RV64I-NEXT:    ret
2037;
2038; CHECKIZFHMIN-LABEL: fnmsub_h:
2039; CHECKIZFHMIN:       # %bb.0:
2040; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa0
2041; CHECKIZFHMIN-NEXT:    fmv.w.x fa4, zero
2042; CHECKIZFHMIN-NEXT:    lui a0, 1048568
2043; CHECKIZFHMIN-NEXT:    fcvt.s.h fa3, fa2
2044; CHECKIZFHMIN-NEXT:    fadd.s fa5, fa5, fa4
2045; CHECKIZFHMIN-NEXT:    fcvt.h.s fa5, fa5
2046; CHECKIZFHMIN-NEXT:    fmv.x.h a1, fa5
2047; CHECKIZFHMIN-NEXT:    xor a0, a1, a0
2048; CHECKIZFHMIN-NEXT:    fmv.h.x fa5, a0
2049; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa5
2050; CHECKIZFHMIN-NEXT:    fcvt.s.h fa4, fa1
2051; CHECKIZFHMIN-NEXT:    fmadd.s fa5, fa5, fa4, fa3
2052; CHECKIZFHMIN-NEXT:    fcvt.h.s fa0, fa5
2053; CHECKIZFHMIN-NEXT:    ret
2054;
2055; CHECKIZHINXMIN-LABEL: fnmsub_h:
2056; CHECKIZHINXMIN:       # %bb.0:
2057; CHECKIZHINXMIN-NEXT:    fcvt.s.h a0, a0
2058; CHECKIZHINXMIN-NEXT:    lui a3, 1048568
2059; CHECKIZHINXMIN-NEXT:    fcvt.s.h a2, a2
2060; CHECKIZHINXMIN-NEXT:    fadd.s a0, a0, zero
2061; CHECKIZHINXMIN-NEXT:    fcvt.h.s a0, a0
2062; CHECKIZHINXMIN-NEXT:    xor a0, a0, a3
2063; CHECKIZHINXMIN-NEXT:    fcvt.s.h a0, a0
2064; CHECKIZHINXMIN-NEXT:    fcvt.s.h a1, a1
2065; CHECKIZHINXMIN-NEXT:    fmadd.s a0, a0, a1, a2
2066; CHECKIZHINXMIN-NEXT:    fcvt.h.s a0, a0
2067; CHECKIZHINXMIN-NEXT:    ret
2068  %a_ = fadd half 0.0, %a
2069  %nega = fsub half -0.0, %a_
2070  %1 = call half @llvm.fma.f16(half %nega, half %b, half %c)
2071  ret half %1
2072}
2073
2074define half @fnmsub_h_2(half %a, half %b, half %c) nounwind {
2075; CHECKIZFH-LABEL: fnmsub_h_2:
2076; CHECKIZFH:       # %bb.0:
2077; CHECKIZFH-NEXT:    fmv.h.x fa5, zero
2078; CHECKIZFH-NEXT:    fadd.h fa5, fa1, fa5
2079; CHECKIZFH-NEXT:    fnmsub.h fa0, fa5, fa0, fa2
2080; CHECKIZFH-NEXT:    ret
2081;
2082; CHECKIZHINX-LABEL: fnmsub_h_2:
2083; CHECKIZHINX:       # %bb.0:
2084; CHECKIZHINX-NEXT:    fadd.h a1, a1, zero
2085; CHECKIZHINX-NEXT:    fnmsub.h a0, a1, a0, a2
2086; CHECKIZHINX-NEXT:    ret
2087;
2088; RV32I-LABEL: fnmsub_h_2:
2089; RV32I:       # %bb.0:
2090; RV32I-NEXT:    addi sp, sp, -32
2091; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
2092; RV32I-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
2093; RV32I-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
2094; RV32I-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
2095; RV32I-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
2096; RV32I-NEXT:    mv s0, a2
2097; RV32I-NEXT:    mv s1, a0
2098; RV32I-NEXT:    lui a0, 16
2099; RV32I-NEXT:    addi s3, a0, -1
2100; RV32I-NEXT:    and a0, a1, s3
2101; RV32I-NEXT:    call __extendhfsf2
2102; RV32I-NEXT:    li a1, 0
2103; RV32I-NEXT:    call __addsf3
2104; RV32I-NEXT:    call __truncsfhf2
2105; RV32I-NEXT:    and a0, a0, s3
2106; RV32I-NEXT:    call __extendhfsf2
2107; RV32I-NEXT:    lui a1, 524288
2108; RV32I-NEXT:    xor a0, a0, a1
2109; RV32I-NEXT:    call __truncsfhf2
2110; RV32I-NEXT:    mv s2, a0
2111; RV32I-NEXT:    and a0, s1, s3
2112; RV32I-NEXT:    call __extendhfsf2
2113; RV32I-NEXT:    mv s1, a0
2114; RV32I-NEXT:    and a0, s0, s3
2115; RV32I-NEXT:    call __extendhfsf2
2116; RV32I-NEXT:    mv s0, a0
2117; RV32I-NEXT:    and a0, s2, s3
2118; RV32I-NEXT:    call __extendhfsf2
2119; RV32I-NEXT:    mv a1, a0
2120; RV32I-NEXT:    mv a0, s1
2121; RV32I-NEXT:    mv a2, s0
2122; RV32I-NEXT:    call fmaf
2123; RV32I-NEXT:    call __truncsfhf2
2124; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
2125; RV32I-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
2126; RV32I-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
2127; RV32I-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
2128; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
2129; RV32I-NEXT:    addi sp, sp, 32
2130; RV32I-NEXT:    ret
2131;
2132; RV64I-LABEL: fnmsub_h_2:
2133; RV64I:       # %bb.0:
2134; RV64I-NEXT:    addi sp, sp, -48
2135; RV64I-NEXT:    sd ra, 40(sp) # 8-byte Folded Spill
2136; RV64I-NEXT:    sd s0, 32(sp) # 8-byte Folded Spill
2137; RV64I-NEXT:    sd s1, 24(sp) # 8-byte Folded Spill
2138; RV64I-NEXT:    sd s2, 16(sp) # 8-byte Folded Spill
2139; RV64I-NEXT:    sd s3, 8(sp) # 8-byte Folded Spill
2140; RV64I-NEXT:    mv s0, a2
2141; RV64I-NEXT:    mv s1, a0
2142; RV64I-NEXT:    lui a0, 16
2143; RV64I-NEXT:    addiw s3, a0, -1
2144; RV64I-NEXT:    and a0, a1, s3
2145; RV64I-NEXT:    call __extendhfsf2
2146; RV64I-NEXT:    li a1, 0
2147; RV64I-NEXT:    call __addsf3
2148; RV64I-NEXT:    call __truncsfhf2
2149; RV64I-NEXT:    and a0, a0, s3
2150; RV64I-NEXT:    call __extendhfsf2
2151; RV64I-NEXT:    lui a1, 524288
2152; RV64I-NEXT:    xor a0, a0, a1
2153; RV64I-NEXT:    call __truncsfhf2
2154; RV64I-NEXT:    mv s2, a0
2155; RV64I-NEXT:    and a0, s1, s3
2156; RV64I-NEXT:    call __extendhfsf2
2157; RV64I-NEXT:    mv s1, a0
2158; RV64I-NEXT:    and a0, s0, s3
2159; RV64I-NEXT:    call __extendhfsf2
2160; RV64I-NEXT:    mv s0, a0
2161; RV64I-NEXT:    and a0, s2, s3
2162; RV64I-NEXT:    call __extendhfsf2
2163; RV64I-NEXT:    mv a1, a0
2164; RV64I-NEXT:    mv a0, s1
2165; RV64I-NEXT:    mv a2, s0
2166; RV64I-NEXT:    call fmaf
2167; RV64I-NEXT:    call __truncsfhf2
2168; RV64I-NEXT:    ld ra, 40(sp) # 8-byte Folded Reload
2169; RV64I-NEXT:    ld s0, 32(sp) # 8-byte Folded Reload
2170; RV64I-NEXT:    ld s1, 24(sp) # 8-byte Folded Reload
2171; RV64I-NEXT:    ld s2, 16(sp) # 8-byte Folded Reload
2172; RV64I-NEXT:    ld s3, 8(sp) # 8-byte Folded Reload
2173; RV64I-NEXT:    addi sp, sp, 48
2174; RV64I-NEXT:    ret
2175;
2176; CHECKIZFHMIN-LABEL: fnmsub_h_2:
2177; CHECKIZFHMIN:       # %bb.0:
2178; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa1
2179; CHECKIZFHMIN-NEXT:    fmv.w.x fa4, zero
2180; CHECKIZFHMIN-NEXT:    lui a0, 1048568
2181; CHECKIZFHMIN-NEXT:    fcvt.s.h fa3, fa2
2182; CHECKIZFHMIN-NEXT:    fadd.s fa5, fa5, fa4
2183; CHECKIZFHMIN-NEXT:    fcvt.h.s fa5, fa5
2184; CHECKIZFHMIN-NEXT:    fmv.x.h a1, fa5
2185; CHECKIZFHMIN-NEXT:    xor a0, a1, a0
2186; CHECKIZFHMIN-NEXT:    fmv.h.x fa5, a0
2187; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa5
2188; CHECKIZFHMIN-NEXT:    fcvt.s.h fa4, fa0
2189; CHECKIZFHMIN-NEXT:    fmadd.s fa5, fa4, fa5, fa3
2190; CHECKIZFHMIN-NEXT:    fcvt.h.s fa0, fa5
2191; CHECKIZFHMIN-NEXT:    ret
2192;
2193; CHECKIZHINXMIN-LABEL: fnmsub_h_2:
2194; CHECKIZHINXMIN:       # %bb.0:
2195; CHECKIZHINXMIN-NEXT:    fcvt.s.h a1, a1
2196; CHECKIZHINXMIN-NEXT:    lui a3, 1048568
2197; CHECKIZHINXMIN-NEXT:    fcvt.s.h a2, a2
2198; CHECKIZHINXMIN-NEXT:    fadd.s a1, a1, zero
2199; CHECKIZHINXMIN-NEXT:    fcvt.h.s a1, a1
2200; CHECKIZHINXMIN-NEXT:    xor a1, a1, a3
2201; CHECKIZHINXMIN-NEXT:    fcvt.s.h a1, a1
2202; CHECKIZHINXMIN-NEXT:    fcvt.s.h a0, a0
2203; CHECKIZHINXMIN-NEXT:    fmadd.s a0, a0, a1, a2
2204; CHECKIZHINXMIN-NEXT:    fcvt.h.s a0, a0
2205; CHECKIZHINXMIN-NEXT:    ret
2206  %b_ = fadd half 0.0, %b
2207  %negb = fsub half -0.0, %b_
2208  %1 = call half @llvm.fma.f16(half %a, half %negb, half %c)
2209  ret half %1
2210}
2211
2212define half @fmadd_h_contract(half %a, half %b, half %c) nounwind {
2213; CHECKIZFH-LABEL: fmadd_h_contract:
2214; CHECKIZFH:       # %bb.0:
2215; CHECKIZFH-NEXT:    fmadd.h fa0, fa0, fa1, fa2
2216; CHECKIZFH-NEXT:    ret
2217;
2218; CHECKIZHINX-LABEL: fmadd_h_contract:
2219; CHECKIZHINX:       # %bb.0:
2220; CHECKIZHINX-NEXT:    fmadd.h a0, a0, a1, a2
2221; CHECKIZHINX-NEXT:    ret
2222;
2223; RV32I-LABEL: fmadd_h_contract:
2224; RV32I:       # %bb.0:
2225; RV32I-NEXT:    addi sp, sp, -32
2226; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
2227; RV32I-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
2228; RV32I-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
2229; RV32I-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
2230; RV32I-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
2231; RV32I-NEXT:    mv s0, a2
2232; RV32I-NEXT:    mv s1, a1
2233; RV32I-NEXT:    lui a1, 16
2234; RV32I-NEXT:    addi s3, a1, -1
2235; RV32I-NEXT:    and a0, a0, s3
2236; RV32I-NEXT:    call __extendhfsf2
2237; RV32I-NEXT:    mv s2, a0
2238; RV32I-NEXT:    and a0, s1, s3
2239; RV32I-NEXT:    call __extendhfsf2
2240; RV32I-NEXT:    mv a1, a0
2241; RV32I-NEXT:    mv a0, s2
2242; RV32I-NEXT:    call __mulsf3
2243; RV32I-NEXT:    call __truncsfhf2
2244; RV32I-NEXT:    mv s1, a0
2245; RV32I-NEXT:    and a0, s0, s3
2246; RV32I-NEXT:    call __extendhfsf2
2247; RV32I-NEXT:    mv s0, a0
2248; RV32I-NEXT:    and a0, s1, s3
2249; RV32I-NEXT:    call __extendhfsf2
2250; RV32I-NEXT:    mv a1, s0
2251; RV32I-NEXT:    call __addsf3
2252; RV32I-NEXT:    call __truncsfhf2
2253; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
2254; RV32I-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
2255; RV32I-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
2256; RV32I-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
2257; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
2258; RV32I-NEXT:    addi sp, sp, 32
2259; RV32I-NEXT:    ret
2260;
2261; RV64I-LABEL: fmadd_h_contract:
2262; RV64I:       # %bb.0:
2263; RV64I-NEXT:    addi sp, sp, -48
2264; RV64I-NEXT:    sd ra, 40(sp) # 8-byte Folded Spill
2265; RV64I-NEXT:    sd s0, 32(sp) # 8-byte Folded Spill
2266; RV64I-NEXT:    sd s1, 24(sp) # 8-byte Folded Spill
2267; RV64I-NEXT:    sd s2, 16(sp) # 8-byte Folded Spill
2268; RV64I-NEXT:    sd s3, 8(sp) # 8-byte Folded Spill
2269; RV64I-NEXT:    mv s0, a2
2270; RV64I-NEXT:    mv s1, a1
2271; RV64I-NEXT:    lui a1, 16
2272; RV64I-NEXT:    addiw s3, a1, -1
2273; RV64I-NEXT:    and a0, a0, s3
2274; RV64I-NEXT:    call __extendhfsf2
2275; RV64I-NEXT:    mv s2, a0
2276; RV64I-NEXT:    and a0, s1, s3
2277; RV64I-NEXT:    call __extendhfsf2
2278; RV64I-NEXT:    mv a1, a0
2279; RV64I-NEXT:    mv a0, s2
2280; RV64I-NEXT:    call __mulsf3
2281; RV64I-NEXT:    call __truncsfhf2
2282; RV64I-NEXT:    mv s1, a0
2283; RV64I-NEXT:    and a0, s0, s3
2284; RV64I-NEXT:    call __extendhfsf2
2285; RV64I-NEXT:    mv s0, a0
2286; RV64I-NEXT:    and a0, s1, s3
2287; RV64I-NEXT:    call __extendhfsf2
2288; RV64I-NEXT:    mv a1, s0
2289; RV64I-NEXT:    call __addsf3
2290; RV64I-NEXT:    call __truncsfhf2
2291; RV64I-NEXT:    ld ra, 40(sp) # 8-byte Folded Reload
2292; RV64I-NEXT:    ld s0, 32(sp) # 8-byte Folded Reload
2293; RV64I-NEXT:    ld s1, 24(sp) # 8-byte Folded Reload
2294; RV64I-NEXT:    ld s2, 16(sp) # 8-byte Folded Reload
2295; RV64I-NEXT:    ld s3, 8(sp) # 8-byte Folded Reload
2296; RV64I-NEXT:    addi sp, sp, 48
2297; RV64I-NEXT:    ret
2298;
2299; CHECKIZFHMIN-LABEL: fmadd_h_contract:
2300; CHECKIZFHMIN:       # %bb.0:
2301; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa1
2302; CHECKIZFHMIN-NEXT:    fcvt.s.h fa4, fa0
2303; CHECKIZFHMIN-NEXT:    fmul.s fa5, fa4, fa5
2304; CHECKIZFHMIN-NEXT:    fcvt.h.s fa5, fa5
2305; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa5
2306; CHECKIZFHMIN-NEXT:    fcvt.s.h fa4, fa2
2307; CHECKIZFHMIN-NEXT:    fadd.s fa5, fa5, fa4
2308; CHECKIZFHMIN-NEXT:    fcvt.h.s fa0, fa5
2309; CHECKIZFHMIN-NEXT:    ret
2310;
2311; CHECKIZHINXMIN-LABEL: fmadd_h_contract:
2312; CHECKIZHINXMIN:       # %bb.0:
2313; CHECKIZHINXMIN-NEXT:    fcvt.s.h a1, a1
2314; CHECKIZHINXMIN-NEXT:    fcvt.s.h a0, a0
2315; CHECKIZHINXMIN-NEXT:    fmul.s a0, a0, a1
2316; CHECKIZHINXMIN-NEXT:    fcvt.h.s a0, a0
2317; CHECKIZHINXMIN-NEXT:    fcvt.s.h a0, a0
2318; CHECKIZHINXMIN-NEXT:    fcvt.s.h a1, a2
2319; CHECKIZHINXMIN-NEXT:    fadd.s a0, a0, a1
2320; CHECKIZHINXMIN-NEXT:    fcvt.h.s a0, a0
2321; CHECKIZHINXMIN-NEXT:    ret
2322  %1 = fmul contract half %a, %b
2323  %2 = fadd contract half %1, %c
2324  ret half %2
2325}
2326
2327define half @fmsub_h_contract(half %a, half %b, half %c) nounwind {
2328; CHECKIZFH-LABEL: fmsub_h_contract:
2329; CHECKIZFH:       # %bb.0:
2330; CHECKIZFH-NEXT:    fmv.h.x fa5, zero
2331; CHECKIZFH-NEXT:    fadd.h fa5, fa2, fa5
2332; CHECKIZFH-NEXT:    fmsub.h fa0, fa0, fa1, fa5
2333; CHECKIZFH-NEXT:    ret
2334;
2335; CHECKIZHINX-LABEL: fmsub_h_contract:
2336; CHECKIZHINX:       # %bb.0:
2337; CHECKIZHINX-NEXT:    fadd.h a2, a2, zero
2338; CHECKIZHINX-NEXT:    fmsub.h a0, a0, a1, a2
2339; CHECKIZHINX-NEXT:    ret
2340;
2341; RV32I-LABEL: fmsub_h_contract:
2342; RV32I:       # %bb.0:
2343; RV32I-NEXT:    addi sp, sp, -32
2344; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
2345; RV32I-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
2346; RV32I-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
2347; RV32I-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
2348; RV32I-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
2349; RV32I-NEXT:    mv s0, a1
2350; RV32I-NEXT:    mv s1, a0
2351; RV32I-NEXT:    lui a0, 16
2352; RV32I-NEXT:    addi s3, a0, -1
2353; RV32I-NEXT:    and a0, a2, s3
2354; RV32I-NEXT:    call __extendhfsf2
2355; RV32I-NEXT:    li a1, 0
2356; RV32I-NEXT:    call __addsf3
2357; RV32I-NEXT:    call __truncsfhf2
2358; RV32I-NEXT:    mv s2, a0
2359; RV32I-NEXT:    and a0, s1, s3
2360; RV32I-NEXT:    call __extendhfsf2
2361; RV32I-NEXT:    mv s1, a0
2362; RV32I-NEXT:    and a0, s0, s3
2363; RV32I-NEXT:    call __extendhfsf2
2364; RV32I-NEXT:    mv a1, a0
2365; RV32I-NEXT:    mv a0, s1
2366; RV32I-NEXT:    call __mulsf3
2367; RV32I-NEXT:    call __truncsfhf2
2368; RV32I-NEXT:    and a0, a0, s3
2369; RV32I-NEXT:    call __extendhfsf2
2370; RV32I-NEXT:    mv s0, a0
2371; RV32I-NEXT:    and a0, s2, s3
2372; RV32I-NEXT:    call __extendhfsf2
2373; RV32I-NEXT:    mv a1, a0
2374; RV32I-NEXT:    mv a0, s0
2375; RV32I-NEXT:    call __subsf3
2376; RV32I-NEXT:    call __truncsfhf2
2377; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
2378; RV32I-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
2379; RV32I-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
2380; RV32I-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
2381; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
2382; RV32I-NEXT:    addi sp, sp, 32
2383; RV32I-NEXT:    ret
2384;
2385; RV64I-LABEL: fmsub_h_contract:
2386; RV64I:       # %bb.0:
2387; RV64I-NEXT:    addi sp, sp, -48
2388; RV64I-NEXT:    sd ra, 40(sp) # 8-byte Folded Spill
2389; RV64I-NEXT:    sd s0, 32(sp) # 8-byte Folded Spill
2390; RV64I-NEXT:    sd s1, 24(sp) # 8-byte Folded Spill
2391; RV64I-NEXT:    sd s2, 16(sp) # 8-byte Folded Spill
2392; RV64I-NEXT:    sd s3, 8(sp) # 8-byte Folded Spill
2393; RV64I-NEXT:    mv s0, a1
2394; RV64I-NEXT:    mv s1, a0
2395; RV64I-NEXT:    lui a0, 16
2396; RV64I-NEXT:    addiw s3, a0, -1
2397; RV64I-NEXT:    and a0, a2, s3
2398; RV64I-NEXT:    call __extendhfsf2
2399; RV64I-NEXT:    li a1, 0
2400; RV64I-NEXT:    call __addsf3
2401; RV64I-NEXT:    call __truncsfhf2
2402; RV64I-NEXT:    mv s2, a0
2403; RV64I-NEXT:    and a0, s1, s3
2404; RV64I-NEXT:    call __extendhfsf2
2405; RV64I-NEXT:    mv s1, a0
2406; RV64I-NEXT:    and a0, s0, s3
2407; RV64I-NEXT:    call __extendhfsf2
2408; RV64I-NEXT:    mv a1, a0
2409; RV64I-NEXT:    mv a0, s1
2410; RV64I-NEXT:    call __mulsf3
2411; RV64I-NEXT:    call __truncsfhf2
2412; RV64I-NEXT:    and a0, a0, s3
2413; RV64I-NEXT:    call __extendhfsf2
2414; RV64I-NEXT:    mv s0, a0
2415; RV64I-NEXT:    and a0, s2, s3
2416; RV64I-NEXT:    call __extendhfsf2
2417; RV64I-NEXT:    mv a1, a0
2418; RV64I-NEXT:    mv a0, s0
2419; RV64I-NEXT:    call __subsf3
2420; RV64I-NEXT:    call __truncsfhf2
2421; RV64I-NEXT:    ld ra, 40(sp) # 8-byte Folded Reload
2422; RV64I-NEXT:    ld s0, 32(sp) # 8-byte Folded Reload
2423; RV64I-NEXT:    ld s1, 24(sp) # 8-byte Folded Reload
2424; RV64I-NEXT:    ld s2, 16(sp) # 8-byte Folded Reload
2425; RV64I-NEXT:    ld s3, 8(sp) # 8-byte Folded Reload
2426; RV64I-NEXT:    addi sp, sp, 48
2427; RV64I-NEXT:    ret
2428;
2429; CHECKIZFHMIN-LABEL: fmsub_h_contract:
2430; CHECKIZFHMIN:       # %bb.0:
2431; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa2
2432; CHECKIZFHMIN-NEXT:    fmv.w.x fa4, zero
2433; CHECKIZFHMIN-NEXT:    fcvt.s.h fa3, fa1
2434; CHECKIZFHMIN-NEXT:    fcvt.s.h fa2, fa0
2435; CHECKIZFHMIN-NEXT:    fadd.s fa5, fa5, fa4
2436; CHECKIZFHMIN-NEXT:    fmul.s fa4, fa2, fa3
2437; CHECKIZFHMIN-NEXT:    fcvt.h.s fa5, fa5
2438; CHECKIZFHMIN-NEXT:    fcvt.h.s fa4, fa4
2439; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa5
2440; CHECKIZFHMIN-NEXT:    fcvt.s.h fa4, fa4
2441; CHECKIZFHMIN-NEXT:    fsub.s fa5, fa4, fa5
2442; CHECKIZFHMIN-NEXT:    fcvt.h.s fa0, fa5
2443; CHECKIZFHMIN-NEXT:    ret
2444;
2445; CHECKIZHINXMIN-LABEL: fmsub_h_contract:
2446; CHECKIZHINXMIN:       # %bb.0:
2447; CHECKIZHINXMIN-NEXT:    fcvt.s.h a2, a2
2448; CHECKIZHINXMIN-NEXT:    fcvt.s.h a1, a1
2449; CHECKIZHINXMIN-NEXT:    fcvt.s.h a0, a0
2450; CHECKIZHINXMIN-NEXT:    fadd.s a2, a2, zero
2451; CHECKIZHINXMIN-NEXT:    fmul.s a0, a0, a1
2452; CHECKIZHINXMIN-NEXT:    fcvt.h.s a1, a2
2453; CHECKIZHINXMIN-NEXT:    fcvt.h.s a0, a0
2454; CHECKIZHINXMIN-NEXT:    fcvt.s.h a1, a1
2455; CHECKIZHINXMIN-NEXT:    fcvt.s.h a0, a0
2456; CHECKIZHINXMIN-NEXT:    fsub.s a0, a0, a1
2457; CHECKIZHINXMIN-NEXT:    fcvt.h.s a0, a0
2458; CHECKIZHINXMIN-NEXT:    ret
2459  %c_ = fadd half 0.0, %c ; avoid negation using xor
2460  %1 = fmul contract half %a, %b
2461  %2 = fsub contract half %1, %c_
2462  ret half %2
2463}
2464
2465define half @fnmadd_h_contract(half %a, half %b, half %c) nounwind {
2466; CHECKIZFH-LABEL: fnmadd_h_contract:
2467; CHECKIZFH:       # %bb.0:
2468; CHECKIZFH-NEXT:    fmv.h.x fa5, zero
2469; CHECKIZFH-NEXT:    fadd.h fa4, fa0, fa5
2470; CHECKIZFH-NEXT:    fadd.h fa3, fa1, fa5
2471; CHECKIZFH-NEXT:    fadd.h fa5, fa2, fa5
2472; CHECKIZFH-NEXT:    fnmadd.h fa0, fa4, fa3, fa5
2473; CHECKIZFH-NEXT:    ret
2474;
2475; CHECKIZHINX-LABEL: fnmadd_h_contract:
2476; CHECKIZHINX:       # %bb.0:
2477; CHECKIZHINX-NEXT:    fadd.h a0, a0, zero
2478; CHECKIZHINX-NEXT:    fadd.h a1, a1, zero
2479; CHECKIZHINX-NEXT:    fadd.h a2, a2, zero
2480; CHECKIZHINX-NEXT:    fnmadd.h a0, a0, a1, a2
2481; CHECKIZHINX-NEXT:    ret
2482;
2483; RV32I-LABEL: fnmadd_h_contract:
2484; RV32I:       # %bb.0:
2485; RV32I-NEXT:    addi sp, sp, -32
2486; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
2487; RV32I-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
2488; RV32I-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
2489; RV32I-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
2490; RV32I-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
2491; RV32I-NEXT:    mv s0, a2
2492; RV32I-NEXT:    mv s1, a1
2493; RV32I-NEXT:    lui s3, 16
2494; RV32I-NEXT:    addi s3, s3, -1
2495; RV32I-NEXT:    and a0, a0, s3
2496; RV32I-NEXT:    call __extendhfsf2
2497; RV32I-NEXT:    li a1, 0
2498; RV32I-NEXT:    call __addsf3
2499; RV32I-NEXT:    call __truncsfhf2
2500; RV32I-NEXT:    mv s2, a0
2501; RV32I-NEXT:    and a0, s1, s3
2502; RV32I-NEXT:    call __extendhfsf2
2503; RV32I-NEXT:    li a1, 0
2504; RV32I-NEXT:    call __addsf3
2505; RV32I-NEXT:    call __truncsfhf2
2506; RV32I-NEXT:    mv s1, a0
2507; RV32I-NEXT:    and a0, s0, s3
2508; RV32I-NEXT:    call __extendhfsf2
2509; RV32I-NEXT:    li a1, 0
2510; RV32I-NEXT:    call __addsf3
2511; RV32I-NEXT:    call __truncsfhf2
2512; RV32I-NEXT:    mv s0, a0
2513; RV32I-NEXT:    and a0, s2, s3
2514; RV32I-NEXT:    call __extendhfsf2
2515; RV32I-NEXT:    mv s2, a0
2516; RV32I-NEXT:    and a0, s1, s3
2517; RV32I-NEXT:    call __extendhfsf2
2518; RV32I-NEXT:    mv a1, a0
2519; RV32I-NEXT:    mv a0, s2
2520; RV32I-NEXT:    call __mulsf3
2521; RV32I-NEXT:    call __truncsfhf2
2522; RV32I-NEXT:    and a0, a0, s3
2523; RV32I-NEXT:    call __extendhfsf2
2524; RV32I-NEXT:    lui a1, 524288
2525; RV32I-NEXT:    xor a0, a0, a1
2526; RV32I-NEXT:    call __truncsfhf2
2527; RV32I-NEXT:    mv s1, a0
2528; RV32I-NEXT:    and a0, s0, s3
2529; RV32I-NEXT:    call __extendhfsf2
2530; RV32I-NEXT:    mv s0, a0
2531; RV32I-NEXT:    and a0, s1, s3
2532; RV32I-NEXT:    call __extendhfsf2
2533; RV32I-NEXT:    mv a1, s0
2534; RV32I-NEXT:    call __subsf3
2535; RV32I-NEXT:    call __truncsfhf2
2536; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
2537; RV32I-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
2538; RV32I-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
2539; RV32I-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
2540; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
2541; RV32I-NEXT:    addi sp, sp, 32
2542; RV32I-NEXT:    ret
2543;
2544; RV64I-LABEL: fnmadd_h_contract:
2545; RV64I:       # %bb.0:
2546; RV64I-NEXT:    addi sp, sp, -48
2547; RV64I-NEXT:    sd ra, 40(sp) # 8-byte Folded Spill
2548; RV64I-NEXT:    sd s0, 32(sp) # 8-byte Folded Spill
2549; RV64I-NEXT:    sd s1, 24(sp) # 8-byte Folded Spill
2550; RV64I-NEXT:    sd s2, 16(sp) # 8-byte Folded Spill
2551; RV64I-NEXT:    sd s3, 8(sp) # 8-byte Folded Spill
2552; RV64I-NEXT:    mv s0, a2
2553; RV64I-NEXT:    mv s1, a1
2554; RV64I-NEXT:    lui s3, 16
2555; RV64I-NEXT:    addiw s3, s3, -1
2556; RV64I-NEXT:    and a0, a0, s3
2557; RV64I-NEXT:    call __extendhfsf2
2558; RV64I-NEXT:    li a1, 0
2559; RV64I-NEXT:    call __addsf3
2560; RV64I-NEXT:    call __truncsfhf2
2561; RV64I-NEXT:    mv s2, a0
2562; RV64I-NEXT:    and a0, s1, s3
2563; RV64I-NEXT:    call __extendhfsf2
2564; RV64I-NEXT:    li a1, 0
2565; RV64I-NEXT:    call __addsf3
2566; RV64I-NEXT:    call __truncsfhf2
2567; RV64I-NEXT:    mv s1, a0
2568; RV64I-NEXT:    and a0, s0, s3
2569; RV64I-NEXT:    call __extendhfsf2
2570; RV64I-NEXT:    li a1, 0
2571; RV64I-NEXT:    call __addsf3
2572; RV64I-NEXT:    call __truncsfhf2
2573; RV64I-NEXT:    mv s0, a0
2574; RV64I-NEXT:    and a0, s2, s3
2575; RV64I-NEXT:    call __extendhfsf2
2576; RV64I-NEXT:    mv s2, a0
2577; RV64I-NEXT:    and a0, s1, s3
2578; RV64I-NEXT:    call __extendhfsf2
2579; RV64I-NEXT:    mv a1, a0
2580; RV64I-NEXT:    mv a0, s2
2581; RV64I-NEXT:    call __mulsf3
2582; RV64I-NEXT:    call __truncsfhf2
2583; RV64I-NEXT:    and a0, a0, s3
2584; RV64I-NEXT:    call __extendhfsf2
2585; RV64I-NEXT:    lui a1, 524288
2586; RV64I-NEXT:    xor a0, a0, a1
2587; RV64I-NEXT:    call __truncsfhf2
2588; RV64I-NEXT:    mv s1, a0
2589; RV64I-NEXT:    and a0, s0, s3
2590; RV64I-NEXT:    call __extendhfsf2
2591; RV64I-NEXT:    mv s0, a0
2592; RV64I-NEXT:    and a0, s1, s3
2593; RV64I-NEXT:    call __extendhfsf2
2594; RV64I-NEXT:    mv a1, s0
2595; RV64I-NEXT:    call __subsf3
2596; RV64I-NEXT:    call __truncsfhf2
2597; RV64I-NEXT:    ld ra, 40(sp) # 8-byte Folded Reload
2598; RV64I-NEXT:    ld s0, 32(sp) # 8-byte Folded Reload
2599; RV64I-NEXT:    ld s1, 24(sp) # 8-byte Folded Reload
2600; RV64I-NEXT:    ld s2, 16(sp) # 8-byte Folded Reload
2601; RV64I-NEXT:    ld s3, 8(sp) # 8-byte Folded Reload
2602; RV64I-NEXT:    addi sp, sp, 48
2603; RV64I-NEXT:    ret
2604;
2605; CHECKIZFHMIN-LABEL: fnmadd_h_contract:
2606; CHECKIZFHMIN:       # %bb.0:
2607; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa0
2608; CHECKIZFHMIN-NEXT:    fmv.w.x fa4, zero
2609; CHECKIZFHMIN-NEXT:    fcvt.s.h fa3, fa1
2610; CHECKIZFHMIN-NEXT:    fcvt.s.h fa2, fa2
2611; CHECKIZFHMIN-NEXT:    lui a0, 1048568
2612; CHECKIZFHMIN-NEXT:    fadd.s fa5, fa5, fa4
2613; CHECKIZFHMIN-NEXT:    fadd.s fa3, fa3, fa4
2614; CHECKIZFHMIN-NEXT:    fadd.s fa4, fa2, fa4
2615; CHECKIZFHMIN-NEXT:    fcvt.h.s fa5, fa5
2616; CHECKIZFHMIN-NEXT:    fcvt.h.s fa3, fa3
2617; CHECKIZFHMIN-NEXT:    fcvt.h.s fa4, fa4
2618; CHECKIZFHMIN-NEXT:    fcvt.s.h fa3, fa3
2619; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa5
2620; CHECKIZFHMIN-NEXT:    fmul.s fa5, fa5, fa3
2621; CHECKIZFHMIN-NEXT:    fcvt.h.s fa5, fa5
2622; CHECKIZFHMIN-NEXT:    fmv.x.h a1, fa5
2623; CHECKIZFHMIN-NEXT:    xor a0, a1, a0
2624; CHECKIZFHMIN-NEXT:    fmv.h.x fa5, a0
2625; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa5
2626; CHECKIZFHMIN-NEXT:    fcvt.s.h fa4, fa4
2627; CHECKIZFHMIN-NEXT:    fsub.s fa5, fa5, fa4
2628; CHECKIZFHMIN-NEXT:    fcvt.h.s fa0, fa5
2629; CHECKIZFHMIN-NEXT:    ret
2630;
2631; CHECKIZHINXMIN-LABEL: fnmadd_h_contract:
2632; CHECKIZHINXMIN:       # %bb.0:
2633; CHECKIZHINXMIN-NEXT:    fcvt.s.h a0, a0
2634; CHECKIZHINXMIN-NEXT:    fcvt.s.h a1, a1
2635; CHECKIZHINXMIN-NEXT:    fcvt.s.h a2, a2
2636; CHECKIZHINXMIN-NEXT:    fadd.s a0, a0, zero
2637; CHECKIZHINXMIN-NEXT:    fadd.s a1, a1, zero
2638; CHECKIZHINXMIN-NEXT:    fcvt.h.s a0, a0
2639; CHECKIZHINXMIN-NEXT:    fcvt.h.s a1, a1
2640; CHECKIZHINXMIN-NEXT:    fcvt.s.h a1, a1
2641; CHECKIZHINXMIN-NEXT:    fcvt.s.h a0, a0
2642; CHECKIZHINXMIN-NEXT:    fmul.s a0, a0, a1
2643; CHECKIZHINXMIN-NEXT:    lui a1, 1048568
2644; CHECKIZHINXMIN-NEXT:    fadd.s a2, a2, zero
2645; CHECKIZHINXMIN-NEXT:    fcvt.h.s a2, a2
2646; CHECKIZHINXMIN-NEXT:    fcvt.h.s a0, a0
2647; CHECKIZHINXMIN-NEXT:    xor a0, a0, a1
2648; CHECKIZHINXMIN-NEXT:    fcvt.s.h a0, a0
2649; CHECKIZHINXMIN-NEXT:    fcvt.s.h a1, a2
2650; CHECKIZHINXMIN-NEXT:    fsub.s a0, a0, a1
2651; CHECKIZHINXMIN-NEXT:    fcvt.h.s a0, a0
2652; CHECKIZHINXMIN-NEXT:    ret
2653  %a_ = fadd half 0.0, %a ; avoid negation using xor
2654  %b_ = fadd half 0.0, %b ; avoid negation using xor
2655  %c_ = fadd half 0.0, %c ; avoid negation using xor
2656  %1 = fmul contract half %a_, %b_
2657  %2 = fneg half %1
2658  %3 = fsub contract half %2, %c_
2659  ret half %3
2660}
2661
2662define half @fnmsub_h_contract(half %a, half %b, half %c) nounwind {
2663; CHECKIZFH-LABEL: fnmsub_h_contract:
2664; CHECKIZFH:       # %bb.0:
2665; CHECKIZFH-NEXT:    fmv.h.x fa5, zero
2666; CHECKIZFH-NEXT:    fadd.h fa4, fa0, fa5
2667; CHECKIZFH-NEXT:    fadd.h fa5, fa1, fa5
2668; CHECKIZFH-NEXT:    fnmsub.h fa0, fa4, fa5, fa2
2669; CHECKIZFH-NEXT:    ret
2670;
2671; CHECKIZHINX-LABEL: fnmsub_h_contract:
2672; CHECKIZHINX:       # %bb.0:
2673; CHECKIZHINX-NEXT:    fadd.h a0, a0, zero
2674; CHECKIZHINX-NEXT:    fadd.h a1, a1, zero
2675; CHECKIZHINX-NEXT:    fnmsub.h a0, a0, a1, a2
2676; CHECKIZHINX-NEXT:    ret
2677;
2678; RV32I-LABEL: fnmsub_h_contract:
2679; RV32I:       # %bb.0:
2680; RV32I-NEXT:    addi sp, sp, -32
2681; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
2682; RV32I-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
2683; RV32I-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
2684; RV32I-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
2685; RV32I-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
2686; RV32I-NEXT:    mv s0, a2
2687; RV32I-NEXT:    mv s1, a1
2688; RV32I-NEXT:    lui s3, 16
2689; RV32I-NEXT:    addi s3, s3, -1
2690; RV32I-NEXT:    and a0, a0, s3
2691; RV32I-NEXT:    call __extendhfsf2
2692; RV32I-NEXT:    li a1, 0
2693; RV32I-NEXT:    call __addsf3
2694; RV32I-NEXT:    call __truncsfhf2
2695; RV32I-NEXT:    mv s2, a0
2696; RV32I-NEXT:    and a0, s1, s3
2697; RV32I-NEXT:    call __extendhfsf2
2698; RV32I-NEXT:    li a1, 0
2699; RV32I-NEXT:    call __addsf3
2700; RV32I-NEXT:    call __truncsfhf2
2701; RV32I-NEXT:    mv s1, a0
2702; RV32I-NEXT:    and a0, s2, s3
2703; RV32I-NEXT:    call __extendhfsf2
2704; RV32I-NEXT:    mv s2, a0
2705; RV32I-NEXT:    and a0, s1, s3
2706; RV32I-NEXT:    call __extendhfsf2
2707; RV32I-NEXT:    mv a1, a0
2708; RV32I-NEXT:    mv a0, s2
2709; RV32I-NEXT:    call __mulsf3
2710; RV32I-NEXT:    call __truncsfhf2
2711; RV32I-NEXT:    mv s1, a0
2712; RV32I-NEXT:    and a0, s0, s3
2713; RV32I-NEXT:    call __extendhfsf2
2714; RV32I-NEXT:    mv s0, a0
2715; RV32I-NEXT:    and a0, s1, s3
2716; RV32I-NEXT:    call __extendhfsf2
2717; RV32I-NEXT:    mv a1, a0
2718; RV32I-NEXT:    mv a0, s0
2719; RV32I-NEXT:    call __subsf3
2720; RV32I-NEXT:    call __truncsfhf2
2721; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
2722; RV32I-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
2723; RV32I-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
2724; RV32I-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
2725; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
2726; RV32I-NEXT:    addi sp, sp, 32
2727; RV32I-NEXT:    ret
2728;
2729; RV64I-LABEL: fnmsub_h_contract:
2730; RV64I:       # %bb.0:
2731; RV64I-NEXT:    addi sp, sp, -48
2732; RV64I-NEXT:    sd ra, 40(sp) # 8-byte Folded Spill
2733; RV64I-NEXT:    sd s0, 32(sp) # 8-byte Folded Spill
2734; RV64I-NEXT:    sd s1, 24(sp) # 8-byte Folded Spill
2735; RV64I-NEXT:    sd s2, 16(sp) # 8-byte Folded Spill
2736; RV64I-NEXT:    sd s3, 8(sp) # 8-byte Folded Spill
2737; RV64I-NEXT:    mv s0, a2
2738; RV64I-NEXT:    mv s1, a1
2739; RV64I-NEXT:    lui s3, 16
2740; RV64I-NEXT:    addiw s3, s3, -1
2741; RV64I-NEXT:    and a0, a0, s3
2742; RV64I-NEXT:    call __extendhfsf2
2743; RV64I-NEXT:    li a1, 0
2744; RV64I-NEXT:    call __addsf3
2745; RV64I-NEXT:    call __truncsfhf2
2746; RV64I-NEXT:    mv s2, a0
2747; RV64I-NEXT:    and a0, s1, s3
2748; RV64I-NEXT:    call __extendhfsf2
2749; RV64I-NEXT:    li a1, 0
2750; RV64I-NEXT:    call __addsf3
2751; RV64I-NEXT:    call __truncsfhf2
2752; RV64I-NEXT:    mv s1, a0
2753; RV64I-NEXT:    and a0, s2, s3
2754; RV64I-NEXT:    call __extendhfsf2
2755; RV64I-NEXT:    mv s2, a0
2756; RV64I-NEXT:    and a0, s1, s3
2757; RV64I-NEXT:    call __extendhfsf2
2758; RV64I-NEXT:    mv a1, a0
2759; RV64I-NEXT:    mv a0, s2
2760; RV64I-NEXT:    call __mulsf3
2761; RV64I-NEXT:    call __truncsfhf2
2762; RV64I-NEXT:    mv s1, a0
2763; RV64I-NEXT:    and a0, s0, s3
2764; RV64I-NEXT:    call __extendhfsf2
2765; RV64I-NEXT:    mv s0, a0
2766; RV64I-NEXT:    and a0, s1, s3
2767; RV64I-NEXT:    call __extendhfsf2
2768; RV64I-NEXT:    mv a1, a0
2769; RV64I-NEXT:    mv a0, s0
2770; RV64I-NEXT:    call __subsf3
2771; RV64I-NEXT:    call __truncsfhf2
2772; RV64I-NEXT:    ld ra, 40(sp) # 8-byte Folded Reload
2773; RV64I-NEXT:    ld s0, 32(sp) # 8-byte Folded Reload
2774; RV64I-NEXT:    ld s1, 24(sp) # 8-byte Folded Reload
2775; RV64I-NEXT:    ld s2, 16(sp) # 8-byte Folded Reload
2776; RV64I-NEXT:    ld s3, 8(sp) # 8-byte Folded Reload
2777; RV64I-NEXT:    addi sp, sp, 48
2778; RV64I-NEXT:    ret
2779;
2780; CHECKIZFHMIN-LABEL: fnmsub_h_contract:
2781; CHECKIZFHMIN:       # %bb.0:
2782; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa0
2783; CHECKIZFHMIN-NEXT:    fmv.w.x fa4, zero
2784; CHECKIZFHMIN-NEXT:    fcvt.s.h fa3, fa1
2785; CHECKIZFHMIN-NEXT:    fadd.s fa5, fa5, fa4
2786; CHECKIZFHMIN-NEXT:    fadd.s fa4, fa3, fa4
2787; CHECKIZFHMIN-NEXT:    fcvt.h.s fa5, fa5
2788; CHECKIZFHMIN-NEXT:    fcvt.h.s fa4, fa4
2789; CHECKIZFHMIN-NEXT:    fcvt.s.h fa4, fa4
2790; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa5
2791; CHECKIZFHMIN-NEXT:    fmul.s fa5, fa5, fa4
2792; CHECKIZFHMIN-NEXT:    fcvt.h.s fa5, fa5
2793; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa5
2794; CHECKIZFHMIN-NEXT:    fcvt.s.h fa4, fa2
2795; CHECKIZFHMIN-NEXT:    fsub.s fa5, fa4, fa5
2796; CHECKIZFHMIN-NEXT:    fcvt.h.s fa0, fa5
2797; CHECKIZFHMIN-NEXT:    ret
2798;
2799; CHECKIZHINXMIN-LABEL: fnmsub_h_contract:
2800; CHECKIZHINXMIN:       # %bb.0:
2801; CHECKIZHINXMIN-NEXT:    fcvt.s.h a0, a0
2802; CHECKIZHINXMIN-NEXT:    fcvt.s.h a1, a1
2803; CHECKIZHINXMIN-NEXT:    fadd.s a0, a0, zero
2804; CHECKIZHINXMIN-NEXT:    fadd.s a1, a1, zero
2805; CHECKIZHINXMIN-NEXT:    fcvt.h.s a0, a0
2806; CHECKIZHINXMIN-NEXT:    fcvt.h.s a1, a1
2807; CHECKIZHINXMIN-NEXT:    fcvt.s.h a1, a1
2808; CHECKIZHINXMIN-NEXT:    fcvt.s.h a0, a0
2809; CHECKIZHINXMIN-NEXT:    fmul.s a0, a0, a1
2810; CHECKIZHINXMIN-NEXT:    fcvt.h.s a0, a0
2811; CHECKIZHINXMIN-NEXT:    fcvt.s.h a0, a0
2812; CHECKIZHINXMIN-NEXT:    fcvt.s.h a1, a2
2813; CHECKIZHINXMIN-NEXT:    fsub.s a0, a1, a0
2814; CHECKIZHINXMIN-NEXT:    fcvt.h.s a0, a0
2815; CHECKIZHINXMIN-NEXT:    ret
2816  %a_ = fadd half 0.0, %a ; avoid negation using xor
2817  %b_ = fadd half 0.0, %b ; avoid negation using xor
2818  %1 = fmul contract half %a_, %b_
2819  %2 = fsub contract half %c, %1
2820  ret half %2
2821}
2822
2823define half @fsgnjx_f16(half %x, half %y) nounwind {
2824; CHECKIZFH-LABEL: fsgnjx_f16:
2825; CHECKIZFH:       # %bb.0:
2826; CHECKIZFH-NEXT:    fsgnjx.h fa0, fa1, fa0
2827; CHECKIZFH-NEXT:    ret
2828;
2829; CHECKIZHINX-LABEL: fsgnjx_f16:
2830; CHECKIZHINX:       # %bb.0:
2831; CHECKIZHINX-NEXT:    fsgnjx.h a0, a1, a0
2832; CHECKIZHINX-NEXT:    ret
2833;
2834; RV32I-LABEL: fsgnjx_f16:
2835; RV32I:       # %bb.0:
2836; RV32I-NEXT:    addi sp, sp, -16
2837; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
2838; RV32I-NEXT:    sw s0, 8(sp) # 4-byte Folded Spill
2839; RV32I-NEXT:    sw s1, 4(sp) # 4-byte Folded Spill
2840; RV32I-NEXT:    li a2, 15
2841; RV32I-NEXT:    slli a2, a2, 10
2842; RV32I-NEXT:    or s1, a0, a2
2843; RV32I-NEXT:    slli a0, a1, 16
2844; RV32I-NEXT:    srli a0, a0, 16
2845; RV32I-NEXT:    call __extendhfsf2
2846; RV32I-NEXT:    mv s0, a0
2847; RV32I-NEXT:    lui a0, 12
2848; RV32I-NEXT:    addi a0, a0, -1024
2849; RV32I-NEXT:    and a0, s1, a0
2850; RV32I-NEXT:    call __extendhfsf2
2851; RV32I-NEXT:    mv a1, s0
2852; RV32I-NEXT:    call __mulsf3
2853; RV32I-NEXT:    call __truncsfhf2
2854; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
2855; RV32I-NEXT:    lw s0, 8(sp) # 4-byte Folded Reload
2856; RV32I-NEXT:    lw s1, 4(sp) # 4-byte Folded Reload
2857; RV32I-NEXT:    addi sp, sp, 16
2858; RV32I-NEXT:    ret
2859;
2860; RV64I-LABEL: fsgnjx_f16:
2861; RV64I:       # %bb.0:
2862; RV64I-NEXT:    addi sp, sp, -32
2863; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
2864; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
2865; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
2866; RV64I-NEXT:    li a2, 15
2867; RV64I-NEXT:    slli a2, a2, 10
2868; RV64I-NEXT:    or s1, a0, a2
2869; RV64I-NEXT:    slli a0, a1, 48
2870; RV64I-NEXT:    srli a0, a0, 48
2871; RV64I-NEXT:    call __extendhfsf2
2872; RV64I-NEXT:    mv s0, a0
2873; RV64I-NEXT:    lui a0, 12
2874; RV64I-NEXT:    addiw a0, a0, -1024
2875; RV64I-NEXT:    and a0, s1, a0
2876; RV64I-NEXT:    call __extendhfsf2
2877; RV64I-NEXT:    mv a1, s0
2878; RV64I-NEXT:    call __mulsf3
2879; RV64I-NEXT:    call __truncsfhf2
2880; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
2881; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
2882; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
2883; RV64I-NEXT:    addi sp, sp, 32
2884; RV64I-NEXT:    ret
2885;
2886; RV32IZFHMIN-LABEL: fsgnjx_f16:
2887; RV32IZFHMIN:       # %bb.0:
2888; RV32IZFHMIN-NEXT:    lui a0, %hi(.LCPI23_0)
2889; RV32IZFHMIN-NEXT:    lhu a0, %lo(.LCPI23_0)(a0)
2890; RV32IZFHMIN-NEXT:    fmv.x.h a1, fa0
2891; RV32IZFHMIN-NEXT:    lui a2, 1048568
2892; RV32IZFHMIN-NEXT:    and a1, a1, a2
2893; RV32IZFHMIN-NEXT:    slli a0, a0, 17
2894; RV32IZFHMIN-NEXT:    srli a0, a0, 17
2895; RV32IZFHMIN-NEXT:    or a0, a0, a1
2896; RV32IZFHMIN-NEXT:    fmv.h.x fa5, a0
2897; RV32IZFHMIN-NEXT:    fcvt.s.h fa5, fa5
2898; RV32IZFHMIN-NEXT:    fcvt.s.h fa4, fa1
2899; RV32IZFHMIN-NEXT:    fmul.s fa5, fa5, fa4
2900; RV32IZFHMIN-NEXT:    fcvt.h.s fa0, fa5
2901; RV32IZFHMIN-NEXT:    ret
2902;
2903; RV64IZFHMIN-LABEL: fsgnjx_f16:
2904; RV64IZFHMIN:       # %bb.0:
2905; RV64IZFHMIN-NEXT:    lui a0, %hi(.LCPI23_0)
2906; RV64IZFHMIN-NEXT:    lhu a0, %lo(.LCPI23_0)(a0)
2907; RV64IZFHMIN-NEXT:    fmv.x.h a1, fa0
2908; RV64IZFHMIN-NEXT:    lui a2, 1048568
2909; RV64IZFHMIN-NEXT:    and a1, a1, a2
2910; RV64IZFHMIN-NEXT:    slli a0, a0, 49
2911; RV64IZFHMIN-NEXT:    srli a0, a0, 49
2912; RV64IZFHMIN-NEXT:    or a0, a0, a1
2913; RV64IZFHMIN-NEXT:    fmv.h.x fa5, a0
2914; RV64IZFHMIN-NEXT:    fcvt.s.h fa5, fa5
2915; RV64IZFHMIN-NEXT:    fcvt.s.h fa4, fa1
2916; RV64IZFHMIN-NEXT:    fmul.s fa5, fa5, fa4
2917; RV64IZFHMIN-NEXT:    fcvt.h.s fa0, fa5
2918; RV64IZFHMIN-NEXT:    ret
2919;
2920; CHECKIZHINXMIN-LABEL: fsgnjx_f16:
2921; CHECKIZHINXMIN:       # %bb.0:
2922; CHECKIZHINXMIN-NEXT:    # kill: def $x10_h killed $x10_h def $x10
2923; CHECKIZHINXMIN-NEXT:    lui a2, 1048568
2924; CHECKIZHINXMIN-NEXT:    and a0, a0, a2
2925; CHECKIZHINXMIN-NEXT:    li a2, 15
2926; CHECKIZHINXMIN-NEXT:    slli a2, a2, 10
2927; CHECKIZHINXMIN-NEXT:    or a0, a0, a2
2928; CHECKIZHINXMIN-NEXT:    fcvt.s.h a0, a0
2929; CHECKIZHINXMIN-NEXT:    fcvt.s.h a1, a1
2930; CHECKIZHINXMIN-NEXT:    fmul.s a0, a0, a1
2931; CHECKIZHINXMIN-NEXT:    fcvt.h.s a0, a0
2932; CHECKIZHINXMIN-NEXT:    ret
2933  %z = call half @llvm.copysign.f16(half 1.0, half %x)
2934  %mul = fmul half %z, %y
2935  ret half %mul
2936}
2937