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:    lui a0, %hi(.LCPI15_0)
464; RV32IFD-NEXT:    addi a0, a0, %lo(.LCPI15_0)
465; RV32IFD-NEXT:    fld ft3, 0(a0)
466; RV32IFD-NEXT:    fadd.d ft2, ft2, ft3
467; RV32IFD-NEXT:    fmsub.d ft0, ft1, ft0, ft2
468; RV32IFD-NEXT:    fsd ft0, 8(sp)
469; RV32IFD-NEXT:    lw a0, 8(sp)
470; RV32IFD-NEXT:    lw a1, 12(sp)
471; RV32IFD-NEXT:    addi sp, sp, 16
472; RV32IFD-NEXT:    ret
473;
474; RV64IFD-LABEL: fmsub_d:
475; RV64IFD:       # %bb.0:
476; RV64IFD-NEXT:    fmv.d.x ft0, a2
477; RV64IFD-NEXT:    lui a2, %hi(.LCPI15_0)
478; RV64IFD-NEXT:    addi a2, a2, %lo(.LCPI15_0)
479; RV64IFD-NEXT:    fld ft1, 0(a2)
480; RV64IFD-NEXT:    fadd.d ft0, ft0, ft1
481; RV64IFD-NEXT:    fmv.d.x ft1, a1
482; RV64IFD-NEXT:    fmv.d.x ft2, a0
483; RV64IFD-NEXT:    fmsub.d ft0, ft2, ft1, ft0
484; RV64IFD-NEXT:    fmv.x.d a0, ft0
485; RV64IFD-NEXT:    ret
486  %c_ = fadd double 0.0, %c ; avoid negation using xor
487  %negc = fsub double -0.0, %c_
488  %1 = call double @llvm.fma.f64(double %a, double %b, double %negc)
489  ret double %1
490}
491
492define double @fnmadd_d(double %a, double %b, double %c) nounwind {
493; RV32IFD-LABEL: fnmadd_d:
494; RV32IFD:       # %bb.0:
495; RV32IFD-NEXT:    addi sp, sp, -16
496; RV32IFD-NEXT:    sw a2, 8(sp)
497; RV32IFD-NEXT:    sw a3, 12(sp)
498; RV32IFD-NEXT:    fld ft0, 8(sp)
499; RV32IFD-NEXT:    sw a0, 8(sp)
500; RV32IFD-NEXT:    sw a1, 12(sp)
501; RV32IFD-NEXT:    fld ft1, 8(sp)
502; RV32IFD-NEXT:    sw a4, 8(sp)
503; RV32IFD-NEXT:    sw a5, 12(sp)
504; RV32IFD-NEXT:    fld ft2, 8(sp)
505; RV32IFD-NEXT:    lui a0, %hi(.LCPI16_0)
506; RV32IFD-NEXT:    addi a0, a0, %lo(.LCPI16_0)
507; RV32IFD-NEXT:    fld ft3, 0(a0)
508; RV32IFD-NEXT:    fadd.d ft2, ft2, ft3
509; RV32IFD-NEXT:    fadd.d ft1, ft1, ft3
510; RV32IFD-NEXT:    fnmadd.d ft0, ft1, ft0, ft2
511; RV32IFD-NEXT:    fsd ft0, 8(sp)
512; RV32IFD-NEXT:    lw a0, 8(sp)
513; RV32IFD-NEXT:    lw a1, 12(sp)
514; RV32IFD-NEXT:    addi sp, sp, 16
515; RV32IFD-NEXT:    ret
516;
517; RV64IFD-LABEL: fnmadd_d:
518; RV64IFD:       # %bb.0:
519; RV64IFD-NEXT:    fmv.d.x ft0, a2
520; RV64IFD-NEXT:    lui a2, %hi(.LCPI16_0)
521; RV64IFD-NEXT:    addi a2, a2, %lo(.LCPI16_0)
522; RV64IFD-NEXT:    fld ft1, 0(a2)
523; RV64IFD-NEXT:    fadd.d ft0, ft0, ft1
524; RV64IFD-NEXT:    fmv.d.x ft2, a0
525; RV64IFD-NEXT:    fadd.d ft1, ft2, ft1
526; RV64IFD-NEXT:    fmv.d.x ft2, a1
527; RV64IFD-NEXT:    fnmadd.d ft0, ft1, ft2, ft0
528; RV64IFD-NEXT:    fmv.x.d a0, ft0
529; RV64IFD-NEXT:    ret
530  %a_ = fadd double 0.0, %a
531  %c_ = fadd double 0.0, %c
532  %nega = fsub double -0.0, %a_
533  %negc = fsub double -0.0, %c_
534  %1 = call double @llvm.fma.f64(double %nega, double %b, double %negc)
535  ret double %1
536}
537
538define double @fnmsub_d(double %a, double %b, double %c) nounwind {
539; RV32IFD-LABEL: fnmsub_d:
540; RV32IFD:       # %bb.0:
541; RV32IFD-NEXT:    addi sp, sp, -16
542; RV32IFD-NEXT:    sw a4, 8(sp)
543; RV32IFD-NEXT:    sw a5, 12(sp)
544; RV32IFD-NEXT:    fld ft0, 8(sp)
545; RV32IFD-NEXT:    sw a2, 8(sp)
546; RV32IFD-NEXT:    sw a3, 12(sp)
547; RV32IFD-NEXT:    fld ft1, 8(sp)
548; RV32IFD-NEXT:    sw a0, 8(sp)
549; RV32IFD-NEXT:    sw a1, 12(sp)
550; RV32IFD-NEXT:    fld ft2, 8(sp)
551; RV32IFD-NEXT:    lui a0, %hi(.LCPI17_0)
552; RV32IFD-NEXT:    addi a0, a0, %lo(.LCPI17_0)
553; RV32IFD-NEXT:    fld ft3, 0(a0)
554; RV32IFD-NEXT:    fadd.d ft2, ft2, ft3
555; RV32IFD-NEXT:    fnmsub.d ft0, ft2, ft1, ft0
556; RV32IFD-NEXT:    fsd ft0, 8(sp)
557; RV32IFD-NEXT:    lw a0, 8(sp)
558; RV32IFD-NEXT:    lw a1, 12(sp)
559; RV32IFD-NEXT:    addi sp, sp, 16
560; RV32IFD-NEXT:    ret
561;
562; RV64IFD-LABEL: fnmsub_d:
563; RV64IFD:       # %bb.0:
564; RV64IFD-NEXT:    fmv.d.x ft0, a0
565; RV64IFD-NEXT:    lui a0, %hi(.LCPI17_0)
566; RV64IFD-NEXT:    addi a0, a0, %lo(.LCPI17_0)
567; RV64IFD-NEXT:    fld ft1, 0(a0)
568; RV64IFD-NEXT:    fadd.d ft0, ft0, ft1
569; RV64IFD-NEXT:    fmv.d.x ft1, a2
570; RV64IFD-NEXT:    fmv.d.x ft2, a1
571; RV64IFD-NEXT:    fnmsub.d ft0, ft0, ft2, ft1
572; RV64IFD-NEXT:    fmv.x.d a0, ft0
573; RV64IFD-NEXT:    ret
574  %a_ = fadd double 0.0, %a
575  %nega = fsub double -0.0, %a_
576  %1 = call double @llvm.fma.f64(double %nega, double %b, double %c)
577  ret double %1
578}
579