| //===-- RISCVInstrInfoZvk.td - RISC-V 'Zvk' 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 'Zvk', |
| // Vector Cryptography Instructions extension, version Release 1.0.0. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| //===----------------------------------------------------------------------===// |
| // Operand and SDNode transformation definitions. |
| //===----------------------------------------------------------------------===// |
| |
| def tuimm5 : RISCVOp, TImmLeaf<XLenVT, [{return isUInt<5>(Imm);}]>; |
| |
| //===----------------------------------------------------------------------===// |
| // Instruction class templates |
| //===----------------------------------------------------------------------===// |
| |
| let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { |
| multiclass VCLMUL_MV_V_X<string opcodestr, bits<6> funct6> { |
| def V : VALUVV<funct6, OPMVV, opcodestr # "." # "vv">, |
| SchedBinaryMC<"WriteVCLMULV", "ReadVCLMULV", "ReadVCLMULV">; |
| def X : VALUVX<funct6, OPMVX, opcodestr # "." # "vx">, |
| SchedBinaryMC<"WriteVCLMULX", "ReadVCLMULV", "ReadVCLMULX">; |
| } |
| |
| class RVInstIVI_VROR<bits<6> funct6, dag outs, dag ins, string opcodestr, |
| string argstr> |
| : RVInst<outs, ins, opcodestr, argstr, [], InstFormatR> { |
| bits<5> vs2; |
| bits<6> imm; |
| bits<5> vd; |
| bit vm; |
| |
| let Inst{31-27} = funct6{5-1}; |
| let Inst{26} = imm{5}; |
| let Inst{25} = vm; |
| let Inst{24-20} = vs2; |
| let Inst{19-15} = imm{4-0}; |
| let Inst{14-12} = OPIVI.Value; |
| let Inst{11-7} = vd; |
| let Inst{6-0} = OPC_OP_V.Value; |
| |
| let Uses = [VL, VTYPE]; |
| let RVVConstraint = VMConstraint; |
| } |
| |
| multiclass VROR_IV_V_X_I<string opcodestr, bits<6> funct6> |
| : VALU_IV_V_X<opcodestr, funct6> { |
| def I : RVInstIVI_VROR<funct6, (outs VR:$vd), |
| (ins VR:$vs2, uimm6:$imm, VMaskOp:$vm), |
| opcodestr # ".vi", "$vd, $vs2, $imm$vm">, |
| SchedUnaryMC<"WriteVRotI", "ReadVRotV">; |
| } |
| |
| // op vd, vs2, vs1 |
| class PALUVVNoVm<bits<6> funct6, RISCVVFormat opv, string opcodestr> |
| : VALUVVNoVm<funct6, opv, opcodestr> { |
| let Inst{6-0} = OPC_OP_VE.Value; |
| } |
| |
| // op vd, vs2, vs1 |
| class PALUVVNoVmTernary<bits<6> funct6, RISCVVFormat opv, string opcodestr> |
| : RVInstVV<funct6, opv, (outs VR:$vd_wb), |
| (ins VR:$vd, VR:$vs2, VR:$vs1), |
| opcodestr, "$vd, $vs2, $vs1"> { |
| let Constraints = "$vd = $vd_wb"; |
| let vm = 1; |
| let Inst{6-0} = OPC_OP_VE.Value; |
| } |
| |
| // op vd, vs2, imm |
| class PALUVINoVm<bits<6> funct6, string opcodestr, Operand optype> |
| : VALUVINoVm<funct6, opcodestr, optype> { |
| let Inst{6-0} = OPC_OP_VE.Value; |
| let Inst{14-12} = OPMVV.Value; |
| } |
| |
| // op vd, vs2, imm where vd is also a source regardless of tail policy |
| class PALUVINoVmBinary<bits<6> funct6, string opcodestr, Operand optype> |
| : RVInstIVI<funct6, (outs VR:$vd_wb), |
| (ins VR:$vd, VR:$vs2, optype:$imm), |
| opcodestr, "$vd, $vs2, $imm"> { |
| let Constraints = "$vd = $vd_wb"; |
| let vm = 1; |
| let Inst{6-0} = OPC_OP_VE.Value; |
| let Inst{14-12} = OPMVV.Value; |
| } |
| |
| // op vd, vs2 (use vs1 as instruction encoding) where vd is also a source |
| // regardless of tail policy |
| class PALUVs2NoVmBinary<bits<6> funct6, bits<5> vs1, RISCVVFormat opv, |
| string opcodestr> |
| : RVInstV<funct6, vs1, opv, (outs VR:$vd_wb), (ins VR:$vd, VR:$vs2), |
| opcodestr, "$vd, $vs2"> { |
| let Constraints = "$vd = $vd_wb"; |
| let vm = 1; |
| let Inst{6-0} = OPC_OP_VE.Value; |
| } |
| |
| multiclass VAES_MV_V_S<bits<6> funct6_vv, bits<6> funct6_vs, bits<5> vs1, |
| RISCVVFormat opv, string opcodestr> { |
| let RVVConstraint = NoConstraint in |
| def NAME # _VV : PALUVs2NoVmBinary<funct6_vv, vs1, opv, opcodestr # ".vv">, |
| SchedBinaryMC<"WriteVAESMVV", "ReadVAESMVV", "ReadVAESMVV">; |
| let RVVConstraint = VS2Constraint in |
| def NAME # _VS : PALUVs2NoVmBinary<funct6_vs, vs1, opv, opcodestr # ".vs">, |
| SchedBinaryMC<"WriteVAESMVV", "ReadVAESMVV", "ReadVAESMVV">; |
| } |
| } // hasSideEffects = 0, mayLoad = 0, mayStore = 0 |
| |
| //===----------------------------------------------------------------------===// |
| // Instructions |
| //===----------------------------------------------------------------------===// |
| |
| let Predicates = [HasStdExtZvbb] in { |
| def VBREV_V : VALUVs2<0b010010, 0b01010, OPMVV, "vbrev.v">; |
| def VCLZ_V : VALUVs2<0b010010, 0b01100, OPMVV, "vclz.v">; |
| def VCPOP_V : VALUVs2<0b010010, 0b01110, OPMVV, "vcpop.v">; |
| def VCTZ_V : VALUVs2<0b010010, 0b01101, OPMVV, "vctz.v">; |
| let Constraints = "@earlyclobber $vd", RVVConstraint = WidenV, |
| DestEEW = EEWSEWx2 in |
| defm VWSLL_V : VSHT_IV_V_X_I<"vwsll", 0b110101>; |
| } // Predicates = [HasStdExtZvbb] |
| |
| let Predicates = [HasStdExtZvbcOrZvbc32e] in { |
| defm VCLMUL_V : VCLMUL_MV_V_X<"vclmul", 0b001100>; |
| defm VCLMULH_V : VCLMUL_MV_V_X<"vclmulh", 0b001101>; |
| } // Predicates = [HasStdExtZvbcOrZvbc32e] |
| |
| let Predicates = [HasStdExtZvkb] in { |
| defm VANDN_V : VALU_IV_V_X<"vandn", 0b000001>; |
| def VBREV8_V : VALUVs2<0b010010, 0b01000, OPMVV, "vbrev8.v">; |
| def VREV8_V : VALUVs2<0b010010, 0b01001, OPMVV, "vrev8.v">; |
| defm VROL_V : VALU_IV_V_X<"vrol", 0b010101>; |
| defm VROR_V : VROR_IV_V_X_I<"vror", 0b010100>; |
| } // Predicates = [HasStdExtZvkb] |
| |
| let ElementsDependOn = EltDepsVLMask in { |
| |
| let Predicates = [HasStdExtZvkg], RVVConstraint = NoConstraint in { |
| def VGHSH_VV : PALUVVNoVmTernary<0b101100, OPMVV, "vghsh.vv">, |
| SchedTernaryMC<"WriteVGHSHV", "ReadVGHSHV", "ReadVGHSHV", |
| "ReadVGHSHV">; |
| def VGMUL_VV : PALUVs2NoVmBinary<0b101000, 0b10001, OPMVV, "vgmul.vv">, |
| SchedBinaryMC<"WriteVGMULV", "ReadVGMULV", "ReadVGMULV">; |
| } // Predicates = [HasStdExtZvkg] |
| |
| let Predicates = [HasStdExtZvkgs], RVVConstraint = VS2Constraint in { |
| def VGHSH_VS : PALUVVNoVmTernary<0b100011, OPMVV, "vghsh.vs">, |
| SchedTernaryMC<"WriteVGHSHV", "ReadVGHSHV", "ReadVGHSHV", |
| "ReadVGHSHV">; |
| def VGMUL_VS : PALUVs2NoVmBinary<0b101001, 0b10001, OPMVV, "vgmul.vs">, |
| SchedBinaryMC<"WriteVGMULV", "ReadVGMULV", "ReadVGMULV">; |
| } // Predicates = [HasStdExtZvkgs] |
| |
| let Predicates = [HasStdExtZvknhaOrZvknhb], RVVConstraint = Sha2Constraint in { |
| def VSHA2CH_VV : PALUVVNoVmTernary<0b101110, OPMVV, "vsha2ch.vv">, |
| SchedTernaryMC<"WriteVSHA2CHV", "ReadVSHA2CHV", "ReadVSHA2CHV", |
| "ReadVSHA2CHV">; |
| def VSHA2CL_VV : PALUVVNoVmTernary<0b101111, OPMVV, "vsha2cl.vv">, |
| SchedTernaryMC<"WriteVSHA2CLV", "ReadVSHA2CLV", "ReadVSHA2CLV", |
| "ReadVSHA2CLV">; |
| def VSHA2MS_VV : PALUVVNoVmTernary<0b101101, OPMVV, "vsha2ms.vv">, |
| SchedTernaryMC<"WriteVSHA2MSV", "ReadVSHA2MSV", "ReadVSHA2MSV", |
| "ReadVSHA2MSV">; |
| } // Predicates = [HasStdExtZvknhaOrZvknhb] |
| |
| let Predicates = [HasStdExtZvkned] in { |
| defm VAESDF : VAES_MV_V_S<0b101000, 0b101001, 0b00001, OPMVV, "vaesdf">; |
| defm VAESDM : VAES_MV_V_S<0b101000, 0b101001, 0b00000, OPMVV, "vaesdm">; |
| defm VAESEF : VAES_MV_V_S<0b101000, 0b101001, 0b00011, OPMVV, "vaesef">; |
| defm VAESEM : VAES_MV_V_S<0b101000, 0b101001, 0b00010, OPMVV, "vaesem">; |
| def VAESKF1_VI : PALUVINoVm<0b100010, "vaeskf1.vi", uimm5>, |
| SchedUnaryMC<"WriteVAESKF1V", "ReadVAESKF1V">; |
| def VAESKF2_VI : PALUVINoVmBinary<0b101010, "vaeskf2.vi", uimm5>, |
| SchedBinaryMC<"WriteVAESKF2V", "ReadVAESKF2V", "ReadVAESKF2V">; |
| let RVVConstraint = VS2Constraint in |
| def VAESZ_VS : PALUVs2NoVmBinary<0b101001, 0b00111, OPMVV, "vaesz.vs">, |
| SchedBinaryMC<"WriteVAESZV", "ReadVAESZV", "ReadVAESZV">; |
| } // Predicates = [HasStdExtZvkned] |
| |
| let Predicates = [HasStdExtZvksed] in { |
| let RVVConstraint = NoConstraint in |
| def VSM4K_VI : PALUVINoVm<0b100001, "vsm4k.vi", uimm5>, |
| SchedUnaryMC<"WriteVSM4KV", "ReadVSM4KV">; |
| defm VSM4R : VAES_MV_V_S<0b101000, 0b101001, 0b10000, OPMVV, "vsm4r">; |
| } // Predicates = [HasStdExtZvksed] |
| |
| let Predicates = [HasStdExtZvksh], RVVConstraint = VS2Constraint in { |
| def VSM3C_VI : PALUVINoVmBinary<0b101011, "vsm3c.vi", uimm5>, |
| SchedBinaryMC<"WriteVSM3CV", "ReadVSM3CV", "ReadVSM3CV">; |
| def VSM3ME_VV : PALUVVNoVm<0b100000, OPMVV, "vsm3me.vv">, |
| SchedUnaryMC<"WriteVSM3MEV", "ReadVSM3MEV">; |
| } // Predicates = [HasStdExtZvksh] |
| |
| } // ElementsDependOn = EltDepsVLMask |
| |
| //===----------------------------------------------------------------------===// |
| // Pseudo instructions |
| //===----------------------------------------------------------------------===// |
| |
| defvar I32IntegerVectors = !filter(vti, AllIntegerVectors, !eq(vti.SEW, 32)); |
| defvar I32I64IntegerVectors = !filter(vti, AllIntegerVectors, |
| !or(!eq(vti.SEW, 32), !eq(vti.SEW, 64))); |
| |
| class ZvkI32IntegerVectors<string vd_lmul> { |
| list<VTypeInfo> vs2_types = !cond(!eq(vd_lmul, "M8") : !filter(vti, I32IntegerVectors, !le(vti.LMul.octuple, 32)), |
| !eq(vd_lmul, "M4") : !filter(vti, I32IntegerVectors, !le(vti.LMul.octuple, 32)), |
| !eq(vd_lmul, "M2") : !filter(vti, I32IntegerVectors, !le(vti.LMul.octuple, 16)), |
| !eq(vd_lmul, "M1") : !filter(vti, I32IntegerVectors, !le(vti.LMul.octuple, 8)), |
| !eq(vd_lmul, "MF2") : !filter(vti, I32IntegerVectors, !le(vti.LMul.octuple, 4)), |
| !eq(vd_lmul, "MF4") : !filter(vti, I32IntegerVectors, !le(vti.LMul.octuple, 2)), |
| !eq(vd_lmul, "MF8") : !filter(vti, I32IntegerVectors, !le(vti.LMul.octuple, 1))); |
| } |
| |
| class ZvkMxSet<string vd_lmul> { |
| list<LMULInfo> vs2_lmuls = !cond(!eq(vd_lmul, "M8") : [V_MF8, V_MF4, V_MF2, V_M1, V_M2, V_M4], |
| !eq(vd_lmul, "M4") : [V_MF8, V_MF4, V_MF2, V_M1, V_M2, V_M4], |
| !eq(vd_lmul, "M2") : [V_MF8, V_MF4, V_MF2, V_M1, V_M2], |
| !eq(vd_lmul, "M1") : [V_MF8, V_MF4, V_MF2, V_M1], |
| !eq(vd_lmul, "MF2") : [V_MF8, V_MF4, V_MF2], |
| !eq(vd_lmul, "MF4") : [V_MF8, V_MF4], |
| !eq(vd_lmul, "MF8") : [V_MF8]); |
| } |
| |
| class VPseudoBinaryNoMask_Zvk<DAGOperand RetClass, VReg OpClass> : |
| Pseudo<(outs RetClass:$rd_wb), |
| (ins RetClass:$rd, OpClass:$rs2, AVL:$vl, sew:$sew, vec_policy:$policy), []>, |
| RISCVVPseudo { |
| let mayLoad = 0; |
| let mayStore = 0; |
| let hasSideEffects = 0; |
| let Constraints = "$rd_wb = $rd"; |
| let HasVLOp = 1; |
| let HasSEWOp = 1; |
| let HasVecPolicyOp = 1; |
| let BaseInstr = !cast<Instruction>(PseudoToVInst<NAME>.VInst); |
| } |
| |
| class VPseudoTernaryNoMask_Zvk<VReg RetClass, |
| VReg Op1Class, |
| DAGOperand Op2Class> : |
| Pseudo<(outs RetClass:$rd_wb), |
| (ins RetClass:$rd, Op1Class:$rs2, Op2Class:$rs1, |
| AVL:$vl, sew:$sew, vec_policy:$policy), []>, |
| RISCVVPseudo { |
| let mayLoad = 0; |
| let mayStore = 0; |
| let hasSideEffects = 0; |
| let Constraints = "$rd_wb = $rd"; |
| let HasVLOp = 1; |
| let HasSEWOp = 1; |
| let HasVecPolicyOp = 1; |
| let BaseInstr = !cast<Instruction>(PseudoToVInst<NAME>.VInst); |
| } |
| |
| multiclass VPseudoBinaryNoMaskPolicy_Zvk<VReg RetClass, |
| VReg Op1Class, |
| DAGOperand Op2Class, |
| LMULInfo MInfo, |
| string Constraint = ""> { |
| let VLMul = MInfo.value in { |
| def "_" # MInfo.MX : VPseudoBinaryNoMaskPolicy<RetClass, Op1Class, Op2Class, |
| Constraint>; |
| } |
| } |
| |
| multiclass VPseudoTernaryNoMask_Zvk<VReg RetClass, |
| VReg Op1Class, |
| DAGOperand Op2Class, |
| LMULInfo MInfo, int sew = 0> { |
| let VLMul = MInfo.value, SEW = sew in { |
| defvar suffix = !if(sew, "_" # MInfo.MX # "_E" # sew, "_" # MInfo.MX); |
| def suffix : VPseudoTernaryNoMask_Zvk<RetClass, Op1Class, Op2Class>; |
| } |
| } |
| |
| multiclass VPseudoBinaryV_V_NoMask_Zvk<LMULInfo m> { |
| let VLMul = m.value in { |
| def "_VV_" # m.MX : VPseudoBinaryNoMask_Zvk<m.vrclass, m.vrclass>; |
| } |
| } |
| |
| multiclass VPseudoBinaryV_S_NoMask_Zvk<LMULInfo m> { |
| let VLMul = m.value in |
| foreach vs2_lmul = ZvkMxSet<m.MX>.vs2_lmuls in |
| def "_VS_" # m.MX # "_" # vs2_lmul.MX : VPseudoBinaryNoMask_Zvk<m.vrclass, vs2_lmul.vrclass>; |
| } |
| |
| multiclass VPseudoVGMUL { |
| foreach m = MxListVF4 in { |
| defvar mx = m.MX; |
| defm "" : VPseudoBinaryV_V_NoMask_Zvk<m>, |
| SchedBinary<"WriteVGMULV", "ReadVGMULV", "ReadVGMULV", mx>; |
| } |
| } |
| |
| multiclass VPseudoVAESMV { |
| foreach m = MxListVF4 in { |
| defvar mx = m.MX; |
| defm "" : VPseudoBinaryV_V_NoMask_Zvk<m>, |
| SchedBinary<"WriteVAESMVV", "ReadVAESMVV", "ReadVAESMVV", mx>; |
| defm "" : VPseudoBinaryV_S_NoMask_Zvk<m>, |
| SchedBinary<"WriteVAESMVV", "ReadVAESMVV", "ReadVAESMVV", mx>; |
| |
| } |
| } |
| |
| multiclass VPseudoVSM4R { |
| foreach m = MxListVF4 in { |
| defvar mx = m.MX; |
| defm "" : VPseudoBinaryV_V_NoMask_Zvk<m>, |
| SchedBinary<"WriteVSM4RV", "ReadVSM4RV", "ReadVSM4RV", mx>; |
| defm "" : VPseudoBinaryV_S_NoMask_Zvk<m>, |
| SchedBinary<"WriteVSM4RV", "ReadVSM4RV", "ReadVSM4RV", mx>; |
| |
| } |
| } |
| |
| multiclass VPseudoVGHSH { |
| foreach m = MxListVF4 in { |
| defvar mx = m.MX; |
| defm _VV : VPseudoTernaryNoMask_Zvk<m.vrclass, m.vrclass, m.vrclass, m>, |
| SchedTernary<"WriteVGHSHV", "ReadVGHSHV", "ReadVGHSHV", |
| "ReadVGHSHV", mx>; |
| } |
| } |
| |
| multiclass VPseudoVSHA2CH { |
| foreach m = MxListVF4 in { |
| defvar mx = m.MX; |
| defm _VV : VPseudoTernaryNoMask_Zvk<m.vrclass, m.vrclass, m.vrclass, m>, |
| SchedTernary<"WriteVSHA2CHV", "ReadVSHA2CHV", "ReadVSHA2CHV", |
| "ReadVSHA2CHV", mx>; |
| } |
| } |
| |
| multiclass VPseudoVSHA2CL { |
| foreach m = MxListVF4 in { |
| defvar mx = m.MX; |
| defm _VV : VPseudoTernaryNoMask_Zvk<m.vrclass, m.vrclass, m.vrclass, m>, |
| SchedTernary<"WriteVSHA2CLV", "ReadVSHA2CLV", "ReadVSHA2CLV", |
| "ReadVSHA2CLV", mx>; |
| } |
| } |
| |
| multiclass VPseudoVSHA2MS<int sew = 0> { |
| foreach m = !if(!eq(sew, 64), MxListVF8, MxListVF4) in { |
| defvar mx = m.MX; |
| defm _VV : VPseudoTernaryNoMask_Zvk<m.vrclass, m.vrclass, m.vrclass, m, sew = sew>, |
| SchedTernary<"WriteVSHA2MSV", "ReadVSHA2MSV", "ReadVSHA2MSV", |
| "ReadVSHA2MSV", mx, sew>; |
| } |
| } |
| |
| multiclass VPseudoVAESKF1 { |
| foreach m = MxListVF4 in { |
| defvar mx = m.MX; |
| defm _VI : VPseudoBinaryNoMaskPolicy_Zvk<m.vrclass, m.vrclass, uimm5, m>, |
| SchedBinary<"WriteVAESKF1V", "ReadVAESKF1V", "ReadVAESKF1V", mx, |
| forcePassthruRead=true>; |
| } |
| } |
| |
| multiclass VPseudoVAESKF2 { |
| foreach m = MxListVF4 in { |
| defvar mx = m.MX; |
| defm _VI : VPseudoTernaryNoMask_Zvk<m.vrclass, m.vrclass, uimm5, m>, |
| SchedTernary<"WriteVAESKF2V", "ReadVAESKF2V", "ReadVAESKF2V", |
| "ReadVAESKF2V", mx>; |
| } |
| } |
| |
| multiclass VPseudoVAESZ { |
| foreach m = MxListVF4 in { |
| defvar mx = m.MX; |
| defm "" : VPseudoBinaryV_S_NoMask_Zvk<m>, |
| SchedBinary<"WriteVAESZV", "ReadVAESZV", "ReadVAESZV", mx>; |
| } |
| } |
| |
| multiclass VPseudoVSM3C { |
| foreach m = MxListVF4 in { |
| defvar mx = m.MX; |
| defm _VI : VPseudoTernaryNoMask_Zvk<m.vrclass, m.vrclass, uimm5, m>, |
| SchedTernary<"WriteVSM3CV", "ReadVSM3CV", "ReadVSM3CV", |
| "ReadVSM3CV", mx>; |
| } |
| } |
| |
| multiclass VPseudoVSM4K { |
| foreach m = MxListVF4 in { |
| defvar mx = m.MX; |
| defm _VI : VPseudoBinaryNoMaskPolicy_Zvk<m.vrclass, m.vrclass, uimm5, m>, |
| SchedBinary<"WriteVSM4KV", "ReadVSM4KV", "ReadVSM4KV", mx, |
| forcePassthruRead=true>; |
| } |
| } |
| |
| multiclass VPseudoVSM3ME { |
| foreach m = MxListVF4 in { |
| defvar mx = m.MX; |
| defm _VV : VPseudoBinaryNoMaskPolicy_Zvk<m.vrclass, m.vrclass, m.vrclass, m>, |
| SchedBinary<"WriteVSM3MEV", "ReadVSM3MEV", "ReadVSM3MEV", mx, |
| forcePassthruRead=true>; |
| } |
| } |
| |
| multiclass VPseudoVCLMUL_VV_VX { |
| foreach m = MxList in { |
| defvar mx = m.MX; |
| defm "" : VPseudoBinaryV_VV<m>, |
| SchedBinary<"WriteVCLMULV", "ReadVCLMULV", "ReadVCLMULV", mx, |
| forcePassthruRead=true>; |
| defm "" : VPseudoBinaryV_VX<m>, |
| SchedBinary<"WriteVCLMULX", "ReadVCLMULV", "ReadVCLMULX", mx, |
| forcePassthruRead=true>; |
| } |
| } |
| |
| multiclass VPseudoUnaryV_V<LMULInfo m> { |
| let VLMul = m.value in { |
| defvar suffix = "_V_" # m.MX; |
| def suffix : VPseudoUnaryNoMask<m.vrclass, m.vrclass>; |
| def suffix # "_MASK" : VPseudoUnaryMask<m.vrclass, m.vrclass>, |
| RISCVMaskedPseudo<MaskIdx=2>; |
| } |
| } |
| |
| multiclass VPseudoVBREV { |
| foreach m = MxList in { |
| defvar mx = m.MX; |
| defm "" : VPseudoUnaryV_V<m>, |
| SchedUnary<"WriteVBREVV", "ReadVBREVV", mx, forcePassthruRead=true>; |
| } |
| } |
| |
| multiclass VPseudoVCLZ { |
| foreach m = MxList in { |
| defvar mx = m.MX; |
| defm "" : VPseudoUnaryV_V<m>, |
| SchedUnary<"WriteVCLZV", "ReadVCLZV", mx, forcePassthruRead=true>; |
| } |
| } |
| |
| multiclass VPseudoVCTZ { |
| foreach m = MxList in { |
| defvar mx = m.MX; |
| defm "" : VPseudoUnaryV_V<m>, |
| SchedUnary<"WriteVCTZV", "ReadVCTZV", mx, forcePassthruRead=true>; |
| } |
| } |
| |
| multiclass VPseudoVCPOP { |
| foreach m = MxList in { |
| defvar mx = m.MX; |
| defm "" : VPseudoUnaryV_V<m>, |
| SchedUnary<"WriteVCPOPV", "ReadVCPOPV", mx, forcePassthruRead=true>; |
| } |
| } |
| |
| multiclass VPseudoVWSLL { |
| foreach m = MxListW in { |
| defvar mx = m.MX; |
| defm "" : VPseudoBinaryW_VV<m>, |
| SchedBinary<"WriteVWSLLV", "ReadVWSLLV", "ReadVWSLLV", mx, |
| forcePassthruRead=true>; |
| defm "" : VPseudoBinaryW_VX<m>, |
| SchedBinary<"WriteVWSLLX", "ReadVWSLLV", "ReadVWSLLX", mx, |
| forcePassthruRead=true>; |
| defm "" : VPseudoBinaryW_VI<uimm5, m>, |
| SchedUnary<"WriteVWSLLI", "ReadVWSLLV", mx, |
| forcePassthruRead=true>; |
| } |
| } |
| |
| multiclass VPseudoVANDN { |
| foreach m = MxList in { |
| defm "" : VPseudoBinaryV_VV<m>, |
| SchedBinary<"WriteVIALUV", "ReadVIALUV", "ReadVIALUV", m.MX, |
| forcePassthruRead=true>; |
| defm "" : VPseudoBinaryV_VX<m>, |
| SchedBinary<"WriteVIALUX", "ReadVIALUV", "ReadVIALUX", m.MX, |
| forcePassthruRead=true>; |
| } |
| } |
| |
| multiclass VPseudoVBREV8 { |
| foreach m = MxList in { |
| defvar mx = m.MX; |
| defm "" : VPseudoUnaryV_V<m>, |
| SchedUnary<"WriteVBREV8V", "ReadVBREV8V", mx, forcePassthruRead=true>; |
| } |
| } |
| |
| multiclass VPseudoVREV8 { |
| foreach m = MxList in { |
| defvar mx = m.MX; |
| defm "" : VPseudoUnaryV_V<m>, |
| SchedUnary<"WriteVREV8V", "ReadVREV8V", mx, forcePassthruRead=true>; |
| } |
| } |
| |
| multiclass VPseudoVROT_VV_VX { |
| foreach m = MxList in { |
| defm "" : VPseudoBinaryV_VV<m>, |
| SchedBinary<"WriteVRotV", "ReadVRotV", "ReadVRotV", m.MX, |
| forcePassthruRead=true>; |
| defm "" : VPseudoBinaryV_VX<m>, |
| SchedBinary<"WriteVRotX", "ReadVRotV", "ReadVRotX", m.MX, |
| forcePassthruRead=true>; |
| } |
| } |
| |
| multiclass VPseudoVROT_VV_VX_VI |
| : VPseudoVROT_VV_VX { |
| foreach m = MxList in { |
| defm "" : VPseudoBinaryV_VI<uimm6, m>, |
| SchedUnary<"WriteVRotI", "ReadVRotV", m.MX, |
| forcePassthruRead=true>; |
| } |
| } |
| |
| let Predicates = [HasStdExtZvbb] in { |
| defm PseudoVBREV : VPseudoVBREV; |
| defm PseudoVCLZ : VPseudoVCLZ; |
| defm PseudoVCTZ : VPseudoVCTZ; |
| defm PseudoVCPOP : VPseudoVCPOP; |
| defm PseudoVWSLL : VPseudoVWSLL; |
| } // Predicates = [HasStdExtZvbb] |
| |
| let Predicates = [HasStdExtZvbc] in { |
| defm PseudoVCLMUL : VPseudoVCLMUL_VV_VX; |
| defm PseudoVCLMULH : VPseudoVCLMUL_VV_VX; |
| } // Predicates = [HasStdExtZvbc] |
| |
| let Predicates = [HasStdExtZvkb] in { |
| defm PseudoVANDN : VPseudoVANDN; |
| defm PseudoVBREV8 : VPseudoVBREV8; |
| defm PseudoVREV8 : VPseudoVREV8; |
| defm PseudoVROL : VPseudoVROT_VV_VX; |
| defm PseudoVROR : VPseudoVROT_VV_VX_VI; |
| } // Predicates = [HasStdExtZvkb] |
| |
| let Predicates = [HasStdExtZvkg] in { |
| defm PseudoVGHSH : VPseudoVGHSH; |
| defm PseudoVGMUL : VPseudoVGMUL; |
| } // Predicates = [HasStdExtZvkg] |
| |
| let Predicates = [HasStdExtZvkned] in { |
| defm PseudoVAESDF : VPseudoVAESMV; |
| defm PseudoVAESDM : VPseudoVAESMV; |
| defm PseudoVAESEF : VPseudoVAESMV; |
| defm PseudoVAESEM : VPseudoVAESMV; |
| defm PseudoVAESKF1 : VPseudoVAESKF1; |
| defm PseudoVAESKF2 : VPseudoVAESKF2; |
| defm PseudoVAESZ : VPseudoVAESZ; |
| } // Predicates = [HasStdExtZvkned] |
| |
| let Predicates = [HasStdExtZvknhaOrZvknhb] in { |
| defm PseudoVSHA2CH : VPseudoVSHA2CH; |
| defm PseudoVSHA2CL : VPseudoVSHA2CL; |
| defm PseudoVSHA2MS : VPseudoVSHA2MS<sew=32>; |
| let Predicates = [HasStdExtZvknhb] in |
| defm PseudoVSHA2MS : VPseudoVSHA2MS<sew=64>; |
| } // Predicates = [HasStdExtZvknhaOrZvknhb] |
| |
| let Predicates = [HasStdExtZvksed] in { |
| defm PseudoVSM4K : VPseudoVSM4K; |
| defm PseudoVSM4R : VPseudoVSM4R; |
| } // Predicates = [HasStdExtZvksed] |
| |
| let Predicates = [HasStdExtZvksh] in { |
| defm PseudoVSM3C : VPseudoVSM3C; |
| defm PseudoVSM3ME : VPseudoVSM3ME; |
| } // Predicates = [HasStdExtZvksh] |
| |
| //===----------------------------------------------------------------------===// |
| // SDNode patterns |
| //===----------------------------------------------------------------------===// |
| |
| multiclass VPatUnarySDNode_V<SDPatternOperator op, string instruction_name, |
| Predicate predicate = HasStdExtZvbb> { |
| foreach vti = AllIntegerVectors in { |
| let Predicates = !listconcat([predicate], |
| GetVTypePredicates<vti>.Predicates) in { |
| def : Pat<(vti.Vector (op (vti.Vector vti.RegClass:$rs1))), |
| (!cast<Instruction>(instruction_name#"_V_"#vti.LMul.MX) |
| (vti.Vector (IMPLICIT_DEF)), |
| vti.RegClass:$rs1, |
| vti.AVL, vti.Log2SEW, TA_MA)>; |
| } |
| } |
| } |
| |
| // Helpers for detecting splats since we preprocess splat_vector to vmv.v.x |
| // This should match the logic in RISCVDAGToDAGISel::selectVSplat |
| def riscv_splat_vector : PatFrag<(ops node:$rs1), |
| (riscv_vmv_v_x_vl undef, node:$rs1, srcvalue)>; |
| def allonessew8 : ImmLeaf<XLenVT, "return SignExtend64<8>(Imm) == -1LL;">; |
| def allonessew16 : ImmLeaf<XLenVT, "return SignExtend64<16>(Imm) == -1LL;">; |
| def allonessew32 : ImmLeaf<XLenVT, "return SignExtend64<32>(Imm) == -1LL;">; |
| def allonessew64 : ImmLeaf<XLenVT, "return Imm == -1LL;">; |
| |
| foreach vti = AllIntegerVectors in { |
| let Predicates = !listconcat([HasStdExtZvkb], |
| GetVTypePredicates<vti>.Predicates) in { |
| def : Pat<(vti.Vector (and (xor vti.RegClass:$rs1, |
| (riscv_splat_vector !cast<ImmLeaf>("allonessew"#vti.SEW))), |
| vti.RegClass:$rs2)), |
| (!cast<Instruction>("PseudoVANDN_VV_"#vti.LMul.MX) |
| (vti.Vector (IMPLICIT_DEF)), |
| vti.RegClass:$rs2, |
| vti.RegClass:$rs1, |
| vti.AVL, vti.Log2SEW, TA_MA)>; |
| def : Pat<(vti.Vector (and (riscv_splat_vector |
| (not vti.ScalarRegClass:$rs1)), |
| vti.RegClass:$rs2)), |
| (!cast<Instruction>("PseudoVANDN_VX_"#vti.LMul.MX) |
| (vti.Vector (IMPLICIT_DEF)), |
| vti.RegClass:$rs2, |
| vti.ScalarRegClass:$rs1, |
| vti.AVL, vti.Log2SEW, TA_MA)>; |
| def : Pat<(vti.Vector (and (riscv_splat_vector invLogicImm:$rs1), |
| vti.RegClass:$rs2)), |
| (!cast<Instruction>("PseudoVANDN_VX_"#vti.LMul.MX) |
| (vti.Vector (IMPLICIT_DEF)), |
| vti.RegClass:$rs2, |
| invLogicImm:$rs1, |
| vti.AVL, vti.Log2SEW, TA_MA)>; |
| } |
| } |
| |
| defm : VPatUnarySDNode_V<bitreverse, "PseudoVBREV">; |
| defm : VPatUnarySDNode_V<bswap, "PseudoVREV8", HasStdExtZvkb>; |
| defm : VPatUnarySDNode_V<ctlz, "PseudoVCLZ">; |
| defm : VPatUnarySDNode_V<cttz, "PseudoVCTZ">; |
| defm : VPatUnarySDNode_V<ctpop, "PseudoVCPOP">; |
| |
| defm : VPatBinarySDNode_VV_VX<rotl, "PseudoVROL">; |
| |
| // Invert the immediate and mask it to SEW for readability. |
| def InvRot8Imm : SDNodeXForm<imm, [{ |
| return CurDAG->getTargetConstant(0x7 & (64 - N->getZExtValue()), SDLoc(N), |
| N->getValueType(0)); |
| }]>; |
| def InvRot16Imm : SDNodeXForm<imm, [{ |
| return CurDAG->getTargetConstant(0xf & (64 - N->getZExtValue()), SDLoc(N), |
| N->getValueType(0)); |
| }]>; |
| def InvRot32Imm : SDNodeXForm<imm, [{ |
| return CurDAG->getTargetConstant(0x1f & (64 - N->getZExtValue()), SDLoc(N), |
| N->getValueType(0)); |
| }]>; |
| def InvRot64Imm : SDNodeXForm<imm, [{ |
| return CurDAG->getTargetConstant(0x3f & (64 - N->getZExtValue()), SDLoc(N), |
| N->getValueType(0)); |
| }]>; |
| |
| // Although there is no vrol.vi, an immediate rotate left can be achieved by |
| // negating the immediate in vror.vi |
| foreach vti = AllIntegerVectors in { |
| let Predicates = !listconcat([HasStdExtZvkb], |
| GetVTypePredicates<vti>.Predicates) in { |
| def : Pat<(vti.Vector (rotl vti.RegClass:$rs2, |
| (vti.Vector (SplatPat_uimm6 uimm6:$rs1)))), |
| (!cast<Instruction>("PseudoVROR_VI_"#vti.LMul.MX) |
| (vti.Vector (IMPLICIT_DEF)), |
| vti.RegClass:$rs2, |
| (!cast<SDNodeXForm>("InvRot" # vti.SEW # "Imm") uimm6:$rs1), |
| vti.AVL, vti.Log2SEW, TA_MA)>; |
| } |
| } |
| defm : VPatBinarySDNode_VV_VX_VI<rotr, "PseudoVROR", uimm6>; |
| |
| foreach vtiToWti = AllWidenableIntVectors in { |
| defvar vti = vtiToWti.Vti; |
| defvar wti = vtiToWti.Wti; |
| let Predicates = !listconcat([HasStdExtZvbb], |
| GetVTypePredicates<vti>.Predicates, |
| GetVTypePredicates<wti>.Predicates) in { |
| def : Pat<(shl (wti.Vector (zext_oneuse (vti.Vector vti.RegClass:$rs2))), |
| (wti.Vector (ext_oneuse (vti.Vector vti.RegClass:$rs1)))), |
| (!cast<Instruction>("PseudoVWSLL_VV_"#vti.LMul.MX) |
| (wti.Vector (IMPLICIT_DEF)), |
| vti.RegClass:$rs2, vti.RegClass:$rs1, |
| vti.AVL, vti.Log2SEW, TA_MA)>; |
| |
| def : Pat<(shl (wti.Vector (zext_oneuse (vti.Vector vti.RegClass:$rs2))), |
| (wti.Vector (Low8BitsSplatPat (XLenVT GPR:$rs1)))), |
| (!cast<Instruction>("PseudoVWSLL_VX_"#vti.LMul.MX) |
| (wti.Vector (IMPLICIT_DEF)), |
| vti.RegClass:$rs2, GPR:$rs1, |
| vti.AVL, vti.Log2SEW, TA_MA)>; |
| |
| def : Pat<(shl (wti.Vector (zext_oneuse (vti.Vector vti.RegClass:$rs2))), |
| (wti.Vector (SplatPat_uimm5 uimm5:$rs1))), |
| (!cast<Instruction>("PseudoVWSLL_VI_"#vti.LMul.MX) |
| (wti.Vector (IMPLICIT_DEF)), |
| vti.RegClass:$rs2, uimm5:$rs1, |
| vti.AVL, vti.Log2SEW, TA_MA)>; |
| } |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // VL patterns |
| //===----------------------------------------------------------------------===// |
| |
| multiclass VPatUnaryVL_V<SDPatternOperator op, string instruction_name, |
| Predicate predicate = HasStdExtZvbb> { |
| foreach vti = AllIntegerVectors in { |
| let Predicates = !listconcat([predicate], |
| GetVTypePredicates<vti>.Predicates) in { |
| def : Pat<(vti.Vector (op (vti.Vector vti.RegClass:$rs1), |
| (vti.Vector vti.RegClass:$passthru), |
| (vti.Mask VMV0:$vm), |
| VLOpFrag)), |
| (!cast<Instruction>(instruction_name#"_V_"#vti.LMul.MX#"_MASK") |
| vti.RegClass:$passthru, |
| vti.RegClass:$rs1, |
| (vti.Mask VMV0:$vm), |
| GPR:$vl, |
| vti.Log2SEW, |
| TAIL_AGNOSTIC)>; |
| } |
| } |
| } |
| |
| foreach vti = AllIntegerVectors in { |
| let Predicates = !listconcat([HasStdExtZvkb], |
| GetVTypePredicates<vti>.Predicates) in { |
| def : Pat<(vti.Vector (riscv_and_vl (riscv_xor_vl |
| (vti.Vector vti.RegClass:$rs1), |
| (riscv_splat_vector !cast<ImmLeaf>("allonessew"#vti.SEW)), |
| (vti.Vector vti.RegClass:$passthru), |
| (vti.Mask VMV0:$vm), |
| VLOpFrag), |
| (vti.Vector vti.RegClass:$rs2), |
| (vti.Vector vti.RegClass:$passthru), |
| (vti.Mask VMV0:$vm), |
| VLOpFrag)), |
| (!cast<Instruction>("PseudoVANDN_VV_"#vti.LMul.MX#"_MASK") |
| vti.RegClass:$passthru, |
| vti.RegClass:$rs2, |
| vti.RegClass:$rs1, |
| (vti.Mask VMV0:$vm), |
| GPR:$vl, |
| vti.Log2SEW, |
| TAIL_AGNOSTIC)>; |
| |
| def : Pat<(vti.Vector (riscv_and_vl (riscv_splat_vector |
| (not vti.ScalarRegClass:$rs1)), |
| (vti.Vector vti.RegClass:$rs2), |
| (vti.Vector vti.RegClass:$passthru), |
| (vti.Mask VMV0:$vm), |
| VLOpFrag)), |
| (!cast<Instruction>("PseudoVANDN_VX_"#vti.LMul.MX#"_MASK") |
| vti.RegClass:$passthru, |
| vti.RegClass:$rs2, |
| vti.ScalarRegClass:$rs1, |
| (vti.Mask VMV0:$vm), |
| GPR:$vl, |
| vti.Log2SEW, |
| TAIL_AGNOSTIC)>; |
| |
| def : Pat<(vti.Vector (riscv_and_vl (riscv_splat_vector invLogicImm:$rs1), |
| (vti.Vector vti.RegClass:$rs2), |
| (vti.Vector vti.RegClass:$passthru), |
| (vti.Mask VMV0:$vm), |
| VLOpFrag)), |
| (!cast<Instruction>("PseudoVANDN_VX_"#vti.LMul.MX#"_MASK") |
| vti.RegClass:$passthru, |
| vti.RegClass:$rs2, |
| invLogicImm:$rs1, |
| (vti.Mask VMV0:$vm), |
| GPR:$vl, |
| vti.Log2SEW, |
| TAIL_AGNOSTIC)>; |
| } |
| } |
| |
| defm : VPatUnaryVL_V<riscv_bitreverse_vl, "PseudoVBREV">; |
| defm : VPatUnaryVL_V<riscv_bswap_vl, "PseudoVREV8", HasStdExtZvkb>; |
| defm : VPatUnaryVL_V<riscv_ctlz_vl, "PseudoVCLZ">; |
| defm : VPatUnaryVL_V<riscv_cttz_vl, "PseudoVCTZ">; |
| defm : VPatUnaryVL_V<riscv_ctpop_vl, "PseudoVCPOP">; |
| |
| defm : VPatBinaryVL_VV_VX<riscv_rotl_vl, "PseudoVROL">; |
| // Although there is no vrol.vi, an immediate rotate left can be achieved by |
| // negating the immediate in vror.vi |
| foreach vti = AllIntegerVectors in { |
| let Predicates = !listconcat([HasStdExtZvkb], |
| GetVTypePredicates<vti>.Predicates) in { |
| def : Pat<(riscv_rotl_vl vti.RegClass:$rs2, |
| (vti.Vector (SplatPat_uimm6 uimm6:$rs1)), |
| (vti.Vector vti.RegClass:$passthru), |
| (vti.Mask VMV0:$vm), VLOpFrag), |
| (!cast<Instruction>("PseudoVROR_VI_"#vti.LMul.MX#"_MASK") |
| vti.RegClass:$passthru, |
| vti.RegClass:$rs2, |
| (!cast<SDNodeXForm>("InvRot" # vti.SEW # "Imm") uimm6:$rs1), |
| (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>; |
| } |
| } |
| defm : VPatBinaryVL_VV_VX_VI<riscv_rotr_vl, "PseudoVROR", uimm6>; |
| |
| foreach vtiToWti = AllWidenableIntVectors in { |
| defvar vti = vtiToWti.Vti; |
| defvar wti = vtiToWti.Wti; |
| let Predicates = !listconcat([HasStdExtZvbb], |
| GetVTypePredicates<vti>.Predicates, |
| GetVTypePredicates<wti>.Predicates) in { |
| def : Pat<(riscv_shl_vl |
| (wti.Vector (zext_oneuse (vti.Vector vti.RegClass:$rs2))), |
| (wti.Vector (ext_oneuse (vti.Vector vti.RegClass:$rs1))), |
| (wti.Vector wti.RegClass:$passthru), |
| (vti.Mask VMV0:$vm), VLOpFrag), |
| (!cast<Instruction>("PseudoVWSLL_VV_"#vti.LMul.MX#"_MASK") |
| wti.RegClass:$passthru, vti.RegClass:$rs2, vti.RegClass:$rs1, |
| (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>; |
| |
| def : Pat<(riscv_shl_vl |
| (wti.Vector (riscv_zext_vl_oneuse |
| (vti.Vector vti.RegClass:$rs2), |
| (vti.Mask VMV0:$vm), VLOpFrag)), |
| (wti.Vector (riscv_ext_vl_oneuse |
| (vti.Vector vti.RegClass:$rs1), |
| (vti.Mask VMV0:$vm), VLOpFrag)), |
| (wti.Vector wti.RegClass:$passthru), |
| (vti.Mask VMV0:$vm), VLOpFrag), |
| (!cast<Instruction>("PseudoVWSLL_VV_"#vti.LMul.MX#"_MASK") |
| wti.RegClass:$passthru, vti.RegClass:$rs2, vti.RegClass:$rs1, |
| (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>; |
| |
| def : Pat<(riscv_shl_vl |
| (wti.Vector (zext_oneuse (vti.Vector vti.RegClass:$rs2))), |
| (wti.Vector (Low8BitsSplatPat (XLenVT GPR:$rs1))), |
| (wti.Vector wti.RegClass:$passthru), |
| (vti.Mask VMV0:$vm), VLOpFrag), |
| (!cast<Instruction>("PseudoVWSLL_VX_"#vti.LMul.MX#"_MASK") |
| wti.RegClass:$passthru, vti.RegClass:$rs2, GPR:$rs1, |
| (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>; |
| |
| def : Pat<(riscv_shl_vl |
| (wti.Vector (riscv_zext_vl_oneuse |
| (vti.Vector vti.RegClass:$rs2), |
| (vti.Mask VMV0:$vm), VLOpFrag)), |
| (wti.Vector (Low8BitsSplatPat (XLenVT GPR:$rs1))), |
| (wti.Vector wti.RegClass:$passthru), |
| (vti.Mask VMV0:$vm), VLOpFrag), |
| (!cast<Instruction>("PseudoVWSLL_VX_"#vti.LMul.MX#"_MASK") |
| wti.RegClass:$passthru, vti.RegClass:$rs2, GPR:$rs1, |
| (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>; |
| |
| def : Pat<(riscv_shl_vl |
| (wti.Vector (zext_oneuse (vti.Vector vti.RegClass:$rs2))), |
| (wti.Vector (SplatPat_uimm5 uimm5:$rs1)), |
| (wti.Vector wti.RegClass:$passthru), |
| (vti.Mask VMV0:$vm), VLOpFrag), |
| (!cast<Instruction>("PseudoVWSLL_VI_"#vti.LMul.MX#"_MASK") |
| wti.RegClass:$passthru, vti.RegClass:$rs2, uimm5:$rs1, |
| (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>; |
| |
| def : Pat<(riscv_shl_vl |
| (wti.Vector (riscv_zext_vl_oneuse |
| (vti.Vector vti.RegClass:$rs2), |
| (vti.Mask VMV0:$vm), VLOpFrag)), |
| (wti.Vector (SplatPat_uimm5 uimm5:$rs1)), |
| (wti.Vector wti.RegClass:$passthru), |
| (vti.Mask VMV0:$vm), VLOpFrag), |
| (!cast<Instruction>("PseudoVWSLL_VI_"#vti.LMul.MX#"_MASK") |
| wti.RegClass:$passthru, vti.RegClass:$rs2, uimm5:$rs1, |
| (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>; |
| |
| def : Pat<(riscv_vwsll_vl |
| (vti.Vector vti.RegClass:$rs2), |
| (vti.Vector vti.RegClass:$rs1), |
| (wti.Vector wti.RegClass:$passthru), |
| (vti.Mask VMV0:$vm), VLOpFrag), |
| (!cast<Instruction>("PseudoVWSLL_VV_"#vti.LMul.MX#"_MASK") |
| wti.RegClass:$passthru, vti.RegClass:$rs2, vti.RegClass:$rs1, |
| (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>; |
| |
| def : Pat<(riscv_vwsll_vl |
| (vti.Vector vti.RegClass:$rs2), |
| (vti.Vector (Low8BitsSplatPat (XLenVT GPR:$rs1))), |
| (wti.Vector wti.RegClass:$passthru), |
| (vti.Mask VMV0:$vm), VLOpFrag), |
| (!cast<Instruction>("PseudoVWSLL_VX_"#vti.LMul.MX#"_MASK") |
| wti.RegClass:$passthru, vti.RegClass:$rs2, GPR:$rs1, |
| (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>; |
| |
| def : Pat<(riscv_vwsll_vl |
| (vti.Vector vti.RegClass:$rs2), |
| (vti.Vector (SplatPat_uimm5 uimm5:$rs1)), |
| (wti.Vector wti.RegClass:$passthru), |
| (vti.Mask VMV0:$vm), VLOpFrag), |
| (!cast<Instruction>("PseudoVWSLL_VI_"#vti.LMul.MX#"_MASK") |
| wti.RegClass:$passthru, vti.RegClass:$rs2, uimm5:$rs1, |
| (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>; |
| } |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Codegen patterns |
| //===----------------------------------------------------------------------===// |
| |
| class VPatUnaryNoMask_Zvk<string intrinsic_name, |
| string inst, |
| string kind, |
| ValueType result_type, |
| ValueType op2_type, |
| int sew, |
| LMULInfo vlmul, |
| VReg result_reg_class, |
| VReg op2_reg_class> : |
| Pat<(result_type (!cast<Intrinsic>(intrinsic_name) |
| (result_type result_reg_class:$rd), |
| (op2_type op2_reg_class:$rs2), |
| VLOpFrag, (XLenVT timm:$policy))), |
| (!cast<Instruction>(inst#"_"#kind#"_"#vlmul.MX) |
| (result_type result_reg_class:$rd), |
| (op2_type op2_reg_class:$rs2), |
| GPR:$vl, sew, (XLenVT timm:$policy))>; |
| |
| class VPatUnaryNoMask_VS_Zvk<string intrinsic_name, |
| string inst, |
| string kind, |
| ValueType result_type, |
| ValueType op2_type, |
| int sew, |
| LMULInfo vlmul, |
| LMULInfo vs2_lmul, |
| VReg result_reg_class, |
| VReg op2_reg_class> : |
| Pat<(result_type (!cast<Intrinsic>(intrinsic_name) |
| (result_type result_reg_class:$rd), |
| (op2_type op2_reg_class:$rs2), |
| VLOpFrag, (XLenVT timm:$policy))), |
| (!cast<Instruction>(inst#"_"#kind#"_"#vlmul.MX#"_"#vs2_lmul.MX) |
| (result_type result_reg_class:$rd), |
| (op2_type op2_reg_class:$rs2), |
| GPR:$vl, sew, (XLenVT timm:$policy))>; |
| |
| multiclass VPatUnaryV_V_NoMask_Zvk<string intrinsic, string instruction, |
| list<VTypeInfo> vtilist> { |
| foreach vti = vtilist in |
| def : VPatUnaryNoMask_Zvk<intrinsic # "_vv", instruction, "VV", |
| vti.Vector, vti.Vector, vti.Log2SEW, |
| vti.LMul, vti.RegClass, vti.RegClass>; |
| } |
| |
| multiclass VPatUnaryV_S_NoMaskVectorCrypto<string intrinsic, string instruction, |
| list<VTypeInfo> vtilist> { |
| foreach vti = vtilist in |
| foreach vti_vs2 = ZvkI32IntegerVectors<vti.LMul.MX>.vs2_types in |
| def : VPatUnaryNoMask_VS_Zvk<intrinsic # "_vs", instruction, "VS", |
| vti.Vector, vti_vs2.Vector, vti.Log2SEW, |
| vti.LMul, vti_vs2.LMul, vti.RegClass, vti_vs2.RegClass>; |
| } |
| |
| multiclass VPatUnaryV_V_S_NoMask_Zvk<string intrinsic, string instruction, |
| list<VTypeInfo> vtilist> { |
| defm : VPatUnaryV_V_NoMask_Zvk<intrinsic, instruction, vtilist>; |
| defm : VPatUnaryV_S_NoMaskVectorCrypto<intrinsic, instruction, vtilist>; |
| } |
| |
| multiclass VPatBinaryV_VV_NoMask<string intrinsic, string instruction, |
| list<VTypeInfo> vtilist, |
| bit isSEWAware = false> { |
| foreach vti = vtilist in |
| def : VPatTernaryNoMaskWithPolicy<intrinsic, instruction, "VV", |
| vti.Vector, vti.Vector, vti.Vector, |
| vti.Log2SEW, vti.LMul, vti.RegClass, |
| vti.RegClass, vti.RegClass, |
| isSEWAware = isSEWAware>; |
| } |
| |
| multiclass VPatBinaryV_VI_NoMask<string intrinsic, string instruction, |
| list<VTypeInfo> vtilist, |
| Operand imm_type = tuimm5> { |
| foreach vti = vtilist in |
| def : VPatTernaryNoMaskWithPolicy<intrinsic, instruction, "VI", |
| vti.Vector, vti.Vector, XLenVT, |
| vti.Log2SEW, vti.LMul, vti.RegClass, |
| vti.RegClass, imm_type>; |
| } |
| |
| multiclass VPatBinaryV_VI_NoMaskTU<string intrinsic, string instruction, |
| list<VTypeInfo> vtilist, |
| Operand imm_type = tuimm5> { |
| foreach vti = vtilist in |
| def : VPatBinaryNoMaskTU<intrinsic, instruction # "_VI_" # vti.LMul.MX, |
| vti.Vector, vti.Vector, XLenVT, vti.Log2SEW, |
| vti.RegClass, vti.RegClass, imm_type>; |
| } |
| |
| multiclass VPatBinaryV_VV_NoMaskTU<string intrinsic, string instruction, |
| list<VTypeInfo> vtilist> { |
| foreach vti = vtilist in |
| def : VPatBinaryNoMaskTU<intrinsic, instruction # "_VV_" # vti.LMul.MX, |
| vti.Vector, vti.Vector, vti.Vector, vti.Log2SEW, |
| vti.RegClass, vti.RegClass, vti.RegClass>; |
| } |
| |
| multiclass VPatBinaryV_VX_VROTATE<string intrinsic, string instruction, |
| list<VTypeInfo> vtilist, bit isSEWAware = 0> { |
| foreach vti = vtilist in { |
| defvar kind = "V"#vti.ScalarSuffix; |
| let Predicates = GetVTypePredicates<vti>.Predicates in |
| defm : VPatBinary<intrinsic, |
| !if(isSEWAware, |
| instruction#"_"#kind#"_"#vti.LMul.MX#"_E"#vti.SEW, |
| instruction#"_"#kind#"_"#vti.LMul.MX), |
| vti.Vector, vti.Vector, XLenVT, vti.Mask, |
| vti.Log2SEW, vti.RegClass, |
| vti.RegClass, vti.ScalarRegClass>; |
| } |
| } |
| |
| multiclass VPatBinaryV_VI_VROL<string intrinsic, string instruction, |
| list<VTypeInfo> vtilist, bit isSEWAware = 0> { |
| foreach vti = vtilist in { |
| defvar Intr = !cast<Intrinsic>(intrinsic); |
| defvar Pseudo = !cast<Instruction>( |
| !if(isSEWAware, instruction#"_VI_"#vti.LMul.MX#"_E"#vti.SEW, |
| instruction#"_VI_"#vti.LMul.MX)); |
| let Predicates = GetVTypePredicates<vti>.Predicates in |
| def : Pat<(vti.Vector (Intr (vti.Vector vti.RegClass:$passthru), |
| (vti.Vector vti.RegClass:$rs2), |
| (XLenVT uimm6:$rs1), |
| VLOpFrag)), |
| (Pseudo (vti.Vector vti.RegClass:$passthru), |
| (vti.Vector vti.RegClass:$rs2), |
| (InvRot64Imm uimm6:$rs1), |
| GPR:$vl, vti.Log2SEW, TU_MU)>; |
| |
| defvar IntrMask = !cast<Intrinsic>(intrinsic#"_mask"); |
| defvar PseudoMask = !cast<Instruction>( |
| !if(isSEWAware, instruction#"_VI_"#vti.LMul.MX#"_E"#vti.SEW#"_MASK", |
| instruction#"_VI_"#vti.LMul.MX#"_MASK")); |
| let Predicates = GetVTypePredicates<vti>.Predicates in |
| def : Pat<(vti.Vector (IntrMask (vti.Vector vti.RegClass:$passthru), |
| (vti.Vector vti.RegClass:$rs2), |
| (XLenVT uimm6:$rs1), |
| (vti.Mask VMV0:$vm), |
| VLOpFrag, (XLenVT timm:$policy))), |
| (PseudoMask (vti.Vector vti.RegClass:$passthru), |
| (vti.Vector vti.RegClass:$rs2), |
| (InvRot64Imm uimm6:$rs1), |
| (vti.Mask VMV0:$vm), |
| GPR:$vl, vti.Log2SEW, (XLenVT timm:$policy))>; |
| } |
| } |
| |
| multiclass VPatBinaryV_VV_VX_VROL<string intrinsic, string instruction, |
| string instruction2, list<VTypeInfo> vtilist> |
| : VPatBinaryV_VV<intrinsic, instruction, vtilist>, |
| VPatBinaryV_VX_VROTATE<intrinsic, instruction, vtilist>, |
| VPatBinaryV_VI_VROL<intrinsic, instruction2, vtilist>; |
| |
| multiclass VPatBinaryV_VV_VX_VI_VROR<string intrinsic, string instruction, |
| list<VTypeInfo> vtilist> |
| : VPatBinaryV_VV<intrinsic, instruction, vtilist>, |
| VPatBinaryV_VX_VROTATE<intrinsic, instruction, vtilist>, |
| VPatBinaryV_VI<intrinsic, instruction, vtilist, uimm6>; |
| |
| multiclass VPatBinaryW_VV_VX_VI_VWSLL<string intrinsic, string instruction, |
| list<VTypeInfoToWide> vtilist> |
| : VPatBinaryW_VV<intrinsic, instruction, vtilist> { |
| foreach VtiToWti = vtilist in { |
| defvar Vti = VtiToWti.Vti; |
| defvar Wti = VtiToWti.Wti; |
| defvar kind = "V"#Vti.ScalarSuffix; |
| let Predicates = !listconcat(GetVTypePredicates<Vti>.Predicates, |
| GetVTypePredicates<Wti>.Predicates) in { |
| defm : VPatBinary<intrinsic, instruction#"_"#kind#"_"#Vti.LMul.MX, |
| Wti.Vector, Vti.Vector, XLenVT, Vti.Mask, |
| Vti.Log2SEW, Wti.RegClass, |
| Vti.RegClass, Vti.ScalarRegClass>; |
| defm : VPatBinary<intrinsic, instruction # "_VI_" # Vti.LMul.MX, |
| Wti.Vector, Vti.Vector, XLenVT, Vti.Mask, |
| Vti.Log2SEW, Wti.RegClass, |
| Vti.RegClass, uimm5>; |
| } |
| } |
| } |
| |
| let Predicates = [HasStdExtZvbb] in { |
| defm : VPatUnaryV_V<"int_riscv_vbrev", "PseudoVBREV", AllIntegerVectors>; |
| defm : VPatUnaryV_V<"int_riscv_vclz", "PseudoVCLZ", AllIntegerVectors>; |
| defm : VPatUnaryV_V<"int_riscv_vctz", "PseudoVCTZ", AllIntegerVectors>; |
| defm : VPatUnaryV_V<"int_riscv_vcpopv", "PseudoVCPOP", AllIntegerVectors>; |
| defm : VPatBinaryW_VV_VX_VI_VWSLL<"int_riscv_vwsll", "PseudoVWSLL", AllWidenableIntVectors>; |
| } // Predicates = [HasStdExtZvbb] |
| |
| let Predicates = [HasStdExtZvbc] in { |
| defm : VPatBinaryV_VV_VX<"int_riscv_vclmul", "PseudoVCLMUL", I64IntegerVectors>; |
| defm : VPatBinaryV_VV_VX<"int_riscv_vclmulh", "PseudoVCLMULH", I64IntegerVectors>; |
| } // Predicates = [HasStdExtZvbc] |
| |
| let Predicates = [HasStdExtZvkb] in { |
| defm : VPatBinaryV_VV_VX<"int_riscv_vandn", "PseudoVANDN", AllIntegerVectors>; |
| defm : VPatUnaryV_V<"int_riscv_vbrev8", "PseudoVBREV8", AllIntegerVectors>; |
| defm : VPatUnaryV_V<"int_riscv_vrev8", "PseudoVREV8", AllIntegerVectors>; |
| defm : VPatBinaryV_VV_VX_VROL<"int_riscv_vrol", "PseudoVROL", "PseudoVROR", AllIntegerVectors>; |
| defm : VPatBinaryV_VV_VX_VI_VROR<"int_riscv_vror", "PseudoVROR", AllIntegerVectors>; |
| } // Predicates = [HasStdExtZvkb] |
| |
| let Predicates = [HasStdExtZvkg] in { |
| defm : VPatBinaryV_VV_NoMask<"int_riscv_vghsh", "PseudoVGHSH", I32IntegerVectors>; |
| defm : VPatUnaryV_V_NoMask_Zvk<"int_riscv_vgmul", "PseudoVGMUL", I32IntegerVectors>; |
| } // Predicates = [HasStdExtZvkg] |
| |
| let Predicates = [HasStdExtZvkned] in { |
| defm : VPatUnaryV_V_S_NoMask_Zvk<"int_riscv_vaesdf", "PseudoVAESDF", I32IntegerVectors>; |
| defm : VPatUnaryV_V_S_NoMask_Zvk<"int_riscv_vaesdm", "PseudoVAESDM", I32IntegerVectors>; |
| defm : VPatUnaryV_V_S_NoMask_Zvk<"int_riscv_vaesef", "PseudoVAESEF", I32IntegerVectors>; |
| defm : VPatUnaryV_V_S_NoMask_Zvk<"int_riscv_vaesem", "PseudoVAESEM", I32IntegerVectors>; |
| defm : VPatBinaryV_VI_NoMaskTU<"int_riscv_vaeskf1", "PseudoVAESKF1", I32IntegerVectors>; |
| defm : VPatBinaryV_VI_NoMask<"int_riscv_vaeskf2", "PseudoVAESKF2", I32IntegerVectors>; |
| defm : VPatUnaryV_S_NoMaskVectorCrypto<"int_riscv_vaesz", "PseudoVAESZ", I32IntegerVectors>; |
| } // Predicates = [HasStdExtZvkned] |
| |
| let Predicates = [HasStdExtZvknha] in { |
| defm : VPatBinaryV_VV_NoMask<"int_riscv_vsha2ch", "PseudoVSHA2CH", I32IntegerVectors>; |
| defm : VPatBinaryV_VV_NoMask<"int_riscv_vsha2cl", "PseudoVSHA2CH", I32IntegerVectors>; |
| defm : VPatBinaryV_VV_NoMask<"int_riscv_vsha2ms", "PseudoVSHA2MS", I32IntegerVectors, isSEWAware=true>; |
| } // Predicates = [HasStdExtZvknha] |
| |
| let Predicates = [HasStdExtZvknhb] in { |
| defm : VPatBinaryV_VV_NoMask<"int_riscv_vsha2ch", "PseudoVSHA2CH", I32I64IntegerVectors>; |
| defm : VPatBinaryV_VV_NoMask<"int_riscv_vsha2cl", "PseudoVSHA2CH", I32I64IntegerVectors>; |
| defm : VPatBinaryV_VV_NoMask<"int_riscv_vsha2ms", "PseudoVSHA2MS", I32I64IntegerVectors, isSEWAware=true>; |
| } // Predicates = [HasStdExtZvknhb] |
| |
| let Predicates = [HasStdExtZvksed] in { |
| defm : VPatBinaryV_VI_NoMaskTU<"int_riscv_vsm4k", "PseudoVSM4K", I32IntegerVectors>; |
| defm : VPatUnaryV_V_S_NoMask_Zvk<"int_riscv_vsm4r", "PseudoVSM4R", I32IntegerVectors>; |
| } // Predicates = [HasStdExtZvksed] |
| |
| let Predicates = [HasStdExtZvksh] in { |
| defm : VPatBinaryV_VI_NoMask<"int_riscv_vsm3c", "PseudoVSM3C", I32IntegerVectors>; |
| defm : VPatBinaryV_VV_NoMaskTU<"int_riscv_vsm3me", "PseudoVSM3ME", I32IntegerVectors>; |
| } // Predicates = [HasStdExtZvksh] |