1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple=riscv32 -mattr=+f -verify-machineinstrs < %s \
3; RUN:   | FileCheck -check-prefix=RV32IF %s
4; RUN: llc -mtriple=riscv64 -mattr=+f -verify-machineinstrs < %s \
5; RUN:   | FileCheck -check-prefix=RV64IF %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 float-fcmp.ll and float-convert.ll
13; respectively. Some other float-*.ll files in this folder exercise LLVM IR
14; instructions that don't directly match a RISC-V instruction.
15
16define float @fadd_s(float %a, float %b) nounwind {
17; RV32IF-LABEL: fadd_s:
18; RV32IF:       # %bb.0:
19; RV32IF-NEXT:    fmv.w.x ft0, a1
20; RV32IF-NEXT:    fmv.w.x ft1, a0
21; RV32IF-NEXT:    fadd.s ft0, ft1, ft0
22; RV32IF-NEXT:    fmv.x.w a0, ft0
23; RV32IF-NEXT:    ret
24;
25; RV64IF-LABEL: fadd_s:
26; RV64IF:       # %bb.0:
27; RV64IF-NEXT:    fmv.w.x ft0, a1
28; RV64IF-NEXT:    fmv.w.x ft1, a0
29; RV64IF-NEXT:    fadd.s ft0, ft1, ft0
30; RV64IF-NEXT:    fmv.x.w a0, ft0
31; RV64IF-NEXT:    ret
32;
33; RV32I-LABEL: fadd_s:
34; RV32I:       # %bb.0:
35; RV32I-NEXT:    addi sp, sp, -16
36; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
37; RV32I-NEXT:    call __addsf3@plt
38; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
39; RV32I-NEXT:    addi sp, sp, 16
40; RV32I-NEXT:    ret
41;
42; RV64I-LABEL: fadd_s:
43; RV64I:       # %bb.0:
44; RV64I-NEXT:    addi sp, sp, -16
45; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
46; RV64I-NEXT:    call __addsf3@plt
47; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
48; RV64I-NEXT:    addi sp, sp, 16
49; RV64I-NEXT:    ret
50  %1 = fadd float %a, %b
51  ret float %1
52}
53
54define float @fsub_s(float %a, float %b) nounwind {
55; RV32IF-LABEL: fsub_s:
56; RV32IF:       # %bb.0:
57; RV32IF-NEXT:    fmv.w.x ft0, a1
58; RV32IF-NEXT:    fmv.w.x ft1, a0
59; RV32IF-NEXT:    fsub.s ft0, ft1, ft0
60; RV32IF-NEXT:    fmv.x.w a0, ft0
61; RV32IF-NEXT:    ret
62;
63; RV64IF-LABEL: fsub_s:
64; RV64IF:       # %bb.0:
65; RV64IF-NEXT:    fmv.w.x ft0, a1
66; RV64IF-NEXT:    fmv.w.x ft1, a0
67; RV64IF-NEXT:    fsub.s ft0, ft1, ft0
68; RV64IF-NEXT:    fmv.x.w a0, ft0
69; RV64IF-NEXT:    ret
70;
71; RV32I-LABEL: fsub_s:
72; RV32I:       # %bb.0:
73; RV32I-NEXT:    addi sp, sp, -16
74; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
75; RV32I-NEXT:    call __subsf3@plt
76; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
77; RV32I-NEXT:    addi sp, sp, 16
78; RV32I-NEXT:    ret
79;
80; RV64I-LABEL: fsub_s:
81; RV64I:       # %bb.0:
82; RV64I-NEXT:    addi sp, sp, -16
83; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
84; RV64I-NEXT:    call __subsf3@plt
85; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
86; RV64I-NEXT:    addi sp, sp, 16
87; RV64I-NEXT:    ret
88  %1 = fsub float %a, %b
89  ret float %1
90}
91
92define float @fmul_s(float %a, float %b) nounwind {
93; RV32IF-LABEL: fmul_s:
94; RV32IF:       # %bb.0:
95; RV32IF-NEXT:    fmv.w.x ft0, a1
96; RV32IF-NEXT:    fmv.w.x ft1, a0
97; RV32IF-NEXT:    fmul.s ft0, ft1, ft0
98; RV32IF-NEXT:    fmv.x.w a0, ft0
99; RV32IF-NEXT:    ret
100;
101; RV64IF-LABEL: fmul_s:
102; RV64IF:       # %bb.0:
103; RV64IF-NEXT:    fmv.w.x ft0, a1
104; RV64IF-NEXT:    fmv.w.x ft1, a0
105; RV64IF-NEXT:    fmul.s ft0, ft1, ft0
106; RV64IF-NEXT:    fmv.x.w a0, ft0
107; RV64IF-NEXT:    ret
108;
109; RV32I-LABEL: fmul_s:
110; RV32I:       # %bb.0:
111; RV32I-NEXT:    addi sp, sp, -16
112; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
113; RV32I-NEXT:    call __mulsf3@plt
114; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
115; RV32I-NEXT:    addi sp, sp, 16
116; RV32I-NEXT:    ret
117;
118; RV64I-LABEL: fmul_s:
119; RV64I:       # %bb.0:
120; RV64I-NEXT:    addi sp, sp, -16
121; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
122; RV64I-NEXT:    call __mulsf3@plt
123; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
124; RV64I-NEXT:    addi sp, sp, 16
125; RV64I-NEXT:    ret
126  %1 = fmul float %a, %b
127  ret float %1
128}
129
130define float @fdiv_s(float %a, float %b) nounwind {
131; RV32IF-LABEL: fdiv_s:
132; RV32IF:       # %bb.0:
133; RV32IF-NEXT:    fmv.w.x ft0, a1
134; RV32IF-NEXT:    fmv.w.x ft1, a0
135; RV32IF-NEXT:    fdiv.s ft0, ft1, ft0
136; RV32IF-NEXT:    fmv.x.w a0, ft0
137; RV32IF-NEXT:    ret
138;
139; RV64IF-LABEL: fdiv_s:
140; RV64IF:       # %bb.0:
141; RV64IF-NEXT:    fmv.w.x ft0, a1
142; RV64IF-NEXT:    fmv.w.x ft1, a0
143; RV64IF-NEXT:    fdiv.s ft0, ft1, ft0
144; RV64IF-NEXT:    fmv.x.w a0, ft0
145; RV64IF-NEXT:    ret
146;
147; RV32I-LABEL: fdiv_s:
148; RV32I:       # %bb.0:
149; RV32I-NEXT:    addi sp, sp, -16
150; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
151; RV32I-NEXT:    call __divsf3@plt
152; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
153; RV32I-NEXT:    addi sp, sp, 16
154; RV32I-NEXT:    ret
155;
156; RV64I-LABEL: fdiv_s:
157; RV64I:       # %bb.0:
158; RV64I-NEXT:    addi sp, sp, -16
159; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
160; RV64I-NEXT:    call __divsf3@plt
161; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
162; RV64I-NEXT:    addi sp, sp, 16
163; RV64I-NEXT:    ret
164  %1 = fdiv float %a, %b
165  ret float %1
166}
167
168declare float @llvm.sqrt.f32(float)
169
170define float @fsqrt_s(float %a) nounwind {
171; RV32IF-LABEL: fsqrt_s:
172; RV32IF:       # %bb.0:
173; RV32IF-NEXT:    fmv.w.x ft0, a0
174; RV32IF-NEXT:    fsqrt.s ft0, ft0
175; RV32IF-NEXT:    fmv.x.w a0, ft0
176; RV32IF-NEXT:    ret
177;
178; RV64IF-LABEL: fsqrt_s:
179; RV64IF:       # %bb.0:
180; RV64IF-NEXT:    fmv.w.x ft0, a0
181; RV64IF-NEXT:    fsqrt.s ft0, ft0
182; RV64IF-NEXT:    fmv.x.w a0, ft0
183; RV64IF-NEXT:    ret
184;
185; RV32I-LABEL: fsqrt_s:
186; RV32I:       # %bb.0:
187; RV32I-NEXT:    addi sp, sp, -16
188; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
189; RV32I-NEXT:    call sqrtf@plt
190; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
191; RV32I-NEXT:    addi sp, sp, 16
192; RV32I-NEXT:    ret
193;
194; RV64I-LABEL: fsqrt_s:
195; RV64I:       # %bb.0:
196; RV64I-NEXT:    addi sp, sp, -16
197; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
198; RV64I-NEXT:    call sqrtf@plt
199; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
200; RV64I-NEXT:    addi sp, sp, 16
201; RV64I-NEXT:    ret
202  %1 = call float @llvm.sqrt.f32(float %a)
203  ret float %1
204}
205
206declare float @llvm.copysign.f32(float, float)
207
208define float @fsgnj_s(float %a, float %b) nounwind {
209; RV32IF-LABEL: fsgnj_s:
210; RV32IF:       # %bb.0:
211; RV32IF-NEXT:    fmv.w.x ft0, a1
212; RV32IF-NEXT:    fmv.w.x ft1, a0
213; RV32IF-NEXT:    fsgnj.s ft0, ft1, ft0
214; RV32IF-NEXT:    fmv.x.w a0, ft0
215; RV32IF-NEXT:    ret
216;
217; RV64IF-LABEL: fsgnj_s:
218; RV64IF:       # %bb.0:
219; RV64IF-NEXT:    fmv.w.x ft0, a1
220; RV64IF-NEXT:    fmv.w.x ft1, a0
221; RV64IF-NEXT:    fsgnj.s ft0, ft1, ft0
222; RV64IF-NEXT:    fmv.x.w a0, ft0
223; RV64IF-NEXT:    ret
224;
225; RV32I-LABEL: fsgnj_s:
226; RV32I:       # %bb.0:
227; RV32I-NEXT:    lui a2, 524288
228; RV32I-NEXT:    and a1, a1, a2
229; RV32I-NEXT:    addi a2, a2, -1
230; RV32I-NEXT:    and a0, a0, a2
231; RV32I-NEXT:    or a0, a0, a1
232; RV32I-NEXT:    ret
233;
234; RV64I-LABEL: fsgnj_s:
235; RV64I:       # %bb.0:
236; RV64I-NEXT:    lui a2, 524288
237; RV64I-NEXT:    and a1, a1, a2
238; RV64I-NEXT:    addiw a2, a2, -1
239; RV64I-NEXT:    and a0, a0, a2
240; RV64I-NEXT:    or a0, a0, a1
241; RV64I-NEXT:    ret
242  %1 = call float @llvm.copysign.f32(float %a, float %b)
243  ret float %1
244}
245
246; This function performs extra work to ensure that
247; DAGCombiner::visitBITCAST doesn't replace the fneg with an xor.
248define i32 @fneg_s(float %a, float %b) nounwind {
249; RV32IF-LABEL: fneg_s:
250; RV32IF:       # %bb.0:
251; RV32IF-NEXT:    fmv.w.x ft0, a0
252; RV32IF-NEXT:    fadd.s ft0, ft0, ft0
253; RV32IF-NEXT:    fneg.s ft1, ft0
254; RV32IF-NEXT:    feq.s a0, ft0, ft1
255; RV32IF-NEXT:    ret
256;
257; RV64IF-LABEL: fneg_s:
258; RV64IF:       # %bb.0:
259; RV64IF-NEXT:    fmv.w.x ft0, a0
260; RV64IF-NEXT:    fadd.s ft0, ft0, ft0
261; RV64IF-NEXT:    fneg.s ft1, ft0
262; RV64IF-NEXT:    feq.s a0, ft0, ft1
263; RV64IF-NEXT:    ret
264;
265; RV32I-LABEL: fneg_s:
266; RV32I:       # %bb.0:
267; RV32I-NEXT:    addi sp, sp, -16
268; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
269; RV32I-NEXT:    mv a1, a0
270; RV32I-NEXT:    call __addsf3@plt
271; RV32I-NEXT:    lui a1, 524288
272; RV32I-NEXT:    xor a1, a0, a1
273; RV32I-NEXT:    call __eqsf2@plt
274; RV32I-NEXT:    seqz a0, a0
275; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
276; RV32I-NEXT:    addi sp, sp, 16
277; RV32I-NEXT:    ret
278;
279; RV64I-LABEL: fneg_s:
280; RV64I:       # %bb.0:
281; RV64I-NEXT:    addi sp, sp, -16
282; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
283; RV64I-NEXT:    mv a1, a0
284; RV64I-NEXT:    call __addsf3@plt
285; RV64I-NEXT:    lui a1, 524288
286; RV64I-NEXT:    xor a1, a0, a1
287; RV64I-NEXT:    call __eqsf2@plt
288; RV64I-NEXT:    seqz a0, a0
289; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
290; RV64I-NEXT:    addi sp, sp, 16
291; RV64I-NEXT:    ret
292  %1 = fadd float %a, %a
293  %2 = fneg float %1
294  %3 = fcmp oeq float %1, %2
295  %4 = zext i1 %3 to i32
296  ret i32 %4
297}
298
299; This function performs extra work to ensure that
300; DAGCombiner::visitBITCAST doesn't replace the fneg with an xor.
301define float @fsgnjn_s(float %a, float %b) nounwind {
302; RV32IF-LABEL: fsgnjn_s:
303; RV32IF:       # %bb.0:
304; RV32IF-NEXT:    fmv.w.x ft0, a1
305; RV32IF-NEXT:    fmv.w.x ft1, a0
306; RV32IF-NEXT:    fadd.s ft0, ft1, ft0
307; RV32IF-NEXT:    fsgnjn.s ft0, ft1, ft0
308; RV32IF-NEXT:    fmv.x.w a0, ft0
309; RV32IF-NEXT:    ret
310;
311; RV64IF-LABEL: fsgnjn_s:
312; RV64IF:       # %bb.0:
313; RV64IF-NEXT:    fmv.w.x ft0, a1
314; RV64IF-NEXT:    fmv.w.x ft1, a0
315; RV64IF-NEXT:    fadd.s ft0, ft1, ft0
316; RV64IF-NEXT:    fsgnjn.s ft0, ft1, ft0
317; RV64IF-NEXT:    fmv.x.w a0, ft0
318; RV64IF-NEXT:    ret
319;
320; RV32I-LABEL: fsgnjn_s:
321; RV32I:       # %bb.0:
322; RV32I-NEXT:    addi sp, sp, -16
323; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
324; RV32I-NEXT:    sw s0, 8(sp) # 4-byte Folded Spill
325; RV32I-NEXT:    mv s0, a0
326; RV32I-NEXT:    call __addsf3@plt
327; RV32I-NEXT:    not a0, a0
328; RV32I-NEXT:    lui a1, 524288
329; RV32I-NEXT:    addi a2, a1, -1
330; RV32I-NEXT:    and a2, s0, a2
331; RV32I-NEXT:    and a0, a0, a1
332; RV32I-NEXT:    or a0, a2, a0
333; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
334; RV32I-NEXT:    lw s0, 8(sp) # 4-byte Folded Reload
335; RV32I-NEXT:    addi sp, sp, 16
336; RV32I-NEXT:    ret
337;
338; RV64I-LABEL: fsgnjn_s:
339; RV64I:       # %bb.0:
340; RV64I-NEXT:    addi sp, sp, -16
341; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
342; RV64I-NEXT:    sd s0, 0(sp) # 8-byte Folded Spill
343; RV64I-NEXT:    mv s0, a0
344; RV64I-NEXT:    call __addsf3@plt
345; RV64I-NEXT:    not a0, a0
346; RV64I-NEXT:    lui a1, 524288
347; RV64I-NEXT:    addiw a2, a1, -1
348; RV64I-NEXT:    and a2, s0, a2
349; RV64I-NEXT:    and a0, a0, a1
350; RV64I-NEXT:    or a0, a2, a0
351; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
352; RV64I-NEXT:    ld s0, 0(sp) # 8-byte Folded Reload
353; RV64I-NEXT:    addi sp, sp, 16
354; RV64I-NEXT:    ret
355  %1 = fadd float %a, %b
356  %2 = fneg float %1
357  %3 = call float @llvm.copysign.f32(float %a, float %2)
358  ret float %3
359}
360
361declare float @llvm.fabs.f32(float)
362
363; This function performs extra work to ensure that
364; DAGCombiner::visitBITCAST doesn't replace the fabs with an and.
365define float @fabs_s(float %a, float %b) nounwind {
366; RV32IF-LABEL: fabs_s:
367; RV32IF:       # %bb.0:
368; RV32IF-NEXT:    fmv.w.x ft0, a1
369; RV32IF-NEXT:    fmv.w.x ft1, a0
370; RV32IF-NEXT:    fadd.s ft0, ft1, ft0
371; RV32IF-NEXT:    fabs.s ft1, ft0
372; RV32IF-NEXT:    fadd.s ft0, ft1, ft0
373; RV32IF-NEXT:    fmv.x.w a0, ft0
374; RV32IF-NEXT:    ret
375;
376; RV64IF-LABEL: fabs_s:
377; RV64IF:       # %bb.0:
378; RV64IF-NEXT:    fmv.w.x ft0, a1
379; RV64IF-NEXT:    fmv.w.x ft1, a0
380; RV64IF-NEXT:    fadd.s ft0, ft1, ft0
381; RV64IF-NEXT:    fabs.s ft1, ft0
382; RV64IF-NEXT:    fadd.s ft0, ft1, ft0
383; RV64IF-NEXT:    fmv.x.w a0, ft0
384; RV64IF-NEXT:    ret
385;
386; RV32I-LABEL: fabs_s:
387; RV32I:       # %bb.0:
388; RV32I-NEXT:    addi sp, sp, -16
389; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
390; RV32I-NEXT:    call __addsf3@plt
391; RV32I-NEXT:    mv a1, a0
392; RV32I-NEXT:    lui a0, 524288
393; RV32I-NEXT:    addi a0, a0, -1
394; RV32I-NEXT:    and a0, a1, a0
395; RV32I-NEXT:    call __addsf3@plt
396; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
397; RV32I-NEXT:    addi sp, sp, 16
398; RV32I-NEXT:    ret
399;
400; RV64I-LABEL: fabs_s:
401; RV64I:       # %bb.0:
402; RV64I-NEXT:    addi sp, sp, -16
403; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
404; RV64I-NEXT:    call __addsf3@plt
405; RV64I-NEXT:    mv a1, a0
406; RV64I-NEXT:    lui a0, 524288
407; RV64I-NEXT:    addiw a0, a0, -1
408; RV64I-NEXT:    and a0, a1, a0
409; RV64I-NEXT:    call __addsf3@plt
410; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
411; RV64I-NEXT:    addi sp, sp, 16
412; RV64I-NEXT:    ret
413  %1 = fadd float %a, %b
414  %2 = call float @llvm.fabs.f32(float %1)
415  %3 = fadd float %2, %1
416  ret float %3
417}
418
419declare float @llvm.minnum.f32(float, float)
420
421define float @fmin_s(float %a, float %b) nounwind {
422; RV32IF-LABEL: fmin_s:
423; RV32IF:       # %bb.0:
424; RV32IF-NEXT:    fmv.w.x ft0, a1
425; RV32IF-NEXT:    fmv.w.x ft1, a0
426; RV32IF-NEXT:    fmin.s ft0, ft1, ft0
427; RV32IF-NEXT:    fmv.x.w a0, ft0
428; RV32IF-NEXT:    ret
429;
430; RV64IF-LABEL: fmin_s:
431; RV64IF:       # %bb.0:
432; RV64IF-NEXT:    fmv.w.x ft0, a1
433; RV64IF-NEXT:    fmv.w.x ft1, a0
434; RV64IF-NEXT:    fmin.s ft0, ft1, ft0
435; RV64IF-NEXT:    fmv.x.w a0, ft0
436; RV64IF-NEXT:    ret
437;
438; RV32I-LABEL: fmin_s:
439; RV32I:       # %bb.0:
440; RV32I-NEXT:    addi sp, sp, -16
441; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
442; RV32I-NEXT:    call fminf@plt
443; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
444; RV32I-NEXT:    addi sp, sp, 16
445; RV32I-NEXT:    ret
446;
447; RV64I-LABEL: fmin_s:
448; RV64I:       # %bb.0:
449; RV64I-NEXT:    addi sp, sp, -16
450; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
451; RV64I-NEXT:    call fminf@plt
452; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
453; RV64I-NEXT:    addi sp, sp, 16
454; RV64I-NEXT:    ret
455  %1 = call float @llvm.minnum.f32(float %a, float %b)
456  ret float %1
457}
458
459declare float @llvm.maxnum.f32(float, float)
460
461define float @fmax_s(float %a, float %b) nounwind {
462; RV32IF-LABEL: fmax_s:
463; RV32IF:       # %bb.0:
464; RV32IF-NEXT:    fmv.w.x ft0, a1
465; RV32IF-NEXT:    fmv.w.x ft1, a0
466; RV32IF-NEXT:    fmax.s ft0, ft1, ft0
467; RV32IF-NEXT:    fmv.x.w a0, ft0
468; RV32IF-NEXT:    ret
469;
470; RV64IF-LABEL: fmax_s:
471; RV64IF:       # %bb.0:
472; RV64IF-NEXT:    fmv.w.x ft0, a1
473; RV64IF-NEXT:    fmv.w.x ft1, a0
474; RV64IF-NEXT:    fmax.s ft0, ft1, ft0
475; RV64IF-NEXT:    fmv.x.w a0, ft0
476; RV64IF-NEXT:    ret
477;
478; RV32I-LABEL: fmax_s:
479; RV32I:       # %bb.0:
480; RV32I-NEXT:    addi sp, sp, -16
481; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
482; RV32I-NEXT:    call fmaxf@plt
483; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
484; RV32I-NEXT:    addi sp, sp, 16
485; RV32I-NEXT:    ret
486;
487; RV64I-LABEL: fmax_s:
488; RV64I:       # %bb.0:
489; RV64I-NEXT:    addi sp, sp, -16
490; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
491; RV64I-NEXT:    call fmaxf@plt
492; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
493; RV64I-NEXT:    addi sp, sp, 16
494; RV64I-NEXT:    ret
495  %1 = call float @llvm.maxnum.f32(float %a, float %b)
496  ret float %1
497}
498
499declare float @llvm.fma.f32(float, float, float)
500
501define float @fmadd_s(float %a, float %b, float %c) nounwind {
502; RV32IF-LABEL: fmadd_s:
503; RV32IF:       # %bb.0:
504; RV32IF-NEXT:    fmv.w.x ft0, a2
505; RV32IF-NEXT:    fmv.w.x ft1, a1
506; RV32IF-NEXT:    fmv.w.x ft2, a0
507; RV32IF-NEXT:    fmadd.s ft0, ft2, ft1, ft0
508; RV32IF-NEXT:    fmv.x.w a0, ft0
509; RV32IF-NEXT:    ret
510;
511; RV64IF-LABEL: fmadd_s:
512; RV64IF:       # %bb.0:
513; RV64IF-NEXT:    fmv.w.x ft0, a2
514; RV64IF-NEXT:    fmv.w.x ft1, a1
515; RV64IF-NEXT:    fmv.w.x ft2, a0
516; RV64IF-NEXT:    fmadd.s ft0, ft2, ft1, ft0
517; RV64IF-NEXT:    fmv.x.w a0, ft0
518; RV64IF-NEXT:    ret
519;
520; RV32I-LABEL: fmadd_s:
521; RV32I:       # %bb.0:
522; RV32I-NEXT:    addi sp, sp, -16
523; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
524; RV32I-NEXT:    call fmaf@plt
525; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
526; RV32I-NEXT:    addi sp, sp, 16
527; RV32I-NEXT:    ret
528;
529; RV64I-LABEL: fmadd_s:
530; RV64I:       # %bb.0:
531; RV64I-NEXT:    addi sp, sp, -16
532; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
533; RV64I-NEXT:    call fmaf@plt
534; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
535; RV64I-NEXT:    addi sp, sp, 16
536; RV64I-NEXT:    ret
537  %1 = call float @llvm.fma.f32(float %a, float %b, float %c)
538  ret float %1
539}
540
541define float @fmsub_s(float %a, float %b, float %c) nounwind {
542; RV32IF-LABEL: fmsub_s:
543; RV32IF:       # %bb.0:
544; RV32IF-NEXT:    fmv.w.x ft0, a1
545; RV32IF-NEXT:    fmv.w.x ft1, a0
546; RV32IF-NEXT:    fmv.w.x ft2, a2
547; RV32IF-NEXT:    fmv.w.x ft3, zero
548; RV32IF-NEXT:    fadd.s ft2, ft2, ft3
549; RV32IF-NEXT:    fmsub.s ft0, ft1, ft0, ft2
550; RV32IF-NEXT:    fmv.x.w a0, ft0
551; RV32IF-NEXT:    ret
552;
553; RV64IF-LABEL: fmsub_s:
554; RV64IF:       # %bb.0:
555; RV64IF-NEXT:    fmv.w.x ft0, a1
556; RV64IF-NEXT:    fmv.w.x ft1, a0
557; RV64IF-NEXT:    fmv.w.x ft2, a2
558; RV64IF-NEXT:    fmv.w.x ft3, zero
559; RV64IF-NEXT:    fadd.s ft2, ft2, ft3
560; RV64IF-NEXT:    fmsub.s ft0, ft1, ft0, ft2
561; RV64IF-NEXT:    fmv.x.w a0, ft0
562; RV64IF-NEXT:    ret
563;
564; RV32I-LABEL: fmsub_s:
565; RV32I:       # %bb.0:
566; RV32I-NEXT:    addi sp, sp, -16
567; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
568; RV32I-NEXT:    sw s0, 8(sp) # 4-byte Folded Spill
569; RV32I-NEXT:    sw s1, 4(sp) # 4-byte Folded Spill
570; RV32I-NEXT:    mv s0, a1
571; RV32I-NEXT:    mv s1, a0
572; RV32I-NEXT:    mv a0, a2
573; RV32I-NEXT:    li a1, 0
574; RV32I-NEXT:    call __addsf3@plt
575; RV32I-NEXT:    lui a1, 524288
576; RV32I-NEXT:    xor a2, a0, a1
577; RV32I-NEXT:    mv a0, s1
578; RV32I-NEXT:    mv a1, s0
579; RV32I-NEXT:    call fmaf@plt
580; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
581; RV32I-NEXT:    lw s0, 8(sp) # 4-byte Folded Reload
582; RV32I-NEXT:    lw s1, 4(sp) # 4-byte Folded Reload
583; RV32I-NEXT:    addi sp, sp, 16
584; RV32I-NEXT:    ret
585;
586; RV64I-LABEL: fmsub_s:
587; RV64I:       # %bb.0:
588; RV64I-NEXT:    addi sp, sp, -32
589; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
590; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
591; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
592; RV64I-NEXT:    mv s0, a1
593; RV64I-NEXT:    mv s1, a0
594; RV64I-NEXT:    mv a0, a2
595; RV64I-NEXT:    li a1, 0
596; RV64I-NEXT:    call __addsf3@plt
597; RV64I-NEXT:    lui a1, 524288
598; RV64I-NEXT:    xor a2, a0, a1
599; RV64I-NEXT:    mv a0, s1
600; RV64I-NEXT:    mv a1, s0
601; RV64I-NEXT:    call fmaf@plt
602; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
603; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
604; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
605; RV64I-NEXT:    addi sp, sp, 32
606; RV64I-NEXT:    ret
607  %c_ = fadd float 0.0, %c ; avoid negation using xor
608  %negc = fsub float -0.0, %c_
609  %1 = call float @llvm.fma.f32(float %a, float %b, float %negc)
610  ret float %1
611}
612
613define float @fnmadd_s(float %a, float %b, float %c) nounwind {
614; RV32IF-LABEL: fnmadd_s:
615; RV32IF:       # %bb.0:
616; RV32IF-NEXT:    fmv.w.x ft0, a1
617; RV32IF-NEXT:    fmv.w.x ft1, a2
618; RV32IF-NEXT:    fmv.w.x ft2, a0
619; RV32IF-NEXT:    fmv.w.x ft3, zero
620; RV32IF-NEXT:    fadd.s ft2, ft2, ft3
621; RV32IF-NEXT:    fadd.s ft1, ft1, ft3
622; RV32IF-NEXT:    fnmadd.s ft0, ft2, ft0, ft1
623; RV32IF-NEXT:    fmv.x.w a0, ft0
624; RV32IF-NEXT:    ret
625;
626; RV64IF-LABEL: fnmadd_s:
627; RV64IF:       # %bb.0:
628; RV64IF-NEXT:    fmv.w.x ft0, a1
629; RV64IF-NEXT:    fmv.w.x ft1, a2
630; RV64IF-NEXT:    fmv.w.x ft2, a0
631; RV64IF-NEXT:    fmv.w.x ft3, zero
632; RV64IF-NEXT:    fadd.s ft2, ft2, ft3
633; RV64IF-NEXT:    fadd.s ft1, ft1, ft3
634; RV64IF-NEXT:    fnmadd.s ft0, ft2, ft0, ft1
635; RV64IF-NEXT:    fmv.x.w a0, ft0
636; RV64IF-NEXT:    ret
637;
638; RV32I-LABEL: fnmadd_s:
639; RV32I:       # %bb.0:
640; RV32I-NEXT:    addi sp, sp, -16
641; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
642; RV32I-NEXT:    sw s0, 8(sp) # 4-byte Folded Spill
643; RV32I-NEXT:    sw s1, 4(sp) # 4-byte Folded Spill
644; RV32I-NEXT:    sw s2, 0(sp) # 4-byte Folded Spill
645; RV32I-NEXT:    mv s0, a2
646; RV32I-NEXT:    mv s2, a1
647; RV32I-NEXT:    li a1, 0
648; RV32I-NEXT:    call __addsf3@plt
649; RV32I-NEXT:    mv s1, a0
650; RV32I-NEXT:    mv a0, s0
651; RV32I-NEXT:    li a1, 0
652; RV32I-NEXT:    call __addsf3@plt
653; RV32I-NEXT:    lui a2, 524288
654; RV32I-NEXT:    xor a1, s1, a2
655; RV32I-NEXT:    xor a2, a0, a2
656; RV32I-NEXT:    mv a0, a1
657; RV32I-NEXT:    mv a1, s2
658; RV32I-NEXT:    call fmaf@plt
659; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
660; RV32I-NEXT:    lw s0, 8(sp) # 4-byte Folded Reload
661; RV32I-NEXT:    lw s1, 4(sp) # 4-byte Folded Reload
662; RV32I-NEXT:    lw s2, 0(sp) # 4-byte Folded Reload
663; RV32I-NEXT:    addi sp, sp, 16
664; RV32I-NEXT:    ret
665;
666; RV64I-LABEL: fnmadd_s:
667; RV64I:       # %bb.0:
668; RV64I-NEXT:    addi sp, sp, -32
669; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
670; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
671; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
672; RV64I-NEXT:    sd s2, 0(sp) # 8-byte Folded Spill
673; RV64I-NEXT:    mv s0, a2
674; RV64I-NEXT:    mv s2, a1
675; RV64I-NEXT:    li a1, 0
676; RV64I-NEXT:    call __addsf3@plt
677; RV64I-NEXT:    mv s1, a0
678; RV64I-NEXT:    mv a0, s0
679; RV64I-NEXT:    li a1, 0
680; RV64I-NEXT:    call __addsf3@plt
681; RV64I-NEXT:    lui a2, 524288
682; RV64I-NEXT:    xor a1, s1, a2
683; RV64I-NEXT:    xor a2, a0, a2
684; RV64I-NEXT:    mv a0, a1
685; RV64I-NEXT:    mv a1, s2
686; RV64I-NEXT:    call fmaf@plt
687; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
688; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
689; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
690; RV64I-NEXT:    ld s2, 0(sp) # 8-byte Folded Reload
691; RV64I-NEXT:    addi sp, sp, 32
692; RV64I-NEXT:    ret
693  %a_ = fadd float 0.0, %a
694  %c_ = fadd float 0.0, %c
695  %nega = fsub float -0.0, %a_
696  %negc = fsub float -0.0, %c_
697  %1 = call float @llvm.fma.f32(float %nega, float %b, float %negc)
698  ret float %1
699}
700
701define float @fnmadd_s_2(float %a, float %b, float %c) nounwind {
702; RV32IF-LABEL: fnmadd_s_2:
703; RV32IF:       # %bb.0:
704; RV32IF-NEXT:    fmv.w.x ft0, a0
705; RV32IF-NEXT:    fmv.w.x ft1, a2
706; RV32IF-NEXT:    fmv.w.x ft2, a1
707; RV32IF-NEXT:    fmv.w.x ft3, zero
708; RV32IF-NEXT:    fadd.s ft2, ft2, ft3
709; RV32IF-NEXT:    fadd.s ft1, ft1, ft3
710; RV32IF-NEXT:    fnmadd.s ft0, ft2, ft0, ft1
711; RV32IF-NEXT:    fmv.x.w a0, ft0
712; RV32IF-NEXT:    ret
713;
714; RV64IF-LABEL: fnmadd_s_2:
715; RV64IF:       # %bb.0:
716; RV64IF-NEXT:    fmv.w.x ft0, a0
717; RV64IF-NEXT:    fmv.w.x ft1, a2
718; RV64IF-NEXT:    fmv.w.x ft2, a1
719; RV64IF-NEXT:    fmv.w.x ft3, zero
720; RV64IF-NEXT:    fadd.s ft2, ft2, ft3
721; RV64IF-NEXT:    fadd.s ft1, ft1, ft3
722; RV64IF-NEXT:    fnmadd.s ft0, ft2, ft0, ft1
723; RV64IF-NEXT:    fmv.x.w a0, ft0
724; RV64IF-NEXT:    ret
725;
726; RV32I-LABEL: fnmadd_s_2:
727; RV32I:       # %bb.0:
728; RV32I-NEXT:    addi sp, sp, -16
729; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
730; RV32I-NEXT:    sw s0, 8(sp) # 4-byte Folded Spill
731; RV32I-NEXT:    sw s1, 4(sp) # 4-byte Folded Spill
732; RV32I-NEXT:    sw s2, 0(sp) # 4-byte Folded Spill
733; RV32I-NEXT:    mv s0, a2
734; RV32I-NEXT:    mv s2, a0
735; RV32I-NEXT:    mv a0, a1
736; RV32I-NEXT:    li a1, 0
737; RV32I-NEXT:    call __addsf3@plt
738; RV32I-NEXT:    mv s1, a0
739; RV32I-NEXT:    mv a0, s0
740; RV32I-NEXT:    li a1, 0
741; RV32I-NEXT:    call __addsf3@plt
742; RV32I-NEXT:    lui a2, 524288
743; RV32I-NEXT:    xor a1, s1, a2
744; RV32I-NEXT:    xor a2, a0, a2
745; RV32I-NEXT:    mv a0, s2
746; RV32I-NEXT:    call fmaf@plt
747; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
748; RV32I-NEXT:    lw s0, 8(sp) # 4-byte Folded Reload
749; RV32I-NEXT:    lw s1, 4(sp) # 4-byte Folded Reload
750; RV32I-NEXT:    lw s2, 0(sp) # 4-byte Folded Reload
751; RV32I-NEXT:    addi sp, sp, 16
752; RV32I-NEXT:    ret
753;
754; RV64I-LABEL: fnmadd_s_2:
755; RV64I:       # %bb.0:
756; RV64I-NEXT:    addi sp, sp, -32
757; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
758; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
759; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
760; RV64I-NEXT:    sd s2, 0(sp) # 8-byte Folded Spill
761; RV64I-NEXT:    mv s0, a2
762; RV64I-NEXT:    mv s2, a0
763; RV64I-NEXT:    mv a0, a1
764; RV64I-NEXT:    li a1, 0
765; RV64I-NEXT:    call __addsf3@plt
766; RV64I-NEXT:    mv s1, a0
767; RV64I-NEXT:    mv a0, s0
768; RV64I-NEXT:    li a1, 0
769; RV64I-NEXT:    call __addsf3@plt
770; RV64I-NEXT:    lui a2, 524288
771; RV64I-NEXT:    xor a1, s1, a2
772; RV64I-NEXT:    xor a2, a0, a2
773; RV64I-NEXT:    mv a0, s2
774; RV64I-NEXT:    call fmaf@plt
775; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
776; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
777; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
778; RV64I-NEXT:    ld s2, 0(sp) # 8-byte Folded Reload
779; RV64I-NEXT:    addi sp, sp, 32
780; RV64I-NEXT:    ret
781  %b_ = fadd float 0.0, %b
782  %c_ = fadd float 0.0, %c
783  %negb = fsub float -0.0, %b_
784  %negc = fsub float -0.0, %c_
785  %1 = call float @llvm.fma.f32(float %a, float %negb, float %negc)
786  ret float %1
787}
788
789define float @fnmsub_s(float %a, float %b, float %c) nounwind {
790; RV32IF-LABEL: fnmsub_s:
791; RV32IF:       # %bb.0:
792; RV32IF-NEXT:    fmv.w.x ft0, a2
793; RV32IF-NEXT:    fmv.w.x ft1, a1
794; RV32IF-NEXT:    fmv.w.x ft2, a0
795; RV32IF-NEXT:    fmv.w.x ft3, zero
796; RV32IF-NEXT:    fadd.s ft2, ft2, ft3
797; RV32IF-NEXT:    fnmsub.s ft0, ft2, ft1, ft0
798; RV32IF-NEXT:    fmv.x.w a0, ft0
799; RV32IF-NEXT:    ret
800;
801; RV64IF-LABEL: fnmsub_s:
802; RV64IF:       # %bb.0:
803; RV64IF-NEXT:    fmv.w.x ft0, a2
804; RV64IF-NEXT:    fmv.w.x ft1, a1
805; RV64IF-NEXT:    fmv.w.x ft2, a0
806; RV64IF-NEXT:    fmv.w.x ft3, zero
807; RV64IF-NEXT:    fadd.s ft2, ft2, ft3
808; RV64IF-NEXT:    fnmsub.s ft0, ft2, ft1, ft0
809; RV64IF-NEXT:    fmv.x.w a0, ft0
810; RV64IF-NEXT:    ret
811;
812; RV32I-LABEL: fnmsub_s:
813; RV32I:       # %bb.0:
814; RV32I-NEXT:    addi sp, sp, -16
815; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
816; RV32I-NEXT:    sw s0, 8(sp) # 4-byte Folded Spill
817; RV32I-NEXT:    sw s1, 4(sp) # 4-byte Folded Spill
818; RV32I-NEXT:    mv s0, a2
819; RV32I-NEXT:    mv s1, a1
820; RV32I-NEXT:    li a1, 0
821; RV32I-NEXT:    call __addsf3@plt
822; RV32I-NEXT:    lui a1, 524288
823; RV32I-NEXT:    xor a0, a0, a1
824; RV32I-NEXT:    mv a1, s1
825; RV32I-NEXT:    mv a2, s0
826; RV32I-NEXT:    call fmaf@plt
827; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
828; RV32I-NEXT:    lw s0, 8(sp) # 4-byte Folded Reload
829; RV32I-NEXT:    lw s1, 4(sp) # 4-byte Folded Reload
830; RV32I-NEXT:    addi sp, sp, 16
831; RV32I-NEXT:    ret
832;
833; RV64I-LABEL: fnmsub_s:
834; RV64I:       # %bb.0:
835; RV64I-NEXT:    addi sp, sp, -32
836; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
837; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
838; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
839; RV64I-NEXT:    mv s0, a2
840; RV64I-NEXT:    mv s1, a1
841; RV64I-NEXT:    li a1, 0
842; RV64I-NEXT:    call __addsf3@plt
843; RV64I-NEXT:    lui a1, 524288
844; RV64I-NEXT:    xor a0, a0, a1
845; RV64I-NEXT:    mv a1, s1
846; RV64I-NEXT:    mv a2, s0
847; RV64I-NEXT:    call fmaf@plt
848; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
849; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
850; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
851; RV64I-NEXT:    addi sp, sp, 32
852; RV64I-NEXT:    ret
853  %a_ = fadd float 0.0, %a
854  %nega = fsub float -0.0, %a_
855  %1 = call float @llvm.fma.f32(float %nega, float %b, float %c)
856  ret float %1
857}
858
859define float @fnmsub_s_2(float %a, float %b, float %c) nounwind {
860; RV32IF-LABEL: fnmsub_s_2:
861; RV32IF:       # %bb.0:
862; RV32IF-NEXT:    fmv.w.x ft0, a2
863; RV32IF-NEXT:    fmv.w.x ft1, a0
864; RV32IF-NEXT:    fmv.w.x ft2, a1
865; RV32IF-NEXT:    fmv.w.x ft3, zero
866; RV32IF-NEXT:    fadd.s ft2, ft2, ft3
867; RV32IF-NEXT:    fnmsub.s ft0, ft2, ft1, ft0
868; RV32IF-NEXT:    fmv.x.w a0, ft0
869; RV32IF-NEXT:    ret
870;
871; RV64IF-LABEL: fnmsub_s_2:
872; RV64IF:       # %bb.0:
873; RV64IF-NEXT:    fmv.w.x ft0, a2
874; RV64IF-NEXT:    fmv.w.x ft1, a0
875; RV64IF-NEXT:    fmv.w.x ft2, a1
876; RV64IF-NEXT:    fmv.w.x ft3, zero
877; RV64IF-NEXT:    fadd.s ft2, ft2, ft3
878; RV64IF-NEXT:    fnmsub.s ft0, ft2, ft1, ft0
879; RV64IF-NEXT:    fmv.x.w a0, ft0
880; RV64IF-NEXT:    ret
881;
882; RV32I-LABEL: fnmsub_s_2:
883; RV32I:       # %bb.0:
884; RV32I-NEXT:    addi sp, sp, -16
885; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
886; RV32I-NEXT:    sw s0, 8(sp) # 4-byte Folded Spill
887; RV32I-NEXT:    sw s1, 4(sp) # 4-byte Folded Spill
888; RV32I-NEXT:    mv s0, a2
889; RV32I-NEXT:    mv s1, a0
890; RV32I-NEXT:    mv a0, a1
891; RV32I-NEXT:    li a1, 0
892; RV32I-NEXT:    call __addsf3@plt
893; RV32I-NEXT:    lui a1, 524288
894; RV32I-NEXT:    xor a1, a0, a1
895; RV32I-NEXT:    mv a0, s1
896; RV32I-NEXT:    mv a2, s0
897; RV32I-NEXT:    call fmaf@plt
898; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
899; RV32I-NEXT:    lw s0, 8(sp) # 4-byte Folded Reload
900; RV32I-NEXT:    lw s1, 4(sp) # 4-byte Folded Reload
901; RV32I-NEXT:    addi sp, sp, 16
902; RV32I-NEXT:    ret
903;
904; RV64I-LABEL: fnmsub_s_2:
905; RV64I:       # %bb.0:
906; RV64I-NEXT:    addi sp, sp, -32
907; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
908; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
909; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
910; RV64I-NEXT:    mv s0, a2
911; RV64I-NEXT:    mv s1, a0
912; RV64I-NEXT:    mv a0, a1
913; RV64I-NEXT:    li a1, 0
914; RV64I-NEXT:    call __addsf3@plt
915; RV64I-NEXT:    lui a1, 524288
916; RV64I-NEXT:    xor a1, a0, a1
917; RV64I-NEXT:    mv a0, s1
918; RV64I-NEXT:    mv a2, s0
919; RV64I-NEXT:    call fmaf@plt
920; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
921; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
922; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
923; RV64I-NEXT:    addi sp, sp, 32
924; RV64I-NEXT:    ret
925  %b_ = fadd float 0.0, %b
926  %negb = fsub float -0.0, %b_
927  %1 = call float @llvm.fma.f32(float %a, float %negb, float %c)
928  ret float %1
929}
930
931define float @fmadd_s_contract(float %a, float %b, float %c) nounwind {
932; RV32IF-LABEL: fmadd_s_contract:
933; RV32IF:       # %bb.0:
934; RV32IF-NEXT:    fmv.w.x ft0, a2
935; RV32IF-NEXT:    fmv.w.x ft1, a1
936; RV32IF-NEXT:    fmv.w.x ft2, a0
937; RV32IF-NEXT:    fmadd.s ft0, ft2, ft1, ft0
938; RV32IF-NEXT:    fmv.x.w a0, ft0
939; RV32IF-NEXT:    ret
940;
941; RV64IF-LABEL: fmadd_s_contract:
942; RV64IF:       # %bb.0:
943; RV64IF-NEXT:    fmv.w.x ft0, a2
944; RV64IF-NEXT:    fmv.w.x ft1, a1
945; RV64IF-NEXT:    fmv.w.x ft2, a0
946; RV64IF-NEXT:    fmadd.s ft0, ft2, ft1, ft0
947; RV64IF-NEXT:    fmv.x.w a0, ft0
948; RV64IF-NEXT:    ret
949;
950; RV32I-LABEL: fmadd_s_contract:
951; RV32I:       # %bb.0:
952; RV32I-NEXT:    addi sp, sp, -16
953; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
954; RV32I-NEXT:    sw s0, 8(sp) # 4-byte Folded Spill
955; RV32I-NEXT:    mv s0, a2
956; RV32I-NEXT:    call __mulsf3@plt
957; RV32I-NEXT:    mv a1, s0
958; RV32I-NEXT:    call __addsf3@plt
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:    addi sp, sp, 16
962; RV32I-NEXT:    ret
963;
964; RV64I-LABEL: fmadd_s_contract:
965; RV64I:       # %bb.0:
966; RV64I-NEXT:    addi sp, sp, -16
967; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
968; RV64I-NEXT:    sd s0, 0(sp) # 8-byte Folded Spill
969; RV64I-NEXT:    mv s0, a2
970; RV64I-NEXT:    call __mulsf3@plt
971; RV64I-NEXT:    mv a1, s0
972; RV64I-NEXT:    call __addsf3@plt
973; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
974; RV64I-NEXT:    ld s0, 0(sp) # 8-byte Folded Reload
975; RV64I-NEXT:    addi sp, sp, 16
976; RV64I-NEXT:    ret
977  %1 = fmul contract float %a, %b
978  %2 = fadd contract float %1, %c
979  ret float %2
980}
981
982define float @fmsub_s_contract(float %a, float %b, float %c) nounwind {
983; RV32IF-LABEL: fmsub_s_contract:
984; RV32IF:       # %bb.0:
985; RV32IF-NEXT:    fmv.w.x ft0, a1
986; RV32IF-NEXT:    fmv.w.x ft1, a0
987; RV32IF-NEXT:    fmv.w.x ft2, a2
988; RV32IF-NEXT:    fmv.w.x ft3, zero
989; RV32IF-NEXT:    fadd.s ft2, ft2, ft3
990; RV32IF-NEXT:    fmsub.s ft0, ft1, ft0, ft2
991; RV32IF-NEXT:    fmv.x.w a0, ft0
992; RV32IF-NEXT:    ret
993;
994; RV64IF-LABEL: fmsub_s_contract:
995; RV64IF:       # %bb.0:
996; RV64IF-NEXT:    fmv.w.x ft0, a1
997; RV64IF-NEXT:    fmv.w.x ft1, a0
998; RV64IF-NEXT:    fmv.w.x ft2, a2
999; RV64IF-NEXT:    fmv.w.x ft3, zero
1000; RV64IF-NEXT:    fadd.s ft2, ft2, ft3
1001; RV64IF-NEXT:    fmsub.s ft0, ft1, ft0, ft2
1002; RV64IF-NEXT:    fmv.x.w a0, ft0
1003; RV64IF-NEXT:    ret
1004;
1005; RV32I-LABEL: fmsub_s_contract:
1006; RV32I:       # %bb.0:
1007; RV32I-NEXT:    addi sp, sp, -16
1008; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
1009; RV32I-NEXT:    sw s0, 8(sp) # 4-byte Folded Spill
1010; RV32I-NEXT:    sw s1, 4(sp) # 4-byte Folded Spill
1011; RV32I-NEXT:    sw s2, 0(sp) # 4-byte Folded Spill
1012; RV32I-NEXT:    mv s2, a1
1013; RV32I-NEXT:    mv s1, a0
1014; RV32I-NEXT:    mv a0, a2
1015; RV32I-NEXT:    li a1, 0
1016; RV32I-NEXT:    call __addsf3@plt
1017; RV32I-NEXT:    mv s0, a0
1018; RV32I-NEXT:    mv a0, s1
1019; RV32I-NEXT:    mv a1, s2
1020; RV32I-NEXT:    call __mulsf3@plt
1021; RV32I-NEXT:    mv a1, s0
1022; RV32I-NEXT:    call __subsf3@plt
1023; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
1024; RV32I-NEXT:    lw s0, 8(sp) # 4-byte Folded Reload
1025; RV32I-NEXT:    lw s1, 4(sp) # 4-byte Folded Reload
1026; RV32I-NEXT:    lw s2, 0(sp) # 4-byte Folded Reload
1027; RV32I-NEXT:    addi sp, sp, 16
1028; RV32I-NEXT:    ret
1029;
1030; RV64I-LABEL: fmsub_s_contract:
1031; RV64I:       # %bb.0:
1032; RV64I-NEXT:    addi sp, sp, -32
1033; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
1034; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
1035; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
1036; RV64I-NEXT:    sd s2, 0(sp) # 8-byte Folded Spill
1037; RV64I-NEXT:    mv s2, a1
1038; RV64I-NEXT:    mv s1, a0
1039; RV64I-NEXT:    mv a0, a2
1040; RV64I-NEXT:    li a1, 0
1041; RV64I-NEXT:    call __addsf3@plt
1042; RV64I-NEXT:    mv s0, a0
1043; RV64I-NEXT:    mv a0, s1
1044; RV64I-NEXT:    mv a1, s2
1045; RV64I-NEXT:    call __mulsf3@plt
1046; RV64I-NEXT:    mv a1, s0
1047; RV64I-NEXT:    call __subsf3@plt
1048; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
1049; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
1050; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
1051; RV64I-NEXT:    ld s2, 0(sp) # 8-byte Folded Reload
1052; RV64I-NEXT:    addi sp, sp, 32
1053; RV64I-NEXT:    ret
1054  %c_ = fadd float 0.0, %c ; avoid negation using xor
1055  %1 = fmul contract float %a, %b
1056  %2 = fsub contract float %1, %c_
1057  ret float %2
1058}
1059
1060define float @fnmadd_s_contract(float %a, float %b, float %c) nounwind {
1061; RV32IF-LABEL: fnmadd_s_contract:
1062; RV32IF:       # %bb.0:
1063; RV32IF-NEXT:    fmv.w.x ft0, a2
1064; RV32IF-NEXT:    fmv.w.x ft1, a1
1065; RV32IF-NEXT:    fmv.w.x ft2, a0
1066; RV32IF-NEXT:    fmv.w.x ft3, zero
1067; RV32IF-NEXT:    fadd.s ft2, ft2, ft3
1068; RV32IF-NEXT:    fadd.s ft1, ft1, ft3
1069; RV32IF-NEXT:    fadd.s ft0, ft0, ft3
1070; RV32IF-NEXT:    fnmadd.s ft0, ft2, ft1, ft0
1071; RV32IF-NEXT:    fmv.x.w a0, ft0
1072; RV32IF-NEXT:    ret
1073;
1074; RV64IF-LABEL: fnmadd_s_contract:
1075; RV64IF:       # %bb.0:
1076; RV64IF-NEXT:    fmv.w.x ft0, a2
1077; RV64IF-NEXT:    fmv.w.x ft1, a1
1078; RV64IF-NEXT:    fmv.w.x ft2, a0
1079; RV64IF-NEXT:    fmv.w.x ft3, zero
1080; RV64IF-NEXT:    fadd.s ft2, ft2, ft3
1081; RV64IF-NEXT:    fadd.s ft1, ft1, ft3
1082; RV64IF-NEXT:    fadd.s ft0, ft0, ft3
1083; RV64IF-NEXT:    fnmadd.s ft0, ft2, ft1, ft0
1084; RV64IF-NEXT:    fmv.x.w a0, ft0
1085; RV64IF-NEXT:    ret
1086;
1087; RV32I-LABEL: fnmadd_s_contract:
1088; RV32I:       # %bb.0:
1089; RV32I-NEXT:    addi sp, sp, -32
1090; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
1091; RV32I-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
1092; RV32I-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
1093; RV32I-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
1094; RV32I-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
1095; RV32I-NEXT:    mv s2, a2
1096; RV32I-NEXT:    mv s1, a1
1097; RV32I-NEXT:    li a1, 0
1098; RV32I-NEXT:    call __addsf3@plt
1099; RV32I-NEXT:    mv s3, a0
1100; RV32I-NEXT:    mv a0, s1
1101; RV32I-NEXT:    li a1, 0
1102; RV32I-NEXT:    call __addsf3@plt
1103; RV32I-NEXT:    mv s1, a0
1104; RV32I-NEXT:    mv a0, s2
1105; RV32I-NEXT:    li a1, 0
1106; RV32I-NEXT:    call __addsf3@plt
1107; RV32I-NEXT:    mv s0, a0
1108; RV32I-NEXT:    mv a0, s3
1109; RV32I-NEXT:    mv a1, s1
1110; RV32I-NEXT:    call __mulsf3@plt
1111; RV32I-NEXT:    lui a1, 524288
1112; RV32I-NEXT:    xor a0, a0, a1
1113; RV32I-NEXT:    mv a1, s0
1114; RV32I-NEXT:    call __subsf3@plt
1115; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
1116; RV32I-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
1117; RV32I-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
1118; RV32I-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
1119; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
1120; RV32I-NEXT:    addi sp, sp, 32
1121; RV32I-NEXT:    ret
1122;
1123; RV64I-LABEL: fnmadd_s_contract:
1124; RV64I:       # %bb.0:
1125; RV64I-NEXT:    addi sp, sp, -48
1126; RV64I-NEXT:    sd ra, 40(sp) # 8-byte Folded Spill
1127; RV64I-NEXT:    sd s0, 32(sp) # 8-byte Folded Spill
1128; RV64I-NEXT:    sd s1, 24(sp) # 8-byte Folded Spill
1129; RV64I-NEXT:    sd s2, 16(sp) # 8-byte Folded Spill
1130; RV64I-NEXT:    sd s3, 8(sp) # 8-byte Folded Spill
1131; RV64I-NEXT:    mv s2, a2
1132; RV64I-NEXT:    mv s1, a1
1133; RV64I-NEXT:    li a1, 0
1134; RV64I-NEXT:    call __addsf3@plt
1135; RV64I-NEXT:    mv s3, a0
1136; RV64I-NEXT:    mv a0, s1
1137; RV64I-NEXT:    li a1, 0
1138; RV64I-NEXT:    call __addsf3@plt
1139; RV64I-NEXT:    mv s1, a0
1140; RV64I-NEXT:    mv a0, s2
1141; RV64I-NEXT:    li a1, 0
1142; RV64I-NEXT:    call __addsf3@plt
1143; RV64I-NEXT:    mv s0, a0
1144; RV64I-NEXT:    mv a0, s3
1145; RV64I-NEXT:    mv a1, s1
1146; RV64I-NEXT:    call __mulsf3@plt
1147; RV64I-NEXT:    lui a1, 524288
1148; RV64I-NEXT:    xor a0, a0, a1
1149; RV64I-NEXT:    mv a1, s0
1150; RV64I-NEXT:    call __subsf3@plt
1151; RV64I-NEXT:    ld ra, 40(sp) # 8-byte Folded Reload
1152; RV64I-NEXT:    ld s0, 32(sp) # 8-byte Folded Reload
1153; RV64I-NEXT:    ld s1, 24(sp) # 8-byte Folded Reload
1154; RV64I-NEXT:    ld s2, 16(sp) # 8-byte Folded Reload
1155; RV64I-NEXT:    ld s3, 8(sp) # 8-byte Folded Reload
1156; RV64I-NEXT:    addi sp, sp, 48
1157; RV64I-NEXT:    ret
1158  %a_ = fadd float 0.0, %a ; avoid negation using xor
1159  %b_ = fadd float 0.0, %b ; avoid negation using xor
1160  %c_ = fadd float 0.0, %c ; avoid negation using xor
1161  %1 = fmul contract float %a_, %b_
1162  %2 = fneg float %1
1163  %3 = fsub contract float %2, %c_
1164  ret float %3
1165}
1166
1167define float @fnmsub_s_contract(float %a, float %b, float %c) nounwind {
1168; RV32IF-LABEL: fnmsub_s_contract:
1169; RV32IF:       # %bb.0:
1170; RV32IF-NEXT:    fmv.w.x ft0, a2
1171; RV32IF-NEXT:    fmv.w.x ft1, a1
1172; RV32IF-NEXT:    fmv.w.x ft2, a0
1173; RV32IF-NEXT:    fmv.w.x ft3, zero
1174; RV32IF-NEXT:    fadd.s ft2, ft2, ft3
1175; RV32IF-NEXT:    fadd.s ft1, ft1, ft3
1176; RV32IF-NEXT:    fnmsub.s ft0, ft2, ft1, ft0
1177; RV32IF-NEXT:    fmv.x.w a0, ft0
1178; RV32IF-NEXT:    ret
1179;
1180; RV64IF-LABEL: fnmsub_s_contract:
1181; RV64IF:       # %bb.0:
1182; RV64IF-NEXT:    fmv.w.x ft0, a2
1183; RV64IF-NEXT:    fmv.w.x ft1, a1
1184; RV64IF-NEXT:    fmv.w.x ft2, a0
1185; RV64IF-NEXT:    fmv.w.x ft3, zero
1186; RV64IF-NEXT:    fadd.s ft2, ft2, ft3
1187; RV64IF-NEXT:    fadd.s ft1, ft1, ft3
1188; RV64IF-NEXT:    fnmsub.s ft0, ft2, ft1, ft0
1189; RV64IF-NEXT:    fmv.x.w a0, ft0
1190; RV64IF-NEXT:    ret
1191;
1192; RV32I-LABEL: fnmsub_s_contract:
1193; RV32I:       # %bb.0:
1194; RV32I-NEXT:    addi sp, sp, -16
1195; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
1196; RV32I-NEXT:    sw s0, 8(sp) # 4-byte Folded Spill
1197; RV32I-NEXT:    sw s1, 4(sp) # 4-byte Folded Spill
1198; RV32I-NEXT:    sw s2, 0(sp) # 4-byte Folded Spill
1199; RV32I-NEXT:    mv s2, a2
1200; RV32I-NEXT:    mv s1, a1
1201; RV32I-NEXT:    li a1, 0
1202; RV32I-NEXT:    call __addsf3@plt
1203; RV32I-NEXT:    mv s0, a0
1204; RV32I-NEXT:    mv a0, s1
1205; RV32I-NEXT:    li a1, 0
1206; RV32I-NEXT:    call __addsf3@plt
1207; RV32I-NEXT:    mv a1, a0
1208; RV32I-NEXT:    mv a0, s0
1209; RV32I-NEXT:    call __mulsf3@plt
1210; RV32I-NEXT:    mv a1, a0
1211; RV32I-NEXT:    mv a0, s2
1212; RV32I-NEXT:    call __subsf3@plt
1213; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
1214; RV32I-NEXT:    lw s0, 8(sp) # 4-byte Folded Reload
1215; RV32I-NEXT:    lw s1, 4(sp) # 4-byte Folded Reload
1216; RV32I-NEXT:    lw s2, 0(sp) # 4-byte Folded Reload
1217; RV32I-NEXT:    addi sp, sp, 16
1218; RV32I-NEXT:    ret
1219;
1220; RV64I-LABEL: fnmsub_s_contract:
1221; RV64I:       # %bb.0:
1222; RV64I-NEXT:    addi sp, sp, -32
1223; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
1224; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
1225; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
1226; RV64I-NEXT:    sd s2, 0(sp) # 8-byte Folded Spill
1227; RV64I-NEXT:    mv s2, a2
1228; RV64I-NEXT:    mv s1, a1
1229; RV64I-NEXT:    li a1, 0
1230; RV64I-NEXT:    call __addsf3@plt
1231; RV64I-NEXT:    mv s0, a0
1232; RV64I-NEXT:    mv a0, s1
1233; RV64I-NEXT:    li a1, 0
1234; RV64I-NEXT:    call __addsf3@plt
1235; RV64I-NEXT:    mv a1, a0
1236; RV64I-NEXT:    mv a0, s0
1237; RV64I-NEXT:    call __mulsf3@plt
1238; RV64I-NEXT:    mv a1, a0
1239; RV64I-NEXT:    mv a0, s2
1240; RV64I-NEXT:    call __subsf3@plt
1241; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
1242; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
1243; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
1244; RV64I-NEXT:    ld s2, 0(sp) # 8-byte Folded Reload
1245; RV64I-NEXT:    addi sp, sp, 32
1246; RV64I-NEXT:    ret
1247  %a_ = fadd float 0.0, %a ; avoid negation using xor
1248  %b_ = fadd float 0.0, %b ; avoid negation using xor
1249  %1 = fmul contract float %a_, %b_
1250  %2 = fsub contract float %c, %1
1251  ret float %2
1252}
1253