From 76202f09b522b2c106b358570c97eee7797e1ba5 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Sat, 26 Dec 2020 18:47:58 -0800 Subject: [PATCH] [RISCV] Improve VMConstraint checking on more unary and nullary instructions. We weren't consistently marking unary instructions as OneInput and vid.v is really ZeroInput but we had no way to mark that. This patch improves this by removing the error prone OneInput constraint. Instead we just always look for the mask in the last operand. It appears that the "CheckReg" variable used for the check on the broken instruction was unitialized or garbage because it was also used for VS1/VS2 constraints. I've scoped the variable locally to each check now. I've gone through and set NoConstraint on instructions that don't have a real VMConstraint and don't have a mask as the last operand. I've also removed the unused enum values in RISCVBaseInfo.h. We never use them in C++ and we have separate versions in a td file. Reviewed By: HsiangKai Differential Revision: https://reviews.llvm.org/D93784 --- llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp | 13 +++-- llvm/lib/Target/RISCV/RISCVInstrFormats.td | 56 ++++++++++++++++------ llvm/lib/Target/RISCV/RISCVInstrInfoV.td | 18 +++++-- llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.h | 52 ++------------------ llvm/test/MC/RISCV/rvv/invalid.s | 20 ++++++++ 5 files changed, 85 insertions(+), 74 deletions(-) diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp index 557c528..c735aaf 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 21f0514..5c8d8fa 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 b610661..4cd32b2 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 b741cce..fb7b4a0 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 -- 2.7.4