diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp index 557c528cfd03d..c735aaf5ec633 100644 --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -2284,17 +2284,16 @@ bool RISCVAsmParser::validateInstruction(MCInst &Inst, return false; unsigned DestReg = Inst.getOperand(0).getReg(); - unsigned CheckReg; // Operands[1] will be the first operand, DestReg. SMLoc Loc = Operands[1]->getStartLoc(); if (TargetFlags & RISCVII::VS2Constraint) { - CheckReg = Inst.getOperand(1).getReg(); + unsigned CheckReg = Inst.getOperand(1).getReg(); if (DestReg == CheckReg) return Error(Loc, "The destination vector register group cannot overlap" " the source vector register group."); } if ((TargetFlags & RISCVII::VS1Constraint) && (Inst.getOperand(2).isReg())) { - CheckReg = Inst.getOperand(2).getReg(); + unsigned CheckReg = Inst.getOperand(2).getReg(); if (DestReg == CheckReg) return Error(Loc, "The destination vector register group cannot overlap" " the source vector register group."); @@ -2314,10 +2313,10 @@ bool RISCVAsmParser::validateInstruction(MCInst &Inst, // same. For example, "viota.m v0, v2" is "viota.m v0, v2, NoRegister" // actually. We need to check the last operand to ensure whether it is // masked or not. - if ((TargetFlags & RISCVII::OneInput) && (Inst.getNumOperands() == 3)) - CheckReg = Inst.getOperand(2).getReg(); - else if (Inst.getNumOperands() == 4) - CheckReg = Inst.getOperand(3).getReg(); + unsigned CheckReg = Inst.getOperand(Inst.getNumOperands() - 1).getReg(); + assert((CheckReg == RISCV::V0 || CheckReg == RISCV::NoRegister) && + "Unexpected register for mask operand"); + if (DestReg == CheckReg) return Error(Loc, "The destination vector register group cannot overlap" " the mask register."); diff --git a/llvm/lib/Target/RISCV/RISCVInstrFormats.td b/llvm/lib/Target/RISCV/RISCVInstrFormats.td index 21f0514146353..5c8d8fa65b308 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrFormats.td +++ b/llvm/lib/Target/RISCV/RISCVInstrFormats.td @@ -49,33 +49,61 @@ def InstFormatCB : InstFormat<15>; def InstFormatCJ : InstFormat<16>; def InstFormatOther : InstFormat<17>; -class RISCVVConstraint val> { - bits<4> Value = val; +class RISCVVConstraint val> { + bits<3> Value = val; } -def NoConstraint : RISCVVConstraint<0b0000>; -def VS2Constraint : RISCVVConstraint<0b0001>; -def VS1Constraint : RISCVVConstraint<0b0010>; -def VMConstraint : RISCVVConstraint<0b0100>; -def OneInput : RISCVVConstraint<0b1000>; +def NoConstraint : RISCVVConstraint<0b000>; +def VS2Constraint : RISCVVConstraint<0b001>; +def VS1Constraint : RISCVVConstraint<0b010>; +def VMConstraint : RISCVVConstraint<0b100>; +// Illegal instructions: +// +// * The destination vector register group for a masked vector instruction +// cannot overlap the source mask register (v0), unless the destination vector +// register is being written with a mask value (e.g., comparisons) or the +// scalar result of a reduction. +// +// * Widening: The destination vector register group cannot overlap a source +// vector register group of a different EEW +// +// * Narrowing: The destination vector register group cannot overlap the +// first source vector register group +// +// * For vadc and vsbc, an illegal instruction exception is raised if the +// destination vector register is v0. +// +// * For vmadc and vmsbc, an illegal instruction exception is raised if the +// destination vector register overlaps a source vector register group. +// +// * viota: An illegal instruction exception is raised if the destination +// vector register group overlaps the source vector mask register. If the +// instruction is masked, an illegal instruction exception is issued if the +// destination vector register group overlaps v0. +// +// * v[f]slide[1]up: The destination vector register group for vslideup cannot +// overlap the source vector register group. +// +// * vrgather: The destination vector register group cannot overlap with the +// source vector register groups. +// +// * vcompress: The destination vector register group cannot overlap the +// source vector register group or the source mask register def WidenV : RISCVVConstraint; def WidenW : RISCVVConstraint; def WidenCvt : RISCVVConstraint; + VMConstraint.Value)>; def Narrow : RISCVVConstraint; def NarrowCvt : RISCVVConstraint; + VMConstraint.Value)>; def Vmadc : RISCVVConstraint; def Iota : RISCVVConstraint; + VMConstraint.Value)>; def SlideUp : RISCVVConstraint; def Vrgather : RISCVVConstraint nf, string opcodestr> opcodestr, "$vd, (${rs1})"> { let vm = 1; let Uses = []; + let RVVConstraint = NoConstraint; } // segment load vd, (rs1), vm @@ -700,7 +701,8 @@ defm VWMACCUS_V : VALUr_MV_X<"vwmaccus", 0b111110>; defm VMERGE_V : VALUm_IV_V_X_I<"vmerge", 0b010111>; // Vector Integer Move Instructions -let hasSideEffects = 0, mayLoad = 0, mayStore = 0, vs2 = 0, vm = 1 in { +let hasSideEffects = 0, mayLoad = 0, mayStore = 0, vs2 = 0, vm = 1, + RVVConstraint = NoConstraint in { // op vd, vs1 def VMV_V_V : RVInstVV<0b010111, OPIVV, (outs VR:$vd), (ins VR:$vs1), "vmv.v.v", "$vd, $vs1">; @@ -827,6 +829,7 @@ def VFMERGE_VFM : RVInstVX<0b010111, OPFVF, (outs VR:$vd), } // Vector Floating-Point Move Instruction +let RVVConstraint = NoConstraint in def VFMV_V_F : RVInstVX<0b010111, OPFVF, (outs VR:$vd), (ins FPR32:$rs1), "vfmv.v.f", "$vd, $rs1"> { let vs2 = 0; @@ -912,6 +915,7 @@ defm VFWREDSUM : VALU_FV_V<"vfwredsum", 0b110001>; let Predicates = [HasStdExtV] in { // Vector Mask-Register Logical Instructions +let RVVConstraint = NoConstraint in { defm VMAND_M : VALU_MV_Mask<"vmand", 0b011001, "m">; defm VMNAND_M : VALU_MV_Mask<"vmnand", 0b011101, "m">; defm VMANDNOT_M : VALU_MV_Mask<"vmandnot", 0b011000, "m">; @@ -920,6 +924,7 @@ defm VMOR_M : VALU_MV_Mask<"vmor", 0b011010, "m">; defm VMNOR_M : VALU_MV_Mask<"vmnor", 0b011110, "m">; defm VMORNOT_M : VALU_MV_Mask<"vmornot", 0b011100, "m">; defm VMXNOR_M : VALU_MV_Mask<"vmxnor", 0b011111, "m">; +} def : InstAlias<"vmmv.m $vd, $vs", (VMAND_MM VR:$vd, VR:$vs, VR:$vs)>; @@ -930,7 +935,8 @@ def : InstAlias<"vmset.m $vd", def : InstAlias<"vmnot.m $vd, $vs", (VMNAND_MM VR:$vd, VR:$vs, VR:$vs)>; -let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { +let hasSideEffects = 0, mayLoad = 0, mayStore = 0, + RVVConstraint = NoConstraint in { // Vector mask population count vpopc def VPOPC_M : RVInstV<0b010000, 0b10000, OPMVV, (outs GPR:$vd), (ins VR:$vs2, VMaskOp:$vm), @@ -964,7 +970,7 @@ def VID_V : RVInstV<0b010100, 0b10001, OPMVV, (outs VR:$vd), } // Integer Scalar Move Instructions -let vm = 1 in { +let vm = 1, RVVConstraint = NoConstraint in { def VMV_X_S : RVInstV<0b010000, 0b00000, OPMVV, (outs GPR:$vd), (ins VR:$vs2), "vmv.x.s", "$vd, $vs2">; let Constraints = "$vd = $vd_wb" in @@ -976,7 +982,8 @@ def VMV_S_X : RVInstV2<0b010000, 0b00000, OPMVX, (outs VR:$vd_wb), } // Predicates = [HasStdExtV] let Predicates = [HasStdExtV, HasStdExtF] in { -let hasSideEffects = 0, mayLoad = 0, mayStore = 0, vm = 1 in { +let hasSideEffects = 0, mayLoad = 0, mayStore = 0, vm = 1, + RVVConstraint = NoConstraint in { // Floating-Point Scalar Move Instructions def VFMV_F_S : RVInstV<0b010000, 0b00000, OPFVV, (outs FPR32:$vd), (ins VR:$vs2), "vfmv.f.s", "$vd, $vs2">; @@ -1018,7 +1025,8 @@ let Constraints = "@earlyclobber $vd", RVVConstraint = Vcompress in { defm VCOMPRESS_V : VALU_MV_Mask<"vcompress", 0b010111>; } // Constraints = "@earlyclobber $vd", RVVConstraint = Vcompress -let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { +let hasSideEffects = 0, mayLoad = 0, mayStore = 0, + RVVConstraint = NoConstraint in { foreach nf = [1, 2, 4, 8] in { def VMV#nf#R_V : RVInstV<0b100111, !add(nf, -1), OPIVI, (outs VR:$vd), (ins VR:$vs2), "vmv" # nf # "r.v", diff --git a/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.h index b610661a3a846..4cd32b29b04d6 100644 --- a/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.h +++ b/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.h @@ -48,59 +48,15 @@ enum { InstFormatMask = 31, ConstraintOffset = 5, - ConstraintMask = 0b1111 + ConstraintMask = 0b111 }; // Match with the definitions in RISCVInstrFormatsV.td enum RVVConstraintType { NoConstraint = 0, - VS2Constraint = 0b0001, - VS1Constraint = 0b0010, - VMConstraint = 0b0100, - OneInput = 0b1000, - - // Illegal instructions: - // - // * The destination vector register group for a masked vector instruction - // cannot overlap the source mask register (v0), unless the destination vector - // register is being written with a mask value (e.g., comparisons) or the - // scalar result of a reduction. - // - // * Widening: The destination vector register group cannot overlap a source - // vector register group of a different EEW - // - // * Narrowing: The destination vector register group cannot overlap the - // first source vector register group - // - // * For vadc and vsbc, an illegal instruction exception is raised if the - // destination vector register is v0. - // - // * For vmadc and vmsbc, an illegal instruction exception is raised if the - // destination vector register overlaps a source vector register group. - // - // * viota: An illegal instruction exception is raised if the destination - // vector register group overlaps the source vector mask register. If the - // instruction is masked, an illegal instruction exception is issued if the - // destination vector register group overlaps v0. - // - // * v[f]slide[1]up: The destination vector register group for vslideup cannot - // overlap the source vector register group. - // - // * vrgather: The destination vector register group cannot overlap with the - // source vector register groups. - // - // * vcompress: The destination vector register group cannot overlap the - // source vector register group or the source mask register - WidenV = VS2Constraint | VS1Constraint | VMConstraint, - WidenW = VS1Constraint | VMConstraint, - WidenCvt = VS2Constraint | VMConstraint | OneInput, - Narrow = VS2Constraint | VMConstraint, - NarrowCvt = VS2Constraint | VMConstraint | OneInput, - Vmadc = VS2Constraint | VS1Constraint, - Iota = VS2Constraint | VMConstraint | OneInput, - SlideUp = VS2Constraint | VMConstraint, - Vrgather = VS2Constraint | VS1Constraint | VMConstraint, - Vcompress = VS2Constraint | VS1Constraint, + VS2Constraint = 0b001, + VS1Constraint = 0b010, + VMConstraint = 0b100, }; // RISC-V Specific Machine Operand Flags diff --git a/llvm/test/MC/RISCV/rvv/invalid.s b/llvm/test/MC/RISCV/rvv/invalid.s index b741cce7abd71..fb7b4a0378e14 100644 --- a/llvm/test/MC/RISCV/rvv/invalid.s +++ b/llvm/test/MC/RISCV/rvv/invalid.s @@ -632,3 +632,23 @@ vmerge.vxm v0, v1, x1, v0 vfmerge.vfm v0, v1, f1, v0 # CHECK-ERROR: The destination vector register group cannot be V0. # CHECK-ERROR-LABEL: vfmerge.vfm v0, v1, f1, v0 + +vle8.v v0, (a0), v0.t +# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR-LABEL: vle8.v v0, (a0), v0.t + +vfclass.v v0, v1, v0.t +# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR-LABEL: vfclass.v v0, v1, v0.t + +vfsqrt.v v0, v1, v0.t +# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR-LABEL: vfsqrt.v v0, v1, v0.t + +vzext.vf2 v0, v1, v0.t +# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR-LABEL: vzext.vf2 v0, v1, v0.t + +vid.v v0, v0.t +# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR-LABEL: vid.v v0, v0.t