| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py | |
| ; RUN: llc -mtriple=riscv32 -target-abi ilp32f -mattr=+zfa < %s \ | |
| ; RUN: | FileCheck %s | |
| ; RUN: llc -mtriple=riscv64 -target-abi lp64f -mattr=+zfa < %s \ | |
| ; RUN: | FileCheck %s | |
| define float @loadfpimm1() { | |
| ; CHECK-LABEL: loadfpimm1: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: fli.s fa0, 0.0625 | |
| ; CHECK-NEXT: ret | |
| ret float 0.0625 | |
| } | |
| define float @loadfpimm2() { | |
| ; CHECK-LABEL: loadfpimm2: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: fli.s fa0, 0.75 | |
| ; CHECK-NEXT: ret | |
| ret float 0.75 | |
| } | |
| define float @loadfpimm3() { | |
| ; CHECK-LABEL: loadfpimm3: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: fli.s fa0, 1.25 | |
| ; CHECK-NEXT: ret | |
| ret float 1.25 | |
| } | |
| define float @loadfpimm4() { | |
| ; CHECK-LABEL: loadfpimm4: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: fli.s fa0, 3.0 | |
| ; CHECK-NEXT: ret | |
| ret float 3.0 | |
| } | |
| define float @loadfpimm5() { | |
| ; CHECK-LABEL: loadfpimm5: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: fli.s fa0, 256.0 | |
| ; CHECK-NEXT: ret | |
| ret float 256.0 | |
| } | |
| define float @loadfpimm6() { | |
| ; CHECK-LABEL: loadfpimm6: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: fli.s fa0, inf | |
| ; CHECK-NEXT: ret | |
| ret float +inf | |
| } | |
| define float @loadfpimm7() { | |
| ; CHECK-LABEL: loadfpimm7: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: fli.s fa0, nan | |
| ; CHECK-NEXT: ret | |
| ret float +qnan | |
| } | |
| define float @loadfpimm8() { | |
| ; CHECK-LABEL: loadfpimm8: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: fli.s fa0, min | |
| ; CHECK-NEXT: ret | |
| ret float 0x3810000000000000 | |
| } | |
| define float @loadfpimm9() { | |
| ; CHECK-LABEL: loadfpimm9: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: lui a0, 276464 | |
| ; CHECK-NEXT: fmv.w.x fa0, a0 | |
| ; CHECK-NEXT: ret | |
| ret float 255.0 | |
| } | |
| ; This is the f16 minimum value. Make sure we don't use fli.s. | |
| define float @loadfpimm10() { | |
| ; CHECK-LABEL: loadfpimm10: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: lui a0, 231424 | |
| ; CHECK-NEXT: fmv.w.x fa0, a0 | |
| ; CHECK-NEXT: ret | |
| ret float 0.00006103515625 | |
| } | |
| define float @loadfpimm11() { | |
| ; CHECK-LABEL: loadfpimm11: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: fli.s fa0, -1.0 | |
| ; CHECK-NEXT: ret | |
| ret float -1.0 | |
| } | |
| ; Ensure fli isn't directly used for negated versions of numbers in the fli | |
| ; table. | |
| define float @loadfpimm12() { | |
| ; CHECK-LABEL: loadfpimm12: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: fli.s fa5, 2.0 | |
| ; CHECK-NEXT: fneg.s fa0, fa5 | |
| ; CHECK-NEXT: ret | |
| ret float -2.0 | |
| } | |
| ; Ensure fli isn't directly used for negative min normal value. | |
| define float @loadfpimm13() { | |
| ; CHECK-LABEL: loadfpimm13: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: fli.s fa5, min | |
| ; CHECK-NEXT: fneg.s fa0, fa5 | |
| ; CHECK-NEXT: ret | |
| ret float 0xb810000000000000 | |
| } | |
| define float @fminm_s(float %a, float %b) nounwind { | |
| ; CHECK-LABEL: fminm_s: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: fminm.s fa0, fa0, fa1 | |
| ; CHECK-NEXT: ret | |
| %1 = call float @llvm.minimum.f32(float %a, float %b) | |
| ret float %1 | |
| } | |
| define float @fmaxm_s(float %a, float %b) nounwind { | |
| ; CHECK-LABEL: fmaxm_s: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: fmaxm.s fa0, fa0, fa1 | |
| ; CHECK-NEXT: ret | |
| %1 = call float @llvm.maximum.f32(float %a, float %b) | |
| ret float %1 | |
| } | |
| define float @fround_s_1(float %a) nounwind { | |
| ; CHECK-LABEL: fround_s_1: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: fround.s fa0, fa0, rmm | |
| ; CHECK-NEXT: ret | |
| %call = tail call float @llvm.round.f32(float %a) nounwind readnone | |
| ret float %call | |
| } | |
| declare float @llvm.round.f32(float) nounwind readnone | |
| define float @fround_s_2(float %a) nounwind { | |
| ; CHECK-LABEL: fround_s_2: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: fround.s fa0, fa0, rdn | |
| ; CHECK-NEXT: ret | |
| %call = tail call float @llvm.floor.f32(float %a) nounwind readnone | |
| ret float %call | |
| } | |
| declare float @llvm.floor.f32(float) nounwind readnone | |
| define float @fround_s_3(float %a) nounwind { | |
| ; CHECK-LABEL: fround_s_3: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: fround.s fa0, fa0, rup | |
| ; CHECK-NEXT: ret | |
| %call = tail call float @llvm.ceil.f32(float %a) nounwind readnone | |
| ret float %call | |
| } | |
| declare float @llvm.ceil.f32(float) nounwind readnone | |
| define float @fround_s_4(float %a) nounwind { | |
| ; CHECK-LABEL: fround_s_4: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: fround.s fa0, fa0, rtz | |
| ; CHECK-NEXT: ret | |
| %call = tail call float @llvm.trunc.f32(float %a) nounwind readnone | |
| ret float %call | |
| } | |
| declare float @llvm.trunc.f32(float) nounwind readnone | |
| define float @fround_s_5(float %a) nounwind { | |
| ; CHECK-LABEL: fround_s_5: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: fround.s fa0, fa0 | |
| ; CHECK-NEXT: ret | |
| %call = tail call float @llvm.nearbyint.f32(float %a) nounwind readnone | |
| ret float %call | |
| } | |
| define float @fround_s_6(float %a) nounwind { | |
| ; CHECK-LABEL: fround_s_6: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: fround.s fa0, fa0, rne | |
| ; CHECK-NEXT: ret | |
| %call = tail call float @llvm.roundeven.f32(float %a) nounwind readnone | |
| ret float %call | |
| } | |
| define float @froundnx_s(float %a) nounwind { | |
| ; CHECK-LABEL: froundnx_s: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: froundnx.s fa0, fa0 | |
| ; CHECK-NEXT: ret | |
| %call = tail call float @llvm.rint.f32(float %a) nounwind readnone | |
| ret float %call | |
| } | |
| declare float @llvm.rint.f32(float) nounwind readnone | |
| define i32 @fcmp_olt_q(float %a, float %b) nounwind strictfp { | |
| ; CHECK-LABEL: fcmp_olt_q: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: fltq.s a0, fa0, fa1 | |
| ; CHECK-NEXT: ret | |
| %1 = call i1 @llvm.experimental.constrained.fcmp.f32(float %a, float %b, metadata !"olt", metadata !"fpexcept.strict") strictfp | |
| %2 = zext i1 %1 to i32 | |
| ret i32 %2 | |
| } | |
| define i32 @fcmp_ole_q(float %a, float %b) nounwind strictfp { | |
| ; CHECK-LABEL: fcmp_ole_q: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: fleq.s a0, fa0, fa1 | |
| ; CHECK-NEXT: ret | |
| %1 = call i1 @llvm.experimental.constrained.fcmp.f32(float %a, float %b, metadata !"ole", metadata !"fpexcept.strict") strictfp | |
| %2 = zext i1 %1 to i32 | |
| ret i32 %2 | |
| } | |
| define i32 @fcmp_one_q(float %a, float %b) nounwind strictfp { | |
| ; CHECK-LABEL: fcmp_one_q: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: fltq.s a0, fa0, fa1 | |
| ; CHECK-NEXT: fltq.s a1, fa1, fa0 | |
| ; CHECK-NEXT: or a0, a1, a0 | |
| ; CHECK-NEXT: ret | |
| %1 = call i1 @llvm.experimental.constrained.fcmp.f32(float %a, float %b, metadata !"one", metadata !"fpexcept.strict") strictfp | |
| %2 = zext i1 %1 to i32 | |
| ret i32 %2 | |
| } | |
| define i32 @fcmp_ueq_q(float %a, float %b) nounwind strictfp { | |
| ; CHECK-LABEL: fcmp_ueq_q: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: fltq.s a0, fa0, fa1 | |
| ; CHECK-NEXT: fltq.s a1, fa1, fa0 | |
| ; CHECK-NEXT: or a0, a1, a0 | |
| ; CHECK-NEXT: xori a0, a0, 1 | |
| ; CHECK-NEXT: ret | |
| %1 = call i1 @llvm.experimental.constrained.fcmp.f32(float %a, float %b, metadata !"ueq", metadata !"fpexcept.strict") strictfp | |
| %2 = zext i1 %1 to i32 | |
| ret i32 %2 | |
| } | |
| declare void @foo(float, float) | |
| ; Make sure we use two fli instructions instead of copying. | |
| define void @fli_remat() { | |
| ; CHECK-LABEL: fli_remat: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: fli.s fa0, 1.0 | |
| ; CHECK-NEXT: fli.s fa1, 1.0 | |
| ; CHECK-NEXT: tail foo | |
| tail call void @foo(float 1.000000e+00, float 1.000000e+00) | |
| ret void | |
| } | |
| define float @fadd_neg_0p5(float %x) { | |
| ; CHECK-LABEL: fadd_neg_0p5: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: fli.s fa5, 0.5 | |
| ; CHECK-NEXT: fsub.s fa0, fa0, fa5 | |
| ; CHECK-NEXT: ret | |
| %a = fadd float %x, -0.5 | |
| ret float %a | |
| } | |
| define float @fma_neg_addend(float %x, float %y) nounwind { | |
| ; CHECK-LABEL: fma_neg_addend: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: fli.s fa5, 0.5 | |
| ; CHECK-NEXT: fmsub.s fa0, fa0, fa1, fa5 | |
| ; CHECK-NEXT: ret | |
| %a = call float @llvm.fma.f32(float %x, float %y, float -0.5) | |
| ret float %a | |
| } | |
| define float @fma_neg_multiplicand(float %x, float %y) nounwind { | |
| ; CHECK-LABEL: fma_neg_multiplicand: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: fli.s fa5, 0.125 | |
| ; CHECK-NEXT: fnmsub.s fa0, fa5, fa0, fa1 | |
| ; CHECK-NEXT: ret | |
| %a = call float @llvm.fma.f32(float %x, float -0.125, float %y) | |
| ret float %a | |
| } | |
| define float @fma_neg_addend_multiplicand(float %x) nounwind { | |
| ; CHECK-LABEL: fma_neg_addend_multiplicand: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: fli.s fa5, 0.25 | |
| ; CHECK-NEXT: fli.s fa4, 0.5 | |
| ; CHECK-NEXT: fnmadd.s fa0, fa4, fa0, fa5 | |
| ; CHECK-NEXT: ret | |
| %a = call float @llvm.fma.f32(float %x, float -0.5, float -0.25) | |
| ret float %a | |
| } | |
| define float @select_loadfpimm(float %x) nounwind { | |
| ; CHECK-LABEL: select_loadfpimm: | |
| ; CHECK: # %bb.0: # %entry | |
| ; CHECK-NEXT: fmv.w.x fa5, zero | |
| ; CHECK-NEXT: fle.s a0, fa5, fa0 | |
| ; CHECK-NEXT: fli.s fa0, 0.5 | |
| ; CHECK-NEXT: bnez a0, .LBB31_2 | |
| ; CHECK-NEXT: # %bb.1: | |
| ; CHECK-NEXT: fneg.s fa0, fa0 | |
| ; CHECK-NEXT: .LBB31_2: # %entry | |
| ; CHECK-NEXT: ret | |
| entry: | |
| %cmp = fcmp ult float %x, 0.000000e+00 | |
| %sel = select i1 %cmp, float -5.000000e-01, float 5.000000e-01 | |
| ret float %sel | |
| } |