diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -9422,8 +9422,8 @@ "STRICT_FP_EXTEND result type should be vector iff the operand " "type is vector!"); assert((!VTList.VTs[0].isVector() || - VTList.VTs[0].getVectorNumElements() == - Ops[1].getValueType().getVectorNumElements()) && + VTList.VTs[0].getVectorElementCount() == + Ops[1].getValueType().getVectorElementCount()) && "Vector element count mismatch!"); assert(Ops[1].getValueType().bitsLT(VTList.VTs[0]) && "Invalid fpext node, dst <= src!"); diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -6113,8 +6113,8 @@ Check(OperandTy->isVectorTy() == ResultTy->isVectorTy(), "Intrinsic first argument and result disagree on vector use", &FPI); if (OperandTy->isVectorTy()) { - Check(cast(OperandTy)->getNumElements() == - cast(ResultTy)->getNumElements(), + Check(cast(OperandTy)->getElementCount() == + cast(ResultTy)->getElementCount(), "Intrinsic first argument and result vector lengths must be equal", &FPI); } diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h --- a/llvm/lib/Target/RISCV/RISCVISelLowering.h +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h @@ -330,6 +330,7 @@ // result being sign extended to 64 bit. These saturate out of range inputs. STRICT_FCVT_W_RV64 = ISD::FIRST_TARGET_STRICTFP_OPCODE, STRICT_FCVT_WU_RV64, + STRICT_FP_EXTEND_VL, // WARNING: Do not add anything in the end unless you want the node to // have memop! In fact, starting from FIRST_TARGET_MEMORY_OPCODE all @@ -758,6 +759,8 @@ SDValue lowerEH_DWARF_CFA(SDValue Op, SelectionDAG &DAG) const; SDValue lowerCTLZ_CTTZ_ZERO_UNDEF(SDValue Op, SelectionDAG &DAG) const; + SDValue lowerStrictFPExtend(SDValue Op, SelectionDAG &DAG) const; + SDValue expandUnalignedRVVLoad(SDValue Op, SelectionDAG &DAG) const; SDValue expandUnalignedRVVStore(SDValue Op, SelectionDAG &DAG) const; 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 @@ -802,6 +802,8 @@ setOperationAction({ISD::VECTOR_REVERSE, ISD::VECTOR_SPLICE}, VT, Custom); setOperationAction(FloatingPointVPOps, VT, Custom); + + setOperationAction(ISD::STRICT_FP_EXTEND, VT, Custom); }; // Sets common extload/truncstore actions on RVV floating-point vector @@ -1014,6 +1016,8 @@ setOperationAction(FloatingPointVecReduceOps, VT, Custom); setOperationAction(FloatingPointVPOps, VT, Custom); + + setOperationAction(ISD::STRICT_FP_EXTEND, VT, Custom); } // Custom-legalize bitcasts from fixed-length vectors to scalar types. @@ -4096,6 +4100,8 @@ if (!Op.getValueType().isVector()) return Op; return lowerVectorFPExtendOrRoundLike(Op, DAG); + case ISD::STRICT_FP_EXTEND: + return lowerStrictFPExtend(Op, DAG); case ISD::FP_TO_SINT: case ISD::FP_TO_UINT: case ISD::SINT_TO_FP: @@ -5313,6 +5319,46 @@ return Result; } +SDValue RISCVTargetLowering::lowerStrictFPExtend(SDValue Op, + SelectionDAG &DAG) const { + SDLoc DL(Op); + SDValue Chain = Op.getOperand(0); + SDValue Src = Op.getOperand(1); + MVT VT = Op.getSimpleValueType(); + MVT SrcVT = Src.getSimpleValueType(); + + MVT ContainerVT = VT; + if (VT.isFixedLengthVector()) { + MVT SrcContainerVT = getContainerForFixedLengthVector(SrcVT); + ContainerVT = + SrcContainerVT.changeVectorElementType(VT.getVectorElementType()); + Src = convertToScalableVector(SrcContainerVT, Src, DAG, Subtarget); + } + + auto [Mask, VL] = getDefaultVLOps(SrcVT, ContainerVT, DL, DAG, Subtarget); + + // RVV can only widen fp to types double the size as the source, so it needs + // two vfwcvt to achieve extending fp16 to fp64. + if (VT.getVectorElementType() == MVT::f64 && + SrcVT.getVectorElementType() == MVT::f16) { + MVT InterVT = ContainerVT.changeVectorElementType(MVT::f32); + Src = DAG.getNode(RISCVISD::STRICT_FP_EXTEND_VL, DL, + DAG.getVTList(InterVT, MVT::Other), Chain, Src, Mask, VL); + Chain = Src.getValue(1); + } + + SDValue Res = + DAG.getNode(RISCVISD::STRICT_FP_EXTEND_VL, DL, + DAG.getVTList(ContainerVT, MVT::Other), Chain, Src, Mask, VL); + if (VT.isFixedLengthVector()) { + // StrictFP operations have two result values. Their lowered result should + // have same result count. + SDValue SubVec = convertFromScalableVector(VT, Res, DAG, Subtarget); + Res = DAG.getMergeValues({SubVec, Res.getValue(1)}, DL); + } + return Res; +} + SDValue RISCVTargetLowering::lowerVectorFPExtendOrRoundLike(SDValue Op, SelectionDAG &DAG) const { @@ -13962,6 +14008,7 @@ NODE_NAME_CASE(VFCVT_RM_F_XU_VL) NODE_NAME_CASE(VFCVT_RM_F_X_VL) NODE_NAME_CASE(FP_EXTEND_VL) + NODE_NAME_CASE(STRICT_FP_EXTEND_VL) NODE_NAME_CASE(FP_ROUND_VL) NODE_NAME_CASE(VWMUL_VL) NODE_NAME_CASE(VWMULU_VL) diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td b/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td @@ -130,8 +130,13 @@ def riscv_fpround_vl : SDNode<"RISCVISD::FP_ROUND_VL", SDT_RISCVFPRoundOp_VL>; def riscv_fpextend_vl : SDNode<"RISCVISD::FP_EXTEND_VL", SDT_RISCVFPExtendOp_VL>; +def riscv_strict_fpextend_vl : SDNode<"RISCVISD::STRICT_FP_EXTEND_VL", SDT_RISCVFPExtendOp_VL, [SDNPHasChain]>; def riscv_fncvt_rod_vl : SDNode<"RISCVISD::VFNCVT_ROD_VL", SDT_RISCVFPRoundOp_VL>; +def any_riscv_fpextend_vl : PatFrags<(ops node:$src, node:$mask, node:$vl), + [(riscv_fpextend_vl node:$src, node:$mask, node:$vl), + (riscv_strict_fpextend_vl node:$src, node:$mask, node:$vl)]>; + def SDT_RISCVFP2IOp_VL : SDTypeProfile<1, 3, [ SDTCisInt<0>, SDTCisFP<1>, SDTCisSameNumEltsAs<0, 1>, SDTCVecEltisVT<2, i1>, SDTCisSameNumEltsAs<1, 2>, SDTCisVT<3, XLenVT> @@ -1844,9 +1849,10 @@ foreach fvtiToFWti = AllWidenableFloatVectors in { defvar fvti = fvtiToFWti.Vti; defvar fwti = fvtiToFWti.Wti; - def : Pat<(fwti.Vector (riscv_fpextend_vl (fvti.Vector fvti.RegClass:$rs1), - (fvti.Mask V0), - VLOpFrag)), + def : Pat<(fwti.Vector (any_riscv_fpextend_vl + (fvti.Vector fvti.RegClass:$rs1), + (fvti.Mask V0), + VLOpFrag)), (!cast("PseudoVFWCVT_F_F_V_"#fvti.LMul.MX#"_MASK") (fwti.Vector (IMPLICIT_DEF)), fvti.RegClass:$rs1, (fvti.Mask V0), GPR:$vl, fvti.Log2SEW, TA_MA)>; diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vfpext-constrained-sdnode.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vfpext-constrained-sdnode.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vfpext-constrained-sdnode.ll @@ -0,0 +1,116 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -mattr=+d,+zfh,+experimental-zvfh,+v -target-abi=ilp32d -riscv-v-vector-bits-min=128\ +; RUN: -verify-machineinstrs < %s | FileCheck %s +; RUN: llc -mtriple=riscv64 -mattr=+d,+zfh,+experimental-zvfh,+v -target-abi=lp64d -riscv-v-vector-bits-min=128\ +; RUN: -verify-machineinstrs < %s | FileCheck %s + +declare <2 x float> @llvm.experimental.constrained.fpext.v2f32.v2f16(<2 x half>, metadata) +define <2 x float> @vfpext_v2f16_v2f32(<2 x half> %va) { +; CHECK-LABEL: vfpext_v2f16_v2f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 2, e16, mf4, ta, ma +; CHECK-NEXT: vfwcvt.f.f.v v9, v8 +; CHECK-NEXT: vmv1r.v v8, v9 +; CHECK-NEXT: ret + %evec = call <2 x float> @llvm.experimental.constrained.fpext.v2f32.v2f16(<2 x half> %va, metadata !"fpexcept.strict") + ret <2 x float> %evec +} + +declare <2 x double> @llvm.experimental.constrained.fpext.v2f64.v2f16(<2 x half>, metadata) +define <2 x double> @vfpext_v2f16_v2f64(<2 x half> %va) { +; CHECK-LABEL: vfpext_v2f16_v2f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 2, e16, mf4, ta, ma +; CHECK-NEXT: vfwcvt.f.f.v v9, v8 +; CHECK-NEXT: vsetvli zero, zero, e32, mf2, ta, ma +; CHECK-NEXT: vfwcvt.f.f.v v8, v9 +; CHECK-NEXT: ret + %evec = call <2 x double> @llvm.experimental.constrained.fpext.v2f64.v2f16(<2 x half> %va, metadata !"fpexcept.strict") + ret <2 x double> %evec +} + +declare <4 x float> @llvm.experimental.constrained.fpext.v4f32.v4f16(<4 x half>, metadata) +define <4 x float> @vfpext_v4f16_v4f32(<4 x half> %va) { +; CHECK-LABEL: vfpext_v4f16_v4f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e16, mf2, ta, ma +; CHECK-NEXT: vfwcvt.f.f.v v9, v8 +; CHECK-NEXT: vmv1r.v v8, v9 +; CHECK-NEXT: ret + %evec = call <4 x float> @llvm.experimental.constrained.fpext.v4f32.v4f16(<4 x half> %va, metadata !"fpexcept.strict") + ret <4 x float> %evec +} + +declare <4 x double> @llvm.experimental.constrained.fpext.v4f64.v4f16(<4 x half>, metadata) +define <4 x double> @vfpext_v4f16_v4f64(<4 x half> %va) { +; CHECK-LABEL: vfpext_v4f16_v4f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e16, mf2, ta, ma +; CHECK-NEXT: vfwcvt.f.f.v v10, v8 +; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, ma +; CHECK-NEXT: vfwcvt.f.f.v v8, v10 +; CHECK-NEXT: ret + %evec = call <4 x double> @llvm.experimental.constrained.fpext.v4f64.v4f16(<4 x half> %va, metadata !"fpexcept.strict") + ret <4 x double> %evec +} + +declare <8 x float> @llvm.experimental.constrained.fpext.v8f32.v8f16(<8 x half>, metadata) +define <8 x float> @vfpext_v8f16_v8f32(<8 x half> %va) { +; CHECK-LABEL: vfpext_v8f16_v8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 8, e16, m1, ta, ma +; CHECK-NEXT: vfwcvt.f.f.v v10, v8 +; CHECK-NEXT: vmv2r.v v8, v10 +; CHECK-NEXT: ret + %evec = call <8 x float> @llvm.experimental.constrained.fpext.v8f32.v8f16(<8 x half> %va, metadata !"fpexcept.strict") + ret <8 x float> %evec +} + +declare <8 x double> @llvm.experimental.constrained.fpext.v8f64.v8f16(<8 x half>, metadata) +define <8 x double> @vfpext_v8f16_v8f64(<8 x half> %va) { +; CHECK-LABEL: vfpext_v8f16_v8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 8, e16, m1, ta, ma +; CHECK-NEXT: vfwcvt.f.f.v v12, v8 +; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma +; CHECK-NEXT: vfwcvt.f.f.v v8, v12 +; CHECK-NEXT: ret + %evec = call <8 x double> @llvm.experimental.constrained.fpext.v8f64.v8f16(<8 x half> %va, metadata !"fpexcept.strict") + ret <8 x double> %evec +} + +declare <2 x double> @llvm.experimental.constrained.fpext.v2f64.v2f32(<2 x float>, metadata) +define <2 x double> @vfpext_v2f32_v2f64(<2 x float> %va) { +; CHECK-LABEL: vfpext_v2f32_v2f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma +; CHECK-NEXT: vfwcvt.f.f.v v9, v8 +; CHECK-NEXT: vmv1r.v v8, v9 +; CHECK-NEXT: ret + %evec = call <2 x double> @llvm.experimental.constrained.fpext.v2f64.v2f32(<2 x float> %va, metadata !"fpexcept.strict") + ret <2 x double> %evec +} + +declare <4 x double> @llvm.experimental.constrained.fpext.v4f64.v4f32(<4 x float>, metadata) +define <4 x double> @vfpext_v4f32_v4f64(<4 x float> %va) { +; CHECK-LABEL: vfpext_v4f32_v4f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma +; CHECK-NEXT: vfwcvt.f.f.v v10, v8 +; CHECK-NEXT: vmv2r.v v8, v10 +; CHECK-NEXT: ret + %evec = call <4 x double> @llvm.experimental.constrained.fpext.v4f64.v4f32(<4 x float> %va, metadata !"fpexcept.strict") + ret <4 x double> %evec +} + +declare <8 x double> @llvm.experimental.constrained.fpext.v8f64.v8f32(<8 x float>, metadata) +define <8 x double> @vfpext_v8f32_v8f64(<8 x float> %va) { +; CHECK-LABEL: vfpext_v8f32_v8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma +; CHECK-NEXT: vfwcvt.f.f.v v12, v8 +; CHECK-NEXT: vmv4r.v v8, v12 +; CHECK-NEXT: ret + %evec = call <8 x double> @llvm.experimental.constrained.fpext.v8f64.v8f32(<8 x float> %va, metadata !"fpexcept.strict") + ret <8 x double> %evec +} diff --git a/llvm/test/CodeGen/RISCV/rvv/vfpext-constrained-sdnode.ll b/llvm/test/CodeGen/RISCV/rvv/vfpext-constrained-sdnode.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/rvv/vfpext-constrained-sdnode.ll @@ -0,0 +1,153 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -mattr=+d,+zfh,+experimental-zvfh,+v -target-abi=ilp32d \ +; RUN: -verify-machineinstrs < %s | FileCheck %s +; RUN: llc -mtriple=riscv64 -mattr=+d,+zfh,+experimental-zvfh,+v -target-abi=lp64d \ +; RUN: -verify-machineinstrs < %s | FileCheck %s + +declare @llvm.experimental.constrained.fpext.nxv1f32.nxv1f16(, metadata) +define @vfpext_nxv1f16_nxv1f32( %va) { +; CHECK-LABEL: vfpext_nxv1f16_nxv1f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16, mf4, ta, ma +; CHECK-NEXT: vfwcvt.f.f.v v9, v8 +; CHECK-NEXT: vmv1r.v v8, v9 +; CHECK-NEXT: ret + %evec = call @llvm.experimental.constrained.fpext.nxv1f32.nxv1f16( %va, metadata !"fpexcept.strict") + ret %evec +} + +declare @llvm.experimental.constrained.fpext.nxv1f64.nxv1f16(, metadata) +define @vfpext_nxv1f16_nxv1f64( %va) { +; CHECK-LABEL: vfpext_nxv1f16_nxv1f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16, mf4, ta, ma +; CHECK-NEXT: vfwcvt.f.f.v v9, v8 +; CHECK-NEXT: vsetvli zero, zero, e32, mf2, ta, ma +; CHECK-NEXT: vfwcvt.f.f.v v8, v9 +; CHECK-NEXT: ret + %evec = call @llvm.experimental.constrained.fpext.nxv1f64.nxv1f16( %va, metadata !"fpexcept.strict") + ret %evec +} + +declare @llvm.experimental.constrained.fpext.nxv2f32.nxv2f16(, metadata) +define @vfpext_nxv2f16_nxv2f32( %va) { +; CHECK-LABEL: vfpext_nxv2f16_nxv2f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16, mf2, ta, ma +; CHECK-NEXT: vfwcvt.f.f.v v9, v8 +; CHECK-NEXT: vmv1r.v v8, v9 +; CHECK-NEXT: ret + %evec = call @llvm.experimental.constrained.fpext.nxv2f32.nxv2f16( %va, metadata !"fpexcept.strict") + ret %evec +} + +declare @llvm.experimental.constrained.fpext.nxv2f64.nxv2f16(, metadata) +define @vfpext_nxv2f16_nxv2f64( %va) { +; CHECK-LABEL: vfpext_nxv2f16_nxv2f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16, mf2, ta, ma +; CHECK-NEXT: vfwcvt.f.f.v v10, v8 +; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, ma +; CHECK-NEXT: vfwcvt.f.f.v v8, v10 +; CHECK-NEXT: ret + %evec = call @llvm.experimental.constrained.fpext.nxv2f64.nxv2f16( %va, metadata !"fpexcept.strict") + ret %evec +} + +declare @llvm.experimental.constrained.fpext.nxv4f32.nxv4f16(, metadata) +define @vfpext_nxv4f16_nxv4f32( %va) { +; CHECK-LABEL: vfpext_nxv4f16_nxv4f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16, m1, ta, ma +; CHECK-NEXT: vfwcvt.f.f.v v10, v8 +; CHECK-NEXT: vmv2r.v v8, v10 +; CHECK-NEXT: ret + %evec = call @llvm.experimental.constrained.fpext.nxv4f32.nxv4f16( %va, metadata !"fpexcept.strict") + ret %evec +} + +declare @llvm.experimental.constrained.fpext.nxv4f64.nxv4f16(, metadata) +define @vfpext_nxv4f16_nxv4f64( %va) { +; CHECK-LABEL: vfpext_nxv4f16_nxv4f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16, m1, ta, ma +; CHECK-NEXT: vfwcvt.f.f.v v12, v8 +; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma +; CHECK-NEXT: vfwcvt.f.f.v v8, v12 +; CHECK-NEXT: ret + %evec = call @llvm.experimental.constrained.fpext.nxv4f64.nxv4f16( %va, metadata !"fpexcept.strict") + ret %evec +} + +declare @llvm.experimental.constrained.fpext.nxv8f32.nxv8f16(, metadata) +define @vfpext_nxv8f16_nxv8f32( %va) { +; CHECK-LABEL: vfpext_nxv8f16_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16, m2, ta, ma +; CHECK-NEXT: vfwcvt.f.f.v v12, v8 +; CHECK-NEXT: vmv4r.v v8, v12 +; CHECK-NEXT: ret + %evec = call @llvm.experimental.constrained.fpext.nxv8f32.nxv8f16( %va, metadata !"fpexcept.strict") + ret %evec +} + +declare @llvm.experimental.constrained.fpext.nxv8f64.nxv8f16(, metadata) +define @vfpext_nxv8f16_nxv8f64( %va) { +; CHECK-LABEL: vfpext_nxv8f16_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16, m2, ta, ma +; CHECK-NEXT: vfwcvt.f.f.v v16, v8 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vfwcvt.f.f.v v8, v16 +; CHECK-NEXT: ret + %evec = call @llvm.experimental.constrained.fpext.nxv8f64.nxv8f16( %va, metadata !"fpexcept.strict") + ret %evec +} + +declare @llvm.experimental.constrained.fpext.nxv1f64.nxv1f32(, metadata) +define @vfpext_nxv1f32_nxv1f64( %va) { +; CHECK-LABEL: vfpext_nxv1f32_nxv1f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32, mf2, ta, ma +; CHECK-NEXT: vfwcvt.f.f.v v9, v8 +; CHECK-NEXT: vmv1r.v v8, v9 +; CHECK-NEXT: ret + %evec = call @llvm.experimental.constrained.fpext.nxv1f64.nxv1f32( %va, metadata !"fpexcept.strict") + ret %evec +} + +declare @llvm.experimental.constrained.fpext.nxv2f64.nxv2f32(, metadata) +define @vfpext_nxv2f32_nxv2f64( %va) { +; CHECK-LABEL: vfpext_nxv2f32_nxv2f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32, m1, ta, ma +; CHECK-NEXT: vfwcvt.f.f.v v10, v8 +; CHECK-NEXT: vmv2r.v v8, v10 +; CHECK-NEXT: ret + %evec = call @llvm.experimental.constrained.fpext.nxv2f64.nxv2f32( %va, metadata !"fpexcept.strict") + ret %evec +} + +declare @llvm.experimental.constrained.fpext.nxv4f64.nxv4f32(, metadata) +define @vfpext_nxv4f32_nxv4f64( %va) { +; CHECK-LABEL: vfpext_nxv4f32_nxv4f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32, m2, ta, ma +; CHECK-NEXT: vfwcvt.f.f.v v12, v8 +; CHECK-NEXT: vmv4r.v v8, v12 +; CHECK-NEXT: ret + %evec = call @llvm.experimental.constrained.fpext.nxv4f64.nxv4f32( %va, metadata !"fpexcept.strict") + ret %evec +} + +declare @llvm.experimental.constrained.fpext.nxv8f64.nxv8f32(, metadata) +define @vfpext_nxv8f32_nxv8f64( %va) { +; CHECK-LABEL: vfpext_nxv8f32_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32, m4, ta, ma +; CHECK-NEXT: vfwcvt.f.f.v v16, v8 +; CHECK-NEXT: vmv8r.v v8, v16 +; CHECK-NEXT: ret + %evec = call @llvm.experimental.constrained.fpext.nxv8f64.nxv8f32( %va, metadata !"fpexcept.strict") + ret %evec +}