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