[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / test / CodeGen / RISCV / float-arith.ll
blobd302dd5ebc0ac79168008db2e33a9989842a8bb0
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=riscv32 -mattr=+f -verify-machineinstrs < %s \
3 ; RUN:   | FileCheck -check-prefix=RV32IF %s
4 ; RUN: llc -mtriple=riscv64 -mattr=+f -verify-machineinstrs < %s \
5 ; RUN:   | FileCheck -check-prefix=RV64IF %s
7 ; These tests are each targeted at a particular RISC-V FPU instruction. Most
8 ; other files in this folder exercise LLVM IR instructions that don't directly
9 ; match a RISC-V instruction.
11 define float @fadd_s(float %a, float %b) nounwind {
12 ; RV32IF-LABEL: fadd_s:
13 ; RV32IF:       # %bb.0:
14 ; RV32IF-NEXT:    fmv.w.x ft0, a1
15 ; RV32IF-NEXT:    fmv.w.x ft1, a0
16 ; RV32IF-NEXT:    fadd.s ft0, ft1, ft0
17 ; RV32IF-NEXT:    fmv.x.w a0, ft0
18 ; RV32IF-NEXT:    ret
20 ; RV64IF-LABEL: fadd_s:
21 ; RV64IF:       # %bb.0:
22 ; RV64IF-NEXT:    fmv.w.x ft0, a1
23 ; RV64IF-NEXT:    fmv.w.x ft1, a0
24 ; RV64IF-NEXT:    fadd.s ft0, ft1, ft0
25 ; RV64IF-NEXT:    fmv.x.w a0, ft0
26 ; RV64IF-NEXT:    ret
27   %1 = fadd float %a, %b
28   ret float %1
31 define float @fsub_s(float %a, float %b) nounwind {
32 ; RV32IF-LABEL: fsub_s:
33 ; RV32IF:       # %bb.0:
34 ; RV32IF-NEXT:    fmv.w.x ft0, a1
35 ; RV32IF-NEXT:    fmv.w.x ft1, a0
36 ; RV32IF-NEXT:    fsub.s ft0, ft1, ft0
37 ; RV32IF-NEXT:    fmv.x.w a0, ft0
38 ; RV32IF-NEXT:    ret
40 ; RV64IF-LABEL: fsub_s:
41 ; RV64IF:       # %bb.0:
42 ; RV64IF-NEXT:    fmv.w.x ft0, a1
43 ; RV64IF-NEXT:    fmv.w.x ft1, a0
44 ; RV64IF-NEXT:    fsub.s ft0, ft1, ft0
45 ; RV64IF-NEXT:    fmv.x.w a0, ft0
46 ; RV64IF-NEXT:    ret
47   %1 = fsub float %a, %b
48   ret float %1
51 define float @fmul_s(float %a, float %b) nounwind {
52 ; RV32IF-LABEL: fmul_s:
53 ; RV32IF:       # %bb.0:
54 ; RV32IF-NEXT:    fmv.w.x ft0, a1
55 ; RV32IF-NEXT:    fmv.w.x ft1, a0
56 ; RV32IF-NEXT:    fmul.s ft0, ft1, ft0
57 ; RV32IF-NEXT:    fmv.x.w a0, ft0
58 ; RV32IF-NEXT:    ret
60 ; RV64IF-LABEL: fmul_s:
61 ; RV64IF:       # %bb.0:
62 ; RV64IF-NEXT:    fmv.w.x ft0, a1
63 ; RV64IF-NEXT:    fmv.w.x ft1, a0
64 ; RV64IF-NEXT:    fmul.s ft0, ft1, ft0
65 ; RV64IF-NEXT:    fmv.x.w a0, ft0
66 ; RV64IF-NEXT:    ret
67   %1 = fmul float %a, %b
68   ret float %1
71 define float @fdiv_s(float %a, float %b) nounwind {
72 ; RV32IF-LABEL: fdiv_s:
73 ; RV32IF:       # %bb.0:
74 ; RV32IF-NEXT:    fmv.w.x ft0, a1
75 ; RV32IF-NEXT:    fmv.w.x ft1, a0
76 ; RV32IF-NEXT:    fdiv.s ft0, ft1, ft0
77 ; RV32IF-NEXT:    fmv.x.w a0, ft0
78 ; RV32IF-NEXT:    ret
80 ; RV64IF-LABEL: fdiv_s:
81 ; RV64IF:       # %bb.0:
82 ; RV64IF-NEXT:    fmv.w.x ft0, a1
83 ; RV64IF-NEXT:    fmv.w.x ft1, a0
84 ; RV64IF-NEXT:    fdiv.s ft0, ft1, ft0
85 ; RV64IF-NEXT:    fmv.x.w a0, ft0
86 ; RV64IF-NEXT:    ret
87   %1 = fdiv float %a, %b
88   ret float %1
91 declare float @llvm.sqrt.f32(float)
93 define float @fsqrt_s(float %a) nounwind {
94 ; RV32IF-LABEL: fsqrt_s:
95 ; RV32IF:       # %bb.0:
96 ; RV32IF-NEXT:    fmv.w.x ft0, a0
97 ; RV32IF-NEXT:    fsqrt.s ft0, ft0
98 ; RV32IF-NEXT:    fmv.x.w a0, ft0
99 ; RV32IF-NEXT:    ret
101 ; RV64IF-LABEL: fsqrt_s:
102 ; RV64IF:       # %bb.0:
103 ; RV64IF-NEXT:    fmv.w.x ft0, a0
104 ; RV64IF-NEXT:    fsqrt.s ft0, ft0
105 ; RV64IF-NEXT:    fmv.x.w a0, ft0
106 ; RV64IF-NEXT:    ret
107   %1 = call float @llvm.sqrt.f32(float %a)
108   ret float %1
111 declare float @llvm.copysign.f32(float, float)
113 define float @fsgnj_s(float %a, float %b) nounwind {
114 ; RV32IF-LABEL: fsgnj_s:
115 ; RV32IF:       # %bb.0:
116 ; RV32IF-NEXT:    fmv.w.x ft0, a1
117 ; RV32IF-NEXT:    fmv.w.x ft1, a0
118 ; RV32IF-NEXT:    fsgnj.s ft0, ft1, ft0
119 ; RV32IF-NEXT:    fmv.x.w a0, ft0
120 ; RV32IF-NEXT:    ret
122 ; RV64IF-LABEL: fsgnj_s:
123 ; RV64IF:       # %bb.0:
124 ; RV64IF-NEXT:    fmv.w.x ft0, a1
125 ; RV64IF-NEXT:    fmv.w.x ft1, a0
126 ; RV64IF-NEXT:    fsgnj.s ft0, ft1, ft0
127 ; RV64IF-NEXT:    fmv.x.w a0, ft0
128 ; RV64IF-NEXT:    ret
129   %1 = call float @llvm.copysign.f32(float %a, float %b)
130   ret float %1
133 ; This function performs extra work to ensure that
134 ; DAGCombiner::visitBITCAST doesn't replace the fneg with an xor.
135 define i32 @fneg_s(float %a, float %b) nounwind {
136 ; RV32IF-LABEL: fneg_s:
137 ; RV32IF:       # %bb.0:
138 ; RV32IF-NEXT:    fmv.w.x ft0, a0
139 ; RV32IF-NEXT:    fadd.s ft0, ft0, ft0
140 ; RV32IF-NEXT:    fneg.s ft1, ft0
141 ; RV32IF-NEXT:    feq.s a0, ft0, ft1
142 ; RV32IF-NEXT:    ret
144 ; RV64IF-LABEL: fneg_s:
145 ; RV64IF:       # %bb.0:
146 ; RV64IF-NEXT:    fmv.w.x ft0, a0
147 ; RV64IF-NEXT:    fadd.s ft0, ft0, ft0
148 ; RV64IF-NEXT:    fneg.s ft1, ft0
149 ; RV64IF-NEXT:    feq.s a0, ft0, ft1
150 ; RV64IF-NEXT:    ret
151   %1 = fadd float %a, %a
152   %2 = fneg float %1
153   %3 = fcmp oeq float %1, %2
154   %4 = zext i1 %3 to i32
155   ret i32 %4
158 ; This function performs extra work to ensure that
159 ; DAGCombiner::visitBITCAST doesn't replace the fneg with an xor.
160 define float @fsgnjn_s(float %a, float %b) nounwind {
161 ; RV32IF-LABEL: fsgnjn_s:
162 ; RV32IF:       # %bb.0:
163 ; RV32IF-NEXT:    fmv.w.x ft0, a1
164 ; RV32IF-NEXT:    fmv.w.x ft1, a0
165 ; RV32IF-NEXT:    fadd.s ft0, ft1, ft0
166 ; RV32IF-NEXT:    fsgnjn.s ft0, ft1, ft0
167 ; RV32IF-NEXT:    fmv.x.w a0, ft0
168 ; RV32IF-NEXT:    ret
170 ; RV64IF-LABEL: fsgnjn_s:
171 ; RV64IF:       # %bb.0:
172 ; RV64IF-NEXT:    fmv.w.x ft0, a1
173 ; RV64IF-NEXT:    fmv.w.x ft1, a0
174 ; RV64IF-NEXT:    fadd.s ft0, ft1, ft0
175 ; RV64IF-NEXT:    fsgnjn.s ft0, ft1, ft0
176 ; RV64IF-NEXT:    fmv.x.w a0, ft0
177 ; RV64IF-NEXT:    ret
178   %1 = fadd float %a, %b
179   %2 = fneg float %1
180   %3 = call float @llvm.copysign.f32(float %a, float %2)
181   ret float %3
184 declare float @llvm.fabs.f32(float)
186 ; This function performs extra work to ensure that
187 ; DAGCombiner::visitBITCAST doesn't replace the fabs with an and.
188 define float @fabs_s(float %a, float %b) nounwind {
189 ; RV32IF-LABEL: fabs_s:
190 ; RV32IF:       # %bb.0:
191 ; RV32IF-NEXT:    fmv.w.x ft0, a1
192 ; RV32IF-NEXT:    fmv.w.x ft1, a0
193 ; RV32IF-NEXT:    fadd.s ft0, ft1, ft0
194 ; RV32IF-NEXT:    fabs.s ft1, ft0
195 ; RV32IF-NEXT:    fadd.s ft0, ft1, ft0
196 ; RV32IF-NEXT:    fmv.x.w a0, ft0
197 ; RV32IF-NEXT:    ret
199 ; RV64IF-LABEL: fabs_s:
200 ; RV64IF:       # %bb.0:
201 ; RV64IF-NEXT:    fmv.w.x ft0, a1
202 ; RV64IF-NEXT:    fmv.w.x ft1, a0
203 ; RV64IF-NEXT:    fadd.s ft0, ft1, ft0
204 ; RV64IF-NEXT:    fabs.s ft1, ft0
205 ; RV64IF-NEXT:    fadd.s ft0, ft1, ft0
206 ; RV64IF-NEXT:    fmv.x.w a0, ft0
207 ; RV64IF-NEXT:    ret
208   %1 = fadd float %a, %b
209   %2 = call float @llvm.fabs.f32(float %1)
210   %3 = fadd float %2, %1
211   ret float %3
214 declare float @llvm.minnum.f32(float, float)
216 define float @fmin_s(float %a, float %b) nounwind {
217 ; RV32IF-LABEL: fmin_s:
218 ; RV32IF:       # %bb.0:
219 ; RV32IF-NEXT:    fmv.w.x ft0, a1
220 ; RV32IF-NEXT:    fmv.w.x ft1, a0
221 ; RV32IF-NEXT:    fmin.s ft0, ft1, ft0
222 ; RV32IF-NEXT:    fmv.x.w a0, ft0
223 ; RV32IF-NEXT:    ret
225 ; RV64IF-LABEL: fmin_s:
226 ; RV64IF:       # %bb.0:
227 ; RV64IF-NEXT:    fmv.w.x ft0, a1
228 ; RV64IF-NEXT:    fmv.w.x ft1, a0
229 ; RV64IF-NEXT:    fmin.s ft0, ft1, ft0
230 ; RV64IF-NEXT:    fmv.x.w a0, ft0
231 ; RV64IF-NEXT:    ret
232   %1 = call float @llvm.minnum.f32(float %a, float %b)
233   ret float %1
236 declare float @llvm.maxnum.f32(float, float)
238 define float @fmax_s(float %a, float %b) nounwind {
239 ; RV32IF-LABEL: fmax_s:
240 ; RV32IF:       # %bb.0:
241 ; RV32IF-NEXT:    fmv.w.x ft0, a1
242 ; RV32IF-NEXT:    fmv.w.x ft1, a0
243 ; RV32IF-NEXT:    fmax.s ft0, ft1, ft0
244 ; RV32IF-NEXT:    fmv.x.w a0, ft0
245 ; RV32IF-NEXT:    ret
247 ; RV64IF-LABEL: fmax_s:
248 ; RV64IF:       # %bb.0:
249 ; RV64IF-NEXT:    fmv.w.x ft0, a1
250 ; RV64IF-NEXT:    fmv.w.x ft1, a0
251 ; RV64IF-NEXT:    fmax.s ft0, ft1, ft0
252 ; RV64IF-NEXT:    fmv.x.w a0, ft0
253 ; RV64IF-NEXT:    ret
254   %1 = call float @llvm.maxnum.f32(float %a, float %b)
255   ret float %1
258 define i32 @feq_s(float %a, float %b) nounwind {
259 ; RV32IF-LABEL: feq_s:
260 ; RV32IF:       # %bb.0:
261 ; RV32IF-NEXT:    fmv.w.x ft0, a1
262 ; RV32IF-NEXT:    fmv.w.x ft1, a0
263 ; RV32IF-NEXT:    feq.s a0, ft1, ft0
264 ; RV32IF-NEXT:    ret
266 ; RV64IF-LABEL: feq_s:
267 ; RV64IF:       # %bb.0:
268 ; RV64IF-NEXT:    fmv.w.x ft0, a1
269 ; RV64IF-NEXT:    fmv.w.x ft1, a0
270 ; RV64IF-NEXT:    feq.s a0, ft1, ft0
271 ; RV64IF-NEXT:    ret
272   %1 = fcmp oeq float %a, %b
273   %2 = zext i1 %1 to i32
274   ret i32 %2
277 define i32 @flt_s(float %a, float %b) nounwind {
278 ; RV32IF-LABEL: flt_s:
279 ; RV32IF:       # %bb.0:
280 ; RV32IF-NEXT:    fmv.w.x ft0, a1
281 ; RV32IF-NEXT:    fmv.w.x ft1, a0
282 ; RV32IF-NEXT:    flt.s a0, ft1, ft0
283 ; RV32IF-NEXT:    ret
285 ; RV64IF-LABEL: flt_s:
286 ; RV64IF:       # %bb.0:
287 ; RV64IF-NEXT:    fmv.w.x ft0, a1
288 ; RV64IF-NEXT:    fmv.w.x ft1, a0
289 ; RV64IF-NEXT:    flt.s a0, ft1, ft0
290 ; RV64IF-NEXT:    ret
291   %1 = fcmp olt float %a, %b
292   %2 = zext i1 %1 to i32
293   ret i32 %2
296 define i32 @fle_s(float %a, float %b) nounwind {
297 ; RV32IF-LABEL: fle_s:
298 ; RV32IF:       # %bb.0:
299 ; RV32IF-NEXT:    fmv.w.x ft0, a1
300 ; RV32IF-NEXT:    fmv.w.x ft1, a0
301 ; RV32IF-NEXT:    fle.s a0, ft1, ft0
302 ; RV32IF-NEXT:    ret
304 ; RV64IF-LABEL: fle_s:
305 ; RV64IF:       # %bb.0:
306 ; RV64IF-NEXT:    fmv.w.x ft0, a1
307 ; RV64IF-NEXT:    fmv.w.x ft1, a0
308 ; RV64IF-NEXT:    fle.s a0, ft1, ft0
309 ; RV64IF-NEXT:    ret
310   %1 = fcmp ole float %a, %b
311   %2 = zext i1 %1 to i32
312   ret i32 %2
315 declare float @llvm.fma.f32(float, float, float)
317 define float @fmadd_s(float %a, float %b, float %c) nounwind {
318 ; RV32IF-LABEL: fmadd_s:
319 ; RV32IF:       # %bb.0:
320 ; RV32IF-NEXT:    fmv.w.x ft0, a2
321 ; RV32IF-NEXT:    fmv.w.x ft1, a1
322 ; RV32IF-NEXT:    fmv.w.x ft2, a0
323 ; RV32IF-NEXT:    fmadd.s ft0, ft2, ft1, ft0
324 ; RV32IF-NEXT:    fmv.x.w a0, ft0
325 ; RV32IF-NEXT:    ret
327 ; RV64IF-LABEL: fmadd_s:
328 ; RV64IF:       # %bb.0:
329 ; RV64IF-NEXT:    fmv.w.x ft0, a2
330 ; RV64IF-NEXT:    fmv.w.x ft1, a1
331 ; RV64IF-NEXT:    fmv.w.x ft2, a0
332 ; RV64IF-NEXT:    fmadd.s ft0, ft2, ft1, ft0
333 ; RV64IF-NEXT:    fmv.x.w a0, ft0
334 ; RV64IF-NEXT:    ret
335   %1 = call float @llvm.fma.f32(float %a, float %b, float %c)
336   ret float %1
339 define float @fmsub_s(float %a, float %b, float %c) nounwind {
340 ; RV32IF-LABEL: fmsub_s:
341 ; RV32IF:       # %bb.0:
342 ; RV32IF-NEXT:    fmv.w.x ft0, a1
343 ; RV32IF-NEXT:    fmv.w.x ft1, a0
344 ; RV32IF-NEXT:    fmv.w.x ft2, a2
345 ; RV32IF-NEXT:    fmv.w.x ft3, zero
346 ; RV32IF-NEXT:    fadd.s ft2, ft2, ft3
347 ; RV32IF-NEXT:    fmsub.s ft0, ft1, ft0, ft2
348 ; RV32IF-NEXT:    fmv.x.w a0, ft0
349 ; RV32IF-NEXT:    ret
351 ; RV64IF-LABEL: fmsub_s:
352 ; RV64IF:       # %bb.0:
353 ; RV64IF-NEXT:    fmv.w.x ft0, a1
354 ; RV64IF-NEXT:    fmv.w.x ft1, a0
355 ; RV64IF-NEXT:    fmv.w.x ft2, a2
356 ; RV64IF-NEXT:    fmv.w.x ft3, zero
357 ; RV64IF-NEXT:    fadd.s ft2, ft2, ft3
358 ; RV64IF-NEXT:    fmsub.s ft0, ft1, ft0, ft2
359 ; RV64IF-NEXT:    fmv.x.w a0, ft0
360 ; RV64IF-NEXT:    ret
361   %c_ = fadd float 0.0, %c ; avoid negation using xor
362   %negc = fsub float -0.0, %c_
363   %1 = call float @llvm.fma.f32(float %a, float %b, float %negc)
364   ret float %1
367 define float @fnmadd_s(float %a, float %b, float %c) nounwind {
368 ; RV32IF-LABEL: fnmadd_s:
369 ; RV32IF:       # %bb.0:
370 ; RV32IF-NEXT:    fmv.w.x ft0, a1
371 ; RV32IF-NEXT:    fmv.w.x ft1, a2
372 ; RV32IF-NEXT:    fmv.w.x ft2, a0
373 ; RV32IF-NEXT:    fmv.w.x ft3, zero
374 ; RV32IF-NEXT:    fadd.s ft2, ft2, ft3
375 ; RV32IF-NEXT:    fadd.s ft1, ft1, ft3
376 ; RV32IF-NEXT:    fnmadd.s ft0, ft2, ft0, ft1
377 ; RV32IF-NEXT:    fmv.x.w a0, ft0
378 ; RV32IF-NEXT:    ret
380 ; RV64IF-LABEL: fnmadd_s:
381 ; RV64IF:       # %bb.0:
382 ; RV64IF-NEXT:    fmv.w.x ft0, a1
383 ; RV64IF-NEXT:    fmv.w.x ft1, a2
384 ; RV64IF-NEXT:    fmv.w.x ft2, a0
385 ; RV64IF-NEXT:    fmv.w.x ft3, zero
386 ; RV64IF-NEXT:    fadd.s ft2, ft2, ft3
387 ; RV64IF-NEXT:    fadd.s ft1, ft1, ft3
388 ; RV64IF-NEXT:    fnmadd.s ft0, ft2, ft0, ft1
389 ; RV64IF-NEXT:    fmv.x.w a0, ft0
390 ; RV64IF-NEXT:    ret
391   %a_ = fadd float 0.0, %a
392   %c_ = fadd float 0.0, %c
393   %nega = fsub float -0.0, %a_
394   %negc = fsub float -0.0, %c_
395   %1 = call float @llvm.fma.f32(float %nega, float %b, float %negc)
396   ret float %1
399 define float @fnmadd_s_2(float %a, float %b, float %c) nounwind {
400 ; RV32IF-LABEL: fnmadd_s_2:
401 ; RV32IF:       # %bb.0:
402 ; RV32IF-NEXT:    fmv.w.x ft0, a0
403 ; RV32IF-NEXT:    fmv.w.x ft1, a2
404 ; RV32IF-NEXT:    fmv.w.x ft2, a1
405 ; RV32IF-NEXT:    fmv.w.x ft3, zero
406 ; RV32IF-NEXT:    fadd.s ft2, ft2, ft3
407 ; RV32IF-NEXT:    fadd.s ft1, ft1, ft3
408 ; RV32IF-NEXT:    fnmadd.s ft0, ft2, ft0, ft1
409 ; RV32IF-NEXT:    fmv.x.w a0, ft0
410 ; RV32IF-NEXT:    ret
412 ; RV64IF-LABEL: fnmadd_s_2:
413 ; RV64IF:       # %bb.0:
414 ; RV64IF-NEXT:    fmv.w.x ft0, a0
415 ; RV64IF-NEXT:    fmv.w.x ft1, a2
416 ; RV64IF-NEXT:    fmv.w.x ft2, a1
417 ; RV64IF-NEXT:    fmv.w.x ft3, zero
418 ; RV64IF-NEXT:    fadd.s ft2, ft2, ft3
419 ; RV64IF-NEXT:    fadd.s ft1, ft1, ft3
420 ; RV64IF-NEXT:    fnmadd.s ft0, ft2, ft0, ft1
421 ; RV64IF-NEXT:    fmv.x.w a0, ft0
422 ; RV64IF-NEXT:    ret
423   %b_ = fadd float 0.0, %b
424   %c_ = fadd float 0.0, %c
425   %negb = fsub float -0.0, %b_
426   %negc = fsub float -0.0, %c_
427   %1 = call float @llvm.fma.f32(float %a, float %negb, float %negc)
428   ret float %1
431 define float @fnmsub_s(float %a, float %b, float %c) nounwind {
432 ; RV32IF-LABEL: fnmsub_s:
433 ; RV32IF:       # %bb.0:
434 ; RV32IF-NEXT:    fmv.w.x ft0, a2
435 ; RV32IF-NEXT:    fmv.w.x ft1, a1
436 ; RV32IF-NEXT:    fmv.w.x ft2, a0
437 ; RV32IF-NEXT:    fmv.w.x ft3, zero
438 ; RV32IF-NEXT:    fadd.s ft2, ft2, ft3
439 ; RV32IF-NEXT:    fnmsub.s ft0, ft2, ft1, ft0
440 ; RV32IF-NEXT:    fmv.x.w a0, ft0
441 ; RV32IF-NEXT:    ret
443 ; RV64IF-LABEL: fnmsub_s:
444 ; RV64IF:       # %bb.0:
445 ; RV64IF-NEXT:    fmv.w.x ft0, a2
446 ; RV64IF-NEXT:    fmv.w.x ft1, a1
447 ; RV64IF-NEXT:    fmv.w.x ft2, a0
448 ; RV64IF-NEXT:    fmv.w.x ft3, zero
449 ; RV64IF-NEXT:    fadd.s ft2, ft2, ft3
450 ; RV64IF-NEXT:    fnmsub.s ft0, ft2, ft1, ft0
451 ; RV64IF-NEXT:    fmv.x.w a0, ft0
452 ; RV64IF-NEXT:    ret
453   %a_ = fadd float 0.0, %a
454   %nega = fsub float -0.0, %a_
455   %1 = call float @llvm.fma.f32(float %nega, float %b, float %c)
456   ret float %1
459 define float @fnmsub_s_2(float %a, float %b, float %c) nounwind {
460 ; RV32IF-LABEL: fnmsub_s_2:
461 ; RV32IF:       # %bb.0:
462 ; RV32IF-NEXT:    fmv.w.x ft0, a2
463 ; RV32IF-NEXT:    fmv.w.x ft1, a0
464 ; RV32IF-NEXT:    fmv.w.x ft2, a1
465 ; RV32IF-NEXT:    fmv.w.x ft3, zero
466 ; RV32IF-NEXT:    fadd.s ft2, ft2, ft3
467 ; RV32IF-NEXT:    fnmsub.s ft0, ft2, ft1, ft0
468 ; RV32IF-NEXT:    fmv.x.w a0, ft0
469 ; RV32IF-NEXT:    ret
471 ; RV64IF-LABEL: fnmsub_s_2:
472 ; RV64IF:       # %bb.0:
473 ; RV64IF-NEXT:    fmv.w.x ft0, a2
474 ; RV64IF-NEXT:    fmv.w.x ft1, a0
475 ; RV64IF-NEXT:    fmv.w.x ft2, a1
476 ; RV64IF-NEXT:    fmv.w.x ft3, zero
477 ; RV64IF-NEXT:    fadd.s ft2, ft2, ft3
478 ; RV64IF-NEXT:    fnmsub.s ft0, ft2, ft1, ft0
479 ; RV64IF-NEXT:    fmv.x.w a0, ft0
480 ; RV64IF-NEXT:    ret
481   %b_ = fadd float 0.0, %b
482   %negb = fsub float -0.0, %b_
483   %1 = call float @llvm.fma.f32(float %a, float %negb, float %c)
484   ret float %1
487 define float @fmadd_s_contract(float %a, float %b, float %c) nounwind {
488 ; RV32IF-LABEL: fmadd_s_contract:
489 ; RV32IF:       # %bb.0:
490 ; RV32IF-NEXT:    fmv.w.x ft0, a2
491 ; RV32IF-NEXT:    fmv.w.x ft1, a1
492 ; RV32IF-NEXT:    fmv.w.x ft2, a0
493 ; RV32IF-NEXT:    fmadd.s ft0, ft2, ft1, ft0
494 ; RV32IF-NEXT:    fmv.x.w a0, ft0
495 ; RV32IF-NEXT:    ret
497 ; RV64IF-LABEL: fmadd_s_contract:
498 ; RV64IF:       # %bb.0:
499 ; RV64IF-NEXT:    fmv.w.x ft0, a2
500 ; RV64IF-NEXT:    fmv.w.x ft1, a1
501 ; RV64IF-NEXT:    fmv.w.x ft2, a0
502 ; RV64IF-NEXT:    fmadd.s ft0, ft2, ft1, ft0
503 ; RV64IF-NEXT:    fmv.x.w a0, ft0
504 ; RV64IF-NEXT:    ret
505   %1 = fmul contract float %a, %b
506   %2 = fadd contract float %1, %c
507   ret float %2
510 define float @fmsub_s_contract(float %a, float %b, float %c) nounwind {
511 ; RV32IF-LABEL: fmsub_s_contract:
512 ; RV32IF:       # %bb.0:
513 ; RV32IF-NEXT:    fmv.w.x ft0, a1
514 ; RV32IF-NEXT:    fmv.w.x ft1, a0
515 ; RV32IF-NEXT:    fmv.w.x ft2, a2
516 ; RV32IF-NEXT:    fmv.w.x ft3, zero
517 ; RV32IF-NEXT:    fadd.s ft2, ft2, ft3
518 ; RV32IF-NEXT:    fmsub.s ft0, ft1, ft0, ft2
519 ; RV32IF-NEXT:    fmv.x.w a0, ft0
520 ; RV32IF-NEXT:    ret
522 ; RV64IF-LABEL: fmsub_s_contract:
523 ; RV64IF:       # %bb.0:
524 ; RV64IF-NEXT:    fmv.w.x ft0, a1
525 ; RV64IF-NEXT:    fmv.w.x ft1, a0
526 ; RV64IF-NEXT:    fmv.w.x ft2, a2
527 ; RV64IF-NEXT:    fmv.w.x ft3, zero
528 ; RV64IF-NEXT:    fadd.s ft2, ft2, ft3
529 ; RV64IF-NEXT:    fmsub.s ft0, ft1, ft0, ft2
530 ; RV64IF-NEXT:    fmv.x.w a0, ft0
531 ; RV64IF-NEXT:    ret
532   %c_ = fadd float 0.0, %c ; avoid negation using xor
533   %1 = fmul contract float %a, %b
534   %2 = fsub contract float %1, %c_
535   ret float %2
538 define float @fnmadd_s_contract(float %a, float %b, float %c) nounwind {
539 ; RV32IF-LABEL: fnmadd_s_contract:
540 ; RV32IF:       # %bb.0:
541 ; RV32IF-NEXT:    fmv.w.x ft0, a2
542 ; RV32IF-NEXT:    fmv.w.x ft1, a1
543 ; RV32IF-NEXT:    fmv.w.x ft2, a0
544 ; RV32IF-NEXT:    fmv.w.x ft3, zero
545 ; RV32IF-NEXT:    fadd.s ft2, ft2, ft3
546 ; RV32IF-NEXT:    fadd.s ft1, ft1, ft3
547 ; RV32IF-NEXT:    fadd.s ft0, ft0, ft3
548 ; RV32IF-NEXT:    fnmadd.s ft0, ft2, ft1, ft0
549 ; RV32IF-NEXT:    fmv.x.w a0, ft0
550 ; RV32IF-NEXT:    ret
552 ; RV64IF-LABEL: fnmadd_s_contract:
553 ; RV64IF:       # %bb.0:
554 ; RV64IF-NEXT:    fmv.w.x ft0, a2
555 ; RV64IF-NEXT:    fmv.w.x ft1, a1
556 ; RV64IF-NEXT:    fmv.w.x ft2, a0
557 ; RV64IF-NEXT:    fmv.w.x ft3, zero
558 ; RV64IF-NEXT:    fadd.s ft2, ft2, ft3
559 ; RV64IF-NEXT:    fadd.s ft1, ft1, ft3
560 ; RV64IF-NEXT:    fadd.s ft0, ft0, ft3
561 ; RV64IF-NEXT:    fnmadd.s ft0, ft2, ft1, ft0
562 ; RV64IF-NEXT:    fmv.x.w a0, ft0
563 ; RV64IF-NEXT:    ret
564   %a_ = fadd float 0.0, %a ; avoid negation using xor
565   %b_ = fadd float 0.0, %b ; avoid negation using xor
566   %c_ = fadd float 0.0, %c ; avoid negation using xor
567   %1 = fmul contract float %a_, %b_
568   %2 = fneg float %1
569   %3 = fsub contract float %2, %c_
570   ret float %3
573 define float @fnmsub_s_contract(float %a, float %b, float %c) nounwind {
574 ; RV32IF-LABEL: fnmsub_s_contract:
575 ; RV32IF:       # %bb.0:
576 ; RV32IF-NEXT:    fmv.w.x ft0, a2
577 ; RV32IF-NEXT:    fmv.w.x ft1, a1
578 ; RV32IF-NEXT:    fmv.w.x ft2, a0
579 ; RV32IF-NEXT:    fmv.w.x ft3, zero
580 ; RV32IF-NEXT:    fadd.s ft2, ft2, ft3
581 ; RV32IF-NEXT:    fadd.s ft1, ft1, ft3
582 ; RV32IF-NEXT:    fnmsub.s ft0, ft2, ft1, ft0
583 ; RV32IF-NEXT:    fmv.x.w a0, ft0
584 ; RV32IF-NEXT:    ret
586 ; RV64IF-LABEL: fnmsub_s_contract:
587 ; RV64IF:       # %bb.0:
588 ; RV64IF-NEXT:    fmv.w.x ft0, a2
589 ; RV64IF-NEXT:    fmv.w.x ft1, a1
590 ; RV64IF-NEXT:    fmv.w.x ft2, a0
591 ; RV64IF-NEXT:    fmv.w.x ft3, zero
592 ; RV64IF-NEXT:    fadd.s ft2, ft2, ft3
593 ; RV64IF-NEXT:    fadd.s ft1, ft1, ft3
594 ; RV64IF-NEXT:    fnmsub.s ft0, ft2, ft1, ft0
595 ; RV64IF-NEXT:    fmv.x.w a0, ft0
596 ; RV64IF-NEXT:    ret
597   %a_ = fadd float 0.0, %a ; avoid negation using xor
598   %b_ = fadd float 0.0, %b ; avoid negation using xor
599   %1 = fmul contract float %a_, %b_
600   %2 = fsub contract float %c, %1
601   ret float %2