| //===-- RISCVInstrInfoZvfbf.td - 'Zvfbf*' instructions -----*- tablegen -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file describes the RISC-V instructions from the standard 'Zvfbfmin' |
| // extension, providing vector conversion instructions for BFloat16. |
| // This version is still experimental as the 'Zvfbfmin' extension hasn't been |
| // ratified yet. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| //===----------------------------------------------------------------------===// |
| // Instructions |
| //===----------------------------------------------------------------------===// |
| |
| let Predicates = [HasStdExtZvfbfminOrZvfofp8min], |
| Constraints = "@earlyclobber $vd", |
| mayRaiseFPException = true in { |
| let RVVConstraint = WidenCvt, DestEEW = EEWSEWx2 in |
| defm VFWCVTBF16_F_F_V : VWCVTF_FV_VS2<"vfwcvtbf16.f.f.v", 0b010010, 0b01101>; |
| let Uses = [FRM, VL, VTYPE] in |
| defm VFNCVTBF16_F_F_W : VNCVTF_FV_VS2<"vfncvtbf16.f.f.w", 0b010010, 0b11101>; |
| } |
| |
| let Predicates = [HasStdExtZvfbfwma], |
| Constraints = "@earlyclobber $vd_wb, $vd = $vd_wb", |
| RVVConstraint = WidenV, Uses = [FRM, VL, VTYPE], mayRaiseFPException = true, |
| DestEEW = EEWSEWx2 in { |
| defm VFWMACCBF16_V : VWMAC_FV_V_F<"vfwmaccbf16", 0b111011>; |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Pseudo instructions |
| //===----------------------------------------------------------------------===// |
| let Predicates = [HasStdExtZvfbfmin] in { |
| defm PseudoVFWCVTBF16_F_F : VPseudoVWCVTD_V; |
| defm PseudoVFNCVTBF16_F_F : VPseudoVNCVTD_W_RM; |
| } |
| |
| let mayRaiseFPException = true, Predicates = [HasStdExtZvfbfwma] in |
| defm PseudoVFWMACCBF16 : VPseudoVWMAC_VV_VF_BF_RM; |
| |
| defset list<VTypeInfoToWide> AllWidenableIntToBF16Vectors = { |
| def : VTypeInfoToWide<VI8MF8, VBF16MF4>; |
| def : VTypeInfoToWide<VI8MF4, VBF16MF2>; |
| def : VTypeInfoToWide<VI8MF2, VBF16M1>; |
| def : VTypeInfoToWide<VI8M1, VBF16M2>; |
| def : VTypeInfoToWide<VI8M2, VBF16M4>; |
| def : VTypeInfoToWide<VI8M4, VBF16M8>; |
| } |
| |
| multiclass VPseudoVALU_VV_VF_RM_BF16 { |
| foreach m = MxListF in { |
| defm "" : VPseudoBinaryFV_VV_RM<m, 16/*sew*/>, |
| SchedBinary<"WriteVFALUV", "ReadVFALUV", "ReadVFALUV", m.MX, |
| 16/*sew*/, forcePassthruRead=true>; |
| } |
| |
| defvar f = SCALAR_F16; |
| foreach m = f.MxList in { |
| defm "" : VPseudoBinaryV_VF_RM<m, f, f.SEW>, |
| SchedBinary<"WriteVFALUF", "ReadVFALUV", "ReadVFALUF", m.MX, |
| f.SEW, forcePassthruRead=true>; |
| } |
| } |
| |
| multiclass VPseudoVALU_VF_RM_BF16 { |
| defvar f = SCALAR_F16; |
| foreach m = f.MxList in { |
| defm "" : VPseudoBinaryV_VF_RM<m, f, f.SEW>, |
| SchedBinary<"WriteVFALUF", "ReadVFALUV", "ReadVFALUF", m.MX, |
| f.SEW, forcePassthruRead=true>; |
| } |
| } |
| |
| multiclass VPseudoVFWALU_VV_VF_RM_BF16 { |
| foreach m = MxListFW in { |
| defm "" : VPseudoBinaryW_VV_RM<m, sew=16>, |
| SchedBinary<"WriteVFWALUV", "ReadVFWALUV", "ReadVFWALUV", m.MX, |
| 16/*sew*/, forcePassthruRead=true>; |
| } |
| |
| defvar f = SCALAR_F16; |
| foreach m = f.MxListFW in { |
| defm "" : VPseudoBinaryW_VF_RM<m, f, sew=f.SEW>, |
| SchedBinary<"WriteVFWALUF", "ReadVFWALUV", "ReadVFWALUF", m.MX, |
| f.SEW, forcePassthruRead=true>; |
| } |
| } |
| |
| multiclass VPseudoVFWALU_WV_WF_RM_BF16 { |
| foreach m = MxListFW in { |
| defm "" : VPseudoBinaryW_WV_RM<m, sew=16>, |
| SchedBinary<"WriteVFWALUV", "ReadVFWALUV", "ReadVFWALUV", m.MX, |
| 16/*sew*/, forcePassthruRead=true>; |
| } |
| defvar f = SCALAR_F16; |
| foreach m = f.MxListFW in { |
| defm "" : VPseudoBinaryW_WF_RM<m, f, sew=f.SEW>, |
| SchedBinary<"WriteVFWALUF", "ReadVFWALUV", "ReadVFWALUF", m.MX, |
| f.SEW, forcePassthruRead=true>; |
| } |
| } |
| |
| multiclass VPseudoVFMUL_VV_VF_RM_BF16 { |
| foreach m = MxListF in { |
| defm "" : VPseudoBinaryFV_VV_RM<m, 16/*sew*/>, |
| SchedBinary<"WriteVFMulV", "ReadVFMulV", "ReadVFMulV", m.MX, |
| 16/*sew*/, forcePassthruRead=true>; |
| } |
| |
| defvar f = SCALAR_F16; |
| foreach m = f.MxList in { |
| defm "" : VPseudoBinaryV_VF_RM<m, f, f.SEW>, |
| SchedBinary<"WriteVFMulF", "ReadVFMulV", "ReadVFMulF", m.MX, |
| f.SEW, forcePassthruRead=true>; |
| } |
| } |
| |
| multiclass VPseudoVWMUL_VV_VF_RM_BF16 { |
| foreach m = MxListFW in { |
| defm "" : VPseudoBinaryW_VV_RM<m, sew=16>, |
| SchedBinary<"WriteVFWMulV", "ReadVFWMulV", "ReadVFWMulV", m.MX, |
| 16/*sew*/, forcePassthruRead=true>; |
| } |
| |
| defvar f = SCALAR_F16; |
| foreach m = f.MxListFW in { |
| defm "" : VPseudoBinaryW_VF_RM<m, f, sew=f.SEW>, |
| SchedBinary<"WriteVFWMulF", "ReadVFWMulV", "ReadVFWMulF", m.MX, |
| f.SEW, forcePassthruRead=true>; |
| } |
| } |
| |
| multiclass VPseudoVMAC_VV_VF_AAXA_RM_BF16 { |
| foreach m = MxListF in { |
| defm "" : VPseudoTernaryV_VV_AAXA_RM<m, 16/*sew*/>, |
| SchedTernary<"WriteVFMulAddV", "ReadVFMulAddV", "ReadVFMulAddV", |
| "ReadVFMulAddV", m.MX, 16/*sew*/>; |
| } |
| |
| defvar f = SCALAR_F16; |
| foreach m = f.MxList in { |
| defm "" : VPseudoTernaryV_VF_AAXA_RM<m, f, f.SEW>, |
| SchedTernary<"WriteVFMulAddF", "ReadVFMulAddV", "ReadVFMulAddF", |
| "ReadVFMulAddV", m.MX, f.SEW>; |
| } |
| } |
| |
| multiclass VPseudoVWMAC_VV_VF_RM_BF16 { |
| foreach m = MxListFW in { |
| defm "" : VPseudoTernaryW_VV_RM<m, sew=16>, |
| SchedTernary<"WriteVFWMulAddV", "ReadVFWMulAddV", |
| "ReadVFWMulAddV", "ReadVFWMulAddV", m.MX, 16/*sew*/>; |
| } |
| |
| defvar f = SCALAR_F16; |
| foreach m = f.MxListFW in { |
| defm "" : VPseudoTernaryW_VF_RM<m, f, sew=f.SEW>, |
| SchedTernary<"WriteVFWMulAddF", "ReadVFWMulAddV", |
| "ReadVFWMulAddF", "ReadVFWMulAddV", m.MX, f.SEW>; |
| } |
| } |
| |
| multiclass VPseudoVRCP_V_BF16 { |
| foreach m = MxListF in { |
| defvar mx = m.MX; |
| let VLMul = m.value in { |
| def "_V_" # mx # "_E16" |
| : VPseudoUnaryNoMask<m.vrclass, m.vrclass>, |
| SchedUnary<"WriteVFRecpV", "ReadVFRecpV", mx, 16/*sew*/, |
| forcePassthruRead=true>; |
| def "_V_" # mx # "_E16_MASK" |
| : VPseudoUnaryMask<m.vrclass, m.vrclass>, |
| RISCVMaskedPseudo<MaskIdx = 2>, |
| SchedUnary<"WriteVFRecpV", "ReadVFRecpV", mx, 16/*sew*/, |
| forcePassthruRead=true>; |
| } |
| } |
| } |
| |
| multiclass VPseudoVRCP_V_RM_BF16 { |
| foreach m = MxListF in { |
| defvar mx = m.MX; |
| let VLMul = m.value in { |
| def "_V_" # mx # "_E16" |
| : VPseudoUnaryNoMaskRoundingMode<m.vrclass, m.vrclass>, |
| SchedUnary<"WriteVFRecpV", "ReadVFRecpV", mx, 16/*sew*/, |
| forcePassthruRead=true>; |
| def "_V_" # mx # "_E16_MASK" |
| : VPseudoUnaryMaskRoundingMode<m.vrclass, m.vrclass>, |
| RISCVMaskedPseudo<MaskIdx = 2>, |
| SchedUnary<"WriteVFRecpV", "ReadVFRecpV", mx, 16/*sew*/, |
| forcePassthruRead=true>; |
| } |
| } |
| } |
| |
| multiclass VPseudoVMAX_VV_VF_BF16 { |
| foreach m = MxListF in { |
| defm "" : VPseudoBinaryV_VV<m, sew=16>, |
| SchedBinary<"WriteVFMinMaxV", "ReadVFMinMaxV", "ReadVFMinMaxV", |
| m.MX, 16/*sew*/, forcePassthruRead=true>; |
| } |
| |
| defvar f = SCALAR_F16; |
| foreach m = f.MxList in { |
| defm "" : VPseudoBinaryV_VF<m, f, f.SEW>, |
| SchedBinary<"WriteVFMinMaxF", "ReadVFMinMaxV", "ReadVFMinMaxF", |
| m.MX, f.SEW, forcePassthruRead=true>; |
| } |
| } |
| |
| multiclass VPseudoVSGNJ_VV_VF_BF16 { |
| foreach m = MxListF in { |
| defm "" : VPseudoBinaryV_VV<m, sew=16>, |
| SchedBinary<"WriteVFSgnjV", "ReadVFSgnjV", "ReadVFSgnjV", m.MX, |
| 16/*sew*/, forcePassthruRead=true>; |
| } |
| |
| defvar f = SCALAR_F16; |
| foreach m = f.MxList in { |
| defm "" : VPseudoBinaryV_VF<m, f, f.SEW>, |
| SchedBinary<"WriteVFSgnjF", "ReadVFSgnjV", "ReadVFSgnjF", m.MX, |
| f.SEW, forcePassthruRead=true>; |
| } |
| } |
| |
| multiclass VPseudoVWCVTF_V_BF16 { |
| defvar constraint = "@earlyclobber $rd"; |
| foreach m = MxListW in |
| defm _V : VPseudoConversion<m.wvrclass, m.vrclass, m, constraint, sew=8, |
| TargetConstraintType=3>, |
| SchedUnary<"WriteVFWCvtIToFV", "ReadVFWCvtIToFV", m.MX, 8/*sew*/, |
| forcePassthruRead=true>; |
| } |
| |
| multiclass VPseudoVWCVTD_V_BF16 { |
| defvar constraint = "@earlyclobber $rd"; |
| foreach m = MxListFW in |
| defm _V : VPseudoConversion<m.wvrclass, m.vrclass, m, constraint, sew=16, |
| TargetConstraintType=3>, |
| SchedUnary<"WriteVFWCvtFToFV", "ReadVFWCvtFToFV", m.MX, 16/*sew*/, |
| forcePassthruRead=true>; |
| } |
| |
| multiclass VPseudoVNCVTD_W_BF16 { |
| defvar constraint = "@earlyclobber $rd"; |
| foreach m = MxListFW in |
| defm _W : VPseudoConversion<m.vrclass, m.wvrclass, m, constraint, sew=16, |
| TargetConstraintType=2>, |
| SchedUnary<"WriteVFNCvtFToFV", "ReadVFNCvtFToFV", m.MX, 16/*sew*/, |
| forcePassthruRead=true>; |
| } |
| |
| multiclass VPseudoVNCVTD_W_RM_BF16 { |
| defvar constraint = "@earlyclobber $rd"; |
| foreach m = MxListFW in |
| defm _W : VPseudoConversionRoundingMode<m.vrclass, m.wvrclass, m, |
| constraint, sew=16, |
| TargetConstraintType=2>, |
| SchedUnary<"WriteVFNCvtFToFV", "ReadVFNCvtFToFV", m.MX, 16/*sew*/, |
| forcePassthruRead=true>; |
| } |
| |
| let Predicates = [HasStdExtZvfbfa], AltFmtType = IS_ALTFMT in { |
| let mayRaiseFPException = true in { |
| defm PseudoVFADD_ALT : VPseudoVALU_VV_VF_RM_BF16; |
| defm PseudoVFSUB_ALT : VPseudoVALU_VV_VF_RM_BF16; |
| defm PseudoVFRSUB_ALT : VPseudoVALU_VF_RM_BF16; |
| } |
| |
| let mayRaiseFPException = true in { |
| defm PseudoVFWADD_ALT : VPseudoVFWALU_VV_VF_RM_BF16; |
| defm PseudoVFWSUB_ALT : VPseudoVFWALU_VV_VF_RM_BF16; |
| defm PseudoVFWADD_ALT : VPseudoVFWALU_WV_WF_RM_BF16; |
| defm PseudoVFWSUB_ALT : VPseudoVFWALU_WV_WF_RM_BF16; |
| } |
| |
| let mayRaiseFPException = true in |
| defm PseudoVFMUL_ALT : VPseudoVFMUL_VV_VF_RM_BF16; |
| |
| let mayRaiseFPException = true in |
| defm PseudoVFWMUL_ALT : VPseudoVWMUL_VV_VF_RM_BF16; |
| |
| let mayRaiseFPException = true in { |
| defm PseudoVFMACC_ALT : VPseudoVMAC_VV_VF_AAXA_RM_BF16; |
| defm PseudoVFNMACC_ALT : VPseudoVMAC_VV_VF_AAXA_RM_BF16; |
| defm PseudoVFMSAC_ALT : VPseudoVMAC_VV_VF_AAXA_RM_BF16; |
| defm PseudoVFNMSAC_ALT : VPseudoVMAC_VV_VF_AAXA_RM_BF16; |
| defm PseudoVFMADD_ALT : VPseudoVMAC_VV_VF_AAXA_RM_BF16; |
| defm PseudoVFNMADD_ALT : VPseudoVMAC_VV_VF_AAXA_RM_BF16; |
| defm PseudoVFMSUB_ALT : VPseudoVMAC_VV_VF_AAXA_RM_BF16; |
| defm PseudoVFNMSUB_ALT : VPseudoVMAC_VV_VF_AAXA_RM_BF16; |
| } |
| |
| let mayRaiseFPException = true in { |
| defm PseudoVFWMACC_ALT : VPseudoVWMAC_VV_VF_RM_BF16; |
| defm PseudoVFWNMACC_ALT : VPseudoVWMAC_VV_VF_RM_BF16; |
| defm PseudoVFWMSAC_ALT : VPseudoVWMAC_VV_VF_RM_BF16; |
| defm PseudoVFWNMSAC_ALT : VPseudoVWMAC_VV_VF_RM_BF16; |
| } |
| |
| let mayRaiseFPException = true in |
| defm PseudoVFRSQRT7_ALT : VPseudoVRCP_V_BF16; |
| |
| let mayRaiseFPException = true in |
| defm PseudoVFREC7_ALT : VPseudoVRCP_V_RM_BF16; |
| |
| let mayRaiseFPException = true in { |
| defm PseudoVFMIN_ALT : VPseudoVMAX_VV_VF_BF16; |
| defm PseudoVFMAX_ALT : VPseudoVMAX_VV_VF_BF16; |
| } |
| |
| defm PseudoVFSGNJ_ALT : VPseudoVSGNJ_VV_VF_BF16; |
| defm PseudoVFSGNJN_ALT : VPseudoVSGNJ_VV_VF_BF16; |
| defm PseudoVFSGNJX_ALT : VPseudoVSGNJ_VV_VF_BF16; |
| |
| let mayRaiseFPException = true in { |
| defm PseudoVMFEQ_ALT : VPseudoVCMPM_VV_VF; |
| defm PseudoVMFNE_ALT : VPseudoVCMPM_VV_VF; |
| defm PseudoVMFLT_ALT : VPseudoVCMPM_VV_VF; |
| defm PseudoVMFLE_ALT : VPseudoVCMPM_VV_VF; |
| defm PseudoVMFGT_ALT : VPseudoVCMPM_VF; |
| defm PseudoVMFGE_ALT : VPseudoVCMPM_VF; |
| } |
| |
| defm PseudoVFCLASS_ALT : VPseudoVCLS_V; |
| |
| defm PseudoVFMERGE_ALT : VPseudoVMRG_FM; |
| |
| defm PseudoVFMV_V_ALT : VPseudoVMV_F; |
| |
| let mayRaiseFPException = true in { |
| defm PseudoVFWCVT_F_XU_ALT : VPseudoVWCVTF_V_BF16; |
| defm PseudoVFWCVT_F_X_ALT : VPseudoVWCVTF_V_BF16; |
| |
| defm PseudoVFWCVT_F_F_ALT : VPseudoVWCVTD_V_BF16; |
| } // mayRaiseFPException = true |
| |
| let mayRaiseFPException = true in { |
| let hasSideEffects = 0, hasPostISelHook = 1 in { |
| defm PseudoVFNCVT_XU_F_ALT : VPseudoVNCVTI_W_RM; |
| defm PseudoVFNCVT_X_F_ALT : VPseudoVNCVTI_W_RM; |
| } |
| |
| defm PseudoVFNCVT_RTZ_XU_F_ALT : VPseudoVNCVTI_W; |
| defm PseudoVFNCVT_RTZ_X_F_ALT : VPseudoVNCVTI_W; |
| |
| defm PseudoVFNCVT_F_F_ALT : VPseudoVNCVTD_W_RM_BF16; |
| |
| defm PseudoVFNCVT_ROD_F_F_ALT : VPseudoVNCVTD_W_BF16; |
| } // mayRaiseFPException = true |
| |
| let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in { |
| defvar f = SCALAR_F16; |
| let HasSEWOp = 1, BaseInstr = VFMV_F_S in |
| def "PseudoVFMV_" # f.FX # "_S_ALT" : |
| RISCVVPseudo<(outs f.fprclass:$rd), (ins VR:$rs2, sew:$sew)>, |
| Sched<[WriteVMovFS, ReadVMovFS]>; |
| let HasVLOp = 1, HasSEWOp = 1, BaseInstr = VFMV_S_F, isReMaterializable = 1, |
| Constraints = "$rd = $passthru" in |
| def "PseudoVFMV_S_" # f.FX # "_ALT" : |
| RISCVVPseudo<(outs VR:$rd), |
| (ins VR:$passthru, f.fprclass:$rs1, AVL:$vl, sew:$sew)>, |
| Sched<[WriteVMovSF, ReadVMovSF_V, ReadVMovSF_F]>; |
| } |
| |
| defm PseudoVFSLIDE1UP_ALT : VPseudoVSLD1_VF<"@earlyclobber $rd">; |
| defm PseudoVFSLIDE1DOWN_ALT : VPseudoVSLD1_VF; |
| } // Predicates = [HasStdExtZvfbfa], AltFmtType = IS_ALTFMT |
| |
| //===----------------------------------------------------------------------===// |
| // Patterns |
| //===----------------------------------------------------------------------===// |
| multiclass VPatConversionWF_VF_BF<string intrinsic, string instruction, |
| bit isSEWAware = 0> { |
| foreach fvtiToFWti = AllWidenableBF16ToFloatVectors in |
| { |
| defvar fvti = fvtiToFWti.Vti; |
| defvar fwti = fvtiToFWti.Wti; |
| defm : VPatConversion<intrinsic, instruction, "V", |
| fwti.Vector, fvti.Vector, fwti.Mask, fvti.Log2SEW, |
| fvti.LMul, fwti.RegClass, fvti.RegClass, isSEWAware>; |
| } |
| } |
| |
| multiclass VPatConversionVF_WF_BF_RM<string intrinsic, string instruction, |
| bit isSEWAware = 0> { |
| foreach fvtiToFWti = AllWidenableBF16ToFloatVectors in { |
| defvar fvti = fvtiToFWti.Vti; |
| defvar fwti = fvtiToFWti.Wti; |
| defm : VPatConversionRoundingMode<intrinsic, instruction, "W", |
| fvti.Vector, fwti.Vector, fvti.Mask, fvti.Log2SEW, |
| fvti.LMul, fvti.RegClass, fwti.RegClass, |
| isSEWAware>; |
| } |
| } |
| |
| let Predicates = [HasStdExtZvfbfmin] in { |
| defm : VPatConversionWF_VF_BF<"int_riscv_vfwcvtbf16_f_f_v", |
| "PseudoVFWCVTBF16_F_F", isSEWAware=1>; |
| defm : VPatConversionVF_WF_BF_RM<"int_riscv_vfncvtbf16_f_f_w", |
| "PseudoVFNCVTBF16_F_F", isSEWAware=1>; |
| |
| foreach fvtiToFWti = AllWidenableBF16ToFloatVectors in { |
| defvar fvti = fvtiToFWti.Vti; |
| defvar fwti = fvtiToFWti.Wti; |
| def : Pat<(fwti.Vector (any_riscv_fpextend_vl |
| (fvti.Vector fvti.RegClass:$rs1), |
| (fvti.Mask VMV0:$vm), |
| VLOpFrag)), |
| (!cast<Instruction>("PseudoVFWCVTBF16_F_F_V_"#fvti.LMul.MX#"_E"#fvti.SEW#"_MASK") |
| (fwti.Vector (IMPLICIT_DEF)), fvti.RegClass:$rs1, |
| (fvti.Mask VMV0:$vm), |
| GPR:$vl, fvti.Log2SEW, TA_MA)>; |
| |
| def : Pat<(fvti.Vector (any_riscv_fpround_vl |
| (fwti.Vector fwti.RegClass:$rs1), |
| (fwti.Mask VMV0:$vm), VLOpFrag)), |
| (!cast<Instruction>("PseudoVFNCVTBF16_F_F_W_"#fvti.LMul.MX#"_E"#fvti.SEW#"_MASK") |
| (fvti.Vector (IMPLICIT_DEF)), fwti.RegClass:$rs1, |
| (fwti.Mask VMV0:$vm), |
| // Value to indicate no rounding mode change in |
| // RISCVInsertReadWriteCSR |
| FRM_DYN, |
| GPR:$vl, fvti.Log2SEW, TA_MA)>; |
| def : Pat<(fvti.Vector (fpround (fwti.Vector fwti.RegClass:$rs1))), |
| (!cast<Instruction>("PseudoVFNCVTBF16_F_F_W_"#fvti.LMul.MX#"_E"#fvti.SEW) |
| (fvti.Vector (IMPLICIT_DEF)), |
| fwti.RegClass:$rs1, |
| // Value to indicate no rounding mode change in |
| // RISCVInsertReadWriteCSR |
| FRM_DYN, |
| fvti.AVL, fvti.Log2SEW, TA_MA)>; |
| } |
| } |
| |
| let Predicates = [HasStdExtZvfbfwma] in { |
| defm : VPatTernaryW_VV_VX_RM<"int_riscv_vfwmaccbf16", "PseudoVFWMACCBF16", |
| AllWidenableBF16ToFloatVectors, isSEWAware=1>; |
| defm : VPatWidenFPMulAccVL_VV_VF_RM<riscv_vfwmadd_vl, "PseudoVFWMACCBF16", |
| AllWidenableBF16ToFloatVectors>; |
| defm : VPatWidenFPMulAccSDNode_VV_VF_RM<"PseudoVFWMACCBF16", |
| AllWidenableBF16ToFloatVectors>; |
| } |
| |
| multiclass VPatConversionVI_VF_BF16<string intrinsic, string instruction> { |
| foreach fvti = AllBF16Vectors in { |
| defvar ivti = GetIntVTypeInfo<fvti>.Vti; |
| let Predicates = !listconcat(GetVTypePredicates<fvti>.Predicates, |
| GetVTypePredicates<ivti>.Predicates) in |
| defm : VPatConversion<intrinsic, instruction, "V", |
| ivti.Vector, fvti.Vector, ivti.Mask, fvti.Log2SEW, |
| fvti.LMul, ivti.RegClass, fvti.RegClass>; |
| } |
| } |
| |
| multiclass VPatConversionWF_VI_BF16<string intrinsic, string instruction, |
| bit isSEWAware = 0> { |
| foreach vtiToWti = AllWidenableIntToBF16Vectors in { |
| defvar vti = vtiToWti.Vti; |
| defvar fwti = vtiToWti.Wti; |
| let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates, |
| GetVTypePredicates<fwti>.Predicates) in |
| defm : VPatConversion<intrinsic, instruction, "V", |
| fwti.Vector, vti.Vector, fwti.Mask, vti.Log2SEW, |
| vti.LMul, fwti.RegClass, vti.RegClass, isSEWAware>; |
| } |
| } |
| |
| multiclass VPatConversionWF_VF_BF16<string intrinsic, string instruction, |
| bit isSEWAware = 0> { |
| foreach fvtiToFWti = AllWidenableBF16ToFloatVectors in { |
| defvar fvti = fvtiToFWti.Vti; |
| defvar fwti = fvtiToFWti.Wti; |
| let Predicates = !listconcat(GetVTypeMinimalPredicates<fvti>.Predicates, |
| GetVTypeMinimalPredicates<fwti>.Predicates) in |
| defm : VPatConversion<intrinsic, instruction, "V", |
| fwti.Vector, fvti.Vector, fwti.Mask, fvti.Log2SEW, |
| fvti.LMul, fwti.RegClass, fvti.RegClass, isSEWAware>; |
| } |
| } |
| |
| multiclass VPatConversionVI_WF_BF16<string intrinsic, string instruction> { |
| foreach vtiToWti = AllWidenableIntToBF16Vectors in { |
| defvar vti = vtiToWti.Vti; |
| defvar fwti = vtiToWti.Wti; |
| let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates, |
| GetVTypePredicates<fwti>.Predicates) in |
| defm : VPatConversion<intrinsic, instruction, "W", |
| vti.Vector, fwti.Vector, vti.Mask, vti.Log2SEW, |
| vti.LMul, vti.RegClass, fwti.RegClass>; |
| } |
| } |
| |
| multiclass VPatConversionVI_WF_RM_BF16<string intrinsic, string instruction> { |
| foreach vtiToWti = AllWidenableIntToBF16Vectors in { |
| defvar vti = vtiToWti.Vti; |
| defvar fwti = vtiToWti.Wti; |
| let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates, |
| GetVTypePredicates<fwti>.Predicates) in |
| defm : VPatConversionRoundingMode<intrinsic, instruction, "W", |
| vti.Vector, fwti.Vector, vti.Mask, vti.Log2SEW, |
| vti.LMul, vti.RegClass, fwti.RegClass>; |
| } |
| } |
| |
| multiclass VPatConversionVF_WF_BF16<string intrinsic, string instruction, |
| bit isSEWAware = 0> { |
| foreach fvtiToFWti = AllWidenableBF16ToFloatVectors in { |
| defvar fvti = fvtiToFWti.Vti; |
| defvar fwti = fvtiToFWti.Wti; |
| let Predicates = !listconcat(GetVTypePredicates<fvti>.Predicates, |
| GetVTypePredicates<fwti>.Predicates) in |
| defm : VPatConversion<intrinsic, instruction, "W", |
| fvti.Vector, fwti.Vector, fvti.Mask, fvti.Log2SEW, |
| fvti.LMul, fvti.RegClass, fwti.RegClass, isSEWAware>; |
| } |
| } |
| |
| let Predicates = [HasStdExtZvfbfa] in { |
| defm : VPatBinaryV_VV_VX_RM<"int_riscv_vfadd", "PseudoVFADD_ALT", |
| AllBF16Vectors, isSEWAware = 1>; |
| defm : VPatBinaryV_VV_VX_RM<"int_riscv_vfsub", "PseudoVFSUB_ALT", |
| AllBF16Vectors, isSEWAware = 1>; |
| defm : VPatBinaryV_VX_RM<"int_riscv_vfrsub", "PseudoVFRSUB_ALT", |
| AllBF16Vectors, isSEWAware = 1>; |
| defm : VPatBinaryW_VV_VX_RM<"int_riscv_vfwadd", "PseudoVFWADD_ALT", |
| AllWidenableBF16ToFloatVectors, isSEWAware=1>; |
| defm : VPatBinaryW_VV_VX_RM<"int_riscv_vfwsub", "PseudoVFWSUB_ALT", |
| AllWidenableBF16ToFloatVectors, isSEWAware=1>; |
| defm : VPatBinaryW_WV_WX_RM<"int_riscv_vfwadd_w", "PseudoVFWADD_ALT", |
| AllWidenableBF16ToFloatVectors, isSEWAware=1>; |
| defm : VPatBinaryW_WV_WX_RM<"int_riscv_vfwsub_w", "PseudoVFWSUB_ALT", |
| AllWidenableBF16ToFloatVectors, isSEWAware=1>; |
| defm : VPatBinaryV_VV_VX_RM<"int_riscv_vfmul", "PseudoVFMUL_ALT", |
| AllBF16Vectors, isSEWAware=1>; |
| defm : VPatBinaryW_VV_VX_RM<"int_riscv_vfwmul", "PseudoVFWMUL_ALT", |
| AllWidenableBF16ToFloatVectors, isSEWAware=1>; |
| defm : VPatTernaryV_VV_VX_AAXA_RM<"int_riscv_vfmacc", "PseudoVFMACC_ALT", |
| AllBF16Vectors, isSEWAware=1>; |
| defm : VPatTernaryV_VV_VX_AAXA_RM<"int_riscv_vfnmacc", "PseudoVFNMACC_ALT", |
| AllBF16Vectors, isSEWAware=1>; |
| defm : VPatTernaryV_VV_VX_AAXA_RM<"int_riscv_vfmsac", "PseudoVFMSAC_ALT", |
| AllBF16Vectors, isSEWAware=1>; |
| defm : VPatTernaryV_VV_VX_AAXA_RM<"int_riscv_vfnmsac", "PseudoVFNMSAC_ALT", |
| AllBF16Vectors, isSEWAware=1>; |
| defm : VPatTernaryV_VV_VX_AAXA_RM<"int_riscv_vfmadd", "PseudoVFMADD_ALT", |
| AllBF16Vectors, isSEWAware=1>; |
| defm : VPatTernaryV_VV_VX_AAXA_RM<"int_riscv_vfnmadd", "PseudoVFNMADD_ALT", |
| AllBF16Vectors, isSEWAware=1>; |
| defm : VPatTernaryV_VV_VX_AAXA_RM<"int_riscv_vfmsub", "PseudoVFMSUB_ALT", |
| AllBF16Vectors, isSEWAware=1>; |
| defm : VPatTernaryV_VV_VX_AAXA_RM<"int_riscv_vfnmsub", "PseudoVFNMSUB_ALT", |
| AllBF16Vectors, isSEWAware=1>; |
| defm : VPatTernaryW_VV_VX_RM<"int_riscv_vfwmacc", "PseudoVFWMACC_ALT", |
| AllWidenableBF16ToFloatVectors, isSEWAware=1>; |
| defm : VPatTernaryW_VV_VX_RM<"int_riscv_vfwnmacc", "PseudoVFWNMACC_ALT", |
| AllWidenableBF16ToFloatVectors, isSEWAware=1>; |
| defm : VPatTernaryW_VV_VX_RM<"int_riscv_vfwmsac", "PseudoVFWMSAC_ALT", |
| AllWidenableBF16ToFloatVectors, isSEWAware=1>; |
| defm : VPatTernaryW_VV_VX_RM<"int_riscv_vfwnmsac", "PseudoVFWNMSAC_ALT", |
| AllWidenableBF16ToFloatVectors, isSEWAware=1>; |
| defm : VPatUnaryV_V<"int_riscv_vfrsqrt7", "PseudoVFRSQRT7_ALT", |
| AllBF16Vectors, isSEWAware=1>; |
| defm : VPatUnaryV_V_RM<"int_riscv_vfrec7", "PseudoVFREC7_ALT", |
| AllBF16Vectors, isSEWAware=1>; |
| defm : VPatBinaryV_VV_VX<"int_riscv_vfmin", "PseudoVFMIN_ALT", |
| AllBF16Vectors, isSEWAware=1>; |
| defm : VPatBinaryV_VV_VX<"int_riscv_vfmax", "PseudoVFMAX_ALT", |
| AllBF16Vectors, isSEWAware=1>; |
| defm : VPatBinaryV_VV_VX<"int_riscv_vfsgnj", "PseudoVFSGNJ_ALT", |
| AllBF16Vectors, isSEWAware=1>; |
| defm : VPatBinaryV_VV_VX<"int_riscv_vfsgnjn", "PseudoVFSGNJN_ALT", |
| AllBF16Vectors, isSEWAware=1>; |
| defm : VPatBinaryV_VV_VX<"int_riscv_vfsgnjx", "PseudoVFSGNJX_ALT", |
| AllBF16Vectors, isSEWAware=1>; |
| defm : VPatBinaryM_VV_VX<"int_riscv_vmfeq", "PseudoVMFEQ_ALT", AllBF16Vectors>; |
| defm : VPatBinaryM_VV_VX<"int_riscv_vmfle", "PseudoVMFLE_ALT", AllBF16Vectors>; |
| defm : VPatBinaryM_VV_VX<"int_riscv_vmflt", "PseudoVMFLT_ALT", AllBF16Vectors>; |
| defm : VPatBinaryM_VV_VX<"int_riscv_vmfne", "PseudoVMFNE_ALT", AllBF16Vectors>; |
| defm : VPatBinaryM_VX<"int_riscv_vmfgt", "PseudoVMFGT_ALT", AllBF16Vectors>; |
| defm : VPatBinaryM_VX<"int_riscv_vmfge", "PseudoVMFGE_ALT", AllBF16Vectors>; |
| defm : VPatBinarySwappedM_VV<"int_riscv_vmfgt", "PseudoVMFLT_ALT", AllBF16Vectors>; |
| defm : VPatBinarySwappedM_VV<"int_riscv_vmfge", "PseudoVMFLE_ALT", AllBF16Vectors>; |
| defm : VPatConversionVI_VF_BF16<"int_riscv_vfclass", "PseudoVFCLASS_ALT">; |
| foreach vti = AllBF16Vectors in { |
| let Predicates = GetVTypePredicates<vti>.Predicates in |
| defm : VPatBinaryCarryInTAIL<"int_riscv_vfmerge", "PseudoVFMERGE_ALT", |
| "V"#vti.ScalarSuffix#"M", |
| vti.Vector, |
| vti.Vector, vti.Scalar, vti.Mask, |
| vti.Log2SEW, vti.LMul, vti.RegClass, |
| vti.RegClass, vti.ScalarRegClass>; |
| } |
| defm : VPatConversionWF_VI_BF16<"int_riscv_vfwcvt_f_xu_v", "PseudoVFWCVT_F_XU_ALT", |
| isSEWAware=1>; |
| defm : VPatConversionWF_VI_BF16<"int_riscv_vfwcvt_f_x_v", "PseudoVFWCVT_F_X_ALT", |
| isSEWAware=1>; |
| defm : VPatConversionWF_VF_BF16<"int_riscv_vfwcvt_f_f_v", "PseudoVFWCVT_F_F_ALT", |
| isSEWAware=1>; |
| defm : VPatConversionVI_WF_RM_BF16<"int_riscv_vfncvt_xu_f_w", "PseudoVFNCVT_XU_F_ALT">; |
| defm : VPatConversionVI_WF_RM_BF16<"int_riscv_vfncvt_x_f_w", "PseudoVFNCVT_X_F_ALT">; |
| defm : VPatConversionVI_WF_BF16<"int_riscv_vfncvt_rtz_xu_f_w", "PseudoVFNCVT_RTZ_XU_F_ALT">; |
| defm : VPatConversionVI_WF_BF16<"int_riscv_vfncvt_rtz_x_f_w", "PseudoVFNCVT_RTZ_X_F_ALT">; |
| defm : VPatConversionVF_WF_RM<"int_riscv_vfncvt_f_f_w", "PseudoVFNCVT_F_F_ALT", |
| AllWidenableBF16ToFloatVectors, isSEWAware=1>; |
| defm : VPatConversionVF_WF_BF16<"int_riscv_vfncvt_rod_f_f_w", "PseudoVFNCVT_ROD_F_F_ALT", |
| isSEWAware=1>; |
| defm : VPatBinaryV_VX<"int_riscv_vfslide1up", "PseudoVFSLIDE1UP_ALT", AllBF16Vectors>; |
| defm : VPatBinaryV_VX<"int_riscv_vfslide1down", "PseudoVFSLIDE1DOWN_ALT", AllBF16Vectors>; |
| |
| foreach fvti = AllBF16Vectors in { |
| defvar ivti = GetIntVTypeInfo<fvti>.Vti; |
| let Predicates = GetVTypePredicates<ivti>.Predicates in { |
| // 13.16. Vector Floating-Point Move Instruction |
| // If we're splatting fpimm0, use vmv.v.x vd, x0. |
| def : Pat<(fvti.Vector (riscv_vfmv_v_f_vl |
| fvti.Vector:$passthru, (fvti.Scalar (fpimm0)), VLOpFrag)), |
| (!cast<Instruction>("PseudoVMV_V_I_"#fvti.LMul.MX) |
| $passthru, 0, GPR:$vl, fvti.Log2SEW, TU_MU)>; |
| def : Pat<(fvti.Vector (riscv_vfmv_v_f_vl |
| fvti.Vector:$passthru, (fvti.Scalar (SelectScalarFPAsInt (XLenVT GPR:$imm))), VLOpFrag)), |
| (!cast<Instruction>("PseudoVMV_V_X_"#fvti.LMul.MX) |
| $passthru, GPR:$imm, GPR:$vl, fvti.Log2SEW, TU_MU)>; |
| } |
| |
| let Predicates = GetVTypePredicates<fvti>.Predicates in { |
| def : Pat<(fvti.Vector (riscv_vfmv_v_f_vl |
| fvti.Vector:$passthru, (fvti.Scalar fvti.ScalarRegClass:$rs2), VLOpFrag)), |
| (!cast<Instruction>("PseudoVFMV_V_ALT_" # fvti.ScalarSuffix # "_" # |
| fvti.LMul.MX) |
| $passthru, (fvti.Scalar fvti.ScalarRegClass:$rs2), |
| GPR:$vl, fvti.Log2SEW, TU_MU)>; |
| } |
| } |
| |
| foreach vti = NoGroupBF16Vectors in { |
| let Predicates = GetVTypePredicates<vti>.Predicates in { |
| def : Pat<(vti.Vector (riscv_vfmv_s_f_vl (vti.Vector vti.RegClass:$passthru), |
| (vti.Scalar (fpimm0)), |
| VLOpFrag)), |
| (PseudoVMV_S_X $passthru, (XLenVT X0), GPR:$vl, vti.Log2SEW)>; |
| def : Pat<(vti.Vector (riscv_vfmv_s_f_vl (vti.Vector vti.RegClass:$passthru), |
| (vti.Scalar (SelectScalarFPAsInt (XLenVT GPR:$imm))), |
| VLOpFrag)), |
| (PseudoVMV_S_X $passthru, GPR:$imm, GPR:$vl, vti.Log2SEW)>; |
| def : Pat<(vti.Vector (riscv_vfmv_s_f_vl (vti.Vector vti.RegClass:$passthru), |
| vti.ScalarRegClass:$rs1, |
| VLOpFrag)), |
| (!cast<Instruction>("PseudoVFMV_S_"#vti.ScalarSuffix#"_ALT") |
| vti.RegClass:$passthru, |
| (vti.Scalar vti.ScalarRegClass:$rs1), GPR:$vl, vti.Log2SEW)>; |
| } |
| |
| defvar vfmv_f_s_inst = !cast<Instruction>(!strconcat("PseudoVFMV_", |
| vti.ScalarSuffix, |
| "_S_ALT")); |
| // Only pattern-match extract-element operations where the index is 0. Any |
| // other index will have been custom-lowered to slide the vector correctly |
| // into place. |
| let Predicates = GetVTypePredicates<vti>.Predicates in |
| def : Pat<(vti.Scalar (extractelt (vti.Vector vti.RegClass:$rs2), 0)), |
| (vfmv_f_s_inst vti.RegClass:$rs2, vti.Log2SEW)>; |
| } |
| |
| let Predicates = [HasStdExtZvfbfa] in { |
| foreach fvtiToFWti = AllWidenableBF16ToFloatVectors in { |
| defvar fvti = fvtiToFWti.Vti; |
| defvar fwti = fvtiToFWti.Wti; |
| def : Pat<(fwti.Vector (any_riscv_fpextend_vl |
| (fvti.Vector fvti.RegClass:$rs1), |
| (fvti.Mask VMV0:$vm), |
| VLOpFrag)), |
| (!cast<Instruction>("PseudoVFWCVT_F_F_ALT_V_"#fvti.LMul.MX#"_E"#fvti.SEW#"_MASK") |
| (fwti.Vector (IMPLICIT_DEF)), fvti.RegClass:$rs1, |
| (fvti.Mask VMV0:$vm), |
| GPR:$vl, fvti.Log2SEW, TA_MA)>; |
| |
| def : Pat<(fvti.Vector (any_riscv_fpround_vl |
| (fwti.Vector fwti.RegClass:$rs1), |
| (fwti.Mask VMV0:$vm), VLOpFrag)), |
| (!cast<Instruction>("PseudoVFNCVT_F_F_ALT_W_"#fvti.LMul.MX#"_E"#fvti.SEW#"_MASK") |
| (fvti.Vector (IMPLICIT_DEF)), fwti.RegClass:$rs1, |
| (fwti.Mask VMV0:$vm), |
| // Value to indicate no rounding mode change in |
| // RISCVInsertReadWriteCSR |
| FRM_DYN, |
| GPR:$vl, fvti.Log2SEW, TA_MA)>; |
| def : Pat<(fvti.Vector (fpround (fwti.Vector fwti.RegClass:$rs1))), |
| (!cast<Instruction>("PseudoVFNCVT_F_F_ALT_W_"#fvti.LMul.MX#"_E"#fvti.SEW) |
| (fvti.Vector (IMPLICIT_DEF)), |
| fwti.RegClass:$rs1, |
| // Value to indicate no rounding mode change in |
| // RISCVInsertReadWriteCSR |
| FRM_DYN, |
| fvti.AVL, fvti.Log2SEW, TA_MA)>; |
| } |
| } |
| } // Predicates = [HasStdExtZvfbfa] |