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:
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
20 ; RV64IF-LABEL: fadd_s:
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
27 %1 = fadd float %a, %b
31 define float @fsub_s(float %a, float %b) nounwind {
32 ; RV32IF-LABEL: fsub_s:
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
40 ; RV64IF-LABEL: fsub_s:
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
47 %1 = fsub float %a, %b
51 define float @fmul_s(float %a, float %b) nounwind {
52 ; RV32IF-LABEL: fmul_s:
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
60 ; RV64IF-LABEL: fmul_s:
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
67 %1 = fmul float %a, %b
71 define float @fdiv_s(float %a, float %b) nounwind {
72 ; RV32IF-LABEL: fdiv_s:
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
80 ; RV64IF-LABEL: fdiv_s:
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
87 %1 = fdiv float %a, %b
91 declare float @llvm.sqrt.f32(float)
93 define float @fsqrt_s(float %a) nounwind {
94 ; RV32IF-LABEL: fsqrt_s:
96 ; RV32IF-NEXT: fmv.w.x ft0, a0
97 ; RV32IF-NEXT: fsqrt.s ft0, ft0
98 ; RV32IF-NEXT: fmv.x.w a0, ft0
101 ; RV64IF-LABEL: fsqrt_s:
103 ; RV64IF-NEXT: fmv.w.x ft0, a0
104 ; RV64IF-NEXT: fsqrt.s ft0, ft0
105 ; RV64IF-NEXT: fmv.x.w a0, ft0
107 %1 = call float @llvm.sqrt.f32(float %a)
111 declare float @llvm.copysign.f32(float, float)
113 define float @fsgnj_s(float %a, float %b) nounwind {
114 ; RV32IF-LABEL: fsgnj_s:
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
122 ; RV64IF-LABEL: fsgnj_s:
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
129 %1 = call float @llvm.copysign.f32(float %a, float %b)
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:
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
144 ; RV64IF-LABEL: fneg_s:
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
151 %1 = fadd float %a, %a
153 %3 = fcmp oeq float %1, %2
154 %4 = zext i1 %3 to i32
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:
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
170 ; RV64IF-LABEL: fsgnjn_s:
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
178 %1 = fadd float %a, %b
180 %3 = call float @llvm.copysign.f32(float %a, float %2)
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:
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
199 ; RV64IF-LABEL: fabs_s:
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
208 %1 = fadd float %a, %b
209 %2 = call float @llvm.fabs.f32(float %1)
210 %3 = fadd float %2, %1
214 declare float @llvm.minnum.f32(float, float)
216 define float @fmin_s(float %a, float %b) nounwind {
217 ; RV32IF-LABEL: fmin_s:
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
225 ; RV64IF-LABEL: fmin_s:
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
232 %1 = call float @llvm.minnum.f32(float %a, float %b)
236 declare float @llvm.maxnum.f32(float, float)
238 define float @fmax_s(float %a, float %b) nounwind {
239 ; RV32IF-LABEL: fmax_s:
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
247 ; RV64IF-LABEL: fmax_s:
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
254 %1 = call float @llvm.maxnum.f32(float %a, float %b)
258 define i32 @feq_s(float %a, float %b) nounwind {
259 ; RV32IF-LABEL: feq_s:
261 ; RV32IF-NEXT: fmv.w.x ft0, a1
262 ; RV32IF-NEXT: fmv.w.x ft1, a0
263 ; RV32IF-NEXT: feq.s a0, ft1, ft0
266 ; RV64IF-LABEL: feq_s:
268 ; RV64IF-NEXT: fmv.w.x ft0, a1
269 ; RV64IF-NEXT: fmv.w.x ft1, a0
270 ; RV64IF-NEXT: feq.s a0, ft1, ft0
272 %1 = fcmp oeq float %a, %b
273 %2 = zext i1 %1 to i32
277 define i32 @flt_s(float %a, float %b) nounwind {
278 ; RV32IF-LABEL: flt_s:
280 ; RV32IF-NEXT: fmv.w.x ft0, a1
281 ; RV32IF-NEXT: fmv.w.x ft1, a0
282 ; RV32IF-NEXT: flt.s a0, ft1, ft0
285 ; RV64IF-LABEL: flt_s:
287 ; RV64IF-NEXT: fmv.w.x ft0, a1
288 ; RV64IF-NEXT: fmv.w.x ft1, a0
289 ; RV64IF-NEXT: flt.s a0, ft1, ft0
291 %1 = fcmp olt float %a, %b
292 %2 = zext i1 %1 to i32
296 define i32 @fle_s(float %a, float %b) nounwind {
297 ; RV32IF-LABEL: fle_s:
299 ; RV32IF-NEXT: fmv.w.x ft0, a1
300 ; RV32IF-NEXT: fmv.w.x ft1, a0
301 ; RV32IF-NEXT: fle.s a0, ft1, ft0
304 ; RV64IF-LABEL: fle_s:
306 ; RV64IF-NEXT: fmv.w.x ft0, a1
307 ; RV64IF-NEXT: fmv.w.x ft1, a0
308 ; RV64IF-NEXT: fle.s a0, ft1, ft0
310 %1 = fcmp ole float %a, %b
311 %2 = zext i1 %1 to i32
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:
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
327 ; RV64IF-LABEL: fmadd_s:
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
335 %1 = call float @llvm.fma.f32(float %a, float %b, float %c)
339 define float @fmsub_s(float %a, float %b, float %c) nounwind {
340 ; RV32IF-LABEL: fmsub_s:
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
351 ; RV64IF-LABEL: fmsub_s:
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
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)
367 define float @fnmadd_s(float %a, float %b, float %c) nounwind {
368 ; RV32IF-LABEL: fnmadd_s:
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
380 ; RV64IF-LABEL: fnmadd_s:
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
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)
399 define float @fnmadd_s_2(float %a, float %b, float %c) nounwind {
400 ; RV32IF-LABEL: fnmadd_s_2:
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
412 ; RV64IF-LABEL: fnmadd_s_2:
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
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)
431 define float @fnmsub_s(float %a, float %b, float %c) nounwind {
432 ; RV32IF-LABEL: fnmsub_s:
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
443 ; RV64IF-LABEL: fnmsub_s:
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
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)
459 define float @fnmsub_s_2(float %a, float %b, float %c) nounwind {
460 ; RV32IF-LABEL: fnmsub_s_2:
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
471 ; RV64IF-LABEL: fnmsub_s_2:
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
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)
487 define float @fmadd_s_contract(float %a, float %b, float %c) nounwind {
488 ; RV32IF-LABEL: fmadd_s_contract:
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
497 ; RV64IF-LABEL: fmadd_s_contract:
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
505 %1 = fmul contract float %a, %b
506 %2 = fadd contract float %1, %c
510 define float @fmsub_s_contract(float %a, float %b, float %c) nounwind {
511 ; RV32IF-LABEL: fmsub_s_contract:
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
522 ; RV64IF-LABEL: fmsub_s_contract:
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
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_
538 define float @fnmadd_s_contract(float %a, float %b, float %c) nounwind {
539 ; RV32IF-LABEL: fnmadd_s_contract:
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
552 ; RV64IF-LABEL: fnmadd_s_contract:
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
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_
569 %3 = fsub contract float %2, %c_
573 define float @fnmsub_s_contract(float %a, float %b, float %c) nounwind {
574 ; RV32IF-LABEL: fnmsub_s_contract:
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
586 ; RV64IF-LABEL: fnmsub_s_contract:
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
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