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