diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -3446,13 +3446,27 @@ void DAGTypeLegalizer::ExpandIntRes_LLROUND_LLRINT(SDNode *N, SDValue &Lo, SDValue &Hi) { - SDValue Op = N->getOperand(N->isStrictFPOpcode() ? 1 : 0); + SDLoc dl(N); + bool IsStrict = N->isStrictFPOpcode(); + SDValue Op = N->getOperand(IsStrict ? 1 : 0); + SDValue Chain = IsStrict ? N->getOperand(0) : SDValue(); assert(getTypeAction(Op.getValueType()) != TargetLowering::TypePromoteFloat && "Input type needs to be promoted!"); EVT VT = Op.getValueType(); + if (VT == MVT::f16) { + VT = MVT::f32; + // Extend to f32. + if (IsStrict) { + Op = DAG.getNode(ISD::STRICT_FP_EXTEND, dl, { VT, MVT::Other }, {Chain, Op}); + Chain = Op.getValue(1); + } else { + Op = DAG.getNode(ISD::FP_EXTEND, dl, VT, Op); + } + } + RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; if (N->getOpcode() == ISD::LLROUND || N->getOpcode() == ISD::STRICT_LLROUND) { @@ -3483,9 +3497,7 @@ } else llvm_unreachable("Unexpected opcode!"); - SDLoc dl(N); EVT RetVT = N->getValueType(0); - SDValue Chain = N->isStrictFPOpcode() ? N->getOperand(0) : SDValue(); TargetLowering::MakeLibCallOptions CallOptions; CallOptions.setSExt(true); diff --git a/llvm/test/CodeGen/RISCV/rv64zfh-half-intrinsics-strict.ll b/llvm/test/CodeGen/RISCV/rv64zfh-half-intrinsics-strict.ll deleted file mode 100644 --- a/llvm/test/CodeGen/RISCV/rv64zfh-half-intrinsics-strict.ll +++ /dev/null @@ -1,41 +0,0 @@ -; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc < %s -mtriple=riscv64 -mattr=+zfh \ -; RUN: -verify-machineinstrs -target-abi lp64f -disable-strictnode-mutation \ -; RUN: | FileCheck -check-prefix=RV64IZFH %s -; RUN: llc < %s -mtriple=riscv64 -mattr=+d \ -; RUN: -mattr=+zfh -verify-machineinstrs -target-abi lp64d \ -; RUN: -disable-strictnode-mutation | FileCheck -check-prefix=RV64IDZFH %s - -; These intrinsics require half and i64 to be legal types. - -declare i64 @llvm.experimental.constrained.llrint.i64.f16(half, metadata, metadata) - -define i64 @llrint_f16(half %a) nounwind strictfp { -; RV64IZFH-LABEL: llrint_f16: -; RV64IZFH: # %bb.0: -; RV64IZFH-NEXT: fcvt.l.h a0, fa0 -; RV64IZFH-NEXT: ret -; -; RV64IDZFH-LABEL: llrint_f16: -; RV64IDZFH: # %bb.0: -; RV64IDZFH-NEXT: fcvt.l.h a0, fa0 -; RV64IDZFH-NEXT: ret - %1 = call i64 @llvm.experimental.constrained.llrint.i64.f16(half %a, metadata !"round.dynamic", metadata !"fpexcept.strict") strictfp - ret i64 %1 -} - -declare i64 @llvm.experimental.constrained.llround.i64.f16(half, metadata) - -define i64 @llround_f16(half %a) nounwind strictfp { -; RV64IZFH-LABEL: llround_f16: -; RV64IZFH: # %bb.0: -; RV64IZFH-NEXT: fcvt.l.h a0, fa0, rmm -; RV64IZFH-NEXT: ret -; -; RV64IDZFH-LABEL: llround_f16: -; RV64IDZFH: # %bb.0: -; RV64IDZFH-NEXT: fcvt.l.h a0, fa0, rmm -; RV64IDZFH-NEXT: ret - %1 = call i64 @llvm.experimental.constrained.llround.i64.f16(half %a, metadata !"fpexcept.strict") strictfp - ret i64 %1 -} diff --git a/llvm/test/CodeGen/RISCV/zfh-half-intrinsics-strict.ll b/llvm/test/CodeGen/RISCV/zfh-half-intrinsics-strict.ll --- a/llvm/test/CodeGen/RISCV/zfh-half-intrinsics-strict.ll +++ b/llvm/test/CodeGen/RISCV/zfh-half-intrinsics-strict.ll @@ -255,3 +255,45 @@ %1 = call iXLen @llvm.experimental.constrained.lround.iXLen.f16(half %a, metadata !"fpexcept.strict") strictfp ret iXLen %1 } + +declare i64 @llvm.experimental.constrained.llrint.i64.f16(half, metadata, metadata) + +define i64 @llrint_f16(half %a) nounwind strictfp { +; 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: fcvt.s.h fa0, fa0 +; RV32IZFH-NEXT: call llrintf@plt +; RV32IZFH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IZFH-NEXT: addi sp, sp, 16 +; RV32IZFH-NEXT: ret +; +; RV64IZFH-LABEL: llrint_f16: +; RV64IZFH: # %bb.0: +; RV64IZFH-NEXT: fcvt.l.h a0, fa0 +; RV64IZFH-NEXT: ret + %1 = call i64 @llvm.experimental.constrained.llrint.i64.f16(half %a, metadata !"round.dynamic", metadata !"fpexcept.strict") strictfp + ret i64 %1 +} + +declare i64 @llvm.experimental.constrained.llround.i64.f16(half, metadata) + +define i64 @llround_f16(half %a) nounwind strictfp { +; 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: fcvt.s.h fa0, fa0 +; RV32IZFH-NEXT: call llroundf@plt +; RV32IZFH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IZFH-NEXT: addi sp, sp, 16 +; RV32IZFH-NEXT: ret +; +; RV64IZFH-LABEL: llround_f16: +; RV64IZFH: # %bb.0: +; RV64IZFH-NEXT: fcvt.l.h a0, fa0, rmm +; RV64IZFH-NEXT: ret + %1 = call i64 @llvm.experimental.constrained.llround.i64.f16(half %a, metadata !"fpexcept.strict") strictfp + ret i64 %1 +}