xref: /llvm-project/llvm/test/CodeGen/RISCV/double-arith.ll (revision 9122c5235ec85ce0c0ad337e862b006e7b349d84)
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-prefixes=CHECKIFD,RV32IFD %s
4; RUN: llc -mtriple=riscv64 -mattr=+d -verify-machineinstrs < %s \
5; RUN:   -target-abi=lp64d | FileCheck -check-prefixes=CHECKIFD,RV64IFD %s
6; RUN: llc -mtriple=riscv32 -mattr=+zdinx -verify-machineinstrs < %s \
7; RUN:   -target-abi=ilp32 | FileCheck -check-prefix=RV32IZFINXZDINX %s
8; RUN: llc -mtriple=riscv64 -mattr=+zdinx -verify-machineinstrs < %s \
9; RUN:   -target-abi=lp64 | FileCheck -check-prefix=RV64IZFINXZDINX %s
10; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
11; RUN:   | FileCheck -check-prefix=RV32I %s
12; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
13; RUN:   | FileCheck -check-prefix=RV64I %s
14
15; These tests are each targeted at a particular RISC-V FPU instruction.
16; Compares and conversions can be found in double-fcmp.ll and double-convert.ll
17; respectively. Some other double-*.ll files in this folder exercise LLVM IR
18; instructions that don't directly match a RISC-V instruction.
19
20define double @fadd_d(double %a, double %b) nounwind {
21; CHECKIFD-LABEL: fadd_d:
22; CHECKIFD:       # %bb.0:
23; CHECKIFD-NEXT:    fadd.d fa0, fa0, fa1
24; CHECKIFD-NEXT:    ret
25;
26; RV32IZFINXZDINX-LABEL: fadd_d:
27; RV32IZFINXZDINX:       # %bb.0:
28; RV32IZFINXZDINX-NEXT:    fadd.d a0, a0, a2
29; RV32IZFINXZDINX-NEXT:    ret
30;
31; RV64IZFINXZDINX-LABEL: fadd_d:
32; RV64IZFINXZDINX:       # %bb.0:
33; RV64IZFINXZDINX-NEXT:    fadd.d a0, a0, a1
34; RV64IZFINXZDINX-NEXT:    ret
35;
36; RV32I-LABEL: fadd_d:
37; RV32I:       # %bb.0:
38; RV32I-NEXT:    addi sp, sp, -16
39; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
40; RV32I-NEXT:    call __adddf3
41; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
42; RV32I-NEXT:    addi sp, sp, 16
43; RV32I-NEXT:    ret
44;
45; RV64I-LABEL: fadd_d:
46; RV64I:       # %bb.0:
47; RV64I-NEXT:    addi sp, sp, -16
48; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
49; RV64I-NEXT:    call __adddf3
50; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
51; RV64I-NEXT:    addi sp, sp, 16
52; RV64I-NEXT:    ret
53  %1 = fadd double %a, %b
54  ret double %1
55}
56
57define double @fsub_d(double %a, double %b) nounwind {
58; CHECKIFD-LABEL: fsub_d:
59; CHECKIFD:       # %bb.0:
60; CHECKIFD-NEXT:    fsub.d fa0, fa0, fa1
61; CHECKIFD-NEXT:    ret
62;
63; RV32IZFINXZDINX-LABEL: fsub_d:
64; RV32IZFINXZDINX:       # %bb.0:
65; RV32IZFINXZDINX-NEXT:    fsub.d a0, a0, a2
66; RV32IZFINXZDINX-NEXT:    ret
67;
68; RV64IZFINXZDINX-LABEL: fsub_d:
69; RV64IZFINXZDINX:       # %bb.0:
70; RV64IZFINXZDINX-NEXT:    fsub.d a0, a0, a1
71; RV64IZFINXZDINX-NEXT:    ret
72;
73; RV32I-LABEL: fsub_d:
74; RV32I:       # %bb.0:
75; RV32I-NEXT:    addi sp, sp, -16
76; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
77; RV32I-NEXT:    call __subdf3
78; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
79; RV32I-NEXT:    addi sp, sp, 16
80; RV32I-NEXT:    ret
81;
82; RV64I-LABEL: fsub_d:
83; RV64I:       # %bb.0:
84; RV64I-NEXT:    addi sp, sp, -16
85; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
86; RV64I-NEXT:    call __subdf3
87; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
88; RV64I-NEXT:    addi sp, sp, 16
89; RV64I-NEXT:    ret
90  %1 = fsub double %a, %b
91  ret double %1
92}
93
94define double @fmul_d(double %a, double %b) nounwind {
95; CHECKIFD-LABEL: fmul_d:
96; CHECKIFD:       # %bb.0:
97; CHECKIFD-NEXT:    fmul.d fa0, fa0, fa1
98; CHECKIFD-NEXT:    ret
99;
100; RV32IZFINXZDINX-LABEL: fmul_d:
101; RV32IZFINXZDINX:       # %bb.0:
102; RV32IZFINXZDINX-NEXT:    fmul.d a0, a0, a2
103; RV32IZFINXZDINX-NEXT:    ret
104;
105; RV64IZFINXZDINX-LABEL: fmul_d:
106; RV64IZFINXZDINX:       # %bb.0:
107; RV64IZFINXZDINX-NEXT:    fmul.d a0, a0, a1
108; RV64IZFINXZDINX-NEXT:    ret
109;
110; RV32I-LABEL: fmul_d:
111; RV32I:       # %bb.0:
112; RV32I-NEXT:    addi sp, sp, -16
113; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
114; RV32I-NEXT:    call __muldf3
115; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
116; RV32I-NEXT:    addi sp, sp, 16
117; RV32I-NEXT:    ret
118;
119; RV64I-LABEL: fmul_d:
120; RV64I:       # %bb.0:
121; RV64I-NEXT:    addi sp, sp, -16
122; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
123; RV64I-NEXT:    call __muldf3
124; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
125; RV64I-NEXT:    addi sp, sp, 16
126; RV64I-NEXT:    ret
127  %1 = fmul double %a, %b
128  ret double %1
129}
130
131define double @fdiv_d(double %a, double %b) nounwind {
132; CHECKIFD-LABEL: fdiv_d:
133; CHECKIFD:       # %bb.0:
134; CHECKIFD-NEXT:    fdiv.d fa0, fa0, fa1
135; CHECKIFD-NEXT:    ret
136;
137; RV32IZFINXZDINX-LABEL: fdiv_d:
138; RV32IZFINXZDINX:       # %bb.0:
139; RV32IZFINXZDINX-NEXT:    fdiv.d a0, a0, a2
140; RV32IZFINXZDINX-NEXT:    ret
141;
142; RV64IZFINXZDINX-LABEL: fdiv_d:
143; RV64IZFINXZDINX:       # %bb.0:
144; RV64IZFINXZDINX-NEXT:    fdiv.d a0, a0, a1
145; RV64IZFINXZDINX-NEXT:    ret
146;
147; RV32I-LABEL: fdiv_d:
148; RV32I:       # %bb.0:
149; RV32I-NEXT:    addi sp, sp, -16
150; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
151; RV32I-NEXT:    call __divdf3
152; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
153; RV32I-NEXT:    addi sp, sp, 16
154; RV32I-NEXT:    ret
155;
156; RV64I-LABEL: fdiv_d:
157; RV64I:       # %bb.0:
158; RV64I-NEXT:    addi sp, sp, -16
159; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
160; RV64I-NEXT:    call __divdf3
161; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
162; RV64I-NEXT:    addi sp, sp, 16
163; RV64I-NEXT:    ret
164  %1 = fdiv double %a, %b
165  ret double %1
166}
167
168declare double @llvm.sqrt.f64(double)
169
170define double @fsqrt_d(double %a) nounwind {
171; CHECKIFD-LABEL: fsqrt_d:
172; CHECKIFD:       # %bb.0:
173; CHECKIFD-NEXT:    fsqrt.d fa0, fa0
174; CHECKIFD-NEXT:    ret
175;
176; RV32IZFINXZDINX-LABEL: fsqrt_d:
177; RV32IZFINXZDINX:       # %bb.0:
178; RV32IZFINXZDINX-NEXT:    fsqrt.d a0, a0
179; RV32IZFINXZDINX-NEXT:    ret
180;
181; RV64IZFINXZDINX-LABEL: fsqrt_d:
182; RV64IZFINXZDINX:       # %bb.0:
183; RV64IZFINXZDINX-NEXT:    fsqrt.d a0, a0
184; RV64IZFINXZDINX-NEXT:    ret
185;
186; RV32I-LABEL: fsqrt_d:
187; RV32I:       # %bb.0:
188; RV32I-NEXT:    addi sp, sp, -16
189; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
190; RV32I-NEXT:    call sqrt
191; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
192; RV32I-NEXT:    addi sp, sp, 16
193; RV32I-NEXT:    ret
194;
195; RV64I-LABEL: fsqrt_d:
196; RV64I:       # %bb.0:
197; RV64I-NEXT:    addi sp, sp, -16
198; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
199; RV64I-NEXT:    call sqrt
200; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
201; RV64I-NEXT:    addi sp, sp, 16
202; RV64I-NEXT:    ret
203  %1 = call double @llvm.sqrt.f64(double %a)
204  ret double %1
205}
206
207declare double @llvm.copysign.f64(double, double)
208
209define double @fsgnj_d(double %a, double %b) nounwind {
210; CHECKIFD-LABEL: fsgnj_d:
211; CHECKIFD:       # %bb.0:
212; CHECKIFD-NEXT:    fsgnj.d fa0, fa0, fa1
213; CHECKIFD-NEXT:    ret
214;
215; RV32IZFINXZDINX-LABEL: fsgnj_d:
216; RV32IZFINXZDINX:       # %bb.0:
217; RV32IZFINXZDINX-NEXT:    fsgnj.d a0, a0, a2
218; RV32IZFINXZDINX-NEXT:    ret
219;
220; RV64IZFINXZDINX-LABEL: fsgnj_d:
221; RV64IZFINXZDINX:       # %bb.0:
222; RV64IZFINXZDINX-NEXT:    fsgnj.d a0, a0, a1
223; RV64IZFINXZDINX-NEXT:    ret
224;
225; RV32I-LABEL: fsgnj_d:
226; RV32I:       # %bb.0:
227; RV32I-NEXT:    lui a2, 524288
228; RV32I-NEXT:    slli a1, a1, 1
229; RV32I-NEXT:    and a2, a3, a2
230; RV32I-NEXT:    srli a1, a1, 1
231; RV32I-NEXT:    or a1, a1, a2
232; RV32I-NEXT:    ret
233;
234; RV64I-LABEL: fsgnj_d:
235; RV64I:       # %bb.0:
236; RV64I-NEXT:    srli a1, a1, 63
237; RV64I-NEXT:    slli a0, a0, 1
238; RV64I-NEXT:    slli a1, a1, 63
239; RV64I-NEXT:    srli a0, a0, 1
240; RV64I-NEXT:    or a0, a0, a1
241; RV64I-NEXT:    ret
242  %1 = call double @llvm.copysign.f64(double %a, double %b)
243  ret double %1
244}
245
246; This function performs extra work to ensure that
247; DAGCombiner::visitBITCAST doesn't replace the fneg with an xor.
248define i32 @fneg_d(double %a, double %b) nounwind {
249; CHECKIFD-LABEL: fneg_d:
250; CHECKIFD:       # %bb.0:
251; CHECKIFD-NEXT:    fadd.d fa5, fa0, fa0
252; CHECKIFD-NEXT:    fneg.d fa4, fa5
253; CHECKIFD-NEXT:    feq.d a0, fa5, fa4
254; CHECKIFD-NEXT:    ret
255;
256; RV32IZFINXZDINX-LABEL: fneg_d:
257; RV32IZFINXZDINX:       # %bb.0:
258; RV32IZFINXZDINX-NEXT:    fadd.d a0, a0, a0
259; RV32IZFINXZDINX-NEXT:    fneg.d a2, a0
260; RV32IZFINXZDINX-NEXT:    feq.d a0, a0, a2
261; RV32IZFINXZDINX-NEXT:    ret
262;
263; RV64IZFINXZDINX-LABEL: fneg_d:
264; RV64IZFINXZDINX:       # %bb.0:
265; RV64IZFINXZDINX-NEXT:    fadd.d a0, a0, a0
266; RV64IZFINXZDINX-NEXT:    fneg.d a1, a0
267; RV64IZFINXZDINX-NEXT:    feq.d a0, a0, a1
268; RV64IZFINXZDINX-NEXT:    ret
269;
270; RV32I-LABEL: fneg_d:
271; RV32I:       # %bb.0:
272; RV32I-NEXT:    addi sp, sp, -16
273; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
274; RV32I-NEXT:    mv a2, a0
275; RV32I-NEXT:    mv a3, a1
276; RV32I-NEXT:    call __adddf3
277; RV32I-NEXT:    lui a3, 524288
278; RV32I-NEXT:    xor a3, a1, a3
279; RV32I-NEXT:    mv a2, a0
280; RV32I-NEXT:    call __eqdf2
281; RV32I-NEXT:    seqz a0, a0
282; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
283; RV32I-NEXT:    addi sp, sp, 16
284; RV32I-NEXT:    ret
285;
286; RV64I-LABEL: fneg_d:
287; RV64I:       # %bb.0:
288; RV64I-NEXT:    addi sp, sp, -16
289; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
290; RV64I-NEXT:    mv a1, a0
291; RV64I-NEXT:    call __adddf3
292; RV64I-NEXT:    li a1, -1
293; RV64I-NEXT:    slli a1, a1, 63
294; RV64I-NEXT:    xor a1, a0, a1
295; RV64I-NEXT:    call __eqdf2
296; RV64I-NEXT:    seqz a0, a0
297; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
298; RV64I-NEXT:    addi sp, sp, 16
299; RV64I-NEXT:    ret
300  %1 = fadd double %a, %a
301  %2 = fneg double %1
302  %3 = fcmp oeq double %1, %2
303  %4 = zext i1 %3 to i32
304  ret i32 %4
305}
306
307define double @fsgnjn_d(double %a, double %b) nounwind {
308; TODO: fsgnjn.s isn't selected on RV64 because DAGCombiner::visitBITCAST will
309; convert (bitconvert (fneg x)) to a xor.
310;
311; CHECKIFD-LABEL: fsgnjn_d:
312; CHECKIFD:       # %bb.0:
313; CHECKIFD-NEXT:    fsgnjn.d fa0, fa0, fa1
314; CHECKIFD-NEXT:    ret
315;
316; RV32IZFINXZDINX-LABEL: fsgnjn_d:
317; RV32IZFINXZDINX:       # %bb.0:
318; RV32IZFINXZDINX-NEXT:    fsgnjn.d a0, a0, a2
319; RV32IZFINXZDINX-NEXT:    ret
320;
321; RV64IZFINXZDINX-LABEL: fsgnjn_d:
322; RV64IZFINXZDINX:       # %bb.0:
323; RV64IZFINXZDINX-NEXT:    fsgnjn.d a0, a0, a1
324; RV64IZFINXZDINX-NEXT:    ret
325;
326; RV32I-LABEL: fsgnjn_d:
327; RV32I:       # %bb.0:
328; RV32I-NEXT:    not a2, a3
329; RV32I-NEXT:    lui a3, 524288
330; RV32I-NEXT:    slli a1, a1, 1
331; RV32I-NEXT:    and a2, a2, a3
332; RV32I-NEXT:    srli a1, a1, 1
333; RV32I-NEXT:    or a1, a1, a2
334; RV32I-NEXT:    ret
335;
336; RV64I-LABEL: fsgnjn_d:
337; RV64I:       # %bb.0:
338; RV64I-NEXT:    not a1, a1
339; RV64I-NEXT:    slli a0, a0, 1
340; RV64I-NEXT:    srli a0, a0, 1
341; RV64I-NEXT:    srli a1, a1, 63
342; RV64I-NEXT:    slli a1, a1, 63
343; RV64I-NEXT:    or a0, a0, a1
344; RV64I-NEXT:    ret
345  %1 = fsub double -0.0, %b
346  %2 = call double @llvm.copysign.f64(double %a, double %1)
347  ret double %2
348}
349
350declare double @llvm.fabs.f64(double)
351
352; This function performs extra work to ensure that
353; DAGCombiner::visitBITCAST doesn't replace the fabs with an and.
354define double @fabs_d(double %a, double %b) nounwind {
355; CHECKIFD-LABEL: fabs_d:
356; CHECKIFD:       # %bb.0:
357; CHECKIFD-NEXT:    fadd.d fa5, fa0, fa1
358; CHECKIFD-NEXT:    fabs.d fa4, fa5
359; CHECKIFD-NEXT:    fadd.d fa0, fa4, fa5
360; CHECKIFD-NEXT:    ret
361;
362; RV32IZFINXZDINX-LABEL: fabs_d:
363; RV32IZFINXZDINX:       # %bb.0:
364; RV32IZFINXZDINX-NEXT:    fadd.d a0, a0, a2
365; RV32IZFINXZDINX-NEXT:    fabs.d a2, a0
366; RV32IZFINXZDINX-NEXT:    fadd.d a0, a2, a0
367; RV32IZFINXZDINX-NEXT:    ret
368;
369; RV64IZFINXZDINX-LABEL: fabs_d:
370; RV64IZFINXZDINX:       # %bb.0:
371; RV64IZFINXZDINX-NEXT:    fadd.d a0, a0, a1
372; RV64IZFINXZDINX-NEXT:    fabs.d a1, a0
373; RV64IZFINXZDINX-NEXT:    fadd.d a0, a1, a0
374; RV64IZFINXZDINX-NEXT:    ret
375;
376; RV32I-LABEL: fabs_d:
377; RV32I:       # %bb.0:
378; RV32I-NEXT:    addi sp, sp, -16
379; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
380; RV32I-NEXT:    call __adddf3
381; RV32I-NEXT:    mv a3, a1
382; RV32I-NEXT:    slli a1, a1, 1
383; RV32I-NEXT:    srli a1, a1, 1
384; RV32I-NEXT:    mv a2, a0
385; RV32I-NEXT:    call __adddf3
386; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
387; RV32I-NEXT:    addi sp, sp, 16
388; RV32I-NEXT:    ret
389;
390; RV64I-LABEL: fabs_d:
391; RV64I:       # %bb.0:
392; RV64I-NEXT:    addi sp, sp, -16
393; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
394; RV64I-NEXT:    call __adddf3
395; RV64I-NEXT:    mv a1, a0
396; RV64I-NEXT:    slli a0, a0, 1
397; RV64I-NEXT:    srli a0, a0, 1
398; RV64I-NEXT:    call __adddf3
399; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
400; RV64I-NEXT:    addi sp, sp, 16
401; RV64I-NEXT:    ret
402  %1 = fadd double %a, %b
403  %2 = call double @llvm.fabs.f64(double %1)
404  %3 = fadd double %2, %1
405  ret double %3
406}
407
408declare double @llvm.minnum.f64(double, double)
409
410define double @fmin_d(double %a, double %b) nounwind {
411; CHECKIFD-LABEL: fmin_d:
412; CHECKIFD:       # %bb.0:
413; CHECKIFD-NEXT:    fmin.d fa0, fa0, fa1
414; CHECKIFD-NEXT:    ret
415;
416; RV32IZFINXZDINX-LABEL: fmin_d:
417; RV32IZFINXZDINX:       # %bb.0:
418; RV32IZFINXZDINX-NEXT:    fmin.d a0, a0, a2
419; RV32IZFINXZDINX-NEXT:    ret
420;
421; RV64IZFINXZDINX-LABEL: fmin_d:
422; RV64IZFINXZDINX:       # %bb.0:
423; RV64IZFINXZDINX-NEXT:    fmin.d a0, a0, a1
424; RV64IZFINXZDINX-NEXT:    ret
425;
426; RV32I-LABEL: fmin_d:
427; RV32I:       # %bb.0:
428; RV32I-NEXT:    addi sp, sp, -16
429; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
430; RV32I-NEXT:    call fmin
431; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
432; RV32I-NEXT:    addi sp, sp, 16
433; RV32I-NEXT:    ret
434;
435; RV64I-LABEL: fmin_d:
436; RV64I:       # %bb.0:
437; RV64I-NEXT:    addi sp, sp, -16
438; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
439; RV64I-NEXT:    call fmin
440; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
441; RV64I-NEXT:    addi sp, sp, 16
442; RV64I-NEXT:    ret
443  %1 = call double @llvm.minnum.f64(double %a, double %b)
444  ret double %1
445}
446
447declare double @llvm.maxnum.f64(double, double)
448
449define double @fmax_d(double %a, double %b) nounwind {
450; CHECKIFD-LABEL: fmax_d:
451; CHECKIFD:       # %bb.0:
452; CHECKIFD-NEXT:    fmax.d fa0, fa0, fa1
453; CHECKIFD-NEXT:    ret
454;
455; RV32IZFINXZDINX-LABEL: fmax_d:
456; RV32IZFINXZDINX:       # %bb.0:
457; RV32IZFINXZDINX-NEXT:    fmax.d a0, a0, a2
458; RV32IZFINXZDINX-NEXT:    ret
459;
460; RV64IZFINXZDINX-LABEL: fmax_d:
461; RV64IZFINXZDINX:       # %bb.0:
462; RV64IZFINXZDINX-NEXT:    fmax.d a0, a0, a1
463; RV64IZFINXZDINX-NEXT:    ret
464;
465; RV32I-LABEL: fmax_d:
466; RV32I:       # %bb.0:
467; RV32I-NEXT:    addi sp, sp, -16
468; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
469; RV32I-NEXT:    call fmax
470; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
471; RV32I-NEXT:    addi sp, sp, 16
472; RV32I-NEXT:    ret
473;
474; RV64I-LABEL: fmax_d:
475; RV64I:       # %bb.0:
476; RV64I-NEXT:    addi sp, sp, -16
477; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
478; RV64I-NEXT:    call fmax
479; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
480; RV64I-NEXT:    addi sp, sp, 16
481; RV64I-NEXT:    ret
482  %1 = call double @llvm.maxnum.f64(double %a, double %b)
483  ret double %1
484}
485
486declare double @llvm.fma.f64(double, double, double)
487
488define double @fmadd_d(double %a, double %b, double %c) nounwind {
489; CHECKIFD-LABEL: fmadd_d:
490; CHECKIFD:       # %bb.0:
491; CHECKIFD-NEXT:    fmadd.d fa0, fa0, fa1, fa2
492; CHECKIFD-NEXT:    ret
493;
494; RV32IZFINXZDINX-LABEL: fmadd_d:
495; RV32IZFINXZDINX:       # %bb.0:
496; RV32IZFINXZDINX-NEXT:    fmadd.d a0, a0, a2, a4
497; RV32IZFINXZDINX-NEXT:    ret
498;
499; RV64IZFINXZDINX-LABEL: fmadd_d:
500; RV64IZFINXZDINX:       # %bb.0:
501; RV64IZFINXZDINX-NEXT:    fmadd.d a0, a0, a1, a2
502; RV64IZFINXZDINX-NEXT:    ret
503;
504; RV32I-LABEL: fmadd_d:
505; RV32I:       # %bb.0:
506; RV32I-NEXT:    addi sp, sp, -16
507; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
508; RV32I-NEXT:    call fma
509; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
510; RV32I-NEXT:    addi sp, sp, 16
511; RV32I-NEXT:    ret
512;
513; RV64I-LABEL: fmadd_d:
514; RV64I:       # %bb.0:
515; RV64I-NEXT:    addi sp, sp, -16
516; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
517; RV64I-NEXT:    call fma
518; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
519; RV64I-NEXT:    addi sp, sp, 16
520; RV64I-NEXT:    ret
521  %1 = call double @llvm.fma.f64(double %a, double %b, double %c)
522  ret double %1
523}
524
525define double @fmsub_d(double %a, double %b, double %c) nounwind {
526; RV32IFD-LABEL: fmsub_d:
527; RV32IFD:       # %bb.0:
528; RV32IFD-NEXT:    fcvt.d.w fa5, zero
529; RV32IFD-NEXT:    fadd.d fa5, fa2, fa5
530; RV32IFD-NEXT:    fmsub.d fa0, fa0, fa1, fa5
531; RV32IFD-NEXT:    ret
532;
533; RV64IFD-LABEL: fmsub_d:
534; RV64IFD:       # %bb.0:
535; RV64IFD-NEXT:    fmv.d.x fa5, zero
536; RV64IFD-NEXT:    fadd.d fa5, fa2, fa5
537; RV64IFD-NEXT:    fmsub.d fa0, fa0, fa1, fa5
538; RV64IFD-NEXT:    ret
539;
540; RV32IZFINXZDINX-LABEL: fmsub_d:
541; RV32IZFINXZDINX:       # %bb.0:
542; RV32IZFINXZDINX-NEXT:    fcvt.d.w a6, zero
543; RV32IZFINXZDINX-NEXT:    fadd.d a4, a4, a6
544; RV32IZFINXZDINX-NEXT:    fmsub.d a0, a0, a2, a4
545; RV32IZFINXZDINX-NEXT:    ret
546;
547; RV64IZFINXZDINX-LABEL: fmsub_d:
548; RV64IZFINXZDINX:       # %bb.0:
549; RV64IZFINXZDINX-NEXT:    fadd.d a2, a2, zero
550; RV64IZFINXZDINX-NEXT:    fmsub.d a0, a0, a1, a2
551; RV64IZFINXZDINX-NEXT:    ret
552;
553; RV32I-LABEL: fmsub_d:
554; RV32I:       # %bb.0:
555; RV32I-NEXT:    addi sp, sp, -32
556; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
557; RV32I-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
558; RV32I-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
559; RV32I-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
560; RV32I-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
561; RV32I-NEXT:    mv s0, a3
562; RV32I-NEXT:    mv s1, a2
563; RV32I-NEXT:    mv s2, a1
564; RV32I-NEXT:    mv s3, a0
565; RV32I-NEXT:    mv a0, a4
566; RV32I-NEXT:    mv a1, a5
567; RV32I-NEXT:    li a2, 0
568; RV32I-NEXT:    li a3, 0
569; RV32I-NEXT:    call __adddf3
570; RV32I-NEXT:    mv a4, a0
571; RV32I-NEXT:    lui a5, 524288
572; RV32I-NEXT:    xor a5, a1, a5
573; RV32I-NEXT:    mv a0, s3
574; RV32I-NEXT:    mv a1, s2
575; RV32I-NEXT:    mv a2, s1
576; RV32I-NEXT:    mv a3, s0
577; RV32I-NEXT:    call fma
578; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
579; RV32I-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
580; RV32I-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
581; RV32I-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
582; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
583; RV32I-NEXT:    addi sp, sp, 32
584; RV32I-NEXT:    ret
585;
586; RV64I-LABEL: fmsub_d:
587; RV64I:       # %bb.0:
588; RV64I-NEXT:    addi sp, sp, -32
589; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
590; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
591; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
592; RV64I-NEXT:    mv s0, a1
593; RV64I-NEXT:    mv s1, a0
594; RV64I-NEXT:    mv a0, a2
595; RV64I-NEXT:    li a1, 0
596; RV64I-NEXT:    call __adddf3
597; RV64I-NEXT:    li a1, -1
598; RV64I-NEXT:    slli a1, a1, 63
599; RV64I-NEXT:    xor a2, a0, a1
600; RV64I-NEXT:    mv a0, s1
601; RV64I-NEXT:    mv a1, s0
602; RV64I-NEXT:    call fma
603; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
604; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
605; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
606; RV64I-NEXT:    addi sp, sp, 32
607; RV64I-NEXT:    ret
608  %c_ = fadd double 0.0, %c ; avoid negation using xor
609  %negc = fsub double -0.0, %c_
610  %1 = call double @llvm.fma.f64(double %a, double %b, double %negc)
611  ret double %1
612}
613
614define double @fnmadd_d(double %a, double %b, double %c) nounwind {
615; RV32IFD-LABEL: fnmadd_d:
616; RV32IFD:       # %bb.0:
617; RV32IFD-NEXT:    fcvt.d.w fa5, zero
618; RV32IFD-NEXT:    fadd.d fa4, fa0, fa5
619; RV32IFD-NEXT:    fadd.d fa5, fa2, fa5
620; RV32IFD-NEXT:    fnmadd.d fa0, fa4, fa1, fa5
621; RV32IFD-NEXT:    ret
622;
623; RV64IFD-LABEL: fnmadd_d:
624; RV64IFD:       # %bb.0:
625; RV64IFD-NEXT:    fmv.d.x fa5, zero
626; RV64IFD-NEXT:    fadd.d fa4, fa0, fa5
627; RV64IFD-NEXT:    fadd.d fa5, fa2, fa5
628; RV64IFD-NEXT:    fnmadd.d fa0, fa4, fa1, fa5
629; RV64IFD-NEXT:    ret
630;
631; RV32IZFINXZDINX-LABEL: fnmadd_d:
632; RV32IZFINXZDINX:       # %bb.0:
633; RV32IZFINXZDINX-NEXT:    fcvt.d.w a6, zero
634; RV32IZFINXZDINX-NEXT:    fadd.d a0, a0, a6
635; RV32IZFINXZDINX-NEXT:    fadd.d a4, a4, a6
636; RV32IZFINXZDINX-NEXT:    fnmadd.d a0, a0, a2, a4
637; RV32IZFINXZDINX-NEXT:    ret
638;
639; RV64IZFINXZDINX-LABEL: fnmadd_d:
640; RV64IZFINXZDINX:       # %bb.0:
641; RV64IZFINXZDINX-NEXT:    fadd.d a0, a0, zero
642; RV64IZFINXZDINX-NEXT:    fadd.d a2, a2, zero
643; RV64IZFINXZDINX-NEXT:    fnmadd.d a0, a0, a1, a2
644; RV64IZFINXZDINX-NEXT:    ret
645;
646; RV32I-LABEL: fnmadd_d:
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, a3
659; RV32I-NEXT:    mv s3, a2
660; RV32I-NEXT:    li a2, 0
661; RV32I-NEXT:    li a3, 0
662; RV32I-NEXT:    call __adddf3
663; RV32I-NEXT:    mv s4, a0
664; RV32I-NEXT:    mv s5, a1
665; RV32I-NEXT:    mv a0, s1
666; RV32I-NEXT:    mv a1, s0
667; RV32I-NEXT:    li a2, 0
668; RV32I-NEXT:    li a3, 0
669; RV32I-NEXT:    call __adddf3
670; RV32I-NEXT:    mv a4, a0
671; RV32I-NEXT:    lui a5, 524288
672; RV32I-NEXT:    xor a2, s5, a5
673; RV32I-NEXT:    xor a5, a1, a5
674; RV32I-NEXT:    mv a0, s4
675; RV32I-NEXT:    mv a1, a2
676; RV32I-NEXT:    mv a2, s3
677; RV32I-NEXT:    mv a3, s2
678; RV32I-NEXT:    call fma
679; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
680; RV32I-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
681; RV32I-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
682; RV32I-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
683; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
684; RV32I-NEXT:    lw s4, 8(sp) # 4-byte Folded Reload
685; RV32I-NEXT:    lw s5, 4(sp) # 4-byte Folded Reload
686; RV32I-NEXT:    addi sp, sp, 32
687; RV32I-NEXT:    ret
688;
689; RV64I-LABEL: fnmadd_d:
690; RV64I:       # %bb.0:
691; RV64I-NEXT:    addi sp, sp, -32
692; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
693; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
694; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
695; RV64I-NEXT:    sd s2, 0(sp) # 8-byte Folded Spill
696; RV64I-NEXT:    mv s0, a2
697; RV64I-NEXT:    mv s1, a1
698; RV64I-NEXT:    li a1, 0
699; RV64I-NEXT:    call __adddf3
700; RV64I-NEXT:    mv s2, a0
701; RV64I-NEXT:    mv a0, s0
702; RV64I-NEXT:    li a1, 0
703; RV64I-NEXT:    call __adddf3
704; RV64I-NEXT:    li a1, -1
705; RV64I-NEXT:    slli a2, a1, 63
706; RV64I-NEXT:    xor a1, s2, a2
707; RV64I-NEXT:    xor a2, a0, a2
708; RV64I-NEXT:    mv a0, a1
709; RV64I-NEXT:    mv a1, s1
710; RV64I-NEXT:    call fma
711; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
712; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
713; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
714; RV64I-NEXT:    ld s2, 0(sp) # 8-byte Folded Reload
715; RV64I-NEXT:    addi sp, sp, 32
716; RV64I-NEXT:    ret
717  %a_ = fadd double 0.0, %a
718  %c_ = fadd double 0.0, %c
719  %nega = fsub double -0.0, %a_
720  %negc = fsub double -0.0, %c_
721  %1 = call double @llvm.fma.f64(double %nega, double %b, double %negc)
722  ret double %1
723}
724
725define double @fnmadd_d_2(double %a, double %b, double %c) nounwind {
726; RV32IFD-LABEL: fnmadd_d_2:
727; RV32IFD:       # %bb.0:
728; RV32IFD-NEXT:    fcvt.d.w fa5, zero
729; RV32IFD-NEXT:    fadd.d fa4, fa1, fa5
730; RV32IFD-NEXT:    fadd.d fa5, fa2, fa5
731; RV32IFD-NEXT:    fnmadd.d fa0, fa4, fa0, fa5
732; RV32IFD-NEXT:    ret
733;
734; RV64IFD-LABEL: fnmadd_d_2:
735; RV64IFD:       # %bb.0:
736; RV64IFD-NEXT:    fmv.d.x fa5, zero
737; RV64IFD-NEXT:    fadd.d fa4, fa1, fa5
738; RV64IFD-NEXT:    fadd.d fa5, fa2, fa5
739; RV64IFD-NEXT:    fnmadd.d fa0, fa4, fa0, fa5
740; RV64IFD-NEXT:    ret
741;
742; RV32IZFINXZDINX-LABEL: fnmadd_d_2:
743; RV32IZFINXZDINX:       # %bb.0:
744; RV32IZFINXZDINX-NEXT:    fcvt.d.w a6, zero
745; RV32IZFINXZDINX-NEXT:    fadd.d a2, a2, a6
746; RV32IZFINXZDINX-NEXT:    fadd.d a4, a4, a6
747; RV32IZFINXZDINX-NEXT:    fnmadd.d a0, a2, a0, a4
748; RV32IZFINXZDINX-NEXT:    ret
749;
750; RV64IZFINXZDINX-LABEL: fnmadd_d_2:
751; RV64IZFINXZDINX:       # %bb.0:
752; RV64IZFINXZDINX-NEXT:    fadd.d a1, a1, zero
753; RV64IZFINXZDINX-NEXT:    fadd.d a2, a2, zero
754; RV64IZFINXZDINX-NEXT:    fnmadd.d a0, a1, a0, a2
755; RV64IZFINXZDINX-NEXT:    ret
756;
757; RV32I-LABEL: fnmadd_d_2:
758; RV32I:       # %bb.0:
759; RV32I-NEXT:    addi sp, sp, -32
760; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
761; RV32I-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
762; RV32I-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
763; RV32I-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
764; RV32I-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
765; RV32I-NEXT:    sw s4, 8(sp) # 4-byte Folded Spill
766; RV32I-NEXT:    sw s5, 4(sp) # 4-byte Folded Spill
767; RV32I-NEXT:    mv s0, a5
768; RV32I-NEXT:    mv s1, a4
769; RV32I-NEXT:    mv s2, a1
770; RV32I-NEXT:    mv s3, a0
771; RV32I-NEXT:    mv a0, a2
772; RV32I-NEXT:    mv a1, a3
773; RV32I-NEXT:    li a2, 0
774; RV32I-NEXT:    li a3, 0
775; RV32I-NEXT:    call __adddf3
776; RV32I-NEXT:    mv s4, a0
777; RV32I-NEXT:    mv s5, a1
778; RV32I-NEXT:    mv a0, s1
779; RV32I-NEXT:    mv a1, s0
780; RV32I-NEXT:    li a2, 0
781; RV32I-NEXT:    li a3, 0
782; RV32I-NEXT:    call __adddf3
783; RV32I-NEXT:    mv a4, a0
784; RV32I-NEXT:    lui a5, 524288
785; RV32I-NEXT:    xor a3, s5, a5
786; RV32I-NEXT:    xor a5, a1, a5
787; RV32I-NEXT:    mv a0, s3
788; RV32I-NEXT:    mv a1, s2
789; RV32I-NEXT:    mv a2, s4
790; RV32I-NEXT:    call fma
791; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
792; RV32I-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
793; RV32I-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
794; RV32I-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
795; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
796; RV32I-NEXT:    lw s4, 8(sp) # 4-byte Folded Reload
797; RV32I-NEXT:    lw s5, 4(sp) # 4-byte Folded Reload
798; RV32I-NEXT:    addi sp, sp, 32
799; RV32I-NEXT:    ret
800;
801; RV64I-LABEL: fnmadd_d_2:
802; RV64I:       # %bb.0:
803; RV64I-NEXT:    addi sp, sp, -32
804; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
805; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
806; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
807; RV64I-NEXT:    sd s2, 0(sp) # 8-byte Folded Spill
808; RV64I-NEXT:    mv s0, a2
809; RV64I-NEXT:    mv s1, a0
810; RV64I-NEXT:    mv a0, a1
811; RV64I-NEXT:    li a1, 0
812; RV64I-NEXT:    call __adddf3
813; RV64I-NEXT:    mv s2, a0
814; RV64I-NEXT:    mv a0, s0
815; RV64I-NEXT:    li a1, 0
816; RV64I-NEXT:    call __adddf3
817; RV64I-NEXT:    li a1, -1
818; RV64I-NEXT:    slli a2, a1, 63
819; RV64I-NEXT:    xor a1, s2, a2
820; RV64I-NEXT:    xor a2, a0, a2
821; RV64I-NEXT:    mv a0, s1
822; RV64I-NEXT:    call fma
823; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
824; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
825; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
826; RV64I-NEXT:    ld s2, 0(sp) # 8-byte Folded Reload
827; RV64I-NEXT:    addi sp, sp, 32
828; RV64I-NEXT:    ret
829  %b_ = fadd double 0.0, %b
830  %c_ = fadd double 0.0, %c
831  %negb = fsub double -0.0, %b_
832  %negc = fsub double -0.0, %c_
833  %1 = call double @llvm.fma.f64(double %a, double %negb, double %negc)
834  ret double %1
835}
836
837define double @fnmadd_d_3(double %a, double %b, double %c) nounwind {
838; CHECKIFD-LABEL: fnmadd_d_3:
839; CHECKIFD:       # %bb.0:
840; CHECKIFD-NEXT:    fmadd.d fa5, fa0, fa1, fa2
841; CHECKIFD-NEXT:    fneg.d fa0, fa5
842; CHECKIFD-NEXT:    ret
843;
844; RV32IZFINXZDINX-LABEL: fnmadd_d_3:
845; RV32IZFINXZDINX:       # %bb.0:
846; RV32IZFINXZDINX-NEXT:    fmadd.d a0, a0, a2, a4
847; RV32IZFINXZDINX-NEXT:    fneg.d a0, a0
848; RV32IZFINXZDINX-NEXT:    ret
849;
850; RV64IZFINXZDINX-LABEL: fnmadd_d_3:
851; RV64IZFINXZDINX:       # %bb.0:
852; RV64IZFINXZDINX-NEXT:    fmadd.d a0, a0, a1, a2
853; RV64IZFINXZDINX-NEXT:    fneg.d a0, a0
854; RV64IZFINXZDINX-NEXT:    ret
855;
856; RV32I-LABEL: fnmadd_d_3:
857; RV32I:       # %bb.0:
858; RV32I-NEXT:    addi sp, sp, -16
859; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
860; RV32I-NEXT:    call fma
861; RV32I-NEXT:    lui a2, 524288
862; RV32I-NEXT:    xor a1, a1, a2
863; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
864; RV32I-NEXT:    addi sp, sp, 16
865; RV32I-NEXT:    ret
866;
867; RV64I-LABEL: fnmadd_d_3:
868; RV64I:       # %bb.0:
869; RV64I-NEXT:    addi sp, sp, -16
870; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
871; RV64I-NEXT:    call fma
872; RV64I-NEXT:    li a1, -1
873; RV64I-NEXT:    slli a1, a1, 63
874; RV64I-NEXT:    xor a0, a0, a1
875; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
876; RV64I-NEXT:    addi sp, sp, 16
877; RV64I-NEXT:    ret
878  %1 = call double @llvm.fma.f64(double %a, double %b, double %c)
879  %neg = fneg double %1
880  ret double %neg
881}
882
883
884define double @fnmadd_nsz(double %a, double %b, double %c) nounwind {
885; CHECKIFD-LABEL: fnmadd_nsz:
886; CHECKIFD:       # %bb.0:
887; CHECKIFD-NEXT:    fnmadd.d fa0, fa0, fa1, fa2
888; CHECKIFD-NEXT:    ret
889;
890; RV32IZFINXZDINX-LABEL: fnmadd_nsz:
891; RV32IZFINXZDINX:       # %bb.0:
892; RV32IZFINXZDINX-NEXT:    fnmadd.d a0, a0, a2, a4
893; RV32IZFINXZDINX-NEXT:    ret
894;
895; RV64IZFINXZDINX-LABEL: fnmadd_nsz:
896; RV64IZFINXZDINX:       # %bb.0:
897; RV64IZFINXZDINX-NEXT:    fnmadd.d a0, a0, a1, a2
898; RV64IZFINXZDINX-NEXT:    ret
899;
900; RV32I-LABEL: fnmadd_nsz:
901; RV32I:       # %bb.0:
902; RV32I-NEXT:    addi sp, sp, -16
903; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
904; RV32I-NEXT:    call fma
905; RV32I-NEXT:    lui a2, 524288
906; RV32I-NEXT:    xor a1, a1, a2
907; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
908; RV32I-NEXT:    addi sp, sp, 16
909; RV32I-NEXT:    ret
910;
911; RV64I-LABEL: fnmadd_nsz:
912; RV64I:       # %bb.0:
913; RV64I-NEXT:    addi sp, sp, -16
914; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
915; RV64I-NEXT:    call fma
916; RV64I-NEXT:    li a1, -1
917; RV64I-NEXT:    slli a1, a1, 63
918; RV64I-NEXT:    xor a0, a0, a1
919; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
920; RV64I-NEXT:    addi sp, sp, 16
921; RV64I-NEXT:    ret
922  %1 = call nsz double @llvm.fma.f64(double %a, double %b, double %c)
923  %neg = fneg nsz double %1
924  ret double %neg
925}
926
927define double @fnmsub_d(double %a, double %b, double %c) nounwind {
928; RV32IFD-LABEL: fnmsub_d:
929; RV32IFD:       # %bb.0:
930; RV32IFD-NEXT:    fcvt.d.w fa5, zero
931; RV32IFD-NEXT:    fadd.d fa5, fa0, fa5
932; RV32IFD-NEXT:    fnmsub.d fa0, fa5, fa1, fa2
933; RV32IFD-NEXT:    ret
934;
935; RV64IFD-LABEL: fnmsub_d:
936; RV64IFD:       # %bb.0:
937; RV64IFD-NEXT:    fmv.d.x fa5, zero
938; RV64IFD-NEXT:    fadd.d fa5, fa0, fa5
939; RV64IFD-NEXT:    fnmsub.d fa0, fa5, fa1, fa2
940; RV64IFD-NEXT:    ret
941;
942; RV32IZFINXZDINX-LABEL: fnmsub_d:
943; RV32IZFINXZDINX:       # %bb.0:
944; RV32IZFINXZDINX-NEXT:    fcvt.d.w a6, zero
945; RV32IZFINXZDINX-NEXT:    fadd.d a0, a0, a6
946; RV32IZFINXZDINX-NEXT:    fnmsub.d a0, a0, a2, a4
947; RV32IZFINXZDINX-NEXT:    ret
948;
949; RV64IZFINXZDINX-LABEL: fnmsub_d:
950; RV64IZFINXZDINX:       # %bb.0:
951; RV64IZFINXZDINX-NEXT:    fadd.d a0, a0, zero
952; RV64IZFINXZDINX-NEXT:    fnmsub.d a0, a0, a1, a2
953; RV64IZFINXZDINX-NEXT:    ret
954;
955; RV32I-LABEL: fnmsub_d:
956; RV32I:       # %bb.0:
957; RV32I-NEXT:    addi sp, sp, -32
958; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
959; RV32I-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
960; RV32I-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
961; RV32I-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
962; RV32I-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
963; RV32I-NEXT:    mv s0, a5
964; RV32I-NEXT:    mv s1, a4
965; RV32I-NEXT:    mv s2, a3
966; RV32I-NEXT:    mv s3, a2
967; RV32I-NEXT:    li a2, 0
968; RV32I-NEXT:    li a3, 0
969; RV32I-NEXT:    call __adddf3
970; RV32I-NEXT:    lui a2, 524288
971; RV32I-NEXT:    xor a1, a1, a2
972; RV32I-NEXT:    mv a2, s3
973; RV32I-NEXT:    mv a3, s2
974; RV32I-NEXT:    mv a4, s1
975; RV32I-NEXT:    mv a5, s0
976; RV32I-NEXT:    call fma
977; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
978; RV32I-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
979; RV32I-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
980; RV32I-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
981; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
982; RV32I-NEXT:    addi sp, sp, 32
983; RV32I-NEXT:    ret
984;
985; RV64I-LABEL: fnmsub_d:
986; RV64I:       # %bb.0:
987; RV64I-NEXT:    addi sp, sp, -32
988; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
989; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
990; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
991; RV64I-NEXT:    mv s0, a2
992; RV64I-NEXT:    mv s1, a1
993; RV64I-NEXT:    li a1, 0
994; RV64I-NEXT:    call __adddf3
995; RV64I-NEXT:    li a1, -1
996; RV64I-NEXT:    slli a1, a1, 63
997; RV64I-NEXT:    xor a0, a0, a1
998; RV64I-NEXT:    mv a1, s1
999; RV64I-NEXT:    mv a2, s0
1000; RV64I-NEXT:    call fma
1001; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
1002; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
1003; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
1004; RV64I-NEXT:    addi sp, sp, 32
1005; RV64I-NEXT:    ret
1006  %a_ = fadd double 0.0, %a
1007  %nega = fsub double -0.0, %a_
1008  %1 = call double @llvm.fma.f64(double %nega, double %b, double %c)
1009  ret double %1
1010}
1011
1012define double @fnmsub_d_2(double %a, double %b, double %c) nounwind {
1013; RV32IFD-LABEL: fnmsub_d_2:
1014; RV32IFD:       # %bb.0:
1015; RV32IFD-NEXT:    fcvt.d.w fa5, zero
1016; RV32IFD-NEXT:    fadd.d fa5, fa1, fa5
1017; RV32IFD-NEXT:    fnmsub.d fa0, fa5, fa0, fa2
1018; RV32IFD-NEXT:    ret
1019;
1020; RV64IFD-LABEL: fnmsub_d_2:
1021; RV64IFD:       # %bb.0:
1022; RV64IFD-NEXT:    fmv.d.x fa5, zero
1023; RV64IFD-NEXT:    fadd.d fa5, fa1, fa5
1024; RV64IFD-NEXT:    fnmsub.d fa0, fa5, fa0, fa2
1025; RV64IFD-NEXT:    ret
1026;
1027; RV32IZFINXZDINX-LABEL: fnmsub_d_2:
1028; RV32IZFINXZDINX:       # %bb.0:
1029; RV32IZFINXZDINX-NEXT:    fcvt.d.w a6, zero
1030; RV32IZFINXZDINX-NEXT:    fadd.d a2, a2, a6
1031; RV32IZFINXZDINX-NEXT:    fnmsub.d a0, a2, a0, a4
1032; RV32IZFINXZDINX-NEXT:    ret
1033;
1034; RV64IZFINXZDINX-LABEL: fnmsub_d_2:
1035; RV64IZFINXZDINX:       # %bb.0:
1036; RV64IZFINXZDINX-NEXT:    fadd.d a1, a1, zero
1037; RV64IZFINXZDINX-NEXT:    fnmsub.d a0, a1, a0, a2
1038; RV64IZFINXZDINX-NEXT:    ret
1039;
1040; RV32I-LABEL: fnmsub_d_2:
1041; RV32I:       # %bb.0:
1042; RV32I-NEXT:    addi sp, sp, -32
1043; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
1044; RV32I-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
1045; RV32I-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
1046; RV32I-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
1047; RV32I-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
1048; RV32I-NEXT:    mv s0, a5
1049; RV32I-NEXT:    mv s1, a4
1050; RV32I-NEXT:    mv s2, a1
1051; RV32I-NEXT:    mv s3, a0
1052; RV32I-NEXT:    mv a0, a2
1053; RV32I-NEXT:    mv a1, a3
1054; RV32I-NEXT:    li a2, 0
1055; RV32I-NEXT:    li a3, 0
1056; RV32I-NEXT:    call __adddf3
1057; RV32I-NEXT:    mv a2, a0
1058; RV32I-NEXT:    lui a3, 524288
1059; RV32I-NEXT:    xor a3, a1, a3
1060; RV32I-NEXT:    mv a0, s3
1061; RV32I-NEXT:    mv a1, s2
1062; RV32I-NEXT:    mv a4, s1
1063; RV32I-NEXT:    mv a5, s0
1064; RV32I-NEXT:    call fma
1065; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
1066; RV32I-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
1067; RV32I-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
1068; RV32I-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
1069; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
1070; RV32I-NEXT:    addi sp, sp, 32
1071; RV32I-NEXT:    ret
1072;
1073; RV64I-LABEL: fnmsub_d_2:
1074; RV64I:       # %bb.0:
1075; RV64I-NEXT:    addi sp, sp, -32
1076; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
1077; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
1078; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
1079; RV64I-NEXT:    mv s0, a2
1080; RV64I-NEXT:    mv s1, a0
1081; RV64I-NEXT:    mv a0, a1
1082; RV64I-NEXT:    li a1, 0
1083; RV64I-NEXT:    call __adddf3
1084; RV64I-NEXT:    li a1, -1
1085; RV64I-NEXT:    slli a1, a1, 63
1086; RV64I-NEXT:    xor a1, a0, a1
1087; RV64I-NEXT:    mv a0, s1
1088; RV64I-NEXT:    mv a2, s0
1089; RV64I-NEXT:    call fma
1090; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
1091; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
1092; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
1093; RV64I-NEXT:    addi sp, sp, 32
1094; RV64I-NEXT:    ret
1095  %b_ = fadd double 0.0, %b
1096  %negb = fsub double -0.0, %b_
1097  %1 = call double @llvm.fma.f64(double %a, double %negb, double %c)
1098  ret double %1
1099}
1100
1101define double @fmadd_d_contract(double %a, double %b, double %c) nounwind {
1102; CHECKIFD-LABEL: fmadd_d_contract:
1103; CHECKIFD:       # %bb.0:
1104; CHECKIFD-NEXT:    fmadd.d fa0, fa0, fa1, fa2
1105; CHECKIFD-NEXT:    ret
1106;
1107; RV32IZFINXZDINX-LABEL: fmadd_d_contract:
1108; RV32IZFINXZDINX:       # %bb.0:
1109; RV32IZFINXZDINX-NEXT:    fmadd.d a0, a0, a2, a4
1110; RV32IZFINXZDINX-NEXT:    ret
1111;
1112; RV64IZFINXZDINX-LABEL: fmadd_d_contract:
1113; RV64IZFINXZDINX:       # %bb.0:
1114; RV64IZFINXZDINX-NEXT:    fmadd.d a0, a0, a1, a2
1115; RV64IZFINXZDINX-NEXT:    ret
1116;
1117; RV32I-LABEL: fmadd_d_contract:
1118; RV32I:       # %bb.0:
1119; RV32I-NEXT:    addi sp, sp, -16
1120; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
1121; RV32I-NEXT:    sw s0, 8(sp) # 4-byte Folded Spill
1122; RV32I-NEXT:    sw s1, 4(sp) # 4-byte Folded Spill
1123; RV32I-NEXT:    mv s0, a5
1124; RV32I-NEXT:    mv s1, a4
1125; RV32I-NEXT:    call __muldf3
1126; RV32I-NEXT:    mv a2, s1
1127; RV32I-NEXT:    mv a3, s0
1128; RV32I-NEXT:    call __adddf3
1129; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
1130; RV32I-NEXT:    lw s0, 8(sp) # 4-byte Folded Reload
1131; RV32I-NEXT:    lw s1, 4(sp) # 4-byte Folded Reload
1132; RV32I-NEXT:    addi sp, sp, 16
1133; RV32I-NEXT:    ret
1134;
1135; RV64I-LABEL: fmadd_d_contract:
1136; RV64I:       # %bb.0:
1137; RV64I-NEXT:    addi sp, sp, -16
1138; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
1139; RV64I-NEXT:    sd s0, 0(sp) # 8-byte Folded Spill
1140; RV64I-NEXT:    mv s0, a2
1141; RV64I-NEXT:    call __muldf3
1142; RV64I-NEXT:    mv a1, s0
1143; RV64I-NEXT:    call __adddf3
1144; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
1145; RV64I-NEXT:    ld s0, 0(sp) # 8-byte Folded Reload
1146; RV64I-NEXT:    addi sp, sp, 16
1147; RV64I-NEXT:    ret
1148  %1 = fmul contract double %a, %b
1149  %2 = fadd contract double %1, %c
1150  ret double %2
1151}
1152
1153define double @fmsub_d_contract(double %a, double %b, double %c) nounwind {
1154; RV32IFD-LABEL: fmsub_d_contract:
1155; RV32IFD:       # %bb.0:
1156; RV32IFD-NEXT:    fcvt.d.w fa5, zero
1157; RV32IFD-NEXT:    fadd.d fa5, fa2, fa5
1158; RV32IFD-NEXT:    fmsub.d fa0, fa0, fa1, fa5
1159; RV32IFD-NEXT:    ret
1160;
1161; RV64IFD-LABEL: fmsub_d_contract:
1162; RV64IFD:       # %bb.0:
1163; RV64IFD-NEXT:    fmv.d.x fa5, zero
1164; RV64IFD-NEXT:    fadd.d fa5, fa2, fa5
1165; RV64IFD-NEXT:    fmsub.d fa0, fa0, fa1, fa5
1166; RV64IFD-NEXT:    ret
1167;
1168; RV32IZFINXZDINX-LABEL: fmsub_d_contract:
1169; RV32IZFINXZDINX:       # %bb.0:
1170; RV32IZFINXZDINX-NEXT:    fcvt.d.w a6, zero
1171; RV32IZFINXZDINX-NEXT:    fadd.d a4, a4, a6
1172; RV32IZFINXZDINX-NEXT:    fmsub.d a0, a0, a2, a4
1173; RV32IZFINXZDINX-NEXT:    ret
1174;
1175; RV64IZFINXZDINX-LABEL: fmsub_d_contract:
1176; RV64IZFINXZDINX:       # %bb.0:
1177; RV64IZFINXZDINX-NEXT:    fadd.d a2, a2, zero
1178; RV64IZFINXZDINX-NEXT:    fmsub.d a0, a0, a1, a2
1179; RV64IZFINXZDINX-NEXT:    ret
1180;
1181; RV32I-LABEL: fmsub_d_contract:
1182; RV32I:       # %bb.0:
1183; RV32I-NEXT:    addi sp, sp, -32
1184; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
1185; RV32I-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
1186; RV32I-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
1187; RV32I-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
1188; RV32I-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
1189; RV32I-NEXT:    sw s4, 8(sp) # 4-byte Folded Spill
1190; RV32I-NEXT:    sw s5, 4(sp) # 4-byte Folded Spill
1191; RV32I-NEXT:    mv s0, a3
1192; RV32I-NEXT:    mv s1, a2
1193; RV32I-NEXT:    mv s2, a1
1194; RV32I-NEXT:    mv s3, a0
1195; RV32I-NEXT:    mv a0, a4
1196; RV32I-NEXT:    mv a1, a5
1197; RV32I-NEXT:    li a2, 0
1198; RV32I-NEXT:    li a3, 0
1199; RV32I-NEXT:    call __adddf3
1200; RV32I-NEXT:    mv s4, a0
1201; RV32I-NEXT:    mv s5, a1
1202; RV32I-NEXT:    mv a0, s3
1203; RV32I-NEXT:    mv a1, s2
1204; RV32I-NEXT:    mv a2, s1
1205; RV32I-NEXT:    mv a3, s0
1206; RV32I-NEXT:    call __muldf3
1207; RV32I-NEXT:    mv a2, s4
1208; RV32I-NEXT:    mv a3, s5
1209; RV32I-NEXT:    call __subdf3
1210; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
1211; RV32I-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
1212; RV32I-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
1213; RV32I-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
1214; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
1215; RV32I-NEXT:    lw s4, 8(sp) # 4-byte Folded Reload
1216; RV32I-NEXT:    lw s5, 4(sp) # 4-byte Folded Reload
1217; RV32I-NEXT:    addi sp, sp, 32
1218; RV32I-NEXT:    ret
1219;
1220; RV64I-LABEL: fmsub_d_contract:
1221; RV64I:       # %bb.0:
1222; RV64I-NEXT:    addi sp, sp, -32
1223; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
1224; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
1225; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
1226; RV64I-NEXT:    sd s2, 0(sp) # 8-byte Folded Spill
1227; RV64I-NEXT:    mv s0, a1
1228; RV64I-NEXT:    mv s1, a0
1229; RV64I-NEXT:    mv a0, a2
1230; RV64I-NEXT:    li a1, 0
1231; RV64I-NEXT:    call __adddf3
1232; RV64I-NEXT:    mv s2, a0
1233; RV64I-NEXT:    mv a0, s1
1234; RV64I-NEXT:    mv a1, s0
1235; RV64I-NEXT:    call __muldf3
1236; RV64I-NEXT:    mv a1, s2
1237; RV64I-NEXT:    call __subdf3
1238; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
1239; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
1240; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
1241; RV64I-NEXT:    ld s2, 0(sp) # 8-byte Folded Reload
1242; RV64I-NEXT:    addi sp, sp, 32
1243; RV64I-NEXT:    ret
1244  %c_ = fadd double 0.0, %c ; avoid negation using xor
1245  %1 = fmul contract double %a, %b
1246  %2 = fsub contract double %1, %c_
1247  ret double %2
1248}
1249
1250define double @fnmadd_d_contract(double %a, double %b, double %c) nounwind {
1251; RV32IFD-LABEL: fnmadd_d_contract:
1252; RV32IFD:       # %bb.0:
1253; RV32IFD-NEXT:    fcvt.d.w fa5, zero
1254; RV32IFD-NEXT:    fadd.d fa4, fa0, fa5
1255; RV32IFD-NEXT:    fadd.d fa3, fa1, fa5
1256; RV32IFD-NEXT:    fadd.d fa5, fa2, fa5
1257; RV32IFD-NEXT:    fnmadd.d fa0, fa4, fa3, fa5
1258; RV32IFD-NEXT:    ret
1259;
1260; RV64IFD-LABEL: fnmadd_d_contract:
1261; RV64IFD:       # %bb.0:
1262; RV64IFD-NEXT:    fmv.d.x fa5, zero
1263; RV64IFD-NEXT:    fadd.d fa4, fa0, fa5
1264; RV64IFD-NEXT:    fadd.d fa3, fa1, fa5
1265; RV64IFD-NEXT:    fadd.d fa5, fa2, fa5
1266; RV64IFD-NEXT:    fnmadd.d fa0, fa4, fa3, fa5
1267; RV64IFD-NEXT:    ret
1268;
1269; RV32IZFINXZDINX-LABEL: fnmadd_d_contract:
1270; RV32IZFINXZDINX:       # %bb.0:
1271; RV32IZFINXZDINX-NEXT:    fcvt.d.w a6, zero
1272; RV32IZFINXZDINX-NEXT:    fadd.d a0, a0, a6
1273; RV32IZFINXZDINX-NEXT:    fadd.d a2, a2, a6
1274; RV32IZFINXZDINX-NEXT:    fadd.d a4, a4, a6
1275; RV32IZFINXZDINX-NEXT:    fnmadd.d a0, a0, a2, a4
1276; RV32IZFINXZDINX-NEXT:    ret
1277;
1278; RV64IZFINXZDINX-LABEL: fnmadd_d_contract:
1279; RV64IZFINXZDINX:       # %bb.0:
1280; RV64IZFINXZDINX-NEXT:    fadd.d a0, a0, zero
1281; RV64IZFINXZDINX-NEXT:    fadd.d a1, a1, zero
1282; RV64IZFINXZDINX-NEXT:    fadd.d a2, a2, zero
1283; RV64IZFINXZDINX-NEXT:    fnmadd.d a0, a0, a1, a2
1284; RV64IZFINXZDINX-NEXT:    ret
1285;
1286; RV32I-LABEL: fnmadd_d_contract:
1287; RV32I:       # %bb.0:
1288; RV32I-NEXT:    addi sp, sp, -32
1289; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
1290; RV32I-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
1291; RV32I-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
1292; RV32I-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
1293; RV32I-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
1294; RV32I-NEXT:    sw s4, 8(sp) # 4-byte Folded Spill
1295; RV32I-NEXT:    sw s5, 4(sp) # 4-byte Folded Spill
1296; RV32I-NEXT:    mv s0, a5
1297; RV32I-NEXT:    mv s1, a4
1298; RV32I-NEXT:    mv s2, a3
1299; RV32I-NEXT:    mv s3, a2
1300; RV32I-NEXT:    li a2, 0
1301; RV32I-NEXT:    li a3, 0
1302; RV32I-NEXT:    call __adddf3
1303; RV32I-NEXT:    mv s4, a0
1304; RV32I-NEXT:    mv s5, a1
1305; RV32I-NEXT:    mv a0, s3
1306; RV32I-NEXT:    mv a1, s2
1307; RV32I-NEXT:    li a2, 0
1308; RV32I-NEXT:    li a3, 0
1309; RV32I-NEXT:    call __adddf3
1310; RV32I-NEXT:    mv s2, a0
1311; RV32I-NEXT:    mv s3, a1
1312; RV32I-NEXT:    mv a0, s1
1313; RV32I-NEXT:    mv a1, s0
1314; RV32I-NEXT:    li a2, 0
1315; RV32I-NEXT:    li a3, 0
1316; RV32I-NEXT:    call __adddf3
1317; RV32I-NEXT:    mv s0, a0
1318; RV32I-NEXT:    mv s1, a1
1319; RV32I-NEXT:    mv a0, s4
1320; RV32I-NEXT:    mv a1, s5
1321; RV32I-NEXT:    mv a2, s2
1322; RV32I-NEXT:    mv a3, s3
1323; RV32I-NEXT:    call __muldf3
1324; RV32I-NEXT:    lui a2, 524288
1325; RV32I-NEXT:    xor a1, a1, a2
1326; RV32I-NEXT:    mv a2, s0
1327; RV32I-NEXT:    mv a3, s1
1328; RV32I-NEXT:    call __subdf3
1329; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
1330; RV32I-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
1331; RV32I-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
1332; RV32I-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
1333; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
1334; RV32I-NEXT:    lw s4, 8(sp) # 4-byte Folded Reload
1335; RV32I-NEXT:    lw s5, 4(sp) # 4-byte Folded Reload
1336; RV32I-NEXT:    addi sp, sp, 32
1337; RV32I-NEXT:    ret
1338;
1339; RV64I-LABEL: fnmadd_d_contract:
1340; RV64I:       # %bb.0:
1341; RV64I-NEXT:    addi sp, sp, -32
1342; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
1343; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
1344; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
1345; RV64I-NEXT:    sd s2, 0(sp) # 8-byte Folded Spill
1346; RV64I-NEXT:    mv s0, a2
1347; RV64I-NEXT:    mv s1, a1
1348; RV64I-NEXT:    li a1, 0
1349; RV64I-NEXT:    call __adddf3
1350; RV64I-NEXT:    mv s2, a0
1351; RV64I-NEXT:    mv a0, s1
1352; RV64I-NEXT:    li a1, 0
1353; RV64I-NEXT:    call __adddf3
1354; RV64I-NEXT:    mv s1, a0
1355; RV64I-NEXT:    mv a0, s0
1356; RV64I-NEXT:    li a1, 0
1357; RV64I-NEXT:    call __adddf3
1358; RV64I-NEXT:    mv s0, a0
1359; RV64I-NEXT:    mv a0, s2
1360; RV64I-NEXT:    mv a1, s1
1361; RV64I-NEXT:    call __muldf3
1362; RV64I-NEXT:    li a1, -1
1363; RV64I-NEXT:    slli a1, a1, 63
1364; RV64I-NEXT:    xor a0, a0, a1
1365; RV64I-NEXT:    mv a1, s0
1366; RV64I-NEXT:    call __subdf3
1367; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
1368; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
1369; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
1370; RV64I-NEXT:    ld s2, 0(sp) # 8-byte Folded Reload
1371; RV64I-NEXT:    addi sp, sp, 32
1372; RV64I-NEXT:    ret
1373  %a_ = fadd double 0.0, %a ; avoid negation using xor
1374  %b_ = fadd double 0.0, %b ; avoid negation using xor
1375  %c_ = fadd double 0.0, %c ; avoid negation using xor
1376  %1 = fmul contract double %a_, %b_
1377  %2 = fneg double %1
1378  %3 = fsub contract double %2, %c_
1379  ret double %3
1380}
1381
1382define double @fnmsub_d_contract(double %a, double %b, double %c) nounwind {
1383; RV32IFD-LABEL: fnmsub_d_contract:
1384; RV32IFD:       # %bb.0:
1385; RV32IFD-NEXT:    fcvt.d.w fa5, zero
1386; RV32IFD-NEXT:    fadd.d fa4, fa0, fa5
1387; RV32IFD-NEXT:    fadd.d fa5, fa1, fa5
1388; RV32IFD-NEXT:    fnmsub.d fa0, fa4, fa5, fa2
1389; RV32IFD-NEXT:    ret
1390;
1391; RV64IFD-LABEL: fnmsub_d_contract:
1392; RV64IFD:       # %bb.0:
1393; RV64IFD-NEXT:    fmv.d.x fa5, zero
1394; RV64IFD-NEXT:    fadd.d fa4, fa0, fa5
1395; RV64IFD-NEXT:    fadd.d fa5, fa1, fa5
1396; RV64IFD-NEXT:    fnmsub.d fa0, fa4, fa5, fa2
1397; RV64IFD-NEXT:    ret
1398;
1399; RV32IZFINXZDINX-LABEL: fnmsub_d_contract:
1400; RV32IZFINXZDINX:       # %bb.0:
1401; RV32IZFINXZDINX-NEXT:    fcvt.d.w a6, zero
1402; RV32IZFINXZDINX-NEXT:    fadd.d a0, a0, a6
1403; RV32IZFINXZDINX-NEXT:    fadd.d a2, a2, a6
1404; RV32IZFINXZDINX-NEXT:    fnmsub.d a0, a0, a2, a4
1405; RV32IZFINXZDINX-NEXT:    ret
1406;
1407; RV64IZFINXZDINX-LABEL: fnmsub_d_contract:
1408; RV64IZFINXZDINX:       # %bb.0:
1409; RV64IZFINXZDINX-NEXT:    fadd.d a0, a0, zero
1410; RV64IZFINXZDINX-NEXT:    fadd.d a1, a1, zero
1411; RV64IZFINXZDINX-NEXT:    fnmsub.d a0, a0, a1, a2
1412; RV64IZFINXZDINX-NEXT:    ret
1413;
1414; RV32I-LABEL: fnmsub_d_contract:
1415; RV32I:       # %bb.0:
1416; RV32I-NEXT:    addi sp, sp, -32
1417; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
1418; RV32I-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
1419; RV32I-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
1420; RV32I-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
1421; RV32I-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
1422; RV32I-NEXT:    sw s4, 8(sp) # 4-byte Folded Spill
1423; RV32I-NEXT:    sw s5, 4(sp) # 4-byte Folded Spill
1424; RV32I-NEXT:    mv s0, a5
1425; RV32I-NEXT:    mv s1, a4
1426; RV32I-NEXT:    mv s2, a3
1427; RV32I-NEXT:    mv s3, a2
1428; RV32I-NEXT:    li a2, 0
1429; RV32I-NEXT:    li a3, 0
1430; RV32I-NEXT:    call __adddf3
1431; RV32I-NEXT:    mv s4, a0
1432; RV32I-NEXT:    mv s5, a1
1433; RV32I-NEXT:    mv a0, s3
1434; RV32I-NEXT:    mv a1, s2
1435; RV32I-NEXT:    li a2, 0
1436; RV32I-NEXT:    li a3, 0
1437; RV32I-NEXT:    call __adddf3
1438; RV32I-NEXT:    mv a2, a0
1439; RV32I-NEXT:    mv a3, a1
1440; RV32I-NEXT:    mv a0, s4
1441; RV32I-NEXT:    mv a1, s5
1442; RV32I-NEXT:    call __muldf3
1443; RV32I-NEXT:    mv a2, a0
1444; RV32I-NEXT:    mv a3, a1
1445; RV32I-NEXT:    mv a0, s1
1446; RV32I-NEXT:    mv a1, s0
1447; RV32I-NEXT:    call __subdf3
1448; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
1449; RV32I-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
1450; RV32I-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
1451; RV32I-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
1452; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
1453; RV32I-NEXT:    lw s4, 8(sp) # 4-byte Folded Reload
1454; RV32I-NEXT:    lw s5, 4(sp) # 4-byte Folded Reload
1455; RV32I-NEXT:    addi sp, sp, 32
1456; RV32I-NEXT:    ret
1457;
1458; RV64I-LABEL: fnmsub_d_contract:
1459; RV64I:       # %bb.0:
1460; RV64I-NEXT:    addi sp, sp, -32
1461; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
1462; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
1463; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
1464; RV64I-NEXT:    sd s2, 0(sp) # 8-byte Folded Spill
1465; RV64I-NEXT:    mv s0, a2
1466; RV64I-NEXT:    mv s1, a1
1467; RV64I-NEXT:    li a1, 0
1468; RV64I-NEXT:    call __adddf3
1469; RV64I-NEXT:    mv s2, a0
1470; RV64I-NEXT:    mv a0, s1
1471; RV64I-NEXT:    li a1, 0
1472; RV64I-NEXT:    call __adddf3
1473; RV64I-NEXT:    mv a1, a0
1474; RV64I-NEXT:    mv a0, s2
1475; RV64I-NEXT:    call __muldf3
1476; RV64I-NEXT:    mv a1, a0
1477; RV64I-NEXT:    mv a0, s0
1478; RV64I-NEXT:    call __subdf3
1479; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
1480; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
1481; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
1482; RV64I-NEXT:    ld s2, 0(sp) # 8-byte Folded Reload
1483; RV64I-NEXT:    addi sp, sp, 32
1484; RV64I-NEXT:    ret
1485  %a_ = fadd double 0.0, %a ; avoid negation using xor
1486  %b_ = fadd double 0.0, %b ; avoid negation using xor
1487  %1 = fmul contract double %a_, %b_
1488  %2 = fsub contract double %c, %1
1489  ret double %2
1490}
1491
1492define double @fsgnjx_f64(double %x, double %y) nounwind {
1493; CHECKIFD-LABEL: fsgnjx_f64:
1494; CHECKIFD:       # %bb.0:
1495; CHECKIFD-NEXT:    fsgnjx.d fa0, fa1, fa0
1496; CHECKIFD-NEXT:    ret
1497;
1498; RV32IZFINXZDINX-LABEL: fsgnjx_f64:
1499; RV32IZFINXZDINX:       # %bb.0:
1500; RV32IZFINXZDINX-NEXT:    fsgnjx.d a0, a2, a0
1501; RV32IZFINXZDINX-NEXT:    ret
1502;
1503; RV64IZFINXZDINX-LABEL: fsgnjx_f64:
1504; RV64IZFINXZDINX:       # %bb.0:
1505; RV64IZFINXZDINX-NEXT:    fsgnjx.d a0, a1, a0
1506; RV64IZFINXZDINX-NEXT:    ret
1507;
1508; RV32I-LABEL: fsgnjx_f64:
1509; RV32I:       # %bb.0:
1510; RV32I-NEXT:    addi sp, sp, -16
1511; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
1512; RV32I-NEXT:    lui a0, 524288
1513; RV32I-NEXT:    and a0, a1, a0
1514; RV32I-NEXT:    lui a1, 261888
1515; RV32I-NEXT:    or a1, a0, a1
1516; RV32I-NEXT:    li a0, 0
1517; RV32I-NEXT:    call __muldf3
1518; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
1519; RV32I-NEXT:    addi sp, sp, 16
1520; RV32I-NEXT:    ret
1521;
1522; RV64I-LABEL: fsgnjx_f64:
1523; RV64I:       # %bb.0:
1524; RV64I-NEXT:    addi sp, sp, -16
1525; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
1526; RV64I-NEXT:    srli a0, a0, 63
1527; RV64I-NEXT:    li a2, 1023
1528; RV64I-NEXT:    slli a0, a0, 63
1529; RV64I-NEXT:    slli a2, a2, 52
1530; RV64I-NEXT:    or a0, a0, a2
1531; RV64I-NEXT:    call __muldf3
1532; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
1533; RV64I-NEXT:    addi sp, sp, 16
1534; RV64I-NEXT:    ret
1535  %z = call double @llvm.copysign.f64(double 1.0, double %x)
1536  %mul = fmul double %z, %y
1537  ret double %mul
1538}
1539