diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -314,6 +314,10 @@ if (Subtarget.hasStdExtZfh()) { setOperationAction(ISD::FMINNUM, MVT::f16, Legal); setOperationAction(ISD::FMAXNUM, MVT::f16, Legal); + setOperationAction(ISD::LRINT, MVT::f16, Legal); + setOperationAction(ISD::LLRINT, MVT::f16, Legal); + setOperationAction(ISD::LROUND, MVT::f16, Legal); + setOperationAction(ISD::LLROUND, MVT::f16, Legal); for (auto CC : FPCCToExpand) setCondCodeAction(CC, MVT::f16, Expand); setOperationAction(ISD::SELECT_CC, MVT::f16, Expand); @@ -326,6 +330,10 @@ if (Subtarget.hasStdExtF()) { setOperationAction(ISD::FMINNUM, MVT::f32, Legal); setOperationAction(ISD::FMAXNUM, MVT::f32, Legal); + setOperationAction(ISD::LRINT, MVT::f32, Legal); + setOperationAction(ISD::LLRINT, MVT::f32, Legal); + setOperationAction(ISD::LROUND, MVT::f32, Legal); + setOperationAction(ISD::LLROUND, MVT::f32, Legal); for (auto CC : FPCCToExpand) setCondCodeAction(CC, MVT::f32, Expand); setOperationAction(ISD::SELECT_CC, MVT::f32, Expand); @@ -343,6 +351,10 @@ if (Subtarget.hasStdExtD()) { setOperationAction(ISD::FMINNUM, MVT::f64, Legal); setOperationAction(ISD::FMAXNUM, MVT::f64, Legal); + setOperationAction(ISD::LRINT, MVT::f64, Legal); + setOperationAction(ISD::LLRINT, MVT::f64, Legal); + setOperationAction(ISD::LROUND, MVT::f64, Legal); + setOperationAction(ISD::LLROUND, MVT::f64, Legal); for (auto CC : FPCCToExpand) setCondCodeAction(CC, MVT::f64, Expand); setOperationAction(ISD::SELECT_CC, MVT::f64, Expand); diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoD.td b/llvm/lib/Target/RISCV/RISCVInstrInfoD.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoD.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoD.td @@ -331,6 +331,12 @@ def : Pat<(i32 (fp_to_sint FPR64:$rs1)), (FCVT_W_D FPR64:$rs1, 0b001)>; def : Pat<(i32 (fp_to_uint FPR64:$rs1)), (FCVT_WU_D FPR64:$rs1, 0b001)>; +// float->int32 with current rounding mode. +def : Pat<(i32 (lrint FPR64:$rs1)), (FCVT_W_D $rs1, 0b111)>; + +// float->int32 rounded to nearest with ties rounded away from zero. +def : Pat<(i32 (lround FPR64:$rs1)), (FCVT_W_D $rs1, 0b100)>; + // [u]int->double. def : Pat<(sint_to_fp (i32 GPR:$rs1)), (FCVT_D_W GPR:$rs1)>; def : Pat<(uint_to_fp (i32 GPR:$rs1)), (FCVT_D_WU GPR:$rs1)>; @@ -356,9 +362,18 @@ def : Pat<(sint_to_fp (i64 (sexti32 (i64 GPR:$rs1)))), (FCVT_D_W $rs1)>; def : Pat<(uint_to_fp (i64 (zexti32 (i64 GPR:$rs1)))), (FCVT_D_WU $rs1)>; +// double->[u]int64. Round-to-zero must be used. def : Pat<(i64 (fp_to_sint FPR64:$rs1)), (FCVT_L_D FPR64:$rs1, 0b001)>; def : Pat<(i64 (fp_to_uint FPR64:$rs1)), (FCVT_LU_D FPR64:$rs1, 0b001)>; +// double->int64 with current rounding mode. +def : Pat<(i64 (lrint FPR64:$rs1)), (FCVT_L_D $rs1, 0b111)>; +def : Pat<(i64 (llrint FPR64:$rs1)), (FCVT_L_D $rs1, 0b111)>; + +// double->int64 rounded to nearest with ties rounded away from zero. +def : Pat<(i64 (lround FPR64:$rs1)), (FCVT_L_D $rs1, 0b100)>; +def : Pat<(i64 (llround FPR64:$rs1)), (FCVT_L_D $rs1, 0b100)>; + // [u]int64->fp. Match GCC and default to using dynamic rounding mode. def : Pat<(sint_to_fp (i64 GPR:$rs1)), (FCVT_D_L GPR:$rs1, 0b111)>; def : Pat<(uint_to_fp (i64 GPR:$rs1)), (FCVT_D_LU GPR:$rs1, 0b111)>; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoF.td b/llvm/lib/Target/RISCV/RISCVInstrInfoF.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoF.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoF.td @@ -373,6 +373,12 @@ def : Pat<(i32 (fp_to_sint FPR32:$rs1)), (FCVT_W_S $rs1, 0b001)>; def : Pat<(i32 (fp_to_uint FPR32:$rs1)), (FCVT_WU_S $rs1, 0b001)>; +// float->int32 with current rounding mode. +def : Pat<(i32 (lrint FPR32:$rs1)), (FCVT_W_S $rs1, 0b111)>; + +// float->int32 rounded to nearest with ties rounded away from zero. +def : Pat<(i32 (lround FPR32:$rs1)), (FCVT_W_S $rs1, 0b100)>; + // [u]int->float. Match GCC and default to using dynamic rounding mode. def : Pat<(sint_to_fp (i32 GPR:$rs1)), (FCVT_S_W $rs1, 0b111)>; def : Pat<(uint_to_fp (i32 GPR:$rs1)), (FCVT_S_WU $rs1, 0b111)>; @@ -392,10 +398,18 @@ def : Pat<(sext_inreg (assertzexti32 (fp_to_uint FPR32:$rs1)), i32), (FCVT_WU_S $rs1, 0b001)>; -// FP->[u]int64 +// float->[u]int64. Round-to-zero must be used. def : Pat<(i64 (fp_to_sint FPR32:$rs1)), (FCVT_L_S $rs1, 0b001)>; def : Pat<(i64 (fp_to_uint FPR32:$rs1)), (FCVT_LU_S $rs1, 0b001)>; +// float->int64 with current rounding mode. +def : Pat<(i64 (lrint FPR32:$rs1)), (FCVT_L_S $rs1, 0b111)>; +def : Pat<(i64 (llrint FPR32:$rs1)), (FCVT_L_S $rs1, 0b111)>; + +// float->int64 rounded to neartest with ties rounded away from zero. +def : Pat<(i64 (lround FPR32:$rs1)), (FCVT_L_S $rs1, 0b100)>; +def : Pat<(i64 (llround FPR32:$rs1)), (FCVT_L_S $rs1, 0b100)>; + // [u]int->fp. Match GCC and default to using dynamic rounding mode. def : Pat<(sint_to_fp (i64 (sexti32 (i64 GPR:$rs1)))), (FCVT_S_W $rs1, 0b111)>; def : Pat<(uint_to_fp (i64 (zexti32 (i64 GPR:$rs1)))), (FCVT_S_WU $rs1, 0b111)>; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td @@ -334,11 +334,17 @@ } // Predicates = [HasStdExtZfh] let Predicates = [HasStdExtZfh, IsRV32] in { -// float->[u]int. Round-to-zero must be used. +// half->[u]int. Round-to-zero must be used. def : Pat<(i32 (fp_to_sint FPR16:$rs1)), (FCVT_W_H $rs1, 0b001)>; def : Pat<(i32 (fp_to_uint FPR16:$rs1)), (FCVT_WU_H $rs1, 0b001)>; -// [u]int->float. Match GCC and default to using dynamic rounding mode. +// half->int32 with current rounding mode. +def : Pat<(i32 (lrint FPR16:$rs1)), (FCVT_W_H $rs1, 0b111)>; + +// half->int32 rounded to nearest with ties rounded away from zero. +def : Pat<(i32 (lround FPR16:$rs1)), (FCVT_W_H $rs1, 0b100)>; + +// [u]int->half. Match GCC and default to using dynamic rounding mode. def : Pat<(sint_to_fp (i32 GPR:$rs1)), (FCVT_H_W $rs1, 0b111)>; def : Pat<(uint_to_fp (i32 GPR:$rs1)), (FCVT_H_WU $rs1, 0b111)>; } // Predicates = [HasStdExtZfh, IsRV32] @@ -351,10 +357,18 @@ def : Pat<(sext_inreg (assertzexti32 (fp_to_uint FPR16:$rs1)), i32), (FCVT_WU_H $rs1, 0b001)>; -// FP->[u]int64 +// half->[u]int64. Round-to-zero must be used. def : Pat<(i64 (fp_to_sint FPR16:$rs1)), (FCVT_L_H $rs1, 0b001)>; def : Pat<(i64 (fp_to_uint FPR16:$rs1)), (FCVT_LU_H $rs1, 0b001)>; +// half->int64 with current rounding mode. +def : Pat<(i64 (lrint FPR16:$rs1)), (FCVT_L_H $rs1, 0b111)>; +def : Pat<(i64 (llrint FPR16:$rs1)), (FCVT_L_H $rs1, 0b111)>; + +// half->int64 rounded to nearest with ties rounded away from zero. +def : Pat<(i64 (lround FPR16:$rs1)), (FCVT_L_H $rs1, 0b100)>; +def : Pat<(i64 (llround FPR16:$rs1)), (FCVT_L_H $rs1, 0b100)>; + // [u]int->fp. Match GCC and default to using dynamic rounding mode. def : Pat<(sint_to_fp (i64 (sexti32 (i64 GPR:$rs1)))), (FCVT_H_W $rs1, 0b111)>; def : Pat<(uint_to_fp (i64 (zexti32 (i64 GPR:$rs1)))), (FCVT_H_WU $rs1, 0b111)>; diff --git a/llvm/test/CodeGen/RISCV/double-intrinsics.ll b/llvm/test/CodeGen/RISCV/double-intrinsics.ll --- a/llvm/test/CodeGen/RISCV/double-intrinsics.ll +++ b/llvm/test/CodeGen/RISCV/double-intrinsics.ll @@ -1,8 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mtriple=riscv32 -mattr=+d -verify-machineinstrs < %s \ -; RUN: | FileCheck -check-prefix=RV32IFD %s -; RUN: llc -mtriple=riscv64 -mattr=+d -verify-machineinstrs < %s \ -; RUN: | FileCheck -check-prefix=RV64IFD %s +; RUN: sed 's/iXLen/i32/g' %s | llc -mtriple=riscv32 -mattr=+d \ +; RUN: -verify-machineinstrs | FileCheck -check-prefix=RV32IFD %s +; RUN: sed 's/iXLen/i64/g' %s | llc -mtriple=riscv64 -mattr=+d \ +; RUN: -verify-machineinstrs | FileCheck -check-prefix=RV64IFD %s declare double @llvm.sqrt.f64(double) @@ -642,3 +642,81 @@ %1 = call double @llvm.round.f64(double %a) ret double %1 } + +declare iXLen @llvm.lrint.iXLen.f64(float) + +define iXLen @lrint_f64(float %a) nounwind { +; RV32IFD-LABEL: lrint_f64: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.w.x ft0, a0 +; RV32IFD-NEXT: fcvt.w.s a0, ft0 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: lrint_f64: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.w.x ft0, a0 +; RV64IFD-NEXT: fcvt.l.s a0, ft0 +; RV64IFD-NEXT: ret + %1 = call iXLen @llvm.lrint.iXLen.f64(float %a) + ret iXLen %1 +} + +declare iXLen @llvm.lround.iXLen.f64(float) + +define iXLen @lround_f64(float %a) nounwind { +; RV32IFD-LABEL: lround_f64: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.w.x ft0, a0 +; RV32IFD-NEXT: fcvt.w.s a0, ft0, rmm +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: lround_f64: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.w.x ft0, a0 +; RV64IFD-NEXT: fcvt.l.s a0, ft0, rmm +; RV64IFD-NEXT: ret + %1 = call iXLen @llvm.lround.iXLen.f64(float %a) + ret iXLen %1 +} + +declare i64 @llvm.llrint.i64.f64(float) + +define i64 @llrint_f64(float %a) nounwind { +; RV32IFD-LABEL: llrint_f64: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: call llrintf@plt +; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: addi sp, sp, 16 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: llrint_f64: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.w.x ft0, a0 +; RV64IFD-NEXT: fcvt.l.s a0, ft0 +; RV64IFD-NEXT: ret + %1 = call i64 @llvm.llrint.i64.f64(float %a) + ret i64 %1 +} + +declare i64 @llvm.llround.i64.f64(float) + +define i64 @llround_f64(float %a) nounwind { +; RV32IFD-LABEL: llround_f64: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: call llroundf@plt +; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: addi sp, sp, 16 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: llround_f64: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.w.x ft0, a0 +; RV64IFD-NEXT: fcvt.l.s a0, ft0, rmm +; RV64IFD-NEXT: ret + %1 = call i64 @llvm.llround.i64.f64(float %a) + ret i64 %1 +} diff --git a/llvm/test/CodeGen/RISCV/float-intrinsics.ll b/llvm/test/CodeGen/RISCV/float-intrinsics.ll --- a/llvm/test/CodeGen/RISCV/float-intrinsics.ll +++ b/llvm/test/CodeGen/RISCV/float-intrinsics.ll @@ -1,12 +1,12 @@ ; 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=+d -verify-machineinstrs < %s \ -; RUN: | FileCheck -check-prefix=RV32IF %s -; RUN: llc -mtriple=riscv64 -mattr=+f -verify-machineinstrs < %s \ -; RUN: | FileCheck -check-prefix=RV64IF %s -; RUN: llc -mtriple=riscv64 -mattr=+d -verify-machineinstrs < %s \ -; RUN: | FileCheck -check-prefix=RV64IF %s +; RUN: sed 's/iXLen/i32/g' %s | llc -mtriple=riscv32 -mattr=+f \ +; RUN: -verify-machineinstrs | FileCheck -check-prefix=RV32IF %s +; RUN: sed 's/iXLen/i32/g' %s | llc -mtriple=riscv32 -mattr=+d \ +; RUN: -verify-machineinstrs | FileCheck -check-prefix=RV32IF %s +; RUN: sed 's/iXLen/i64/g' %s | llc -mtriple=riscv64 -mattr=+f \ +; RUN: -verify-machineinstrs | FileCheck -check-prefix=RV64IF %s +; RUN: sed 's/iXLen/i64/g' %s | llc -mtriple=riscv64 -mattr=+d \ +; RUN: -verify-machineinstrs | FileCheck -check-prefix=RV64IF %s declare float @llvm.sqrt.f32(float) @@ -586,3 +586,81 @@ %1 = call float @llvm.round.f32(float %a) ret float %1 } + +declare iXLen @llvm.lrint.iXLen.f32(float) + +define iXLen @lrint_f32(float %a) nounwind { +; RV32IF-LABEL: lrint_f32: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.w.x ft0, a0 +; RV32IF-NEXT: fcvt.w.s a0, ft0 +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: lrint_f32: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.w.x ft0, a0 +; RV64IF-NEXT: fcvt.l.s a0, ft0 +; RV64IF-NEXT: ret + %1 = call iXLen @llvm.lrint.iXLen.f32(float %a) + ret iXLen %1 +} + +declare iXLen @llvm.lround.iXLen.f32(float) + +define iXLen @lround_f32(float %a) nounwind { +; RV32IF-LABEL: lround_f32: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.w.x ft0, a0 +; RV32IF-NEXT: fcvt.w.s a0, ft0, rmm +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: lround_f32: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.w.x ft0, a0 +; RV64IF-NEXT: fcvt.l.s a0, ft0, rmm +; RV64IF-NEXT: ret + %1 = call iXLen @llvm.lround.iXLen.f32(float %a) + ret iXLen %1 +} + +declare i64 @llvm.llrint.i64.f32(float) + +define i64 @llrint_f32(float %a) nounwind { +; RV32IF-LABEL: llrint_f32: +; RV32IF: # %bb.0: +; RV32IF-NEXT: addi sp, sp, -16 +; RV32IF-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IF-NEXT: call llrintf@plt +; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IF-NEXT: addi sp, sp, 16 +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: llrint_f32: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.w.x ft0, a0 +; RV64IF-NEXT: fcvt.l.s a0, ft0 +; RV64IF-NEXT: ret + %1 = call i64 @llvm.llrint.i64.f32(float %a) + ret i64 %1 +} + +declare i64 @llvm.llround.i64.f32(float) + +define i64 @llround_f32(float %a) nounwind { +; RV32IF-LABEL: llround_f32: +; RV32IF: # %bb.0: +; RV32IF-NEXT: addi sp, sp, -16 +; RV32IF-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IF-NEXT: call llroundf@plt +; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IF-NEXT: addi sp, sp, 16 +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: llround_f32: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.w.x ft0, a0 +; RV64IF-NEXT: fcvt.l.s a0, ft0, rmm +; RV64IF-NEXT: ret + %1 = call i64 @llvm.llround.i64.f32(float %a) + ret i64 %1 +} diff --git a/llvm/test/CodeGen/RISCV/half-intrinsics.ll b/llvm/test/CodeGen/RISCV/half-intrinsics.ll --- a/llvm/test/CodeGen/RISCV/half-intrinsics.ll +++ b/llvm/test/CodeGen/RISCV/half-intrinsics.ll @@ -1,12 +1,16 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mtriple=riscv32 -mattr=+experimental-zfh -verify-machineinstrs \ -; RUN: -target-abi ilp32f < %s | FileCheck -check-prefix=RV32IZFH %s -; RUN: llc -mtriple=riscv32 -mattr=+d -mattr=+experimental-zfh -verify-machineinstrs \ -; RUN: -target-abi ilp32d < %s | FileCheck -check-prefix=RV32IDZFH %s -; RUN: llc -mtriple=riscv64 -mattr=+experimental-zfh -verify-machineinstrs \ -; RUN: -target-abi lp64f < %s | FileCheck -check-prefix=RV64IZFH %s -; RUN: llc -mtriple=riscv64 -mattr=+d -mattr=+experimental-zfh -verify-machineinstrs \ -; RUN: -target-abi lp64d < %s | FileCheck -check-prefix=RV64IDZFH %s +; RUN: sed 's/iXLen/i32/g' %s | llc -mtriple=riscv32 -mattr=+experimental-zfh \ +; RUN: -verify-machineinstrs -target-abi ilp32f | \ +; RUN: FileCheck -check-prefix=RV32IZFH %s +; RUN: sed 's/iXLen/i32/g' %s | llc -mtriple=riscv32 -mattr=+d \ +; RUN: -mattr=+experimental-zfh -verify-machineinstrs -target-abi ilp32d | \ +; RUN: FileCheck -check-prefix=RV32IDZFH %s +; RUN: sed 's/iXLen/i64/g' %s | llc -mtriple=riscv64 -mattr=+experimental-zfh \ +; RUN: -verify-machineinstrs -target-abi lp64f | \ +; RUN: FileCheck -check-prefix=RV64IZFH %s +; RUN: sed 's/iXLen/i64/g' %s | llc -mtriple=riscv64 -mattr=+d \ +; RUN: -mattr=+experimental-zfh -verify-machineinstrs -target-abi lp64d | \ +; RUN: FileCheck -check-prefix=RV64IDZFH %s declare half @llvm.sqrt.f16(half) @@ -189,3 +193,123 @@ %1 = call half @llvm.copysign.f16(half %a, half %b) ret half %1 } + +declare iXLen @llvm.lrint.iXLen.f16(float) + +define iXLen @lrint_f16(float %a) nounwind { +; RV32IZFH-LABEL: lrint_f16: +; RV32IZFH: # %bb.0: +; RV32IZFH-NEXT: fcvt.w.s a0, fa0 +; RV32IZFH-NEXT: ret +; +; RV32IDZFH-LABEL: lrint_f16: +; RV32IDZFH: # %bb.0: +; RV32IDZFH-NEXT: fcvt.w.s a0, fa0 +; RV32IDZFH-NEXT: ret +; +; RV64IZFH-LABEL: lrint_f16: +; RV64IZFH: # %bb.0: +; RV64IZFH-NEXT: fcvt.l.s a0, fa0 +; RV64IZFH-NEXT: ret +; +; RV64IDZFH-LABEL: lrint_f16: +; RV64IDZFH: # %bb.0: +; RV64IDZFH-NEXT: fcvt.l.s a0, fa0 +; RV64IDZFH-NEXT: ret + %1 = call iXLen @llvm.lrint.iXLen.f16(float %a) + ret iXLen %1 +} + +declare iXLen @llvm.lround.iXLen.f16(float) + +define iXLen @lround_f16(float %a) nounwind { +; RV32IZFH-LABEL: lround_f16: +; RV32IZFH: # %bb.0: +; RV32IZFH-NEXT: fcvt.w.s a0, fa0, rmm +; RV32IZFH-NEXT: ret +; +; RV32IDZFH-LABEL: lround_f16: +; RV32IDZFH: # %bb.0: +; RV32IDZFH-NEXT: fcvt.w.s a0, fa0, rmm +; RV32IDZFH-NEXT: ret +; +; RV64IZFH-LABEL: lround_f16: +; RV64IZFH: # %bb.0: +; RV64IZFH-NEXT: fcvt.l.s a0, fa0, rmm +; RV64IZFH-NEXT: ret +; +; RV64IDZFH-LABEL: lround_f16: +; RV64IDZFH: # %bb.0: +; RV64IDZFH-NEXT: fcvt.l.s a0, fa0, rmm +; RV64IDZFH-NEXT: ret + %1 = call iXLen @llvm.lround.iXLen.f16(float %a) + ret iXLen %1 +} + +declare i64 @llvm.llrint.i64.f16(float) + +define i64 @llrint_f16(float %a) nounwind { +; RV32IZFH-LABEL: llrint_f16: +; RV32IZFH: # %bb.0: +; RV32IZFH-NEXT: addi sp, sp, -16 +; RV32IZFH-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IZFH-NEXT: call llrintf@plt +; RV32IZFH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IZFH-NEXT: addi sp, sp, 16 +; RV32IZFH-NEXT: ret +; +; RV32IDZFH-LABEL: llrint_f16: +; RV32IDZFH: # %bb.0: +; RV32IDZFH-NEXT: addi sp, sp, -16 +; RV32IDZFH-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IDZFH-NEXT: call llrintf@plt +; RV32IDZFH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IDZFH-NEXT: addi sp, sp, 16 +; RV32IDZFH-NEXT: ret +; +; RV64IZFH-LABEL: llrint_f16: +; RV64IZFH: # %bb.0: +; RV64IZFH-NEXT: fcvt.l.s a0, fa0 +; RV64IZFH-NEXT: ret +; +; RV64IDZFH-LABEL: llrint_f16: +; RV64IDZFH: # %bb.0: +; RV64IDZFH-NEXT: fcvt.l.s a0, fa0 +; RV64IDZFH-NEXT: ret + %1 = call i64 @llvm.llrint.i64.f16(float %a) + ret i64 %1 +} + +declare i64 @llvm.llround.i64.f16(float) + +define i64 @llround_f16(float %a) nounwind { +; RV32IZFH-LABEL: llround_f16: +; RV32IZFH: # %bb.0: +; RV32IZFH-NEXT: addi sp, sp, -16 +; RV32IZFH-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IZFH-NEXT: call llroundf@plt +; RV32IZFH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IZFH-NEXT: addi sp, sp, 16 +; RV32IZFH-NEXT: ret +; +; RV32IDZFH-LABEL: llround_f16: +; RV32IDZFH: # %bb.0: +; RV32IDZFH-NEXT: addi sp, sp, -16 +; RV32IDZFH-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IDZFH-NEXT: call llroundf@plt +; RV32IDZFH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IDZFH-NEXT: addi sp, sp, 16 +; RV32IDZFH-NEXT: ret +; +; RV64IZFH-LABEL: llround_f16: +; RV64IZFH: # %bb.0: +; RV64IZFH-NEXT: fcvt.l.s a0, fa0, rmm +; RV64IZFH-NEXT: ret +; +; RV64IDZFH-LABEL: llround_f16: +; RV64IDZFH: # %bb.0: +; RV64IDZFH-NEXT: fcvt.l.s a0, fa0, rmm +; RV64IDZFH-NEXT: ret + %1 = call i64 @llvm.llround.i64.f16(float %a) + ret i64 %1 +}