; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc -mtriple=riscv32 -target-abi ilp32d -mattr=+zfa,+d < %s \ ; RUN: | FileCheck --check-prefixes=CHECK,RV32IDZFA %s ; RUN: llc -mtriple=riscv64 -target-abi lp64d -mattr=+zfa,+d < %s \ ; RUN: | FileCheck --check-prefixes=CHECK,RV64DZFA %s define double @loadfpimm1() { ; CHECK-LABEL: loadfpimm1: ; CHECK: # %bb.0: ; CHECK-NEXT: fli.d fa0, 0.0625 ; CHECK-NEXT: ret ret double 0.0625 } define double @loadfpimm2() { ; CHECK-LABEL: loadfpimm2: ; CHECK: # %bb.0: ; CHECK-NEXT: fli.d fa0, 0.75 ; CHECK-NEXT: ret ret double 0.75 } define double @loadfpimm3() { ; CHECK-LABEL: loadfpimm3: ; CHECK: # %bb.0: ; CHECK-NEXT: fli.d fa0, 1.25 ; CHECK-NEXT: ret ret double 1.25 } define double @loadfpimm4() { ; CHECK-LABEL: loadfpimm4: ; CHECK: # %bb.0: ; CHECK-NEXT: fli.d fa0, 3.0 ; CHECK-NEXT: ret ret double 3.0 } define double @loadfpimm5() { ; CHECK-LABEL: loadfpimm5: ; CHECK: # %bb.0: ; CHECK-NEXT: fli.d fa0, 256.0 ; CHECK-NEXT: ret ret double 256.0 } define double @loadfpimm6() { ; CHECK-LABEL: loadfpimm6: ; CHECK: # %bb.0: ; CHECK-NEXT: fli.d fa0, inf ; CHECK-NEXT: ret ret double 0x7FF0000000000000 } define double @loadfpimm7() { ; CHECK-LABEL: loadfpimm7: ; CHECK: # %bb.0: ; CHECK-NEXT: fli.d fa0, nan ; CHECK-NEXT: ret ret double 0x7FF8000000000000 } define double @loadfpimm8() { ; CHECK-LABEL: loadfpimm8: ; CHECK: # %bb.0: ; CHECK-NEXT: fli.d fa0, min ; CHECK-NEXT: ret ret double 0x0010000000000000 } define double @loadfpimm9() { ; RV32IDZFA-LABEL: loadfpimm9: ; RV32IDZFA: # %bb.0: ; RV32IDZFA-NEXT: lui a0, %hi(.LCPI8_0) ; RV32IDZFA-NEXT: fld fa0, %lo(.LCPI8_0)(a0) ; RV32IDZFA-NEXT: ret ; ; RV64DZFA-LABEL: loadfpimm9: ; RV64DZFA: # %bb.0: ; RV64DZFA-NEXT: lui a0, 131967 ; RV64DZFA-NEXT: slli a0, a0, 33 ; RV64DZFA-NEXT: fmv.d.x fa0, a0 ; RV64DZFA-NEXT: ret ret double 255.0 } ; Negative test. This is 1 * 2^256. define double @loadfpimm10() { ; RV32IDZFA-LABEL: loadfpimm10: ; RV32IDZFA: # %bb.0: ; RV32IDZFA-NEXT: lui a0, %hi(.LCPI9_0) ; RV32IDZFA-NEXT: fld fa0, %lo(.LCPI9_0)(a0) ; RV32IDZFA-NEXT: ret ; ; RV64DZFA-LABEL: loadfpimm10: ; RV64DZFA: # %bb.0: ; RV64DZFA-NEXT: li a0, 1 ; RV64DZFA-NEXT: slli a0, a0, 60 ; RV64DZFA-NEXT: fmv.d.x fa0, a0 ; RV64DZFA-NEXT: ret ret double 0x1000000000000000 } ; Negative test. This is a qnan with payload of 1. define double @loadfpimm11() { ; CHECK-LABEL: loadfpimm11: ; CHECK: # %bb.0: ; CHECK-NEXT: lui a0, %hi(.LCPI10_0) ; CHECK-NEXT: fld fa0, %lo(.LCPI10_0)(a0) ; CHECK-NEXT: ret ret double 0x7ff8000000000001 } ; Negative test. This is an snan with payload of 1. define double @loadfpimm12() { ; CHECK-LABEL: loadfpimm12: ; CHECK: # %bb.0: ; CHECK-NEXT: lui a0, %hi(.LCPI11_0) ; CHECK-NEXT: fld fa0, %lo(.LCPI11_0)(a0) ; CHECK-NEXT: ret ret double 0x7ff0000000000001 } ; Negative test. This is the smallest denormal. define double @loadfpimm13() { ; RV32IDZFA-LABEL: loadfpimm13: ; RV32IDZFA: # %bb.0: ; RV32IDZFA-NEXT: lui a0, %hi(.LCPI12_0) ; RV32IDZFA-NEXT: fld fa0, %lo(.LCPI12_0)(a0) ; RV32IDZFA-NEXT: ret ; ; RV64DZFA-LABEL: loadfpimm13: ; RV64DZFA: # %bb.0: ; RV64DZFA-NEXT: li a0, 1 ; RV64DZFA-NEXT: fmv.d.x fa0, a0 ; RV64DZFA-NEXT: ret ret double 0x0000000000000001 } ; Negative test. This is 2^-1023, a denormal. define double @loadfpimm15() { ; RV32IDZFA-LABEL: loadfpimm15: ; RV32IDZFA: # %bb.0: ; RV32IDZFA-NEXT: lui a0, %hi(.LCPI13_0) ; RV32IDZFA-NEXT: fld fa0, %lo(.LCPI13_0)(a0) ; RV32IDZFA-NEXT: ret ; ; RV64DZFA-LABEL: loadfpimm15: ; RV64DZFA: # %bb.0: ; RV64DZFA-NEXT: li a0, 1 ; RV64DZFA-NEXT: slli a0, a0, 51 ; RV64DZFA-NEXT: fmv.d.x fa0, a0 ; RV64DZFA-NEXT: ret ret double 0x0008000000000000 } define double @loadfpimm16() { ; CHECK-LABEL: loadfpimm16: ; CHECK: # %bb.0: ; CHECK-NEXT: fli.d fa0, -1.0 ; CHECK-NEXT: ret ret double -1.0 } ; Ensure fli isn't directly used for negated versions of numbers in the fli ; table. define double @loadfpimm17() { ; CHECK-LABEL: loadfpimm17: ; CHECK: # %bb.0: ; CHECK-NEXT: fli.d fa5, 2.0 ; CHECK-NEXT: fneg.d fa0, fa5 ; CHECK-NEXT: ret ret double -2.0 } ; Ensure fli isn't directly used for negative min normal value. define double @loadfpimm18() { ; CHECK-LABEL: loadfpimm18: ; CHECK: # %bb.0: ; CHECK-NEXT: fli.d fa5, min ; CHECK-NEXT: fneg.d fa0, fa5 ; CHECK-NEXT: ret ret double 0x8010000000000000 } define double @fminm_d(double %a, double %b) nounwind { ; CHECK-LABEL: fminm_d: ; CHECK: # %bb.0: ; CHECK-NEXT: fminm.d fa0, fa0, fa1 ; CHECK-NEXT: ret %1 = call double @llvm.minimum.f64(double %a, double %b) ret double %1 } define double @fmaxm_d(double %a, double %b) nounwind { ; CHECK-LABEL: fmaxm_d: ; CHECK: # %bb.0: ; CHECK-NEXT: fmaxm.d fa0, fa0, fa1 ; CHECK-NEXT: ret %1 = call double @llvm.maximum.f64(double %a, double %b) ret double %1 } define double @fround_d_1(double %a) nounwind { ; CHECK-LABEL: fround_d_1: ; CHECK: # %bb.0: ; CHECK-NEXT: fround.d fa0, fa0, rmm ; CHECK-NEXT: ret %call = tail call double @llvm.round.f64(double %a) nounwind readnone ret double %call } declare double @llvm.round.f64(double) nounwind readnone define double @fround_d_2(double %a) nounwind { ; CHECK-LABEL: fround_d_2: ; CHECK: # %bb.0: ; CHECK-NEXT: fround.d fa0, fa0, rdn ; CHECK-NEXT: ret %call = tail call double @llvm.floor.f64(double %a) nounwind readnone ret double %call } declare double @llvm.floor.f64(double) nounwind readnone define double @fround_d_3(double %a) nounwind { ; CHECK-LABEL: fround_d_3: ; CHECK: # %bb.0: ; CHECK-NEXT: fround.d fa0, fa0, rup ; CHECK-NEXT: ret %call = tail call double @llvm.ceil.f64(double %a) nounwind readnone ret double %call } declare double @llvm.ceil.f64(double) nounwind readnone define double @fround_d_4(double %a) nounwind { ; CHECK-LABEL: fround_d_4: ; CHECK: # %bb.0: ; CHECK-NEXT: fround.d fa0, fa0, rtz ; CHECK-NEXT: ret %call = tail call double @llvm.trunc.f64(double %a) nounwind readnone ret double %call } declare double @llvm.trunc.f64(double) nounwind readnone define double @fround_d_5(double %a) nounwind { ; CHECK-LABEL: fround_d_5: ; CHECK: # %bb.0: ; CHECK-NEXT: fround.d fa0, fa0 ; CHECK-NEXT: ret %call = tail call double @llvm.nearbyint.f64(double %a) nounwind readnone ret double %call } define double @fround_d_6(double %a) nounwind { ; CHECK-LABEL: fround_d_6: ; CHECK: # %bb.0: ; CHECK-NEXT: fround.d fa0, fa0, rne ; CHECK-NEXT: ret %call = tail call double @llvm.roundeven.f64(double %a) nounwind readnone ret double %call } define double @froundnx_d(double %a) nounwind { ; CHECK-LABEL: froundnx_d: ; CHECK: # %bb.0: ; CHECK-NEXT: froundnx.d fa0, fa0 ; CHECK-NEXT: ret %call = tail call double @llvm.rint.f64(double %a) nounwind readnone ret double %call } declare double @llvm.rint.f64(double) nounwind readnone define i32 @fcmp_olt_q(double %a, double %b) nounwind strictfp { ; CHECK-LABEL: fcmp_olt_q: ; CHECK: # %bb.0: ; CHECK-NEXT: fltq.d a0, fa0, fa1 ; CHECK-NEXT: ret %1 = call i1 @llvm.experimental.constrained.fcmp.f64(double %a, double %b, metadata !"olt", metadata !"fpexcept.strict") strictfp %2 = zext i1 %1 to i32 ret i32 %2 } define i32 @fcmp_ole_q(double %a, double %b) nounwind strictfp { ; CHECK-LABEL: fcmp_ole_q: ; CHECK: # %bb.0: ; CHECK-NEXT: fleq.d a0, fa0, fa1 ; CHECK-NEXT: ret %1 = call i1 @llvm.experimental.constrained.fcmp.f64(double %a, double %b, metadata !"ole", metadata !"fpexcept.strict") strictfp %2 = zext i1 %1 to i32 ret i32 %2 } define i32 @fcmp_one_q(double %a, double %b) nounwind strictfp { ; CHECK-LABEL: fcmp_one_q: ; CHECK: # %bb.0: ; CHECK-NEXT: fltq.d a0, fa0, fa1 ; CHECK-NEXT: fltq.d a1, fa1, fa0 ; CHECK-NEXT: or a0, a1, a0 ; CHECK-NEXT: ret %1 = call i1 @llvm.experimental.constrained.fcmp.f64(double %a, double %b, metadata !"one", metadata !"fpexcept.strict") strictfp %2 = zext i1 %1 to i32 ret i32 %2 } define i32 @fcmp_ueq_q(double %a, double %b) nounwind strictfp { ; CHECK-LABEL: fcmp_ueq_q: ; CHECK: # %bb.0: ; CHECK-NEXT: fltq.d a0, fa0, fa1 ; CHECK-NEXT: fltq.d 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.f64(double %a, double %b, metadata !"ueq", metadata !"fpexcept.strict") strictfp %2 = zext i1 %1 to i32 ret i32 %2 } define i64 @fmvh_x_d(double %fa) { ; RV32IDZFA-LABEL: fmvh_x_d: ; RV32IDZFA: # %bb.0: ; RV32IDZFA-NEXT: fmv.x.w a0, fa0 ; RV32IDZFA-NEXT: fmvh.x.d a1, fa0 ; RV32IDZFA-NEXT: ret ; ; RV64DZFA-LABEL: fmvh_x_d: ; RV64DZFA: # %bb.0: ; RV64DZFA-NEXT: fmv.x.d a0, fa0 ; RV64DZFA-NEXT: ret %i = bitcast double %fa to i64 ret i64 %i } define double @fmvp_d_x(i64 %a) { ; RV32IDZFA-LABEL: fmvp_d_x: ; RV32IDZFA: # %bb.0: ; RV32IDZFA-NEXT: fmvp.d.x fa0, a0, a1 ; RV32IDZFA-NEXT: ret ; ; RV64DZFA-LABEL: fmvp_d_x: ; RV64DZFA: # %bb.0: ; RV64DZFA-NEXT: fmv.d.x fa0, a0 ; RV64DZFA-NEXT: ret %or = bitcast i64 %a to double ret double %or } define double @fadd_neg_0p5(double %x) { ; CHECK-LABEL: fadd_neg_0p5: ; CHECK: # %bb.0: ; CHECK-NEXT: fli.d fa5, 0.5 ; CHECK-NEXT: fsub.d fa0, fa0, fa5 ; CHECK-NEXT: ret %a = fadd double %x, -0.5 ret double %a } define double @fma_neg_addend(double %x, double %y) nounwind { ; CHECK-LABEL: fma_neg_addend: ; CHECK: # %bb.0: ; CHECK-NEXT: fli.d fa5, 0.5 ; CHECK-NEXT: fmsub.d fa0, fa0, fa1, fa5 ; CHECK-NEXT: ret %a = call double @llvm.fma.f32(double %x, double %y, double -0.5) ret double %a } define double @fma_neg_multiplicand(double %x, double %y) nounwind { ; CHECK-LABEL: fma_neg_multiplicand: ; CHECK: # %bb.0: ; CHECK-NEXT: fli.d fa5, 0.125 ; CHECK-NEXT: fnmsub.d fa0, fa5, fa0, fa1 ; CHECK-NEXT: ret %a = call double @llvm.fma.f32(double %x, double -0.125, double %y) ret double %a } define double @fma_neg_addend_multiplicand(double %x) nounwind { ; CHECK-LABEL: fma_neg_addend_multiplicand: ; CHECK: # %bb.0: ; CHECK-NEXT: fli.d fa5, 0.25 ; CHECK-NEXT: fli.d fa4, 0.5 ; CHECK-NEXT: fnmadd.d fa0, fa4, fa0, fa5 ; CHECK-NEXT: ret %a = call double @llvm.fma.f32(double %x, double -0.5, double -0.25) ret double %a } define double @select_loadfpimm(double %x) nounwind { ; RV32IDZFA-LABEL: select_loadfpimm: ; RV32IDZFA: # %bb.0: # %entry ; RV32IDZFA-NEXT: fcvt.d.w fa5, zero ; RV32IDZFA-NEXT: fle.d a0, fa5, fa0 ; RV32IDZFA-NEXT: fli.d fa0, 0.5 ; RV32IDZFA-NEXT: bnez a0, .LBB36_2 ; RV32IDZFA-NEXT: # %bb.1: ; RV32IDZFA-NEXT: fneg.d fa0, fa0 ; RV32IDZFA-NEXT: .LBB36_2: # %entry ; RV32IDZFA-NEXT: ret ; ; RV64DZFA-LABEL: select_loadfpimm: ; RV64DZFA: # %bb.0: # %entry ; RV64DZFA-NEXT: fmv.d.x fa5, zero ; RV64DZFA-NEXT: fle.d a0, fa5, fa0 ; RV64DZFA-NEXT: fli.d fa0, 0.5 ; RV64DZFA-NEXT: bnez a0, .LBB36_2 ; RV64DZFA-NEXT: # %bb.1: ; RV64DZFA-NEXT: fneg.d fa0, fa0 ; RV64DZFA-NEXT: .LBB36_2: # %entry ; RV64DZFA-NEXT: ret entry: %cmp = fcmp ult double %x, 0.000000e+00 %sel = select i1 %cmp, double -5.000000e-01, double 5.000000e-01 ret double %sel }