1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple=riscv32 -mattr=+d -verify-machineinstrs < %s \
3; RUN:   | FileCheck -check-prefix=RV32IFD %s
4; RUN: llc -mtriple=riscv64 -mattr=+d -verify-machineinstrs < %s \
5; RUN:   | FileCheck -check-prefix=RV64IFD %s
6
7; These tests are each targeted at a particular RISC-V FPU instruction. Most
8; other files in this folder exercise LLVM IR instructions that don't directly
9; match a RISC-V instruction.
10
11define double @fadd_d(double %a, double %b) nounwind {
12; RV32IFD-LABEL: fadd_d:
13; RV32IFD:       # %bb.0:
14; RV32IFD-NEXT:    addi sp, sp, -16
15; RV32IFD-NEXT:    sw a2, 8(sp)
16; RV32IFD-NEXT:    sw a3, 12(sp)
17; RV32IFD-NEXT:    fld ft0, 8(sp)
18; RV32IFD-NEXT:    sw a0, 8(sp)
19; RV32IFD-NEXT:    sw a1, 12(sp)
20; RV32IFD-NEXT:    fld ft1, 8(sp)
21; RV32IFD-NEXT:    fadd.d ft0, ft1, ft0
22; RV32IFD-NEXT:    fsd ft0, 8(sp)
23; RV32IFD-NEXT:    lw a0, 8(sp)
24; RV32IFD-NEXT:    lw a1, 12(sp)
25; RV32IFD-NEXT:    addi sp, sp, 16
26; RV32IFD-NEXT:    ret
27;
28; RV64IFD-LABEL: fadd_d:
29; RV64IFD:       # %bb.0:
30; RV64IFD-NEXT:    fmv.d.x ft0, a1
31; RV64IFD-NEXT:    fmv.d.x ft1, a0
32; RV64IFD-NEXT:    fadd.d ft0, ft1, ft0
33; RV64IFD-NEXT:    fmv.x.d a0, ft0
34; RV64IFD-NEXT:    ret
35  %1 = fadd double %a, %b
36  ret double %1
37}
38
39define double @fsub_d(double %a, double %b) nounwind {
40; RV32IFD-LABEL: fsub_d:
41; RV32IFD:       # %bb.0:
42; RV32IFD-NEXT:    addi sp, sp, -16
43; RV32IFD-NEXT:    sw a2, 8(sp)
44; RV32IFD-NEXT:    sw a3, 12(sp)
45; RV32IFD-NEXT:    fld ft0, 8(sp)
46; RV32IFD-NEXT:    sw a0, 8(sp)
47; RV32IFD-NEXT:    sw a1, 12(sp)
48; RV32IFD-NEXT:    fld ft1, 8(sp)
49; RV32IFD-NEXT:    fsub.d ft0, ft1, ft0
50; RV32IFD-NEXT:    fsd ft0, 8(sp)
51; RV32IFD-NEXT:    lw a0, 8(sp)
52; RV32IFD-NEXT:    lw a1, 12(sp)
53; RV32IFD-NEXT:    addi sp, sp, 16
54; RV32IFD-NEXT:    ret
55;
56; RV64IFD-LABEL: fsub_d:
57; RV64IFD:       # %bb.0:
58; RV64IFD-NEXT:    fmv.d.x ft0, a1
59; RV64IFD-NEXT:    fmv.d.x ft1, a0
60; RV64IFD-NEXT:    fsub.d ft0, ft1, ft0
61; RV64IFD-NEXT:    fmv.x.d a0, ft0
62; RV64IFD-NEXT:    ret
63  %1 = fsub double %a, %b
64  ret double %1
65}
66
67define double @fmul_d(double %a, double %b) nounwind {
68; RV32IFD-LABEL: fmul_d:
69; RV32IFD:       # %bb.0:
70; RV32IFD-NEXT:    addi sp, sp, -16
71; RV32IFD-NEXT:    sw a2, 8(sp)
72; RV32IFD-NEXT:    sw a3, 12(sp)
73; RV32IFD-NEXT:    fld ft0, 8(sp)
74; RV32IFD-NEXT:    sw a0, 8(sp)
75; RV32IFD-NEXT:    sw a1, 12(sp)
76; RV32IFD-NEXT:    fld ft1, 8(sp)
77; RV32IFD-NEXT:    fmul.d ft0, ft1, ft0
78; RV32IFD-NEXT:    fsd ft0, 8(sp)
79; RV32IFD-NEXT:    lw a0, 8(sp)
80; RV32IFD-NEXT:    lw a1, 12(sp)
81; RV32IFD-NEXT:    addi sp, sp, 16
82; RV32IFD-NEXT:    ret
83;
84; RV64IFD-LABEL: fmul_d:
85; RV64IFD:       # %bb.0:
86; RV64IFD-NEXT:    fmv.d.x ft0, a1
87; RV64IFD-NEXT:    fmv.d.x ft1, a0
88; RV64IFD-NEXT:    fmul.d ft0, ft1, ft0
89; RV64IFD-NEXT:    fmv.x.d a0, ft0
90; RV64IFD-NEXT:    ret
91  %1 = fmul double %a, %b
92  ret double %1
93}
94
95define double @fdiv_d(double %a, double %b) nounwind {
96; RV32IFD-LABEL: fdiv_d:
97; RV32IFD:       # %bb.0:
98; RV32IFD-NEXT:    addi sp, sp, -16
99; RV32IFD-NEXT:    sw a2, 8(sp)
100; RV32IFD-NEXT:    sw a3, 12(sp)
101; RV32IFD-NEXT:    fld ft0, 8(sp)
102; RV32IFD-NEXT:    sw a0, 8(sp)
103; RV32IFD-NEXT:    sw a1, 12(sp)
104; RV32IFD-NEXT:    fld ft1, 8(sp)
105; RV32IFD-NEXT:    fdiv.d ft0, ft1, ft0
106; RV32IFD-NEXT:    fsd ft0, 8(sp)
107; RV32IFD-NEXT:    lw a0, 8(sp)
108; RV32IFD-NEXT:    lw a1, 12(sp)
109; RV32IFD-NEXT:    addi sp, sp, 16
110; RV32IFD-NEXT:    ret
111;
112; RV64IFD-LABEL: fdiv_d:
113; RV64IFD:       # %bb.0:
114; RV64IFD-NEXT:    fmv.d.x ft0, a1
115; RV64IFD-NEXT:    fmv.d.x ft1, a0
116; RV64IFD-NEXT:    fdiv.d ft0, ft1, ft0
117; RV64IFD-NEXT:    fmv.x.d a0, ft0
118; RV64IFD-NEXT:    ret
119  %1 = fdiv double %a, %b
120  ret double %1
121}
122
123declare double @llvm.sqrt.f64(double)
124
125define double @fsqrt_d(double %a) nounwind {
126; RV32IFD-LABEL: fsqrt_d:
127; RV32IFD:       # %bb.0:
128; RV32IFD-NEXT:    addi sp, sp, -16
129; RV32IFD-NEXT:    sw a0, 8(sp)
130; RV32IFD-NEXT:    sw a1, 12(sp)
131; RV32IFD-NEXT:    fld ft0, 8(sp)
132; RV32IFD-NEXT:    fsqrt.d ft0, ft0
133; RV32IFD-NEXT:    fsd ft0, 8(sp)
134; RV32IFD-NEXT:    lw a0, 8(sp)
135; RV32IFD-NEXT:    lw a1, 12(sp)
136; RV32IFD-NEXT:    addi sp, sp, 16
137; RV32IFD-NEXT:    ret
138;
139; RV64IFD-LABEL: fsqrt_d:
140; RV64IFD:       # %bb.0:
141; RV64IFD-NEXT:    fmv.d.x ft0, a0
142; RV64IFD-NEXT:    fsqrt.d ft0, ft0
143; RV64IFD-NEXT:    fmv.x.d a0, ft0
144; RV64IFD-NEXT:    ret
145  %1 = call double @llvm.sqrt.f64(double %a)
146  ret double %1
147}
148
149declare double @llvm.copysign.f64(double, double)
150
151define double @fsgnj_d(double %a, double %b) nounwind {
152; RV32IFD-LABEL: fsgnj_d:
153; RV32IFD:       # %bb.0:
154; RV32IFD-NEXT:    addi sp, sp, -16
155; RV32IFD-NEXT:    sw a2, 8(sp)
156; RV32IFD-NEXT:    sw a3, 12(sp)
157; RV32IFD-NEXT:    fld ft0, 8(sp)
158; RV32IFD-NEXT:    sw a0, 8(sp)
159; RV32IFD-NEXT:    sw a1, 12(sp)
160; RV32IFD-NEXT:    fld ft1, 8(sp)
161; RV32IFD-NEXT:    fsgnj.d ft0, ft1, ft0
162; RV32IFD-NEXT:    fsd ft0, 8(sp)
163; RV32IFD-NEXT:    lw a0, 8(sp)
164; RV32IFD-NEXT:    lw a1, 12(sp)
165; RV32IFD-NEXT:    addi sp, sp, 16
166; RV32IFD-NEXT:    ret
167;
168; RV64IFD-LABEL: fsgnj_d:
169; RV64IFD:       # %bb.0:
170; RV64IFD-NEXT:    fmv.d.x ft0, a1
171; RV64IFD-NEXT:    fmv.d.x ft1, a0
172; RV64IFD-NEXT:    fsgnj.d ft0, ft1, ft0
173; RV64IFD-NEXT:    fmv.x.d a0, ft0
174; RV64IFD-NEXT:    ret
175  %1 = call double @llvm.copysign.f64(double %a, double %b)
176  ret double %1
177}
178
179; This function performs extra work to ensure that
180; DAGCombiner::visitBITCAST doesn't replace the fneg with an xor.
181define i32 @fneg_d(double %a, double %b) nounwind {
182; RV32IFD-LABEL: fneg_d:
183; RV32IFD:       # %bb.0:
184; RV32IFD-NEXT:    addi sp, sp, -16
185; RV32IFD-NEXT:    sw a0, 8(sp)
186; RV32IFD-NEXT:    sw a1, 12(sp)
187; RV32IFD-NEXT:    fld ft0, 8(sp)
188; RV32IFD-NEXT:    fadd.d ft0, ft0, ft0
189; RV32IFD-NEXT:    fneg.d ft1, ft0
190; RV32IFD-NEXT:    feq.d a0, ft0, ft1
191; RV32IFD-NEXT:    addi sp, sp, 16
192; RV32IFD-NEXT:    ret
193;
194; RV64IFD-LABEL: fneg_d:
195; RV64IFD:       # %bb.0:
196; RV64IFD-NEXT:    fmv.d.x ft0, a0
197; RV64IFD-NEXT:    fadd.d ft0, ft0, ft0
198; RV64IFD-NEXT:    fneg.d ft1, ft0
199; RV64IFD-NEXT:    feq.d a0, ft0, ft1
200; RV64IFD-NEXT:    ret
201  %1 = fadd double %a, %a
202  %2 = fneg double %1
203  %3 = fcmp oeq double %1, %2
204  %4 = zext i1 %3 to i32
205  ret i32 %4
206}
207
208define double @fsgnjn_d(double %a, double %b) nounwind {
209; TODO: fsgnjn.s isn't selected on RV64 because DAGCombiner::visitBITCAST will
210; convert (bitconvert (fneg x)) to a xor.
211;
212; RV32IFD-LABEL: fsgnjn_d:
213; RV32IFD:       # %bb.0:
214; RV32IFD-NEXT:    addi sp, sp, -16
215; RV32IFD-NEXT:    sw a2, 8(sp)
216; RV32IFD-NEXT:    sw a3, 12(sp)
217; RV32IFD-NEXT:    fld ft0, 8(sp)
218; RV32IFD-NEXT:    sw a0, 8(sp)
219; RV32IFD-NEXT:    sw a1, 12(sp)
220; RV32IFD-NEXT:    fld ft1, 8(sp)
221; RV32IFD-NEXT:    fsgnjn.d ft0, ft1, ft0
222; RV32IFD-NEXT:    fsd ft0, 8(sp)
223; RV32IFD-NEXT:    lw a0, 8(sp)
224; RV32IFD-NEXT:    lw a1, 12(sp)
225; RV32IFD-NEXT:    addi sp, sp, 16
226; RV32IFD-NEXT:    ret
227;
228; RV64IFD-LABEL: fsgnjn_d:
229; RV64IFD:       # %bb.0:
230; RV64IFD-NEXT:    addi a2, zero, -1
231; RV64IFD-NEXT:    slli a2, a2, 63
232; RV64IFD-NEXT:    xor a1, a1, a2
233; RV64IFD-NEXT:    fmv.d.x ft0, a1
234; RV64IFD-NEXT:    fmv.d.x ft1, a0
235; RV64IFD-NEXT:    fsgnj.d ft0, ft1, ft0
236; RV64IFD-NEXT:    fmv.x.d a0, ft0
237; RV64IFD-NEXT:    ret
238  %1 = fsub double -0.0, %b
239  %2 = call double @llvm.copysign.f64(double %a, double %1)
240  ret double %2
241}
242
243declare double @llvm.fabs.f64(double)
244
245; This function performs extra work to ensure that
246; DAGCombiner::visitBITCAST doesn't replace the fabs with an and.
247define double @fabs_d(double %a, double %b) nounwind {
248; RV32IFD-LABEL: fabs_d:
249; RV32IFD:       # %bb.0:
250; RV32IFD-NEXT:    addi sp, sp, -16
251; RV32IFD-NEXT:    sw a2, 8(sp)
252; RV32IFD-NEXT:    sw a3, 12(sp)
253; RV32IFD-NEXT:    fld ft0, 8(sp)
254; RV32IFD-NEXT:    sw a0, 8(sp)
255; RV32IFD-NEXT:    sw a1, 12(sp)
256; RV32IFD-NEXT:    fld ft1, 8(sp)
257; RV32IFD-NEXT:    fadd.d ft0, ft1, ft0
258; RV32IFD-NEXT:    fabs.d ft1, ft0
259; RV32IFD-NEXT:    fadd.d ft0, ft1, ft0
260; RV32IFD-NEXT:    fsd ft0, 8(sp)
261; RV32IFD-NEXT:    lw a0, 8(sp)
262; RV32IFD-NEXT:    lw a1, 12(sp)
263; RV32IFD-NEXT:    addi sp, sp, 16
264; RV32IFD-NEXT:    ret
265;
266; RV64IFD-LABEL: fabs_d:
267; RV64IFD:       # %bb.0:
268; RV64IFD-NEXT:    fmv.d.x ft0, a1
269; RV64IFD-NEXT:    fmv.d.x ft1, a0
270; RV64IFD-NEXT:    fadd.d ft0, ft1, ft0
271; RV64IFD-NEXT:    fabs.d ft1, ft0
272; RV64IFD-NEXT:    fadd.d ft0, ft1, ft0
273; RV64IFD-NEXT:    fmv.x.d a0, ft0
274; RV64IFD-NEXT:    ret
275  %1 = fadd double %a, %b
276  %2 = call double @llvm.fabs.f64(double %1)
277  %3 = fadd double %2, %1
278  ret double %3
279}
280
281declare double @llvm.minnum.f64(double, double)
282
283define double @fmin_d(double %a, double %b) nounwind {
284; RV32IFD-LABEL: fmin_d:
285; RV32IFD:       # %bb.0:
286; RV32IFD-NEXT:    addi sp, sp, -16
287; RV32IFD-NEXT:    sw a2, 8(sp)
288; RV32IFD-NEXT:    sw a3, 12(sp)
289; RV32IFD-NEXT:    fld ft0, 8(sp)
290; RV32IFD-NEXT:    sw a0, 8(sp)
291; RV32IFD-NEXT:    sw a1, 12(sp)
292; RV32IFD-NEXT:    fld ft1, 8(sp)
293; RV32IFD-NEXT:    fmin.d ft0, ft1, ft0
294; RV32IFD-NEXT:    fsd ft0, 8(sp)
295; RV32IFD-NEXT:    lw a0, 8(sp)
296; RV32IFD-NEXT:    lw a1, 12(sp)
297; RV32IFD-NEXT:    addi sp, sp, 16
298; RV32IFD-NEXT:    ret
299;
300; RV64IFD-LABEL: fmin_d:
301; RV64IFD:       # %bb.0:
302; RV64IFD-NEXT:    fmv.d.x ft0, a1
303; RV64IFD-NEXT:    fmv.d.x ft1, a0
304; RV64IFD-NEXT:    fmin.d ft0, ft1, ft0
305; RV64IFD-NEXT:    fmv.x.d a0, ft0
306; RV64IFD-NEXT:    ret
307  %1 = call double @llvm.minnum.f64(double %a, double %b)
308  ret double %1
309}
310
311declare double @llvm.maxnum.f64(double, double)
312
313define double @fmax_d(double %a, double %b) nounwind {
314; RV32IFD-LABEL: fmax_d:
315; RV32IFD:       # %bb.0:
316; RV32IFD-NEXT:    addi sp, sp, -16
317; RV32IFD-NEXT:    sw a2, 8(sp)
318; RV32IFD-NEXT:    sw a3, 12(sp)
319; RV32IFD-NEXT:    fld ft0, 8(sp)
320; RV32IFD-NEXT:    sw a0, 8(sp)
321; RV32IFD-NEXT:    sw a1, 12(sp)
322; RV32IFD-NEXT:    fld ft1, 8(sp)
323; RV32IFD-NEXT:    fmax.d ft0, ft1, ft0
324; RV32IFD-NEXT:    fsd ft0, 8(sp)
325; RV32IFD-NEXT:    lw a0, 8(sp)
326; RV32IFD-NEXT:    lw a1, 12(sp)
327; RV32IFD-NEXT:    addi sp, sp, 16
328; RV32IFD-NEXT:    ret
329;
330; RV64IFD-LABEL: fmax_d:
331; RV64IFD:       # %bb.0:
332; RV64IFD-NEXT:    fmv.d.x ft0, a1
333; RV64IFD-NEXT:    fmv.d.x ft1, a0
334; RV64IFD-NEXT:    fmax.d ft0, ft1, ft0
335; RV64IFD-NEXT:    fmv.x.d a0, ft0
336; RV64IFD-NEXT:    ret
337  %1 = call double @llvm.maxnum.f64(double %a, double %b)
338  ret double %1
339}
340
341define i32 @feq_d(double %a, double %b) nounwind {
342; RV32IFD-LABEL: feq_d:
343; RV32IFD:       # %bb.0:
344; RV32IFD-NEXT:    addi sp, sp, -16
345; RV32IFD-NEXT:    sw a2, 8(sp)
346; RV32IFD-NEXT:    sw a3, 12(sp)
347; RV32IFD-NEXT:    fld ft0, 8(sp)
348; RV32IFD-NEXT:    sw a0, 8(sp)
349; RV32IFD-NEXT:    sw a1, 12(sp)
350; RV32IFD-NEXT:    fld ft1, 8(sp)
351; RV32IFD-NEXT:    feq.d a0, ft1, ft0
352; RV32IFD-NEXT:    addi sp, sp, 16
353; RV32IFD-NEXT:    ret
354;
355; RV64IFD-LABEL: feq_d:
356; RV64IFD:       # %bb.0:
357; RV64IFD-NEXT:    fmv.d.x ft0, a1
358; RV64IFD-NEXT:    fmv.d.x ft1, a0
359; RV64IFD-NEXT:    feq.d a0, ft1, ft0
360; RV64IFD-NEXT:    ret
361  %1 = fcmp oeq double %a, %b
362  %2 = zext i1 %1 to i32
363  ret i32 %2
364}
365
366define i32 @flt_d(double %a, double %b) nounwind {
367; RV32IFD-LABEL: flt_d:
368; RV32IFD:       # %bb.0:
369; RV32IFD-NEXT:    addi sp, sp, -16
370; RV32IFD-NEXT:    sw a2, 8(sp)
371; RV32IFD-NEXT:    sw a3, 12(sp)
372; RV32IFD-NEXT:    fld ft0, 8(sp)
373; RV32IFD-NEXT:    sw a0, 8(sp)
374; RV32IFD-NEXT:    sw a1, 12(sp)
375; RV32IFD-NEXT:    fld ft1, 8(sp)
376; RV32IFD-NEXT:    flt.d a0, ft1, ft0
377; RV32IFD-NEXT:    addi sp, sp, 16
378; RV32IFD-NEXT:    ret
379;
380; RV64IFD-LABEL: flt_d:
381; RV64IFD:       # %bb.0:
382; RV64IFD-NEXT:    fmv.d.x ft0, a1
383; RV64IFD-NEXT:    fmv.d.x ft1, a0
384; RV64IFD-NEXT:    flt.d a0, ft1, ft0
385; RV64IFD-NEXT:    ret
386  %1 = fcmp olt double %a, %b
387  %2 = zext i1 %1 to i32
388  ret i32 %2
389}
390
391define i32 @fle_d(double %a, double %b) nounwind {
392; RV32IFD-LABEL: fle_d:
393; RV32IFD:       # %bb.0:
394; RV32IFD-NEXT:    addi sp, sp, -16
395; RV32IFD-NEXT:    sw a2, 8(sp)
396; RV32IFD-NEXT:    sw a3, 12(sp)
397; RV32IFD-NEXT:    fld ft0, 8(sp)
398; RV32IFD-NEXT:    sw a0, 8(sp)
399; RV32IFD-NEXT:    sw a1, 12(sp)
400; RV32IFD-NEXT:    fld ft1, 8(sp)
401; RV32IFD-NEXT:    fle.d a0, ft1, ft0
402; RV32IFD-NEXT:    addi sp, sp, 16
403; RV32IFD-NEXT:    ret
404;
405; RV64IFD-LABEL: fle_d:
406; RV64IFD:       # %bb.0:
407; RV64IFD-NEXT:    fmv.d.x ft0, a1
408; RV64IFD-NEXT:    fmv.d.x ft1, a0
409; RV64IFD-NEXT:    fle.d a0, ft1, ft0
410; RV64IFD-NEXT:    ret
411  %1 = fcmp ole double %a, %b
412  %2 = zext i1 %1 to i32
413  ret i32 %2
414}
415
416declare double @llvm.fma.f64(double, double, double)
417
418define double @fmadd_d(double %a, double %b, double %c) nounwind {
419; RV32IFD-LABEL: fmadd_d:
420; RV32IFD:       # %bb.0:
421; RV32IFD-NEXT:    addi sp, sp, -16
422; RV32IFD-NEXT:    sw a4, 8(sp)
423; RV32IFD-NEXT:    sw a5, 12(sp)
424; RV32IFD-NEXT:    fld ft0, 8(sp)
425; RV32IFD-NEXT:    sw a2, 8(sp)
426; RV32IFD-NEXT:    sw a3, 12(sp)
427; RV32IFD-NEXT:    fld ft1, 8(sp)
428; RV32IFD-NEXT:    sw a0, 8(sp)
429; RV32IFD-NEXT:    sw a1, 12(sp)
430; RV32IFD-NEXT:    fld ft2, 8(sp)
431; RV32IFD-NEXT:    fmadd.d ft0, ft2, ft1, ft0
432; RV32IFD-NEXT:    fsd ft0, 8(sp)
433; RV32IFD-NEXT:    lw a0, 8(sp)
434; RV32IFD-NEXT:    lw a1, 12(sp)
435; RV32IFD-NEXT:    addi sp, sp, 16
436; RV32IFD-NEXT:    ret
437;
438; RV64IFD-LABEL: fmadd_d:
439; RV64IFD:       # %bb.0:
440; RV64IFD-NEXT:    fmv.d.x ft0, a2
441; RV64IFD-NEXT:    fmv.d.x ft1, a1
442; RV64IFD-NEXT:    fmv.d.x ft2, a0
443; RV64IFD-NEXT:    fmadd.d ft0, ft2, ft1, ft0
444; RV64IFD-NEXT:    fmv.x.d a0, ft0
445; RV64IFD-NEXT:    ret
446  %1 = call double @llvm.fma.f64(double %a, double %b, double %c)
447  ret double %1
448}
449
450define double @fmsub_d(double %a, double %b, double %c) nounwind {
451; RV32IFD-LABEL: fmsub_d:
452; RV32IFD:       # %bb.0:
453; RV32IFD-NEXT:    addi sp, sp, -16
454; RV32IFD-NEXT:    sw a2, 8(sp)
455; RV32IFD-NEXT:    sw a3, 12(sp)
456; RV32IFD-NEXT:    fld ft0, 8(sp)
457; RV32IFD-NEXT:    sw a0, 8(sp)
458; RV32IFD-NEXT:    sw a1, 12(sp)
459; RV32IFD-NEXT:    fld ft1, 8(sp)
460; RV32IFD-NEXT:    sw a4, 8(sp)
461; RV32IFD-NEXT:    sw a5, 12(sp)
462; RV32IFD-NEXT:    fld ft2, 8(sp)
463; RV32IFD-NEXT:    fcvt.d.w ft3, zero
464; RV32IFD-NEXT:    fadd.d ft2, ft2, ft3
465; RV32IFD-NEXT:    fmsub.d ft0, ft1, ft0, ft2
466; RV32IFD-NEXT:    fsd ft0, 8(sp)
467; RV32IFD-NEXT:    lw a0, 8(sp)
468; RV32IFD-NEXT:    lw a1, 12(sp)
469; RV32IFD-NEXT:    addi sp, sp, 16
470; RV32IFD-NEXT:    ret
471;
472; RV64IFD-LABEL: fmsub_d:
473; RV64IFD:       # %bb.0:
474; RV64IFD-NEXT:    fmv.d.x ft0, a1
475; RV64IFD-NEXT:    fmv.d.x ft1, a0
476; RV64IFD-NEXT:    fmv.d.x ft2, a2
477; RV64IFD-NEXT:    fmv.d.x ft3, zero
478; RV64IFD-NEXT:    fadd.d ft2, ft2, ft3
479; RV64IFD-NEXT:    fmsub.d ft0, ft1, ft0, ft2
480; RV64IFD-NEXT:    fmv.x.d a0, ft0
481; RV64IFD-NEXT:    ret
482  %c_ = fadd double 0.0, %c ; avoid negation using xor
483  %negc = fsub double -0.0, %c_
484  %1 = call double @llvm.fma.f64(double %a, double %b, double %negc)
485  ret double %1
486}
487
488define double @fnmadd_d(double %a, double %b, double %c) nounwind {
489; RV32IFD-LABEL: fnmadd_d:
490; RV32IFD:       # %bb.0:
491; RV32IFD-NEXT:    addi sp, sp, -16
492; RV32IFD-NEXT:    sw a2, 8(sp)
493; RV32IFD-NEXT:    sw a3, 12(sp)
494; RV32IFD-NEXT:    fld ft0, 8(sp)
495; RV32IFD-NEXT:    sw a4, 8(sp)
496; RV32IFD-NEXT:    sw a5, 12(sp)
497; RV32IFD-NEXT:    fld ft1, 8(sp)
498; RV32IFD-NEXT:    sw a0, 8(sp)
499; RV32IFD-NEXT:    sw a1, 12(sp)
500; RV32IFD-NEXT:    fld ft2, 8(sp)
501; RV32IFD-NEXT:    fcvt.d.w ft3, zero
502; RV32IFD-NEXT:    fadd.d ft2, ft2, ft3
503; RV32IFD-NEXT:    fadd.d ft1, ft1, ft3
504; RV32IFD-NEXT:    fnmadd.d ft0, ft2, ft0, ft1
505; RV32IFD-NEXT:    fsd ft0, 8(sp)
506; RV32IFD-NEXT:    lw a0, 8(sp)
507; RV32IFD-NEXT:    lw a1, 12(sp)
508; RV32IFD-NEXT:    addi sp, sp, 16
509; RV32IFD-NEXT:    ret
510;
511; RV64IFD-LABEL: fnmadd_d:
512; RV64IFD:       # %bb.0:
513; RV64IFD-NEXT:    fmv.d.x ft0, a1
514; RV64IFD-NEXT:    fmv.d.x ft1, a2
515; RV64IFD-NEXT:    fmv.d.x ft2, a0
516; RV64IFD-NEXT:    fmv.d.x ft3, zero
517; RV64IFD-NEXT:    fadd.d ft2, ft2, ft3
518; RV64IFD-NEXT:    fadd.d ft1, ft1, ft3
519; RV64IFD-NEXT:    fnmadd.d ft0, ft2, ft0, ft1
520; RV64IFD-NEXT:    fmv.x.d a0, ft0
521; RV64IFD-NEXT:    ret
522  %a_ = fadd double 0.0, %a
523  %c_ = fadd double 0.0, %c
524  %nega = fsub double -0.0, %a_
525  %negc = fsub double -0.0, %c_
526  %1 = call double @llvm.fma.f64(double %nega, double %b, double %negc)
527  ret double %1
528}
529
530define double @fnmadd_d_2(double %a, double %b, double %c) nounwind {
531; RV32IFD-LABEL: fnmadd_d_2:
532; RV32IFD:       # %bb.0:
533; RV32IFD-NEXT:    addi sp, sp, -16
534; RV32IFD-NEXT:    sw a0, 8(sp)
535; RV32IFD-NEXT:    sw a1, 12(sp)
536; RV32IFD-NEXT:    fld ft0, 8(sp)
537; RV32IFD-NEXT:    sw a4, 8(sp)
538; RV32IFD-NEXT:    sw a5, 12(sp)
539; RV32IFD-NEXT:    fld ft1, 8(sp)
540; RV32IFD-NEXT:    sw a2, 8(sp)
541; RV32IFD-NEXT:    sw a3, 12(sp)
542; RV32IFD-NEXT:    fld ft2, 8(sp)
543; RV32IFD-NEXT:    fcvt.d.w ft3, zero
544; RV32IFD-NEXT:    fadd.d ft2, ft2, ft3
545; RV32IFD-NEXT:    fadd.d ft1, ft1, ft3
546; RV32IFD-NEXT:    fnmadd.d ft0, ft2, ft0, ft1
547; RV32IFD-NEXT:    fsd ft0, 8(sp)
548; RV32IFD-NEXT:    lw a0, 8(sp)
549; RV32IFD-NEXT:    lw a1, 12(sp)
550; RV32IFD-NEXT:    addi sp, sp, 16
551; RV32IFD-NEXT:    ret
552;
553; RV64IFD-LABEL: fnmadd_d_2:
554; RV64IFD:       # %bb.0:
555; RV64IFD-NEXT:    fmv.d.x ft0, a0
556; RV64IFD-NEXT:    fmv.d.x ft1, a2
557; RV64IFD-NEXT:    fmv.d.x ft2, a1
558; RV64IFD-NEXT:    fmv.d.x ft3, zero
559; RV64IFD-NEXT:    fadd.d ft2, ft2, ft3
560; RV64IFD-NEXT:    fadd.d ft1, ft1, ft3
561; RV64IFD-NEXT:    fnmadd.d ft0, ft2, ft0, ft1
562; RV64IFD-NEXT:    fmv.x.d a0, ft0
563; RV64IFD-NEXT:    ret
564  %b_ = fadd double 0.0, %b
565  %c_ = fadd double 0.0, %c
566  %negb = fsub double -0.0, %b_
567  %negc = fsub double -0.0, %c_
568  %1 = call double @llvm.fma.f64(double %a, double %negb, double %negc)
569  ret double %1
570}
571
572define double @fnmsub_d(double %a, double %b, double %c) nounwind {
573; RV32IFD-LABEL: fnmsub_d:
574; RV32IFD:       # %bb.0:
575; RV32IFD-NEXT:    addi sp, sp, -16
576; RV32IFD-NEXT:    sw a4, 8(sp)
577; RV32IFD-NEXT:    sw a5, 12(sp)
578; RV32IFD-NEXT:    fld ft0, 8(sp)
579; RV32IFD-NEXT:    sw a2, 8(sp)
580; RV32IFD-NEXT:    sw a3, 12(sp)
581; RV32IFD-NEXT:    fld ft1, 8(sp)
582; RV32IFD-NEXT:    sw a0, 8(sp)
583; RV32IFD-NEXT:    sw a1, 12(sp)
584; RV32IFD-NEXT:    fld ft2, 8(sp)
585; RV32IFD-NEXT:    fcvt.d.w ft3, zero
586; RV32IFD-NEXT:    fadd.d ft2, ft2, ft3
587; RV32IFD-NEXT:    fnmsub.d ft0, ft2, ft1, ft0
588; RV32IFD-NEXT:    fsd ft0, 8(sp)
589; RV32IFD-NEXT:    lw a0, 8(sp)
590; RV32IFD-NEXT:    lw a1, 12(sp)
591; RV32IFD-NEXT:    addi sp, sp, 16
592; RV32IFD-NEXT:    ret
593;
594; RV64IFD-LABEL: fnmsub_d:
595; RV64IFD:       # %bb.0:
596; RV64IFD-NEXT:    fmv.d.x ft0, a2
597; RV64IFD-NEXT:    fmv.d.x ft1, a1
598; RV64IFD-NEXT:    fmv.d.x ft2, a0
599; RV64IFD-NEXT:    fmv.d.x ft3, zero
600; RV64IFD-NEXT:    fadd.d ft2, ft2, ft3
601; RV64IFD-NEXT:    fnmsub.d ft0, ft2, ft1, ft0
602; RV64IFD-NEXT:    fmv.x.d a0, ft0
603; RV64IFD-NEXT:    ret
604  %a_ = fadd double 0.0, %a
605  %nega = fsub double -0.0, %a_
606  %1 = call double @llvm.fma.f64(double %nega, double %b, double %c)
607  ret double %1
608}
609
610define double @fnmsub_d_2(double %a, double %b, double %c) nounwind {
611; RV32IFD-LABEL: fnmsub_d_2:
612; RV32IFD:       # %bb.0:
613; RV32IFD-NEXT:    addi sp, sp, -16
614; RV32IFD-NEXT:    sw a4, 8(sp)
615; RV32IFD-NEXT:    sw a5, 12(sp)
616; RV32IFD-NEXT:    fld ft0, 8(sp)
617; RV32IFD-NEXT:    sw a0, 8(sp)
618; RV32IFD-NEXT:    sw a1, 12(sp)
619; RV32IFD-NEXT:    fld ft1, 8(sp)
620; RV32IFD-NEXT:    sw a2, 8(sp)
621; RV32IFD-NEXT:    sw a3, 12(sp)
622; RV32IFD-NEXT:    fld ft2, 8(sp)
623; RV32IFD-NEXT:    fcvt.d.w ft3, zero
624; RV32IFD-NEXT:    fadd.d ft2, ft2, ft3
625; RV32IFD-NEXT:    fnmsub.d ft0, ft2, ft1, ft0
626; RV32IFD-NEXT:    fsd ft0, 8(sp)
627; RV32IFD-NEXT:    lw a0, 8(sp)
628; RV32IFD-NEXT:    lw a1, 12(sp)
629; RV32IFD-NEXT:    addi sp, sp, 16
630; RV32IFD-NEXT:    ret
631;
632; RV64IFD-LABEL: fnmsub_d_2:
633; RV64IFD:       # %bb.0:
634; RV64IFD-NEXT:    fmv.d.x ft0, a2
635; RV64IFD-NEXT:    fmv.d.x ft1, a0
636; RV64IFD-NEXT:    fmv.d.x ft2, a1
637; RV64IFD-NEXT:    fmv.d.x ft3, zero
638; RV64IFD-NEXT:    fadd.d ft2, ft2, ft3
639; RV64IFD-NEXT:    fnmsub.d ft0, ft2, ft1, ft0
640; RV64IFD-NEXT:    fmv.x.d a0, ft0
641; RV64IFD-NEXT:    ret
642  %b_ = fadd double 0.0, %b
643  %negb = fsub double -0.0, %b_
644  %1 = call double @llvm.fma.f64(double %a, double %negb, double %c)
645  ret double %1
646}
647
648define double @fmadd_d_contract(double %a, double %b, double %c) nounwind {
649; RV32IFD-LABEL: fmadd_d_contract:
650; RV32IFD:       # %bb.0:
651; RV32IFD-NEXT:    addi sp, sp, -16
652; RV32IFD-NEXT:    sw a4, 8(sp)
653; RV32IFD-NEXT:    sw a5, 12(sp)
654; RV32IFD-NEXT:    fld ft0, 8(sp)
655; RV32IFD-NEXT:    sw a2, 8(sp)
656; RV32IFD-NEXT:    sw a3, 12(sp)
657; RV32IFD-NEXT:    fld ft1, 8(sp)
658; RV32IFD-NEXT:    sw a0, 8(sp)
659; RV32IFD-NEXT:    sw a1, 12(sp)
660; RV32IFD-NEXT:    fld ft2, 8(sp)
661; RV32IFD-NEXT:    fmadd.d ft0, ft2, ft1, ft0
662; RV32IFD-NEXT:    fsd ft0, 8(sp)
663; RV32IFD-NEXT:    lw a0, 8(sp)
664; RV32IFD-NEXT:    lw a1, 12(sp)
665; RV32IFD-NEXT:    addi sp, sp, 16
666; RV32IFD-NEXT:    ret
667;
668; RV64IFD-LABEL: fmadd_d_contract:
669; RV64IFD:       # %bb.0:
670; RV64IFD-NEXT:    fmv.d.x ft0, a2
671; RV64IFD-NEXT:    fmv.d.x ft1, a1
672; RV64IFD-NEXT:    fmv.d.x ft2, a0
673; RV64IFD-NEXT:    fmadd.d ft0, ft2, ft1, ft0
674; RV64IFD-NEXT:    fmv.x.d a0, ft0
675; RV64IFD-NEXT:    ret
676  %1 = fmul contract double %a, %b
677  %2 = fadd contract double %1, %c
678  ret double %2
679}
680
681define double @fmsub_d_contract(double %a, double %b, double %c) nounwind {
682; RV32IFD-LABEL: fmsub_d_contract:
683; RV32IFD:       # %bb.0:
684; RV32IFD-NEXT:    addi sp, sp, -16
685; RV32IFD-NEXT:    sw a2, 8(sp)
686; RV32IFD-NEXT:    sw a3, 12(sp)
687; RV32IFD-NEXT:    fld ft0, 8(sp)
688; RV32IFD-NEXT:    sw a0, 8(sp)
689; RV32IFD-NEXT:    sw a1, 12(sp)
690; RV32IFD-NEXT:    fld ft1, 8(sp)
691; RV32IFD-NEXT:    sw a4, 8(sp)
692; RV32IFD-NEXT:    sw a5, 12(sp)
693; RV32IFD-NEXT:    fld ft2, 8(sp)
694; RV32IFD-NEXT:    fcvt.d.w ft3, zero
695; RV32IFD-NEXT:    fadd.d ft2, ft2, ft3
696; RV32IFD-NEXT:    fmsub.d ft0, ft1, ft0, ft2
697; RV32IFD-NEXT:    fsd ft0, 8(sp)
698; RV32IFD-NEXT:    lw a0, 8(sp)
699; RV32IFD-NEXT:    lw a1, 12(sp)
700; RV32IFD-NEXT:    addi sp, sp, 16
701; RV32IFD-NEXT:    ret
702;
703; RV64IFD-LABEL: fmsub_d_contract:
704; RV64IFD:       # %bb.0:
705; RV64IFD-NEXT:    fmv.d.x ft0, a1
706; RV64IFD-NEXT:    fmv.d.x ft1, a0
707; RV64IFD-NEXT:    fmv.d.x ft2, a2
708; RV64IFD-NEXT:    fmv.d.x ft3, zero
709; RV64IFD-NEXT:    fadd.d ft2, ft2, ft3
710; RV64IFD-NEXT:    fmsub.d ft0, ft1, ft0, ft2
711; RV64IFD-NEXT:    fmv.x.d a0, ft0
712; RV64IFD-NEXT:    ret
713  %c_ = fadd double 0.0, %c ; avoid negation using xor
714  %1 = fmul contract double %a, %b
715  %2 = fsub contract double %1, %c_
716  ret double %2
717}
718
719define double @fnmadd_d_contract(double %a, double %b, double %c) nounwind {
720; RV32IFD-LABEL: fnmadd_d_contract:
721; RV32IFD:       # %bb.0:
722; RV32IFD-NEXT:    addi sp, sp, -16
723; RV32IFD-NEXT:    sw a4, 8(sp)
724; RV32IFD-NEXT:    sw a5, 12(sp)
725; RV32IFD-NEXT:    fld ft0, 8(sp)
726; RV32IFD-NEXT:    sw a2, 8(sp)
727; RV32IFD-NEXT:    sw a3, 12(sp)
728; RV32IFD-NEXT:    fld ft1, 8(sp)
729; RV32IFD-NEXT:    sw a0, 8(sp)
730; RV32IFD-NEXT:    sw a1, 12(sp)
731; RV32IFD-NEXT:    fld ft2, 8(sp)
732; RV32IFD-NEXT:    fcvt.d.w ft3, zero
733; RV32IFD-NEXT:    fadd.d ft2, ft2, ft3
734; RV32IFD-NEXT:    fadd.d ft1, ft1, ft3
735; RV32IFD-NEXT:    fadd.d ft0, ft0, ft3
736; RV32IFD-NEXT:    fnmadd.d ft0, ft2, ft1, ft0
737; RV32IFD-NEXT:    fsd ft0, 8(sp)
738; RV32IFD-NEXT:    lw a0, 8(sp)
739; RV32IFD-NEXT:    lw a1, 12(sp)
740; RV32IFD-NEXT:    addi sp, sp, 16
741; RV32IFD-NEXT:    ret
742;
743; RV64IFD-LABEL: fnmadd_d_contract:
744; RV64IFD:       # %bb.0:
745; RV64IFD-NEXT:    fmv.d.x ft0, a2
746; RV64IFD-NEXT:    fmv.d.x ft1, a1
747; RV64IFD-NEXT:    fmv.d.x ft2, a0
748; RV64IFD-NEXT:    fmv.d.x ft3, zero
749; RV64IFD-NEXT:    fadd.d ft2, ft2, ft3
750; RV64IFD-NEXT:    fadd.d ft1, ft1, ft3
751; RV64IFD-NEXT:    fadd.d ft0, ft0, ft3
752; RV64IFD-NEXT:    fnmadd.d ft0, ft2, ft1, ft0
753; RV64IFD-NEXT:    fmv.x.d a0, ft0
754; RV64IFD-NEXT:    ret
755  %a_ = fadd double 0.0, %a ; avoid negation using xor
756  %b_ = fadd double 0.0, %b ; avoid negation using xor
757  %c_ = fadd double 0.0, %c ; avoid negation using xor
758  %1 = fmul contract double %a_, %b_
759  %2 = fneg double %1
760  %3 = fsub contract double %2, %c_
761  ret double %3
762}
763
764define double @fnmsub_d_contract(double %a, double %b, double %c) nounwind {
765; RV32IFD-LABEL: fnmsub_d_contract:
766; RV32IFD:       # %bb.0:
767; RV32IFD-NEXT:    addi sp, sp, -16
768; RV32IFD-NEXT:    sw a4, 8(sp)
769; RV32IFD-NEXT:    sw a5, 12(sp)
770; RV32IFD-NEXT:    fld ft0, 8(sp)
771; RV32IFD-NEXT:    sw a2, 8(sp)
772; RV32IFD-NEXT:    sw a3, 12(sp)
773; RV32IFD-NEXT:    fld ft1, 8(sp)
774; RV32IFD-NEXT:    sw a0, 8(sp)
775; RV32IFD-NEXT:    sw a1, 12(sp)
776; RV32IFD-NEXT:    fld ft2, 8(sp)
777; RV32IFD-NEXT:    fcvt.d.w ft3, zero
778; RV32IFD-NEXT:    fadd.d ft2, ft2, ft3
779; RV32IFD-NEXT:    fadd.d ft1, ft1, ft3
780; RV32IFD-NEXT:    fnmsub.d ft0, ft2, ft1, ft0
781; RV32IFD-NEXT:    fsd ft0, 8(sp)
782; RV32IFD-NEXT:    lw a0, 8(sp)
783; RV32IFD-NEXT:    lw a1, 12(sp)
784; RV32IFD-NEXT:    addi sp, sp, 16
785; RV32IFD-NEXT:    ret
786;
787; RV64IFD-LABEL: fnmsub_d_contract:
788; RV64IFD:       # %bb.0:
789; RV64IFD-NEXT:    fmv.d.x ft0, a2
790; RV64IFD-NEXT:    fmv.d.x ft1, a1
791; RV64IFD-NEXT:    fmv.d.x ft2, a0
792; RV64IFD-NEXT:    fmv.d.x ft3, zero
793; RV64IFD-NEXT:    fadd.d ft2, ft2, ft3
794; RV64IFD-NEXT:    fadd.d ft1, ft1, ft3
795; RV64IFD-NEXT:    fnmsub.d ft0, ft2, ft1, ft0
796; RV64IFD-NEXT:    fmv.x.d a0, ft0
797; RV64IFD-NEXT:    ret
798  %a_ = fadd double 0.0, %a ; avoid negation using xor
799  %b_ = fadd double 0.0, %b ; avoid negation using xor
800  %1 = fmul contract double %a_, %b_
801  %2 = fsub contract double %c, %1
802  ret double %2
803}
804