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=RV32IZFH %s
4; RUN: llc -mtriple=riscv64 -mattr=+zfh -verify-machineinstrs \
5; RUN:   -target-abi lp64f < %s | FileCheck -check-prefix=RV64IZFH %s
6; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
7; RUN:   | FileCheck -check-prefix=RV32I %s
8; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
9; RUN:   | FileCheck -check-prefix=RV64I %s
10
11; These tests are each targeted at a particular RISC-V FPU instruction.
12; Compares and conversions can be found in half-fcmp.ll and half-convert.ll
13; respectively. Some other half-*.ll files in this folder exercise LLVM IR
14; instructions that don't directly match a RISC-V instruction.
15
16define half @fadd_s(half %a, half %b) nounwind {
17; RV32IZFH-LABEL: fadd_s:
18; RV32IZFH:       # %bb.0:
19; RV32IZFH-NEXT:    fadd.h fa0, fa0, fa1
20; RV32IZFH-NEXT:    ret
21;
22; RV64IZFH-LABEL: fadd_s:
23; RV64IZFH:       # %bb.0:
24; RV64IZFH-NEXT:    fadd.h fa0, fa0, fa1
25; RV64IZFH-NEXT:    ret
26;
27; RV32I-LABEL: fadd_s:
28; RV32I:       # %bb.0:
29; RV32I-NEXT:    addi sp, sp, -16
30; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
31; RV32I-NEXT:    sw s0, 8(sp) # 4-byte Folded Spill
32; RV32I-NEXT:    sw s1, 4(sp) # 4-byte Folded Spill
33; RV32I-NEXT:    sw s2, 0(sp) # 4-byte Folded Spill
34; RV32I-NEXT:    mv s0, a1
35; RV32I-NEXT:    lui a1, 16
36; RV32I-NEXT:    addi s2, a1, -1
37; RV32I-NEXT:    and a0, a0, s2
38; RV32I-NEXT:    call __extendhfsf2@plt
39; RV32I-NEXT:    mv s1, a0
40; RV32I-NEXT:    and a0, s0, s2
41; RV32I-NEXT:    call __extendhfsf2@plt
42; RV32I-NEXT:    mv a1, a0
43; RV32I-NEXT:    mv a0, s1
44; RV32I-NEXT:    call __addsf3@plt
45; RV32I-NEXT:    call __truncsfhf2@plt
46; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
47; RV32I-NEXT:    lw s0, 8(sp) # 4-byte Folded Reload
48; RV32I-NEXT:    lw s1, 4(sp) # 4-byte Folded Reload
49; RV32I-NEXT:    lw s2, 0(sp) # 4-byte Folded Reload
50; RV32I-NEXT:    addi sp, sp, 16
51; RV32I-NEXT:    ret
52;
53; RV64I-LABEL: fadd_s:
54; RV64I:       # %bb.0:
55; RV64I-NEXT:    addi sp, sp, -32
56; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
57; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
58; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
59; RV64I-NEXT:    sd s2, 0(sp) # 8-byte Folded Spill
60; RV64I-NEXT:    mv s0, a1
61; RV64I-NEXT:    lui a1, 16
62; RV64I-NEXT:    addiw s2, a1, -1
63; RV64I-NEXT:    and a0, a0, s2
64; RV64I-NEXT:    call __extendhfsf2@plt
65; RV64I-NEXT:    mv s1, a0
66; RV64I-NEXT:    and a0, s0, s2
67; RV64I-NEXT:    call __extendhfsf2@plt
68; RV64I-NEXT:    mv a1, a0
69; RV64I-NEXT:    mv a0, s1
70; RV64I-NEXT:    call __addsf3@plt
71; RV64I-NEXT:    call __truncsfhf2@plt
72; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
73; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
74; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
75; RV64I-NEXT:    ld s2, 0(sp) # 8-byte Folded Reload
76; RV64I-NEXT:    addi sp, sp, 32
77; RV64I-NEXT:    ret
78  %1 = fadd half %a, %b
79  ret half %1
80}
81
82define half @fsub_s(half %a, half %b) nounwind {
83; RV32IZFH-LABEL: fsub_s:
84; RV32IZFH:       # %bb.0:
85; RV32IZFH-NEXT:    fsub.h fa0, fa0, fa1
86; RV32IZFH-NEXT:    ret
87;
88; RV64IZFH-LABEL: fsub_s:
89; RV64IZFH:       # %bb.0:
90; RV64IZFH-NEXT:    fsub.h fa0, fa0, fa1
91; RV64IZFH-NEXT:    ret
92;
93; RV32I-LABEL: fsub_s:
94; RV32I:       # %bb.0:
95; RV32I-NEXT:    addi sp, sp, -16
96; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
97; RV32I-NEXT:    sw s0, 8(sp) # 4-byte Folded Spill
98; RV32I-NEXT:    sw s1, 4(sp) # 4-byte Folded Spill
99; RV32I-NEXT:    sw s2, 0(sp) # 4-byte Folded Spill
100; RV32I-NEXT:    mv s0, a1
101; RV32I-NEXT:    lui a1, 16
102; RV32I-NEXT:    addi s2, a1, -1
103; RV32I-NEXT:    and a0, a0, s2
104; RV32I-NEXT:    call __extendhfsf2@plt
105; RV32I-NEXT:    mv s1, a0
106; RV32I-NEXT:    and a0, s0, s2
107; RV32I-NEXT:    call __extendhfsf2@plt
108; RV32I-NEXT:    mv a1, a0
109; RV32I-NEXT:    mv a0, s1
110; RV32I-NEXT:    call __subsf3@plt
111; RV32I-NEXT:    call __truncsfhf2@plt
112; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
113; RV32I-NEXT:    lw s0, 8(sp) # 4-byte Folded Reload
114; RV32I-NEXT:    lw s1, 4(sp) # 4-byte Folded Reload
115; RV32I-NEXT:    lw s2, 0(sp) # 4-byte Folded Reload
116; RV32I-NEXT:    addi sp, sp, 16
117; RV32I-NEXT:    ret
118;
119; RV64I-LABEL: fsub_s:
120; RV64I:       # %bb.0:
121; RV64I-NEXT:    addi sp, sp, -32
122; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
123; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
124; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
125; RV64I-NEXT:    sd s2, 0(sp) # 8-byte Folded Spill
126; RV64I-NEXT:    mv s0, a1
127; RV64I-NEXT:    lui a1, 16
128; RV64I-NEXT:    addiw s2, a1, -1
129; RV64I-NEXT:    and a0, a0, s2
130; RV64I-NEXT:    call __extendhfsf2@plt
131; RV64I-NEXT:    mv s1, a0
132; RV64I-NEXT:    and a0, s0, s2
133; RV64I-NEXT:    call __extendhfsf2@plt
134; RV64I-NEXT:    mv a1, a0
135; RV64I-NEXT:    mv a0, s1
136; RV64I-NEXT:    call __subsf3@plt
137; RV64I-NEXT:    call __truncsfhf2@plt
138; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
139; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
140; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
141; RV64I-NEXT:    ld s2, 0(sp) # 8-byte Folded Reload
142; RV64I-NEXT:    addi sp, sp, 32
143; RV64I-NEXT:    ret
144  %1 = fsub half %a, %b
145  ret half %1
146}
147
148define half @fmul_s(half %a, half %b) nounwind {
149; RV32IZFH-LABEL: fmul_s:
150; RV32IZFH:       # %bb.0:
151; RV32IZFH-NEXT:    fmul.h fa0, fa0, fa1
152; RV32IZFH-NEXT:    ret
153;
154; RV64IZFH-LABEL: fmul_s:
155; RV64IZFH:       # %bb.0:
156; RV64IZFH-NEXT:    fmul.h fa0, fa0, fa1
157; RV64IZFH-NEXT:    ret
158;
159; RV32I-LABEL: fmul_s:
160; RV32I:       # %bb.0:
161; RV32I-NEXT:    addi sp, sp, -16
162; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
163; RV32I-NEXT:    sw s0, 8(sp) # 4-byte Folded Spill
164; RV32I-NEXT:    sw s1, 4(sp) # 4-byte Folded Spill
165; RV32I-NEXT:    sw s2, 0(sp) # 4-byte Folded Spill
166; RV32I-NEXT:    mv s0, a1
167; RV32I-NEXT:    lui a1, 16
168; RV32I-NEXT:    addi s2, a1, -1
169; RV32I-NEXT:    and a0, a0, s2
170; RV32I-NEXT:    call __extendhfsf2@plt
171; RV32I-NEXT:    mv s1, a0
172; RV32I-NEXT:    and a0, s0, s2
173; RV32I-NEXT:    call __extendhfsf2@plt
174; RV32I-NEXT:    mv a1, a0
175; RV32I-NEXT:    mv a0, s1
176; RV32I-NEXT:    call __mulsf3@plt
177; RV32I-NEXT:    call __truncsfhf2@plt
178; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
179; RV32I-NEXT:    lw s0, 8(sp) # 4-byte Folded Reload
180; RV32I-NEXT:    lw s1, 4(sp) # 4-byte Folded Reload
181; RV32I-NEXT:    lw s2, 0(sp) # 4-byte Folded Reload
182; RV32I-NEXT:    addi sp, sp, 16
183; RV32I-NEXT:    ret
184;
185; RV64I-LABEL: fmul_s:
186; RV64I:       # %bb.0:
187; RV64I-NEXT:    addi sp, sp, -32
188; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
189; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
190; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
191; RV64I-NEXT:    sd s2, 0(sp) # 8-byte Folded Spill
192; RV64I-NEXT:    mv s0, a1
193; RV64I-NEXT:    lui a1, 16
194; RV64I-NEXT:    addiw s2, a1, -1
195; RV64I-NEXT:    and a0, a0, s2
196; RV64I-NEXT:    call __extendhfsf2@plt
197; RV64I-NEXT:    mv s1, a0
198; RV64I-NEXT:    and a0, s0, s2
199; RV64I-NEXT:    call __extendhfsf2@plt
200; RV64I-NEXT:    mv a1, a0
201; RV64I-NEXT:    mv a0, s1
202; RV64I-NEXT:    call __mulsf3@plt
203; RV64I-NEXT:    call __truncsfhf2@plt
204; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
205; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
206; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
207; RV64I-NEXT:    ld s2, 0(sp) # 8-byte Folded Reload
208; RV64I-NEXT:    addi sp, sp, 32
209; RV64I-NEXT:    ret
210  %1 = fmul half %a, %b
211  ret half %1
212}
213
214define half @fdiv_s(half %a, half %b) nounwind {
215; RV32IZFH-LABEL: fdiv_s:
216; RV32IZFH:       # %bb.0:
217; RV32IZFH-NEXT:    fdiv.h fa0, fa0, fa1
218; RV32IZFH-NEXT:    ret
219;
220; RV64IZFH-LABEL: fdiv_s:
221; RV64IZFH:       # %bb.0:
222; RV64IZFH-NEXT:    fdiv.h fa0, fa0, fa1
223; RV64IZFH-NEXT:    ret
224;
225; RV32I-LABEL: fdiv_s:
226; RV32I:       # %bb.0:
227; RV32I-NEXT:    addi sp, sp, -16
228; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
229; RV32I-NEXT:    sw s0, 8(sp) # 4-byte Folded Spill
230; RV32I-NEXT:    sw s1, 4(sp) # 4-byte Folded Spill
231; RV32I-NEXT:    sw s2, 0(sp) # 4-byte Folded Spill
232; RV32I-NEXT:    mv s0, a1
233; RV32I-NEXT:    lui a1, 16
234; RV32I-NEXT:    addi s2, a1, -1
235; RV32I-NEXT:    and a0, a0, s2
236; RV32I-NEXT:    call __extendhfsf2@plt
237; RV32I-NEXT:    mv s1, a0
238; RV32I-NEXT:    and a0, s0, s2
239; RV32I-NEXT:    call __extendhfsf2@plt
240; RV32I-NEXT:    mv a1, a0
241; RV32I-NEXT:    mv a0, s1
242; RV32I-NEXT:    call __divsf3@plt
243; RV32I-NEXT:    call __truncsfhf2@plt
244; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
245; RV32I-NEXT:    lw s0, 8(sp) # 4-byte Folded Reload
246; RV32I-NEXT:    lw s1, 4(sp) # 4-byte Folded Reload
247; RV32I-NEXT:    lw s2, 0(sp) # 4-byte Folded Reload
248; RV32I-NEXT:    addi sp, sp, 16
249; RV32I-NEXT:    ret
250;
251; RV64I-LABEL: fdiv_s:
252; RV64I:       # %bb.0:
253; RV64I-NEXT:    addi sp, sp, -32
254; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
255; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
256; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
257; RV64I-NEXT:    sd s2, 0(sp) # 8-byte Folded Spill
258; RV64I-NEXT:    mv s0, a1
259; RV64I-NEXT:    lui a1, 16
260; RV64I-NEXT:    addiw s2, a1, -1
261; RV64I-NEXT:    and a0, a0, s2
262; RV64I-NEXT:    call __extendhfsf2@plt
263; RV64I-NEXT:    mv s1, a0
264; RV64I-NEXT:    and a0, s0, s2
265; RV64I-NEXT:    call __extendhfsf2@plt
266; RV64I-NEXT:    mv a1, a0
267; RV64I-NEXT:    mv a0, s1
268; RV64I-NEXT:    call __divsf3@plt
269; RV64I-NEXT:    call __truncsfhf2@plt
270; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
271; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
272; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
273; RV64I-NEXT:    ld s2, 0(sp) # 8-byte Folded Reload
274; RV64I-NEXT:    addi sp, sp, 32
275; RV64I-NEXT:    ret
276  %1 = fdiv half %a, %b
277  ret half %1
278}
279
280declare half @llvm.sqrt.f16(half)
281
282define half @fsqrt_s(half %a) nounwind {
283; RV32IZFH-LABEL: fsqrt_s:
284; RV32IZFH:       # %bb.0:
285; RV32IZFH-NEXT:    fsqrt.h fa0, fa0
286; RV32IZFH-NEXT:    ret
287;
288; RV64IZFH-LABEL: fsqrt_s:
289; RV64IZFH:       # %bb.0:
290; RV64IZFH-NEXT:    fsqrt.h fa0, fa0
291; RV64IZFH-NEXT:    ret
292;
293; RV32I-LABEL: fsqrt_s:
294; RV32I:       # %bb.0:
295; RV32I-NEXT:    addi sp, sp, -16
296; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
297; RV32I-NEXT:    slli a0, a0, 16
298; RV32I-NEXT:    srli a0, a0, 16
299; RV32I-NEXT:    call __extendhfsf2@plt
300; RV32I-NEXT:    call sqrtf@plt
301; RV32I-NEXT:    call __truncsfhf2@plt
302; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
303; RV32I-NEXT:    addi sp, sp, 16
304; RV32I-NEXT:    ret
305;
306; RV64I-LABEL: fsqrt_s:
307; RV64I:       # %bb.0:
308; RV64I-NEXT:    addi sp, sp, -16
309; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
310; RV64I-NEXT:    slli a0, a0, 48
311; RV64I-NEXT:    srli a0, a0, 48
312; RV64I-NEXT:    call __extendhfsf2@plt
313; RV64I-NEXT:    call sqrtf@plt
314; RV64I-NEXT:    call __truncsfhf2@plt
315; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
316; RV64I-NEXT:    addi sp, sp, 16
317; RV64I-NEXT:    ret
318  %1 = call half @llvm.sqrt.f16(half %a)
319  ret half %1
320}
321
322declare half @llvm.copysign.f16(half, half)
323
324define half @fsgnj_s(half %a, half %b) nounwind {
325; RV32IZFH-LABEL: fsgnj_s:
326; RV32IZFH:       # %bb.0:
327; RV32IZFH-NEXT:    fsgnj.h fa0, fa0, fa1
328; RV32IZFH-NEXT:    ret
329;
330; RV64IZFH-LABEL: fsgnj_s:
331; RV64IZFH:       # %bb.0:
332; RV64IZFH-NEXT:    fsgnj.h fa0, fa0, fa1
333; RV64IZFH-NEXT:    ret
334;
335; RV32I-LABEL: fsgnj_s:
336; RV32I:       # %bb.0:
337; RV32I-NEXT:    lui a2, 1048568
338; RV32I-NEXT:    and a1, a1, a2
339; RV32I-NEXT:    slli a0, a0, 17
340; RV32I-NEXT:    srli a0, a0, 17
341; RV32I-NEXT:    or a0, a0, a1
342; RV32I-NEXT:    ret
343;
344; RV64I-LABEL: fsgnj_s:
345; RV64I:       # %bb.0:
346; RV64I-NEXT:    lui a2, 1048568
347; RV64I-NEXT:    and a1, a1, a2
348; RV64I-NEXT:    slli a0, a0, 49
349; RV64I-NEXT:    srli a0, a0, 49
350; RV64I-NEXT:    or a0, a0, a1
351; RV64I-NEXT:    ret
352  %1 = call half @llvm.copysign.f16(half %a, half %b)
353  ret half %1
354}
355
356; This function performs extra work to ensure that
357; DAGCombiner::visitBITCAST doesn't replace the fneg with an xor.
358define i32 @fneg_s(half %a, half %b) nounwind {
359; RV32IZFH-LABEL: fneg_s:
360; RV32IZFH:       # %bb.0:
361; RV32IZFH-NEXT:    fadd.h ft0, fa0, fa0
362; RV32IZFH-NEXT:    fneg.h ft1, ft0
363; RV32IZFH-NEXT:    feq.h a0, ft0, ft1
364; RV32IZFH-NEXT:    ret
365;
366; RV64IZFH-LABEL: fneg_s:
367; RV64IZFH:       # %bb.0:
368; RV64IZFH-NEXT:    fadd.h ft0, fa0, fa0
369; RV64IZFH-NEXT:    fneg.h ft1, ft0
370; RV64IZFH-NEXT:    feq.h a0, ft0, ft1
371; RV64IZFH-NEXT:    ret
372;
373; RV32I-LABEL: fneg_s:
374; RV32I:       # %bb.0:
375; RV32I-NEXT:    addi sp, sp, -16
376; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
377; RV32I-NEXT:    sw s0, 8(sp) # 4-byte Folded Spill
378; RV32I-NEXT:    sw s1, 4(sp) # 4-byte Folded Spill
379; RV32I-NEXT:    lui a1, 16
380; RV32I-NEXT:    addi s1, a1, -1
381; RV32I-NEXT:    and a0, a0, s1
382; RV32I-NEXT:    call __extendhfsf2@plt
383; RV32I-NEXT:    mv a1, a0
384; RV32I-NEXT:    call __addsf3@plt
385; RV32I-NEXT:    call __truncsfhf2@plt
386; RV32I-NEXT:    and a0, a0, s1
387; RV32I-NEXT:    call __extendhfsf2@plt
388; RV32I-NEXT:    mv s0, a0
389; RV32I-NEXT:    lui a0, 524288
390; RV32I-NEXT:    xor a0, s0, a0
391; RV32I-NEXT:    call __truncsfhf2@plt
392; RV32I-NEXT:    and a0, a0, s1
393; RV32I-NEXT:    call __extendhfsf2@plt
394; RV32I-NEXT:    mv a1, a0
395; RV32I-NEXT:    mv a0, s0
396; RV32I-NEXT:    call __eqsf2@plt
397; RV32I-NEXT:    seqz a0, a0
398; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
399; RV32I-NEXT:    lw s0, 8(sp) # 4-byte Folded Reload
400; RV32I-NEXT:    lw s1, 4(sp) # 4-byte Folded Reload
401; RV32I-NEXT:    addi sp, sp, 16
402; RV32I-NEXT:    ret
403;
404; RV64I-LABEL: fneg_s:
405; RV64I:       # %bb.0:
406; RV64I-NEXT:    addi sp, sp, -32
407; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
408; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
409; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
410; RV64I-NEXT:    lui a1, 16
411; RV64I-NEXT:    addiw s1, a1, -1
412; RV64I-NEXT:    and a0, a0, s1
413; RV64I-NEXT:    call __extendhfsf2@plt
414; RV64I-NEXT:    mv a1, a0
415; RV64I-NEXT:    call __addsf3@plt
416; RV64I-NEXT:    call __truncsfhf2@plt
417; RV64I-NEXT:    and a0, a0, s1
418; RV64I-NEXT:    call __extendhfsf2@plt
419; RV64I-NEXT:    mv s0, a0
420; RV64I-NEXT:    lui a0, 524288
421; RV64I-NEXT:    xor a0, s0, a0
422; RV64I-NEXT:    call __truncsfhf2@plt
423; RV64I-NEXT:    and a0, a0, s1
424; RV64I-NEXT:    call __extendhfsf2@plt
425; RV64I-NEXT:    mv a1, a0
426; RV64I-NEXT:    mv a0, s0
427; RV64I-NEXT:    call __eqsf2@plt
428; RV64I-NEXT:    seqz a0, a0
429; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
430; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
431; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
432; RV64I-NEXT:    addi sp, sp, 32
433; RV64I-NEXT:    ret
434  %1 = fadd half %a, %a
435  %2 = fneg half %1
436  %3 = fcmp oeq half %1, %2
437  %4 = zext i1 %3 to i32
438  ret i32 %4
439}
440
441; This function performs extra work to ensure that
442; DAGCombiner::visitBITCAST doesn't replace the fneg with an xor.
443define half @fsgnjn_s(half %a, half %b) nounwind {
444; RV32IZFH-LABEL: fsgnjn_s:
445; RV32IZFH:       # %bb.0:
446; RV32IZFH-NEXT:    fadd.h ft0, fa0, fa1
447; RV32IZFH-NEXT:    fsgnjn.h fa0, fa0, ft0
448; RV32IZFH-NEXT:    ret
449;
450; RV64IZFH-LABEL: fsgnjn_s:
451; RV64IZFH:       # %bb.0:
452; RV64IZFH-NEXT:    fadd.h ft0, fa0, fa1
453; RV64IZFH-NEXT:    fsgnjn.h fa0, fa0, ft0
454; RV64IZFH-NEXT:    ret
455;
456; RV32I-LABEL: fsgnjn_s:
457; RV32I:       # %bb.0:
458; RV32I-NEXT:    addi sp, sp, -32
459; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
460; RV32I-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
461; RV32I-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
462; RV32I-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
463; RV32I-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
464; RV32I-NEXT:    mv s0, a1
465; RV32I-NEXT:    mv s1, a0
466; RV32I-NEXT:    lui a0, 16
467; RV32I-NEXT:    addi s3, a0, -1
468; RV32I-NEXT:    and a0, s1, s3
469; RV32I-NEXT:    call __extendhfsf2@plt
470; RV32I-NEXT:    mv s2, a0
471; RV32I-NEXT:    and a0, s0, s3
472; RV32I-NEXT:    call __extendhfsf2@plt
473; RV32I-NEXT:    mv a1, a0
474; RV32I-NEXT:    mv a0, s2
475; RV32I-NEXT:    call __addsf3@plt
476; RV32I-NEXT:    call __truncsfhf2@plt
477; RV32I-NEXT:    and a0, a0, s3
478; RV32I-NEXT:    call __extendhfsf2@plt
479; RV32I-NEXT:    lui a1, 524288
480; RV32I-NEXT:    xor a0, a0, a1
481; RV32I-NEXT:    call __truncsfhf2@plt
482; RV32I-NEXT:    lui a1, 1048568
483; RV32I-NEXT:    and a0, a0, a1
484; RV32I-NEXT:    slli a1, s1, 17
485; RV32I-NEXT:    srli a1, a1, 17
486; RV32I-NEXT:    or a0, a1, a0
487; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
488; RV32I-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
489; RV32I-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
490; RV32I-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
491; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
492; RV32I-NEXT:    addi sp, sp, 32
493; RV32I-NEXT:    ret
494;
495; RV64I-LABEL: fsgnjn_s:
496; RV64I:       # %bb.0:
497; RV64I-NEXT:    addi sp, sp, -48
498; RV64I-NEXT:    sd ra, 40(sp) # 8-byte Folded Spill
499; RV64I-NEXT:    sd s0, 32(sp) # 8-byte Folded Spill
500; RV64I-NEXT:    sd s1, 24(sp) # 8-byte Folded Spill
501; RV64I-NEXT:    sd s2, 16(sp) # 8-byte Folded Spill
502; RV64I-NEXT:    sd s3, 8(sp) # 8-byte Folded Spill
503; RV64I-NEXT:    mv s0, a1
504; RV64I-NEXT:    mv s1, a0
505; RV64I-NEXT:    lui a0, 16
506; RV64I-NEXT:    addiw s3, a0, -1
507; RV64I-NEXT:    and a0, s1, s3
508; RV64I-NEXT:    call __extendhfsf2@plt
509; RV64I-NEXT:    mv s2, a0
510; RV64I-NEXT:    and a0, s0, s3
511; RV64I-NEXT:    call __extendhfsf2@plt
512; RV64I-NEXT:    mv a1, a0
513; RV64I-NEXT:    mv a0, s2
514; RV64I-NEXT:    call __addsf3@plt
515; RV64I-NEXT:    call __truncsfhf2@plt
516; RV64I-NEXT:    and a0, a0, s3
517; RV64I-NEXT:    call __extendhfsf2@plt
518; RV64I-NEXT:    lui a1, 524288
519; RV64I-NEXT:    xor a0, a0, a1
520; RV64I-NEXT:    call __truncsfhf2@plt
521; RV64I-NEXT:    lui a1, 1048568
522; RV64I-NEXT:    and a0, a0, a1
523; RV64I-NEXT:    slli a1, s1, 49
524; RV64I-NEXT:    srli a1, a1, 49
525; RV64I-NEXT:    or a0, a1, a0
526; RV64I-NEXT:    ld ra, 40(sp) # 8-byte Folded Reload
527; RV64I-NEXT:    ld s0, 32(sp) # 8-byte Folded Reload
528; RV64I-NEXT:    ld s1, 24(sp) # 8-byte Folded Reload
529; RV64I-NEXT:    ld s2, 16(sp) # 8-byte Folded Reload
530; RV64I-NEXT:    ld s3, 8(sp) # 8-byte Folded Reload
531; RV64I-NEXT:    addi sp, sp, 48
532; RV64I-NEXT:    ret
533  %1 = fadd half %a, %b
534  %2 = fneg half %1
535  %3 = call half @llvm.copysign.f16(half %a, half %2)
536  ret half %3
537}
538
539declare half @llvm.fabs.f16(half)
540
541; This function performs extra work to ensure that
542; DAGCombiner::visitBITCAST doesn't replace the fabs with an and.
543define half @fabs_s(half %a, half %b) nounwind {
544; RV32IZFH-LABEL: fabs_s:
545; RV32IZFH:       # %bb.0:
546; RV32IZFH-NEXT:    fadd.h ft0, fa0, fa1
547; RV32IZFH-NEXT:    fabs.h ft1, ft0
548; RV32IZFH-NEXT:    fadd.h fa0, ft1, ft0
549; RV32IZFH-NEXT:    ret
550;
551; RV64IZFH-LABEL: fabs_s:
552; RV64IZFH:       # %bb.0:
553; RV64IZFH-NEXT:    fadd.h ft0, fa0, fa1
554; RV64IZFH-NEXT:    fabs.h ft1, ft0
555; RV64IZFH-NEXT:    fadd.h fa0, ft1, ft0
556; RV64IZFH-NEXT:    ret
557;
558; RV32I-LABEL: fabs_s:
559; RV32I:       # %bb.0:
560; RV32I-NEXT:    addi sp, sp, -16
561; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
562; RV32I-NEXT:    sw s0, 8(sp) # 4-byte Folded Spill
563; RV32I-NEXT:    sw s1, 4(sp) # 4-byte Folded Spill
564; RV32I-NEXT:    sw s2, 0(sp) # 4-byte Folded Spill
565; RV32I-NEXT:    mv s0, a1
566; RV32I-NEXT:    lui a1, 16
567; RV32I-NEXT:    addi s2, a1, -1
568; RV32I-NEXT:    and a0, a0, s2
569; RV32I-NEXT:    call __extendhfsf2@plt
570; RV32I-NEXT:    mv s1, a0
571; RV32I-NEXT:    and a0, s0, s2
572; RV32I-NEXT:    call __extendhfsf2@plt
573; RV32I-NEXT:    mv a1, a0
574; RV32I-NEXT:    mv a0, s1
575; RV32I-NEXT:    call __addsf3@plt
576; RV32I-NEXT:    call __truncsfhf2@plt
577; RV32I-NEXT:    and a0, a0, s2
578; RV32I-NEXT:    call __extendhfsf2@plt
579; RV32I-NEXT:    mv s0, a0
580; RV32I-NEXT:    slli a0, a0, 1
581; RV32I-NEXT:    srli a0, a0, 1
582; RV32I-NEXT:    call __truncsfhf2@plt
583; RV32I-NEXT:    and a0, a0, s2
584; RV32I-NEXT:    call __extendhfsf2@plt
585; RV32I-NEXT:    mv a1, s0
586; RV32I-NEXT:    call __addsf3@plt
587; RV32I-NEXT:    call __truncsfhf2@plt
588; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
589; RV32I-NEXT:    lw s0, 8(sp) # 4-byte Folded Reload
590; RV32I-NEXT:    lw s1, 4(sp) # 4-byte Folded Reload
591; RV32I-NEXT:    lw s2, 0(sp) # 4-byte Folded Reload
592; RV32I-NEXT:    addi sp, sp, 16
593; RV32I-NEXT:    ret
594;
595; RV64I-LABEL: fabs_s:
596; RV64I:       # %bb.0:
597; RV64I-NEXT:    addi sp, sp, -32
598; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
599; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
600; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
601; RV64I-NEXT:    sd s2, 0(sp) # 8-byte Folded Spill
602; RV64I-NEXT:    mv s0, a1
603; RV64I-NEXT:    lui a1, 16
604; RV64I-NEXT:    addiw s2, a1, -1
605; RV64I-NEXT:    and a0, a0, s2
606; RV64I-NEXT:    call __extendhfsf2@plt
607; RV64I-NEXT:    mv s1, a0
608; RV64I-NEXT:    and a0, s0, s2
609; RV64I-NEXT:    call __extendhfsf2@plt
610; RV64I-NEXT:    mv a1, a0
611; RV64I-NEXT:    mv a0, s1
612; RV64I-NEXT:    call __addsf3@plt
613; RV64I-NEXT:    call __truncsfhf2@plt
614; RV64I-NEXT:    and a0, a0, s2
615; RV64I-NEXT:    call __extendhfsf2@plt
616; RV64I-NEXT:    mv s0, a0
617; RV64I-NEXT:    slli a0, a0, 33
618; RV64I-NEXT:    srli a0, a0, 33
619; RV64I-NEXT:    call __truncsfhf2@plt
620; RV64I-NEXT:    and a0, a0, s2
621; RV64I-NEXT:    call __extendhfsf2@plt
622; RV64I-NEXT:    mv a1, s0
623; RV64I-NEXT:    call __addsf3@plt
624; RV64I-NEXT:    call __truncsfhf2@plt
625; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
626; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
627; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
628; RV64I-NEXT:    ld s2, 0(sp) # 8-byte Folded Reload
629; RV64I-NEXT:    addi sp, sp, 32
630; RV64I-NEXT:    ret
631  %1 = fadd half %a, %b
632  %2 = call half @llvm.fabs.f16(half %1)
633  %3 = fadd half %2, %1
634  ret half %3
635}
636
637declare half @llvm.minnum.f16(half, half)
638
639define half @fmin_s(half %a, half %b) nounwind {
640; RV32IZFH-LABEL: fmin_s:
641; RV32IZFH:       # %bb.0:
642; RV32IZFH-NEXT:    fmin.h fa0, fa0, fa1
643; RV32IZFH-NEXT:    ret
644;
645; RV64IZFH-LABEL: fmin_s:
646; RV64IZFH:       # %bb.0:
647; RV64IZFH-NEXT:    fmin.h fa0, fa0, fa1
648; RV64IZFH-NEXT:    ret
649;
650; RV32I-LABEL: fmin_s:
651; RV32I:       # %bb.0:
652; RV32I-NEXT:    addi sp, sp, -16
653; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
654; RV32I-NEXT:    sw s0, 8(sp) # 4-byte Folded Spill
655; RV32I-NEXT:    sw s1, 4(sp) # 4-byte Folded Spill
656; RV32I-NEXT:    sw s2, 0(sp) # 4-byte Folded Spill
657; RV32I-NEXT:    mv s0, a1
658; RV32I-NEXT:    lui a1, 16
659; RV32I-NEXT:    addi s2, a1, -1
660; RV32I-NEXT:    and a0, a0, s2
661; RV32I-NEXT:    call __extendhfsf2@plt
662; RV32I-NEXT:    mv s1, a0
663; RV32I-NEXT:    and a0, s0, s2
664; RV32I-NEXT:    call __extendhfsf2@plt
665; RV32I-NEXT:    mv a1, a0
666; RV32I-NEXT:    mv a0, s1
667; RV32I-NEXT:    call fminf@plt
668; RV32I-NEXT:    call __truncsfhf2@plt
669; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
670; RV32I-NEXT:    lw s0, 8(sp) # 4-byte Folded Reload
671; RV32I-NEXT:    lw s1, 4(sp) # 4-byte Folded Reload
672; RV32I-NEXT:    lw s2, 0(sp) # 4-byte Folded Reload
673; RV32I-NEXT:    addi sp, sp, 16
674; RV32I-NEXT:    ret
675;
676; RV64I-LABEL: fmin_s:
677; RV64I:       # %bb.0:
678; RV64I-NEXT:    addi sp, sp, -32
679; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
680; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
681; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
682; RV64I-NEXT:    sd s2, 0(sp) # 8-byte Folded Spill
683; RV64I-NEXT:    mv s0, a1
684; RV64I-NEXT:    lui a1, 16
685; RV64I-NEXT:    addiw s2, a1, -1
686; RV64I-NEXT:    and a0, a0, s2
687; RV64I-NEXT:    call __extendhfsf2@plt
688; RV64I-NEXT:    mv s1, a0
689; RV64I-NEXT:    and a0, s0, s2
690; RV64I-NEXT:    call __extendhfsf2@plt
691; RV64I-NEXT:    mv a1, a0
692; RV64I-NEXT:    mv a0, s1
693; RV64I-NEXT:    call fminf@plt
694; RV64I-NEXT:    call __truncsfhf2@plt
695; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
696; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
697; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
698; RV64I-NEXT:    ld s2, 0(sp) # 8-byte Folded Reload
699; RV64I-NEXT:    addi sp, sp, 32
700; RV64I-NEXT:    ret
701  %1 = call half @llvm.minnum.f16(half %a, half %b)
702  ret half %1
703}
704
705declare half @llvm.maxnum.f16(half, half)
706
707define half @fmax_s(half %a, half %b) nounwind {
708; RV32IZFH-LABEL: fmax_s:
709; RV32IZFH:       # %bb.0:
710; RV32IZFH-NEXT:    fmax.h fa0, fa0, fa1
711; RV32IZFH-NEXT:    ret
712;
713; RV64IZFH-LABEL: fmax_s:
714; RV64IZFH:       # %bb.0:
715; RV64IZFH-NEXT:    fmax.h fa0, fa0, fa1
716; RV64IZFH-NEXT:    ret
717;
718; RV32I-LABEL: fmax_s:
719; RV32I:       # %bb.0:
720; RV32I-NEXT:    addi sp, sp, -16
721; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
722; RV32I-NEXT:    sw s0, 8(sp) # 4-byte Folded Spill
723; RV32I-NEXT:    sw s1, 4(sp) # 4-byte Folded Spill
724; RV32I-NEXT:    sw s2, 0(sp) # 4-byte Folded Spill
725; RV32I-NEXT:    mv s0, a1
726; RV32I-NEXT:    lui a1, 16
727; RV32I-NEXT:    addi s2, a1, -1
728; RV32I-NEXT:    and a0, a0, s2
729; RV32I-NEXT:    call __extendhfsf2@plt
730; RV32I-NEXT:    mv s1, a0
731; RV32I-NEXT:    and a0, s0, s2
732; RV32I-NEXT:    call __extendhfsf2@plt
733; RV32I-NEXT:    mv a1, a0
734; RV32I-NEXT:    mv a0, s1
735; RV32I-NEXT:    call fmaxf@plt
736; RV32I-NEXT:    call __truncsfhf2@plt
737; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
738; RV32I-NEXT:    lw s0, 8(sp) # 4-byte Folded Reload
739; RV32I-NEXT:    lw s1, 4(sp) # 4-byte Folded Reload
740; RV32I-NEXT:    lw s2, 0(sp) # 4-byte Folded Reload
741; RV32I-NEXT:    addi sp, sp, 16
742; RV32I-NEXT:    ret
743;
744; RV64I-LABEL: fmax_s:
745; RV64I:       # %bb.0:
746; RV64I-NEXT:    addi sp, sp, -32
747; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
748; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
749; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
750; RV64I-NEXT:    sd s2, 0(sp) # 8-byte Folded Spill
751; RV64I-NEXT:    mv s0, a1
752; RV64I-NEXT:    lui a1, 16
753; RV64I-NEXT:    addiw s2, a1, -1
754; RV64I-NEXT:    and a0, a0, s2
755; RV64I-NEXT:    call __extendhfsf2@plt
756; RV64I-NEXT:    mv s1, a0
757; RV64I-NEXT:    and a0, s0, s2
758; RV64I-NEXT:    call __extendhfsf2@plt
759; RV64I-NEXT:    mv a1, a0
760; RV64I-NEXT:    mv a0, s1
761; RV64I-NEXT:    call fmaxf@plt
762; RV64I-NEXT:    call __truncsfhf2@plt
763; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
764; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
765; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
766; RV64I-NEXT:    ld s2, 0(sp) # 8-byte Folded Reload
767; RV64I-NEXT:    addi sp, sp, 32
768; RV64I-NEXT:    ret
769  %1 = call half @llvm.maxnum.f16(half %a, half %b)
770  ret half %1
771}
772
773declare half @llvm.fma.f16(half, half, half)
774
775define half @fmadd_s(half %a, half %b, half %c) nounwind {
776; RV32IZFH-LABEL: fmadd_s:
777; RV32IZFH:       # %bb.0:
778; RV32IZFH-NEXT:    fmadd.h fa0, fa0, fa1, fa2
779; RV32IZFH-NEXT:    ret
780;
781; RV64IZFH-LABEL: fmadd_s:
782; RV64IZFH:       # %bb.0:
783; RV64IZFH-NEXT:    fmadd.h fa0, fa0, fa1, fa2
784; RV64IZFH-NEXT:    ret
785;
786; RV32I-LABEL: fmadd_s:
787; RV32I:       # %bb.0:
788; RV32I-NEXT:    addi sp, sp, -32
789; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
790; RV32I-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
791; RV32I-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
792; RV32I-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
793; RV32I-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
794; RV32I-NEXT:    mv s0, a2
795; RV32I-NEXT:    mv s1, a1
796; RV32I-NEXT:    lui a1, 16
797; RV32I-NEXT:    addi s3, a1, -1
798; RV32I-NEXT:    and a0, a0, s3
799; RV32I-NEXT:    call __extendhfsf2@plt
800; RV32I-NEXT:    mv s2, a0
801; RV32I-NEXT:    and a0, s1, s3
802; RV32I-NEXT:    call __extendhfsf2@plt
803; RV32I-NEXT:    mv s1, a0
804; RV32I-NEXT:    and a0, s0, s3
805; RV32I-NEXT:    call __extendhfsf2@plt
806; RV32I-NEXT:    mv a2, a0
807; RV32I-NEXT:    mv a0, s2
808; RV32I-NEXT:    mv a1, s1
809; RV32I-NEXT:    call fmaf@plt
810; RV32I-NEXT:    call __truncsfhf2@plt
811; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
812; RV32I-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
813; RV32I-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
814; RV32I-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
815; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
816; RV32I-NEXT:    addi sp, sp, 32
817; RV32I-NEXT:    ret
818;
819; RV64I-LABEL: fmadd_s:
820; RV64I:       # %bb.0:
821; RV64I-NEXT:    addi sp, sp, -48
822; RV64I-NEXT:    sd ra, 40(sp) # 8-byte Folded Spill
823; RV64I-NEXT:    sd s0, 32(sp) # 8-byte Folded Spill
824; RV64I-NEXT:    sd s1, 24(sp) # 8-byte Folded Spill
825; RV64I-NEXT:    sd s2, 16(sp) # 8-byte Folded Spill
826; RV64I-NEXT:    sd s3, 8(sp) # 8-byte Folded Spill
827; RV64I-NEXT:    mv s0, a2
828; RV64I-NEXT:    mv s1, a1
829; RV64I-NEXT:    lui a1, 16
830; RV64I-NEXT:    addiw s3, a1, -1
831; RV64I-NEXT:    and a0, a0, s3
832; RV64I-NEXT:    call __extendhfsf2@plt
833; RV64I-NEXT:    mv s2, a0
834; RV64I-NEXT:    and a0, s1, s3
835; RV64I-NEXT:    call __extendhfsf2@plt
836; RV64I-NEXT:    mv s1, a0
837; RV64I-NEXT:    and a0, s0, s3
838; RV64I-NEXT:    call __extendhfsf2@plt
839; RV64I-NEXT:    mv a2, a0
840; RV64I-NEXT:    mv a0, s2
841; RV64I-NEXT:    mv a1, s1
842; RV64I-NEXT:    call fmaf@plt
843; RV64I-NEXT:    call __truncsfhf2@plt
844; RV64I-NEXT:    ld ra, 40(sp) # 8-byte Folded Reload
845; RV64I-NEXT:    ld s0, 32(sp) # 8-byte Folded Reload
846; RV64I-NEXT:    ld s1, 24(sp) # 8-byte Folded Reload
847; RV64I-NEXT:    ld s2, 16(sp) # 8-byte Folded Reload
848; RV64I-NEXT:    ld s3, 8(sp) # 8-byte Folded Reload
849; RV64I-NEXT:    addi sp, sp, 48
850; RV64I-NEXT:    ret
851  %1 = call half @llvm.fma.f16(half %a, half %b, half %c)
852  ret half %1
853}
854
855define half @fmsub_s(half %a, half %b, half %c) nounwind {
856; RV32IZFH-LABEL: fmsub_s:
857; RV32IZFH:       # %bb.0:
858; RV32IZFH-NEXT:    fmv.h.x ft0, zero
859; RV32IZFH-NEXT:    fadd.h ft0, fa2, ft0
860; RV32IZFH-NEXT:    fmsub.h fa0, fa0, fa1, ft0
861; RV32IZFH-NEXT:    ret
862;
863; RV64IZFH-LABEL: fmsub_s:
864; RV64IZFH:       # %bb.0:
865; RV64IZFH-NEXT:    fmv.h.x ft0, zero
866; RV64IZFH-NEXT:    fadd.h ft0, fa2, ft0
867; RV64IZFH-NEXT:    fmsub.h fa0, fa0, fa1, ft0
868; RV64IZFH-NEXT:    ret
869;
870; RV32I-LABEL: fmsub_s:
871; RV32I:       # %bb.0:
872; RV32I-NEXT:    addi sp, sp, -32
873; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
874; RV32I-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
875; RV32I-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
876; RV32I-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
877; RV32I-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
878; RV32I-NEXT:    mv s0, a1
879; RV32I-NEXT:    mv s1, a0
880; RV32I-NEXT:    lui a0, 16
881; RV32I-NEXT:    addi s3, a0, -1
882; RV32I-NEXT:    and a0, a2, s3
883; RV32I-NEXT:    call __extendhfsf2@plt
884; RV32I-NEXT:    li a1, 0
885; RV32I-NEXT:    call __addsf3@plt
886; RV32I-NEXT:    call __truncsfhf2@plt
887; RV32I-NEXT:    and a0, a0, s3
888; RV32I-NEXT:    call __extendhfsf2@plt
889; RV32I-NEXT:    lui a1, 524288
890; RV32I-NEXT:    xor a0, a0, a1
891; RV32I-NEXT:    call __truncsfhf2@plt
892; RV32I-NEXT:    mv s2, a0
893; RV32I-NEXT:    and a0, s1, s3
894; RV32I-NEXT:    call __extendhfsf2@plt
895; RV32I-NEXT:    mv s1, a0
896; RV32I-NEXT:    and a0, s0, s3
897; RV32I-NEXT:    call __extendhfsf2@plt
898; RV32I-NEXT:    mv s0, a0
899; RV32I-NEXT:    and a0, s2, s3
900; RV32I-NEXT:    call __extendhfsf2@plt
901; RV32I-NEXT:    mv a2, a0
902; RV32I-NEXT:    mv a0, s1
903; RV32I-NEXT:    mv a1, s0
904; RV32I-NEXT:    call fmaf@plt
905; RV32I-NEXT:    call __truncsfhf2@plt
906; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
907; RV32I-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
908; RV32I-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
909; RV32I-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
910; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
911; RV32I-NEXT:    addi sp, sp, 32
912; RV32I-NEXT:    ret
913;
914; RV64I-LABEL: fmsub_s:
915; RV64I:       # %bb.0:
916; RV64I-NEXT:    addi sp, sp, -48
917; RV64I-NEXT:    sd ra, 40(sp) # 8-byte Folded Spill
918; RV64I-NEXT:    sd s0, 32(sp) # 8-byte Folded Spill
919; RV64I-NEXT:    sd s1, 24(sp) # 8-byte Folded Spill
920; RV64I-NEXT:    sd s2, 16(sp) # 8-byte Folded Spill
921; RV64I-NEXT:    sd s3, 8(sp) # 8-byte Folded Spill
922; RV64I-NEXT:    mv s0, a1
923; RV64I-NEXT:    mv s1, a0
924; RV64I-NEXT:    lui a0, 16
925; RV64I-NEXT:    addiw s3, a0, -1
926; RV64I-NEXT:    and a0, a2, s3
927; RV64I-NEXT:    call __extendhfsf2@plt
928; RV64I-NEXT:    li a1, 0
929; RV64I-NEXT:    call __addsf3@plt
930; RV64I-NEXT:    call __truncsfhf2@plt
931; RV64I-NEXT:    and a0, a0, s3
932; RV64I-NEXT:    call __extendhfsf2@plt
933; RV64I-NEXT:    lui a1, 524288
934; RV64I-NEXT:    xor a0, a0, a1
935; RV64I-NEXT:    call __truncsfhf2@plt
936; RV64I-NEXT:    mv s2, a0
937; RV64I-NEXT:    and a0, s1, s3
938; RV64I-NEXT:    call __extendhfsf2@plt
939; RV64I-NEXT:    mv s1, a0
940; RV64I-NEXT:    and a0, s0, s3
941; RV64I-NEXT:    call __extendhfsf2@plt
942; RV64I-NEXT:    mv s0, a0
943; RV64I-NEXT:    and a0, s2, s3
944; RV64I-NEXT:    call __extendhfsf2@plt
945; RV64I-NEXT:    mv a2, a0
946; RV64I-NEXT:    mv a0, s1
947; RV64I-NEXT:    mv a1, s0
948; RV64I-NEXT:    call fmaf@plt
949; RV64I-NEXT:    call __truncsfhf2@plt
950; RV64I-NEXT:    ld ra, 40(sp) # 8-byte Folded Reload
951; RV64I-NEXT:    ld s0, 32(sp) # 8-byte Folded Reload
952; RV64I-NEXT:    ld s1, 24(sp) # 8-byte Folded Reload
953; RV64I-NEXT:    ld s2, 16(sp) # 8-byte Folded Reload
954; RV64I-NEXT:    ld s3, 8(sp) # 8-byte Folded Reload
955; RV64I-NEXT:    addi sp, sp, 48
956; RV64I-NEXT:    ret
957  %c_ = fadd half 0.0, %c ; avoid negation using xor
958  %negc = fsub half -0.0, %c_
959  %1 = call half @llvm.fma.f16(half %a, half %b, half %negc)
960  ret half %1
961}
962
963define half @fnmadd_s(half %a, half %b, half %c) nounwind {
964; RV32IZFH-LABEL: fnmadd_s:
965; RV32IZFH:       # %bb.0:
966; RV32IZFH-NEXT:    fmv.h.x ft0, zero
967; RV32IZFH-NEXT:    fadd.h ft1, fa0, ft0
968; RV32IZFH-NEXT:    fadd.h ft0, fa2, ft0
969; RV32IZFH-NEXT:    fnmadd.h fa0, ft1, fa1, ft0
970; RV32IZFH-NEXT:    ret
971;
972; RV64IZFH-LABEL: fnmadd_s:
973; RV64IZFH:       # %bb.0:
974; RV64IZFH-NEXT:    fmv.h.x ft0, zero
975; RV64IZFH-NEXT:    fadd.h ft1, fa0, ft0
976; RV64IZFH-NEXT:    fadd.h ft0, fa2, ft0
977; RV64IZFH-NEXT:    fnmadd.h fa0, ft1, fa1, ft0
978; RV64IZFH-NEXT:    ret
979;
980; RV32I-LABEL: fnmadd_s:
981; RV32I:       # %bb.0:
982; RV32I-NEXT:    addi sp, sp, -32
983; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
984; RV32I-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
985; RV32I-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
986; RV32I-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
987; RV32I-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
988; RV32I-NEXT:    sw s4, 8(sp) # 4-byte Folded Spill
989; RV32I-NEXT:    mv s1, a2
990; RV32I-NEXT:    mv s0, a1
991; RV32I-NEXT:    lui a1, 16
992; RV32I-NEXT:    addi s3, a1, -1
993; RV32I-NEXT:    and a0, a0, s3
994; RV32I-NEXT:    call __extendhfsf2@plt
995; RV32I-NEXT:    li a1, 0
996; RV32I-NEXT:    call __addsf3@plt
997; RV32I-NEXT:    call __truncsfhf2@plt
998; RV32I-NEXT:    mv s2, a0
999; RV32I-NEXT:    and a0, s1, s3
1000; RV32I-NEXT:    call __extendhfsf2@plt
1001; RV32I-NEXT:    li a1, 0
1002; RV32I-NEXT:    call __addsf3@plt
1003; RV32I-NEXT:    call __truncsfhf2@plt
1004; RV32I-NEXT:    mv s1, a0
1005; RV32I-NEXT:    and a0, s2, s3
1006; RV32I-NEXT:    call __extendhfsf2@plt
1007; RV32I-NEXT:    lui s4, 524288
1008; RV32I-NEXT:    xor a0, a0, s4
1009; RV32I-NEXT:    call __truncsfhf2@plt
1010; RV32I-NEXT:    mv s2, a0
1011; RV32I-NEXT:    and a0, s1, s3
1012; RV32I-NEXT:    call __extendhfsf2@plt
1013; RV32I-NEXT:    xor a0, a0, s4
1014; RV32I-NEXT:    call __truncsfhf2@plt
1015; RV32I-NEXT:    mv s1, a0
1016; RV32I-NEXT:    and a0, s0, s3
1017; RV32I-NEXT:    call __extendhfsf2@plt
1018; RV32I-NEXT:    mv s0, a0
1019; RV32I-NEXT:    and a0, s2, s3
1020; RV32I-NEXT:    call __extendhfsf2@plt
1021; RV32I-NEXT:    mv s2, a0
1022; RV32I-NEXT:    and a0, s1, s3
1023; RV32I-NEXT:    call __extendhfsf2@plt
1024; RV32I-NEXT:    mv a2, a0
1025; RV32I-NEXT:    mv a0, s2
1026; RV32I-NEXT:    mv a1, s0
1027; RV32I-NEXT:    call fmaf@plt
1028; RV32I-NEXT:    call __truncsfhf2@plt
1029; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
1030; RV32I-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
1031; RV32I-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
1032; RV32I-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
1033; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
1034; RV32I-NEXT:    lw s4, 8(sp) # 4-byte Folded Reload
1035; RV32I-NEXT:    addi sp, sp, 32
1036; RV32I-NEXT:    ret
1037;
1038; RV64I-LABEL: fnmadd_s:
1039; RV64I:       # %bb.0:
1040; RV64I-NEXT:    addi sp, sp, -48
1041; RV64I-NEXT:    sd ra, 40(sp) # 8-byte Folded Spill
1042; RV64I-NEXT:    sd s0, 32(sp) # 8-byte Folded Spill
1043; RV64I-NEXT:    sd s1, 24(sp) # 8-byte Folded Spill
1044; RV64I-NEXT:    sd s2, 16(sp) # 8-byte Folded Spill
1045; RV64I-NEXT:    sd s3, 8(sp) # 8-byte Folded Spill
1046; RV64I-NEXT:    sd s4, 0(sp) # 8-byte Folded Spill
1047; RV64I-NEXT:    mv s1, a2
1048; RV64I-NEXT:    mv s0, a1
1049; RV64I-NEXT:    lui a1, 16
1050; RV64I-NEXT:    addiw s3, a1, -1
1051; RV64I-NEXT:    and a0, a0, s3
1052; RV64I-NEXT:    call __extendhfsf2@plt
1053; RV64I-NEXT:    li a1, 0
1054; RV64I-NEXT:    call __addsf3@plt
1055; RV64I-NEXT:    call __truncsfhf2@plt
1056; RV64I-NEXT:    mv s2, a0
1057; RV64I-NEXT:    and a0, s1, s3
1058; RV64I-NEXT:    call __extendhfsf2@plt
1059; RV64I-NEXT:    li a1, 0
1060; RV64I-NEXT:    call __addsf3@plt
1061; RV64I-NEXT:    call __truncsfhf2@plt
1062; RV64I-NEXT:    mv s1, a0
1063; RV64I-NEXT:    and a0, s2, s3
1064; RV64I-NEXT:    call __extendhfsf2@plt
1065; RV64I-NEXT:    lui s4, 524288
1066; RV64I-NEXT:    xor a0, a0, s4
1067; RV64I-NEXT:    call __truncsfhf2@plt
1068; RV64I-NEXT:    mv s2, a0
1069; RV64I-NEXT:    and a0, s1, s3
1070; RV64I-NEXT:    call __extendhfsf2@plt
1071; RV64I-NEXT:    xor a0, a0, s4
1072; RV64I-NEXT:    call __truncsfhf2@plt
1073; RV64I-NEXT:    mv s1, a0
1074; RV64I-NEXT:    and a0, s0, s3
1075; RV64I-NEXT:    call __extendhfsf2@plt
1076; RV64I-NEXT:    mv s0, a0
1077; RV64I-NEXT:    and a0, s2, s3
1078; RV64I-NEXT:    call __extendhfsf2@plt
1079; RV64I-NEXT:    mv s2, a0
1080; RV64I-NEXT:    and a0, s1, s3
1081; RV64I-NEXT:    call __extendhfsf2@plt
1082; RV64I-NEXT:    mv a2, a0
1083; RV64I-NEXT:    mv a0, s2
1084; RV64I-NEXT:    mv a1, s0
1085; RV64I-NEXT:    call fmaf@plt
1086; RV64I-NEXT:    call __truncsfhf2@plt
1087; RV64I-NEXT:    ld ra, 40(sp) # 8-byte Folded Reload
1088; RV64I-NEXT:    ld s0, 32(sp) # 8-byte Folded Reload
1089; RV64I-NEXT:    ld s1, 24(sp) # 8-byte Folded Reload
1090; RV64I-NEXT:    ld s2, 16(sp) # 8-byte Folded Reload
1091; RV64I-NEXT:    ld s3, 8(sp) # 8-byte Folded Reload
1092; RV64I-NEXT:    ld s4, 0(sp) # 8-byte Folded Reload
1093; RV64I-NEXT:    addi sp, sp, 48
1094; RV64I-NEXT:    ret
1095  %a_ = fadd half 0.0, %a
1096  %c_ = fadd half 0.0, %c
1097  %nega = fsub half -0.0, %a_
1098  %negc = fsub half -0.0, %c_
1099  %1 = call half @llvm.fma.f16(half %nega, half %b, half %negc)
1100  ret half %1
1101}
1102
1103define half @fnmadd_s_2(half %a, half %b, half %c) nounwind {
1104; RV32IZFH-LABEL: fnmadd_s_2:
1105; RV32IZFH:       # %bb.0:
1106; RV32IZFH-NEXT:    fmv.h.x ft0, zero
1107; RV32IZFH-NEXT:    fadd.h ft1, fa1, ft0
1108; RV32IZFH-NEXT:    fadd.h ft0, fa2, ft0
1109; RV32IZFH-NEXT:    fnmadd.h fa0, ft1, fa0, ft0
1110; RV32IZFH-NEXT:    ret
1111;
1112; RV64IZFH-LABEL: fnmadd_s_2:
1113; RV64IZFH:       # %bb.0:
1114; RV64IZFH-NEXT:    fmv.h.x ft0, zero
1115; RV64IZFH-NEXT:    fadd.h ft1, fa1, ft0
1116; RV64IZFH-NEXT:    fadd.h ft0, fa2, ft0
1117; RV64IZFH-NEXT:    fnmadd.h fa0, ft1, fa0, ft0
1118; RV64IZFH-NEXT:    ret
1119;
1120; RV32I-LABEL: fnmadd_s_2:
1121; RV32I:       # %bb.0:
1122; RV32I-NEXT:    addi sp, sp, -32
1123; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
1124; RV32I-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
1125; RV32I-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
1126; RV32I-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
1127; RV32I-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
1128; RV32I-NEXT:    sw s4, 8(sp) # 4-byte Folded Spill
1129; RV32I-NEXT:    mv s1, a2
1130; RV32I-NEXT:    mv s0, a0
1131; RV32I-NEXT:    lui a0, 16
1132; RV32I-NEXT:    addi s3, a0, -1
1133; RV32I-NEXT:    and a0, a1, s3
1134; RV32I-NEXT:    call __extendhfsf2@plt
1135; RV32I-NEXT:    li a1, 0
1136; RV32I-NEXT:    call __addsf3@plt
1137; RV32I-NEXT:    call __truncsfhf2@plt
1138; RV32I-NEXT:    mv s2, a0
1139; RV32I-NEXT:    and a0, s1, s3
1140; RV32I-NEXT:    call __extendhfsf2@plt
1141; RV32I-NEXT:    li a1, 0
1142; RV32I-NEXT:    call __addsf3@plt
1143; RV32I-NEXT:    call __truncsfhf2@plt
1144; RV32I-NEXT:    mv s1, a0
1145; RV32I-NEXT:    and a0, s2, s3
1146; RV32I-NEXT:    call __extendhfsf2@plt
1147; RV32I-NEXT:    lui s4, 524288
1148; RV32I-NEXT:    xor a0, a0, s4
1149; RV32I-NEXT:    call __truncsfhf2@plt
1150; RV32I-NEXT:    mv s2, a0
1151; RV32I-NEXT:    and a0, s1, s3
1152; RV32I-NEXT:    call __extendhfsf2@plt
1153; RV32I-NEXT:    xor a0, a0, s4
1154; RV32I-NEXT:    call __truncsfhf2@plt
1155; RV32I-NEXT:    mv s1, a0
1156; RV32I-NEXT:    and a0, s0, s3
1157; RV32I-NEXT:    call __extendhfsf2@plt
1158; RV32I-NEXT:    mv s0, a0
1159; RV32I-NEXT:    and a0, s2, s3
1160; RV32I-NEXT:    call __extendhfsf2@plt
1161; RV32I-NEXT:    mv s2, a0
1162; RV32I-NEXT:    and a0, s1, s3
1163; RV32I-NEXT:    call __extendhfsf2@plt
1164; RV32I-NEXT:    mv a2, a0
1165; RV32I-NEXT:    mv a0, s0
1166; RV32I-NEXT:    mv a1, s2
1167; RV32I-NEXT:    call fmaf@plt
1168; RV32I-NEXT:    call __truncsfhf2@plt
1169; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
1170; RV32I-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
1171; RV32I-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
1172; RV32I-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
1173; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
1174; RV32I-NEXT:    lw s4, 8(sp) # 4-byte Folded Reload
1175; RV32I-NEXT:    addi sp, sp, 32
1176; RV32I-NEXT:    ret
1177;
1178; RV64I-LABEL: fnmadd_s_2:
1179; RV64I:       # %bb.0:
1180; RV64I-NEXT:    addi sp, sp, -48
1181; RV64I-NEXT:    sd ra, 40(sp) # 8-byte Folded Spill
1182; RV64I-NEXT:    sd s0, 32(sp) # 8-byte Folded Spill
1183; RV64I-NEXT:    sd s1, 24(sp) # 8-byte Folded Spill
1184; RV64I-NEXT:    sd s2, 16(sp) # 8-byte Folded Spill
1185; RV64I-NEXT:    sd s3, 8(sp) # 8-byte Folded Spill
1186; RV64I-NEXT:    sd s4, 0(sp) # 8-byte Folded Spill
1187; RV64I-NEXT:    mv s1, a2
1188; RV64I-NEXT:    mv s0, a0
1189; RV64I-NEXT:    lui a0, 16
1190; RV64I-NEXT:    addiw s3, a0, -1
1191; RV64I-NEXT:    and a0, a1, s3
1192; RV64I-NEXT:    call __extendhfsf2@plt
1193; RV64I-NEXT:    li a1, 0
1194; RV64I-NEXT:    call __addsf3@plt
1195; RV64I-NEXT:    call __truncsfhf2@plt
1196; RV64I-NEXT:    mv s2, a0
1197; RV64I-NEXT:    and a0, s1, s3
1198; RV64I-NEXT:    call __extendhfsf2@plt
1199; RV64I-NEXT:    li a1, 0
1200; RV64I-NEXT:    call __addsf3@plt
1201; RV64I-NEXT:    call __truncsfhf2@plt
1202; RV64I-NEXT:    mv s1, a0
1203; RV64I-NEXT:    and a0, s2, s3
1204; RV64I-NEXT:    call __extendhfsf2@plt
1205; RV64I-NEXT:    lui s4, 524288
1206; RV64I-NEXT:    xor a0, a0, s4
1207; RV64I-NEXT:    call __truncsfhf2@plt
1208; RV64I-NEXT:    mv s2, a0
1209; RV64I-NEXT:    and a0, s1, s3
1210; RV64I-NEXT:    call __extendhfsf2@plt
1211; RV64I-NEXT:    xor a0, a0, s4
1212; RV64I-NEXT:    call __truncsfhf2@plt
1213; RV64I-NEXT:    mv s1, a0
1214; RV64I-NEXT:    and a0, s0, s3
1215; RV64I-NEXT:    call __extendhfsf2@plt
1216; RV64I-NEXT:    mv s0, a0
1217; RV64I-NEXT:    and a0, s2, s3
1218; RV64I-NEXT:    call __extendhfsf2@plt
1219; RV64I-NEXT:    mv s2, a0
1220; RV64I-NEXT:    and a0, s1, s3
1221; RV64I-NEXT:    call __extendhfsf2@plt
1222; RV64I-NEXT:    mv a2, a0
1223; RV64I-NEXT:    mv a0, s0
1224; RV64I-NEXT:    mv a1, s2
1225; RV64I-NEXT:    call fmaf@plt
1226; RV64I-NEXT:    call __truncsfhf2@plt
1227; RV64I-NEXT:    ld ra, 40(sp) # 8-byte Folded Reload
1228; RV64I-NEXT:    ld s0, 32(sp) # 8-byte Folded Reload
1229; RV64I-NEXT:    ld s1, 24(sp) # 8-byte Folded Reload
1230; RV64I-NEXT:    ld s2, 16(sp) # 8-byte Folded Reload
1231; RV64I-NEXT:    ld s3, 8(sp) # 8-byte Folded Reload
1232; RV64I-NEXT:    ld s4, 0(sp) # 8-byte Folded Reload
1233; RV64I-NEXT:    addi sp, sp, 48
1234; RV64I-NEXT:    ret
1235  %b_ = fadd half 0.0, %b
1236  %c_ = fadd half 0.0, %c
1237  %negb = fsub half -0.0, %b_
1238  %negc = fsub half -0.0, %c_
1239  %1 = call half @llvm.fma.f16(half %a, half %negb, half %negc)
1240  ret half %1
1241}
1242
1243define half @fnmsub_s(half %a, half %b, half %c) nounwind {
1244; RV32IZFH-LABEL: fnmsub_s:
1245; RV32IZFH:       # %bb.0:
1246; RV32IZFH-NEXT:    fmv.h.x ft0, zero
1247; RV32IZFH-NEXT:    fadd.h ft0, fa0, ft0
1248; RV32IZFH-NEXT:    fnmsub.h fa0, ft0, fa1, fa2
1249; RV32IZFH-NEXT:    ret
1250;
1251; RV64IZFH-LABEL: fnmsub_s:
1252; RV64IZFH:       # %bb.0:
1253; RV64IZFH-NEXT:    fmv.h.x ft0, zero
1254; RV64IZFH-NEXT:    fadd.h ft0, fa0, ft0
1255; RV64IZFH-NEXT:    fnmsub.h fa0, ft0, fa1, fa2
1256; RV64IZFH-NEXT:    ret
1257;
1258; RV32I-LABEL: fnmsub_s:
1259; RV32I:       # %bb.0:
1260; RV32I-NEXT:    addi sp, sp, -32
1261; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
1262; RV32I-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
1263; RV32I-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
1264; RV32I-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
1265; RV32I-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
1266; RV32I-NEXT:    mv s0, a2
1267; RV32I-NEXT:    mv s1, a1
1268; RV32I-NEXT:    lui a1, 16
1269; RV32I-NEXT:    addi s3, a1, -1
1270; RV32I-NEXT:    and a0, a0, s3
1271; RV32I-NEXT:    call __extendhfsf2@plt
1272; RV32I-NEXT:    li a1, 0
1273; RV32I-NEXT:    call __addsf3@plt
1274; RV32I-NEXT:    call __truncsfhf2@plt
1275; RV32I-NEXT:    and a0, a0, s3
1276; RV32I-NEXT:    call __extendhfsf2@plt
1277; RV32I-NEXT:    lui a1, 524288
1278; RV32I-NEXT:    xor a0, a0, a1
1279; RV32I-NEXT:    call __truncsfhf2@plt
1280; RV32I-NEXT:    mv s2, a0
1281; RV32I-NEXT:    and a0, s1, s3
1282; RV32I-NEXT:    call __extendhfsf2@plt
1283; RV32I-NEXT:    mv s1, a0
1284; RV32I-NEXT:    and a0, s0, s3
1285; RV32I-NEXT:    call __extendhfsf2@plt
1286; RV32I-NEXT:    mv s0, a0
1287; RV32I-NEXT:    and a0, s2, s3
1288; RV32I-NEXT:    call __extendhfsf2@plt
1289; RV32I-NEXT:    mv a1, s1
1290; RV32I-NEXT:    mv a2, s0
1291; RV32I-NEXT:    call fmaf@plt
1292; RV32I-NEXT:    call __truncsfhf2@plt
1293; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
1294; RV32I-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
1295; RV32I-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
1296; RV32I-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
1297; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
1298; RV32I-NEXT:    addi sp, sp, 32
1299; RV32I-NEXT:    ret
1300;
1301; RV64I-LABEL: fnmsub_s:
1302; RV64I:       # %bb.0:
1303; RV64I-NEXT:    addi sp, sp, -48
1304; RV64I-NEXT:    sd ra, 40(sp) # 8-byte Folded Spill
1305; RV64I-NEXT:    sd s0, 32(sp) # 8-byte Folded Spill
1306; RV64I-NEXT:    sd s1, 24(sp) # 8-byte Folded Spill
1307; RV64I-NEXT:    sd s2, 16(sp) # 8-byte Folded Spill
1308; RV64I-NEXT:    sd s3, 8(sp) # 8-byte Folded Spill
1309; RV64I-NEXT:    mv s0, a2
1310; RV64I-NEXT:    mv s1, a1
1311; RV64I-NEXT:    lui a1, 16
1312; RV64I-NEXT:    addiw s3, a1, -1
1313; RV64I-NEXT:    and a0, a0, s3
1314; RV64I-NEXT:    call __extendhfsf2@plt
1315; RV64I-NEXT:    li a1, 0
1316; RV64I-NEXT:    call __addsf3@plt
1317; RV64I-NEXT:    call __truncsfhf2@plt
1318; RV64I-NEXT:    and a0, a0, s3
1319; RV64I-NEXT:    call __extendhfsf2@plt
1320; RV64I-NEXT:    lui a1, 524288
1321; RV64I-NEXT:    xor a0, a0, a1
1322; RV64I-NEXT:    call __truncsfhf2@plt
1323; RV64I-NEXT:    mv s2, a0
1324; RV64I-NEXT:    and a0, s1, s3
1325; RV64I-NEXT:    call __extendhfsf2@plt
1326; RV64I-NEXT:    mv s1, a0
1327; RV64I-NEXT:    and a0, s0, s3
1328; RV64I-NEXT:    call __extendhfsf2@plt
1329; RV64I-NEXT:    mv s0, a0
1330; RV64I-NEXT:    and a0, s2, s3
1331; RV64I-NEXT:    call __extendhfsf2@plt
1332; RV64I-NEXT:    mv a1, s1
1333; RV64I-NEXT:    mv a2, s0
1334; RV64I-NEXT:    call fmaf@plt
1335; RV64I-NEXT:    call __truncsfhf2@plt
1336; RV64I-NEXT:    ld ra, 40(sp) # 8-byte Folded Reload
1337; RV64I-NEXT:    ld s0, 32(sp) # 8-byte Folded Reload
1338; RV64I-NEXT:    ld s1, 24(sp) # 8-byte Folded Reload
1339; RV64I-NEXT:    ld s2, 16(sp) # 8-byte Folded Reload
1340; RV64I-NEXT:    ld s3, 8(sp) # 8-byte Folded Reload
1341; RV64I-NEXT:    addi sp, sp, 48
1342; RV64I-NEXT:    ret
1343  %a_ = fadd half 0.0, %a
1344  %nega = fsub half -0.0, %a_
1345  %1 = call half @llvm.fma.f16(half %nega, half %b, half %c)
1346  ret half %1
1347}
1348
1349define half @fnmsub_s_2(half %a, half %b, half %c) nounwind {
1350; RV32IZFH-LABEL: fnmsub_s_2:
1351; RV32IZFH:       # %bb.0:
1352; RV32IZFH-NEXT:    fmv.h.x ft0, zero
1353; RV32IZFH-NEXT:    fadd.h ft0, fa1, ft0
1354; RV32IZFH-NEXT:    fnmsub.h fa0, ft0, fa0, fa2
1355; RV32IZFH-NEXT:    ret
1356;
1357; RV64IZFH-LABEL: fnmsub_s_2:
1358; RV64IZFH:       # %bb.0:
1359; RV64IZFH-NEXT:    fmv.h.x ft0, zero
1360; RV64IZFH-NEXT:    fadd.h ft0, fa1, ft0
1361; RV64IZFH-NEXT:    fnmsub.h fa0, ft0, fa0, fa2
1362; RV64IZFH-NEXT:    ret
1363;
1364; RV32I-LABEL: fnmsub_s_2:
1365; RV32I:       # %bb.0:
1366; RV32I-NEXT:    addi sp, sp, -32
1367; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
1368; RV32I-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
1369; RV32I-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
1370; RV32I-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
1371; RV32I-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
1372; RV32I-NEXT:    mv s0, a2
1373; RV32I-NEXT:    mv s1, a0
1374; RV32I-NEXT:    lui a0, 16
1375; RV32I-NEXT:    addi s3, a0, -1
1376; RV32I-NEXT:    and a0, a1, s3
1377; RV32I-NEXT:    call __extendhfsf2@plt
1378; RV32I-NEXT:    li a1, 0
1379; RV32I-NEXT:    call __addsf3@plt
1380; RV32I-NEXT:    call __truncsfhf2@plt
1381; RV32I-NEXT:    and a0, a0, s3
1382; RV32I-NEXT:    call __extendhfsf2@plt
1383; RV32I-NEXT:    lui a1, 524288
1384; RV32I-NEXT:    xor a0, a0, a1
1385; RV32I-NEXT:    call __truncsfhf2@plt
1386; RV32I-NEXT:    mv s2, a0
1387; RV32I-NEXT:    and a0, s1, s3
1388; RV32I-NEXT:    call __extendhfsf2@plt
1389; RV32I-NEXT:    mv s1, a0
1390; RV32I-NEXT:    and a0, s0, s3
1391; RV32I-NEXT:    call __extendhfsf2@plt
1392; RV32I-NEXT:    mv s0, a0
1393; RV32I-NEXT:    and a0, s2, s3
1394; RV32I-NEXT:    call __extendhfsf2@plt
1395; RV32I-NEXT:    mv a1, a0
1396; RV32I-NEXT:    mv a0, s1
1397; RV32I-NEXT:    mv a2, s0
1398; RV32I-NEXT:    call fmaf@plt
1399; RV32I-NEXT:    call __truncsfhf2@plt
1400; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
1401; RV32I-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
1402; RV32I-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
1403; RV32I-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
1404; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
1405; RV32I-NEXT:    addi sp, sp, 32
1406; RV32I-NEXT:    ret
1407;
1408; RV64I-LABEL: fnmsub_s_2:
1409; RV64I:       # %bb.0:
1410; RV64I-NEXT:    addi sp, sp, -48
1411; RV64I-NEXT:    sd ra, 40(sp) # 8-byte Folded Spill
1412; RV64I-NEXT:    sd s0, 32(sp) # 8-byte Folded Spill
1413; RV64I-NEXT:    sd s1, 24(sp) # 8-byte Folded Spill
1414; RV64I-NEXT:    sd s2, 16(sp) # 8-byte Folded Spill
1415; RV64I-NEXT:    sd s3, 8(sp) # 8-byte Folded Spill
1416; RV64I-NEXT:    mv s0, a2
1417; RV64I-NEXT:    mv s1, a0
1418; RV64I-NEXT:    lui a0, 16
1419; RV64I-NEXT:    addiw s3, a0, -1
1420; RV64I-NEXT:    and a0, a1, s3
1421; RV64I-NEXT:    call __extendhfsf2@plt
1422; RV64I-NEXT:    li a1, 0
1423; RV64I-NEXT:    call __addsf3@plt
1424; RV64I-NEXT:    call __truncsfhf2@plt
1425; RV64I-NEXT:    and a0, a0, s3
1426; RV64I-NEXT:    call __extendhfsf2@plt
1427; RV64I-NEXT:    lui a1, 524288
1428; RV64I-NEXT:    xor a0, a0, a1
1429; RV64I-NEXT:    call __truncsfhf2@plt
1430; RV64I-NEXT:    mv s2, a0
1431; RV64I-NEXT:    and a0, s1, s3
1432; RV64I-NEXT:    call __extendhfsf2@plt
1433; RV64I-NEXT:    mv s1, a0
1434; RV64I-NEXT:    and a0, s0, s3
1435; RV64I-NEXT:    call __extendhfsf2@plt
1436; RV64I-NEXT:    mv s0, a0
1437; RV64I-NEXT:    and a0, s2, s3
1438; RV64I-NEXT:    call __extendhfsf2@plt
1439; RV64I-NEXT:    mv a1, a0
1440; RV64I-NEXT:    mv a0, s1
1441; RV64I-NEXT:    mv a2, s0
1442; RV64I-NEXT:    call fmaf@plt
1443; RV64I-NEXT:    call __truncsfhf2@plt
1444; RV64I-NEXT:    ld ra, 40(sp) # 8-byte Folded Reload
1445; RV64I-NEXT:    ld s0, 32(sp) # 8-byte Folded Reload
1446; RV64I-NEXT:    ld s1, 24(sp) # 8-byte Folded Reload
1447; RV64I-NEXT:    ld s2, 16(sp) # 8-byte Folded Reload
1448; RV64I-NEXT:    ld s3, 8(sp) # 8-byte Folded Reload
1449; RV64I-NEXT:    addi sp, sp, 48
1450; RV64I-NEXT:    ret
1451  %b_ = fadd half 0.0, %b
1452  %negb = fsub half -0.0, %b_
1453  %1 = call half @llvm.fma.f16(half %a, half %negb, half %c)
1454  ret half %1
1455}
1456
1457define half @fmadd_s_contract(half %a, half %b, half %c) nounwind {
1458; RV32IZFH-LABEL: fmadd_s_contract:
1459; RV32IZFH:       # %bb.0:
1460; RV32IZFH-NEXT:    fmadd.h fa0, fa0, fa1, fa2
1461; RV32IZFH-NEXT:    ret
1462;
1463; RV64IZFH-LABEL: fmadd_s_contract:
1464; RV64IZFH:       # %bb.0:
1465; RV64IZFH-NEXT:    fmadd.h fa0, fa0, fa1, fa2
1466; RV64IZFH-NEXT:    ret
1467;
1468; RV32I-LABEL: fmadd_s_contract:
1469; RV32I:       # %bb.0:
1470; RV32I-NEXT:    addi sp, sp, -32
1471; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
1472; RV32I-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
1473; RV32I-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
1474; RV32I-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
1475; RV32I-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
1476; RV32I-NEXT:    mv s0, a2
1477; RV32I-NEXT:    mv s1, a1
1478; RV32I-NEXT:    lui a1, 16
1479; RV32I-NEXT:    addi s3, a1, -1
1480; RV32I-NEXT:    and a0, a0, s3
1481; RV32I-NEXT:    call __extendhfsf2@plt
1482; RV32I-NEXT:    mv s2, a0
1483; RV32I-NEXT:    and a0, s1, s3
1484; RV32I-NEXT:    call __extendhfsf2@plt
1485; RV32I-NEXT:    mv a1, a0
1486; RV32I-NEXT:    mv a0, s2
1487; RV32I-NEXT:    call __mulsf3@plt
1488; RV32I-NEXT:    call __truncsfhf2@plt
1489; RV32I-NEXT:    mv s1, a0
1490; RV32I-NEXT:    and a0, s0, s3
1491; RV32I-NEXT:    call __extendhfsf2@plt
1492; RV32I-NEXT:    mv s0, a0
1493; RV32I-NEXT:    and a0, s1, s3
1494; RV32I-NEXT:    call __extendhfsf2@plt
1495; RV32I-NEXT:    mv a1, s0
1496; RV32I-NEXT:    call __addsf3@plt
1497; RV32I-NEXT:    call __truncsfhf2@plt
1498; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
1499; RV32I-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
1500; RV32I-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
1501; RV32I-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
1502; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
1503; RV32I-NEXT:    addi sp, sp, 32
1504; RV32I-NEXT:    ret
1505;
1506; RV64I-LABEL: fmadd_s_contract:
1507; RV64I:       # %bb.0:
1508; RV64I-NEXT:    addi sp, sp, -48
1509; RV64I-NEXT:    sd ra, 40(sp) # 8-byte Folded Spill
1510; RV64I-NEXT:    sd s0, 32(sp) # 8-byte Folded Spill
1511; RV64I-NEXT:    sd s1, 24(sp) # 8-byte Folded Spill
1512; RV64I-NEXT:    sd s2, 16(sp) # 8-byte Folded Spill
1513; RV64I-NEXT:    sd s3, 8(sp) # 8-byte Folded Spill
1514; RV64I-NEXT:    mv s0, a2
1515; RV64I-NEXT:    mv s1, a1
1516; RV64I-NEXT:    lui a1, 16
1517; RV64I-NEXT:    addiw s3, a1, -1
1518; RV64I-NEXT:    and a0, a0, s3
1519; RV64I-NEXT:    call __extendhfsf2@plt
1520; RV64I-NEXT:    mv s2, a0
1521; RV64I-NEXT:    and a0, s1, s3
1522; RV64I-NEXT:    call __extendhfsf2@plt
1523; RV64I-NEXT:    mv a1, a0
1524; RV64I-NEXT:    mv a0, s2
1525; RV64I-NEXT:    call __mulsf3@plt
1526; RV64I-NEXT:    call __truncsfhf2@plt
1527; RV64I-NEXT:    mv s1, a0
1528; RV64I-NEXT:    and a0, s0, s3
1529; RV64I-NEXT:    call __extendhfsf2@plt
1530; RV64I-NEXT:    mv s0, a0
1531; RV64I-NEXT:    and a0, s1, s3
1532; RV64I-NEXT:    call __extendhfsf2@plt
1533; RV64I-NEXT:    mv a1, s0
1534; RV64I-NEXT:    call __addsf3@plt
1535; RV64I-NEXT:    call __truncsfhf2@plt
1536; RV64I-NEXT:    ld ra, 40(sp) # 8-byte Folded Reload
1537; RV64I-NEXT:    ld s0, 32(sp) # 8-byte Folded Reload
1538; RV64I-NEXT:    ld s1, 24(sp) # 8-byte Folded Reload
1539; RV64I-NEXT:    ld s2, 16(sp) # 8-byte Folded Reload
1540; RV64I-NEXT:    ld s3, 8(sp) # 8-byte Folded Reload
1541; RV64I-NEXT:    addi sp, sp, 48
1542; RV64I-NEXT:    ret
1543  %1 = fmul contract half %a, %b
1544  %2 = fadd contract half %1, %c
1545  ret half %2
1546}
1547
1548define half @fmsub_s_contract(half %a, half %b, half %c) nounwind {
1549; RV32IZFH-LABEL: fmsub_s_contract:
1550; RV32IZFH:       # %bb.0:
1551; RV32IZFH-NEXT:    fmv.h.x ft0, zero
1552; RV32IZFH-NEXT:    fadd.h ft0, fa2, ft0
1553; RV32IZFH-NEXT:    fmsub.h fa0, fa0, fa1, ft0
1554; RV32IZFH-NEXT:    ret
1555;
1556; RV64IZFH-LABEL: fmsub_s_contract:
1557; RV64IZFH:       # %bb.0:
1558; RV64IZFH-NEXT:    fmv.h.x ft0, zero
1559; RV64IZFH-NEXT:    fadd.h ft0, fa2, ft0
1560; RV64IZFH-NEXT:    fmsub.h fa0, fa0, fa1, ft0
1561; RV64IZFH-NEXT:    ret
1562;
1563; RV32I-LABEL: fmsub_s_contract:
1564; RV32I:       # %bb.0:
1565; RV32I-NEXT:    addi sp, sp, -32
1566; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
1567; RV32I-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
1568; RV32I-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
1569; RV32I-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
1570; RV32I-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
1571; RV32I-NEXT:    mv s0, a1
1572; RV32I-NEXT:    mv s1, a0
1573; RV32I-NEXT:    lui a0, 16
1574; RV32I-NEXT:    addi s3, a0, -1
1575; RV32I-NEXT:    and a0, a2, s3
1576; RV32I-NEXT:    call __extendhfsf2@plt
1577; RV32I-NEXT:    li a1, 0
1578; RV32I-NEXT:    call __addsf3@plt
1579; RV32I-NEXT:    call __truncsfhf2@plt
1580; RV32I-NEXT:    mv s2, a0
1581; RV32I-NEXT:    and a0, s1, s3
1582; RV32I-NEXT:    call __extendhfsf2@plt
1583; RV32I-NEXT:    mv s1, a0
1584; RV32I-NEXT:    and a0, s0, s3
1585; RV32I-NEXT:    call __extendhfsf2@plt
1586; RV32I-NEXT:    mv a1, a0
1587; RV32I-NEXT:    mv a0, s1
1588; RV32I-NEXT:    call __mulsf3@plt
1589; RV32I-NEXT:    call __truncsfhf2@plt
1590; RV32I-NEXT:    and a0, a0, s3
1591; RV32I-NEXT:    call __extendhfsf2@plt
1592; RV32I-NEXT:    mv s0, a0
1593; RV32I-NEXT:    and a0, s2, s3
1594; RV32I-NEXT:    call __extendhfsf2@plt
1595; RV32I-NEXT:    mv a1, a0
1596; RV32I-NEXT:    mv a0, s0
1597; RV32I-NEXT:    call __subsf3@plt
1598; RV32I-NEXT:    call __truncsfhf2@plt
1599; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
1600; RV32I-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
1601; RV32I-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
1602; RV32I-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
1603; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
1604; RV32I-NEXT:    addi sp, sp, 32
1605; RV32I-NEXT:    ret
1606;
1607; RV64I-LABEL: fmsub_s_contract:
1608; RV64I:       # %bb.0:
1609; RV64I-NEXT:    addi sp, sp, -48
1610; RV64I-NEXT:    sd ra, 40(sp) # 8-byte Folded Spill
1611; RV64I-NEXT:    sd s0, 32(sp) # 8-byte Folded Spill
1612; RV64I-NEXT:    sd s1, 24(sp) # 8-byte Folded Spill
1613; RV64I-NEXT:    sd s2, 16(sp) # 8-byte Folded Spill
1614; RV64I-NEXT:    sd s3, 8(sp) # 8-byte Folded Spill
1615; RV64I-NEXT:    mv s0, a1
1616; RV64I-NEXT:    mv s1, a0
1617; RV64I-NEXT:    lui a0, 16
1618; RV64I-NEXT:    addiw s3, a0, -1
1619; RV64I-NEXT:    and a0, a2, s3
1620; RV64I-NEXT:    call __extendhfsf2@plt
1621; RV64I-NEXT:    li a1, 0
1622; RV64I-NEXT:    call __addsf3@plt
1623; RV64I-NEXT:    call __truncsfhf2@plt
1624; RV64I-NEXT:    mv s2, a0
1625; RV64I-NEXT:    and a0, s1, s3
1626; RV64I-NEXT:    call __extendhfsf2@plt
1627; RV64I-NEXT:    mv s1, a0
1628; RV64I-NEXT:    and a0, s0, s3
1629; RV64I-NEXT:    call __extendhfsf2@plt
1630; RV64I-NEXT:    mv a1, a0
1631; RV64I-NEXT:    mv a0, s1
1632; RV64I-NEXT:    call __mulsf3@plt
1633; RV64I-NEXT:    call __truncsfhf2@plt
1634; RV64I-NEXT:    and a0, a0, s3
1635; RV64I-NEXT:    call __extendhfsf2@plt
1636; RV64I-NEXT:    mv s0, a0
1637; RV64I-NEXT:    and a0, s2, s3
1638; RV64I-NEXT:    call __extendhfsf2@plt
1639; RV64I-NEXT:    mv a1, a0
1640; RV64I-NEXT:    mv a0, s0
1641; RV64I-NEXT:    call __subsf3@plt
1642; RV64I-NEXT:    call __truncsfhf2@plt
1643; RV64I-NEXT:    ld ra, 40(sp) # 8-byte Folded Reload
1644; RV64I-NEXT:    ld s0, 32(sp) # 8-byte Folded Reload
1645; RV64I-NEXT:    ld s1, 24(sp) # 8-byte Folded Reload
1646; RV64I-NEXT:    ld s2, 16(sp) # 8-byte Folded Reload
1647; RV64I-NEXT:    ld s3, 8(sp) # 8-byte Folded Reload
1648; RV64I-NEXT:    addi sp, sp, 48
1649; RV64I-NEXT:    ret
1650  %c_ = fadd half 0.0, %c ; avoid negation using xor
1651  %1 = fmul contract half %a, %b
1652  %2 = fsub contract half %1, %c_
1653  ret half %2
1654}
1655
1656define half @fnmadd_s_contract(half %a, half %b, half %c) nounwind {
1657; RV32IZFH-LABEL: fnmadd_s_contract:
1658; RV32IZFH:       # %bb.0:
1659; RV32IZFH-NEXT:    fmv.h.x ft0, zero
1660; RV32IZFH-NEXT:    fadd.h ft1, fa0, ft0
1661; RV32IZFH-NEXT:    fadd.h ft2, fa1, ft0
1662; RV32IZFH-NEXT:    fadd.h ft0, fa2, ft0
1663; RV32IZFH-NEXT:    fnmadd.h fa0, ft1, ft2, ft0
1664; RV32IZFH-NEXT:    ret
1665;
1666; RV64IZFH-LABEL: fnmadd_s_contract:
1667; RV64IZFH:       # %bb.0:
1668; RV64IZFH-NEXT:    fmv.h.x ft0, zero
1669; RV64IZFH-NEXT:    fadd.h ft1, fa0, ft0
1670; RV64IZFH-NEXT:    fadd.h ft2, fa1, ft0
1671; RV64IZFH-NEXT:    fadd.h ft0, fa2, ft0
1672; RV64IZFH-NEXT:    fnmadd.h fa0, ft1, ft2, ft0
1673; RV64IZFH-NEXT:    ret
1674;
1675; RV32I-LABEL: fnmadd_s_contract:
1676; RV32I:       # %bb.0:
1677; RV32I-NEXT:    addi sp, sp, -32
1678; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
1679; RV32I-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
1680; RV32I-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
1681; RV32I-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
1682; RV32I-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
1683; RV32I-NEXT:    mv s0, a2
1684; RV32I-NEXT:    mv s1, a1
1685; RV32I-NEXT:    lui a1, 16
1686; RV32I-NEXT:    addi s3, a1, -1
1687; RV32I-NEXT:    and a0, a0, s3
1688; RV32I-NEXT:    call __extendhfsf2@plt
1689; RV32I-NEXT:    li a1, 0
1690; RV32I-NEXT:    call __addsf3@plt
1691; RV32I-NEXT:    call __truncsfhf2@plt
1692; RV32I-NEXT:    mv s2, a0
1693; RV32I-NEXT:    and a0, s1, s3
1694; RV32I-NEXT:    call __extendhfsf2@plt
1695; RV32I-NEXT:    li a1, 0
1696; RV32I-NEXT:    call __addsf3@plt
1697; RV32I-NEXT:    call __truncsfhf2@plt
1698; RV32I-NEXT:    mv s1, a0
1699; RV32I-NEXT:    and a0, s0, s3
1700; RV32I-NEXT:    call __extendhfsf2@plt
1701; RV32I-NEXT:    li a1, 0
1702; RV32I-NEXT:    call __addsf3@plt
1703; RV32I-NEXT:    call __truncsfhf2@plt
1704; RV32I-NEXT:    mv s0, a0
1705; RV32I-NEXT:    and a0, s2, s3
1706; RV32I-NEXT:    call __extendhfsf2@plt
1707; RV32I-NEXT:    mv s2, a0
1708; RV32I-NEXT:    and a0, s1, s3
1709; RV32I-NEXT:    call __extendhfsf2@plt
1710; RV32I-NEXT:    mv a1, a0
1711; RV32I-NEXT:    mv a0, s2
1712; RV32I-NEXT:    call __mulsf3@plt
1713; RV32I-NEXT:    call __truncsfhf2@plt
1714; RV32I-NEXT:    and a0, a0, s3
1715; RV32I-NEXT:    call __extendhfsf2@plt
1716; RV32I-NEXT:    lui a1, 524288
1717; RV32I-NEXT:    xor a0, a0, a1
1718; RV32I-NEXT:    call __truncsfhf2@plt
1719; RV32I-NEXT:    mv s1, a0
1720; RV32I-NEXT:    and a0, s0, s3
1721; RV32I-NEXT:    call __extendhfsf2@plt
1722; RV32I-NEXT:    mv s0, a0
1723; RV32I-NEXT:    and a0, s1, s3
1724; RV32I-NEXT:    call __extendhfsf2@plt
1725; RV32I-NEXT:    mv a1, s0
1726; RV32I-NEXT:    call __subsf3@plt
1727; RV32I-NEXT:    call __truncsfhf2@plt
1728; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
1729; RV32I-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
1730; RV32I-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
1731; RV32I-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
1732; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
1733; RV32I-NEXT:    addi sp, sp, 32
1734; RV32I-NEXT:    ret
1735;
1736; RV64I-LABEL: fnmadd_s_contract:
1737; RV64I:       # %bb.0:
1738; RV64I-NEXT:    addi sp, sp, -48
1739; RV64I-NEXT:    sd ra, 40(sp) # 8-byte Folded Spill
1740; RV64I-NEXT:    sd s0, 32(sp) # 8-byte Folded Spill
1741; RV64I-NEXT:    sd s1, 24(sp) # 8-byte Folded Spill
1742; RV64I-NEXT:    sd s2, 16(sp) # 8-byte Folded Spill
1743; RV64I-NEXT:    sd s3, 8(sp) # 8-byte Folded Spill
1744; RV64I-NEXT:    mv s0, a2
1745; RV64I-NEXT:    mv s1, a1
1746; RV64I-NEXT:    lui a1, 16
1747; RV64I-NEXT:    addiw s3, a1, -1
1748; RV64I-NEXT:    and a0, a0, s3
1749; RV64I-NEXT:    call __extendhfsf2@plt
1750; RV64I-NEXT:    li a1, 0
1751; RV64I-NEXT:    call __addsf3@plt
1752; RV64I-NEXT:    call __truncsfhf2@plt
1753; RV64I-NEXT:    mv s2, a0
1754; RV64I-NEXT:    and a0, s1, s3
1755; RV64I-NEXT:    call __extendhfsf2@plt
1756; RV64I-NEXT:    li a1, 0
1757; RV64I-NEXT:    call __addsf3@plt
1758; RV64I-NEXT:    call __truncsfhf2@plt
1759; RV64I-NEXT:    mv s1, a0
1760; RV64I-NEXT:    and a0, s0, s3
1761; RV64I-NEXT:    call __extendhfsf2@plt
1762; RV64I-NEXT:    li a1, 0
1763; RV64I-NEXT:    call __addsf3@plt
1764; RV64I-NEXT:    call __truncsfhf2@plt
1765; RV64I-NEXT:    mv s0, a0
1766; RV64I-NEXT:    and a0, s2, s3
1767; RV64I-NEXT:    call __extendhfsf2@plt
1768; RV64I-NEXT:    mv s2, a0
1769; RV64I-NEXT:    and a0, s1, s3
1770; RV64I-NEXT:    call __extendhfsf2@plt
1771; RV64I-NEXT:    mv a1, a0
1772; RV64I-NEXT:    mv a0, s2
1773; RV64I-NEXT:    call __mulsf3@plt
1774; RV64I-NEXT:    call __truncsfhf2@plt
1775; RV64I-NEXT:    and a0, a0, s3
1776; RV64I-NEXT:    call __extendhfsf2@plt
1777; RV64I-NEXT:    lui a1, 524288
1778; RV64I-NEXT:    xor a0, a0, a1
1779; RV64I-NEXT:    call __truncsfhf2@plt
1780; RV64I-NEXT:    mv s1, a0
1781; RV64I-NEXT:    and a0, s0, s3
1782; RV64I-NEXT:    call __extendhfsf2@plt
1783; RV64I-NEXT:    mv s0, a0
1784; RV64I-NEXT:    and a0, s1, s3
1785; RV64I-NEXT:    call __extendhfsf2@plt
1786; RV64I-NEXT:    mv a1, s0
1787; RV64I-NEXT:    call __subsf3@plt
1788; RV64I-NEXT:    call __truncsfhf2@plt
1789; RV64I-NEXT:    ld ra, 40(sp) # 8-byte Folded Reload
1790; RV64I-NEXT:    ld s0, 32(sp) # 8-byte Folded Reload
1791; RV64I-NEXT:    ld s1, 24(sp) # 8-byte Folded Reload
1792; RV64I-NEXT:    ld s2, 16(sp) # 8-byte Folded Reload
1793; RV64I-NEXT:    ld s3, 8(sp) # 8-byte Folded Reload
1794; RV64I-NEXT:    addi sp, sp, 48
1795; RV64I-NEXT:    ret
1796  %a_ = fadd half 0.0, %a ; avoid negation using xor
1797  %b_ = fadd half 0.0, %b ; avoid negation using xor
1798  %c_ = fadd half 0.0, %c ; avoid negation using xor
1799  %1 = fmul contract half %a_, %b_
1800  %2 = fneg half %1
1801  %3 = fsub contract half %2, %c_
1802  ret half %3
1803}
1804
1805define half @fnmsub_s_contract(half %a, half %b, half %c) nounwind {
1806; RV32IZFH-LABEL: fnmsub_s_contract:
1807; RV32IZFH:       # %bb.0:
1808; RV32IZFH-NEXT:    fmv.h.x ft0, zero
1809; RV32IZFH-NEXT:    fadd.h ft1, fa0, ft0
1810; RV32IZFH-NEXT:    fadd.h ft0, fa1, ft0
1811; RV32IZFH-NEXT:    fnmsub.h fa0, ft1, ft0, fa2
1812; RV32IZFH-NEXT:    ret
1813;
1814; RV64IZFH-LABEL: fnmsub_s_contract:
1815; RV64IZFH:       # %bb.0:
1816; RV64IZFH-NEXT:    fmv.h.x ft0, zero
1817; RV64IZFH-NEXT:    fadd.h ft1, fa0, ft0
1818; RV64IZFH-NEXT:    fadd.h ft0, fa1, ft0
1819; RV64IZFH-NEXT:    fnmsub.h fa0, ft1, ft0, fa2
1820; RV64IZFH-NEXT:    ret
1821;
1822; RV32I-LABEL: fnmsub_s_contract:
1823; RV32I:       # %bb.0:
1824; RV32I-NEXT:    addi sp, sp, -32
1825; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
1826; RV32I-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
1827; RV32I-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
1828; RV32I-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
1829; RV32I-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
1830; RV32I-NEXT:    mv s0, a2
1831; RV32I-NEXT:    mv s1, a1
1832; RV32I-NEXT:    lui a1, 16
1833; RV32I-NEXT:    addi s3, a1, -1
1834; RV32I-NEXT:    and a0, a0, s3
1835; RV32I-NEXT:    call __extendhfsf2@plt
1836; RV32I-NEXT:    li a1, 0
1837; RV32I-NEXT:    call __addsf3@plt
1838; RV32I-NEXT:    call __truncsfhf2@plt
1839; RV32I-NEXT:    mv s2, a0
1840; RV32I-NEXT:    and a0, s1, s3
1841; RV32I-NEXT:    call __extendhfsf2@plt
1842; RV32I-NEXT:    li a1, 0
1843; RV32I-NEXT:    call __addsf3@plt
1844; RV32I-NEXT:    call __truncsfhf2@plt
1845; RV32I-NEXT:    mv s1, a0
1846; RV32I-NEXT:    and a0, s2, s3
1847; RV32I-NEXT:    call __extendhfsf2@plt
1848; RV32I-NEXT:    mv s2, a0
1849; RV32I-NEXT:    and a0, s1, s3
1850; RV32I-NEXT:    call __extendhfsf2@plt
1851; RV32I-NEXT:    mv a1, a0
1852; RV32I-NEXT:    mv a0, s2
1853; RV32I-NEXT:    call __mulsf3@plt
1854; RV32I-NEXT:    call __truncsfhf2@plt
1855; RV32I-NEXT:    mv s1, a0
1856; RV32I-NEXT:    and a0, s0, s3
1857; RV32I-NEXT:    call __extendhfsf2@plt
1858; RV32I-NEXT:    mv s0, a0
1859; RV32I-NEXT:    and a0, s1, s3
1860; RV32I-NEXT:    call __extendhfsf2@plt
1861; RV32I-NEXT:    mv a1, a0
1862; RV32I-NEXT:    mv a0, s0
1863; RV32I-NEXT:    call __subsf3@plt
1864; RV32I-NEXT:    call __truncsfhf2@plt
1865; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
1866; RV32I-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
1867; RV32I-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
1868; RV32I-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
1869; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
1870; RV32I-NEXT:    addi sp, sp, 32
1871; RV32I-NEXT:    ret
1872;
1873; RV64I-LABEL: fnmsub_s_contract:
1874; RV64I:       # %bb.0:
1875; RV64I-NEXT:    addi sp, sp, -48
1876; RV64I-NEXT:    sd ra, 40(sp) # 8-byte Folded Spill
1877; RV64I-NEXT:    sd s0, 32(sp) # 8-byte Folded Spill
1878; RV64I-NEXT:    sd s1, 24(sp) # 8-byte Folded Spill
1879; RV64I-NEXT:    sd s2, 16(sp) # 8-byte Folded Spill
1880; RV64I-NEXT:    sd s3, 8(sp) # 8-byte Folded Spill
1881; RV64I-NEXT:    mv s0, a2
1882; RV64I-NEXT:    mv s1, a1
1883; RV64I-NEXT:    lui a1, 16
1884; RV64I-NEXT:    addiw s3, a1, -1
1885; RV64I-NEXT:    and a0, a0, s3
1886; RV64I-NEXT:    call __extendhfsf2@plt
1887; RV64I-NEXT:    li a1, 0
1888; RV64I-NEXT:    call __addsf3@plt
1889; RV64I-NEXT:    call __truncsfhf2@plt
1890; RV64I-NEXT:    mv s2, a0
1891; RV64I-NEXT:    and a0, s1, s3
1892; RV64I-NEXT:    call __extendhfsf2@plt
1893; RV64I-NEXT:    li a1, 0
1894; RV64I-NEXT:    call __addsf3@plt
1895; RV64I-NEXT:    call __truncsfhf2@plt
1896; RV64I-NEXT:    mv s1, a0
1897; RV64I-NEXT:    and a0, s2, s3
1898; RV64I-NEXT:    call __extendhfsf2@plt
1899; RV64I-NEXT:    mv s2, a0
1900; RV64I-NEXT:    and a0, s1, s3
1901; RV64I-NEXT:    call __extendhfsf2@plt
1902; RV64I-NEXT:    mv a1, a0
1903; RV64I-NEXT:    mv a0, s2
1904; RV64I-NEXT:    call __mulsf3@plt
1905; RV64I-NEXT:    call __truncsfhf2@plt
1906; RV64I-NEXT:    mv s1, a0
1907; RV64I-NEXT:    and a0, s0, s3
1908; RV64I-NEXT:    call __extendhfsf2@plt
1909; RV64I-NEXT:    mv s0, a0
1910; RV64I-NEXT:    and a0, s1, s3
1911; RV64I-NEXT:    call __extendhfsf2@plt
1912; RV64I-NEXT:    mv a1, a0
1913; RV64I-NEXT:    mv a0, s0
1914; RV64I-NEXT:    call __subsf3@plt
1915; RV64I-NEXT:    call __truncsfhf2@plt
1916; RV64I-NEXT:    ld ra, 40(sp) # 8-byte Folded Reload
1917; RV64I-NEXT:    ld s0, 32(sp) # 8-byte Folded Reload
1918; RV64I-NEXT:    ld s1, 24(sp) # 8-byte Folded Reload
1919; RV64I-NEXT:    ld s2, 16(sp) # 8-byte Folded Reload
1920; RV64I-NEXT:    ld s3, 8(sp) # 8-byte Folded Reload
1921; RV64I-NEXT:    addi sp, sp, 48
1922; RV64I-NEXT:    ret
1923  %a_ = fadd half 0.0, %a ; avoid negation using xor
1924  %b_ = fadd half 0.0, %b ; avoid negation using xor
1925  %1 = fmul contract half %a_, %b_
1926  %2 = fsub contract half %c, %1
1927  ret half %2
1928}
1929