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