diff --git a/llvm/test/CodeGen/RISCV/fp-convert-indirect.ll b/llvm/test/CodeGen/RISCV/fp-convert-indirect.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/fp-convert-indirect.ll @@ -0,0 +1,97 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -mattr=+f -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV32IF %s +; RUN: llc -mtriple=riscv32 -mattr=+f,+d -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV32IFD %s +; RUN: llc -mtriple=riscv64 -mattr=+f -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV64IF %s +; RUN: llc -mtriple=riscv64 -mattr=+f,+d -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV64IFD %s + +;; These testcases check that we merge sequences of `fcvt.d.wu; fcvt.s.d` into +;; `fcvt.s.wu`. +;; +;; TODO: Unfortunately, though this only uses 32-bit FP instructions, we cannot +;; do this optimisation without the D extension as we need 64-bit FP values to +;; be legal to get the right operands to match. + +define float @fcvt_s_w_via_d(i32 %a) nounwind { +; RV32IF-LABEL: fcvt_s_w_via_d: +; RV32IF: # %bb.0: +; RV32IF-NEXT: addi sp, sp, -16 +; RV32IF-NEXT: sw ra, 12(sp) +; RV32IF-NEXT: call __floatsidf +; RV32IF-NEXT: call __truncdfsf2 +; RV32IF-NEXT: lw ra, 12(sp) +; RV32IF-NEXT: addi sp, sp, 16 +; RV32IF-NEXT: ret +; +; RV32IFD-LABEL: fcvt_s_w_via_d: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fcvt.d.w ft0, a0 +; RV32IFD-NEXT: fcvt.s.d ft0, ft0 +; RV32IFD-NEXT: fmv.x.w a0, ft0 +; RV32IFD-NEXT: ret +; +; RV64IF-LABEL: fcvt_s_w_via_d: +; RV64IF: # %bb.0: +; RV64IF-NEXT: addi sp, sp, -16 +; RV64IF-NEXT: sd ra, 8(sp) +; RV64IF-NEXT: sext.w a0, a0 +; RV64IF-NEXT: call __floatsidf +; RV64IF-NEXT: call __truncdfsf2 +; RV64IF-NEXT: ld ra, 8(sp) +; RV64IF-NEXT: addi sp, sp, 16 +; RV64IF-NEXT: ret +; +; RV64IFD-LABEL: fcvt_s_w_via_d: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fcvt.d.w ft0, a0 +; RV64IFD-NEXT: fcvt.s.d ft0, ft0 +; RV64IFD-NEXT: fmv.x.w a0, ft0 +; RV64IFD-NEXT: ret + %1 = sitofp i32 %a to double + %2 = fptrunc double %1 to float + ret float %2 +} + +define float @fcvt_s_wu_via_d(i32 %a) nounwind { +; RV32IF-LABEL: fcvt_s_wu_via_d: +; RV32IF: # %bb.0: +; RV32IF-NEXT: addi sp, sp, -16 +; RV32IF-NEXT: sw ra, 12(sp) +; RV32IF-NEXT: call __floatunsidf +; RV32IF-NEXT: call __truncdfsf2 +; RV32IF-NEXT: lw ra, 12(sp) +; RV32IF-NEXT: addi sp, sp, 16 +; RV32IF-NEXT: ret +; +; RV32IFD-LABEL: fcvt_s_wu_via_d: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fcvt.d.wu ft0, a0 +; RV32IFD-NEXT: fcvt.s.d ft0, ft0 +; RV32IFD-NEXT: fmv.x.w a0, ft0 +; RV32IFD-NEXT: ret +; +; RV64IF-LABEL: fcvt_s_wu_via_d: +; RV64IF: # %bb.0: +; RV64IF-NEXT: addi sp, sp, -16 +; RV64IF-NEXT: sd ra, 8(sp) +; RV64IF-NEXT: slli a0, a0, 32 +; RV64IF-NEXT: srli a0, a0, 32 +; RV64IF-NEXT: call __floatunsidf +; RV64IF-NEXT: call __truncdfsf2 +; RV64IF-NEXT: ld ra, 8(sp) +; RV64IF-NEXT: addi sp, sp, 16 +; RV64IF-NEXT: ret +; +; RV64IFD-LABEL: fcvt_s_wu_via_d: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fcvt.d.wu ft0, a0 +; RV64IFD-NEXT: fcvt.s.d ft0, ft0 +; RV64IFD-NEXT: fmv.x.w a0, ft0 +; RV64IFD-NEXT: ret + %1 = uitofp i32 %a to double + %2 = fptrunc double %1 to float + ret float %2 +}