diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -129,6 +129,9 @@ void emitPseudoExtend(MCInst &Inst, bool SignExtend, int64_t Width, SMLoc IDLoc, MCStreamer &Out); + // Helper to emit pseudo vmsge{u}.vx instruction. + void emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, MCStreamer &Out); + // Checks that a PseudoAddTPRel is using x4/tp in its second input operand. // Enforcing this using a restricted register class for the second input // operand of PseudoAddTPRel results in a poor diagnostic due to the fact @@ -2257,6 +2260,59 @@ .addImm(ShAmt)); } +void RISCVAsmParser::emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, + MCStreamer &Out) { + if (Inst.getNumOperands() == 3) { + // unmasked va >= x + // + // pseudoinstruction: vmsge{u}.vx vd, va, x + // expansion: vmslt{u}.vx vd, va, x; vmnand.mm vd, vd, vd + emitToStreamer(Out, MCInstBuilder(Opcode) + .addOperand(Inst.getOperand(0)) + .addOperand(Inst.getOperand(1)) + .addOperand(Inst.getOperand(2)) + .addReg(RISCV::NoRegister)); + emitToStreamer(Out, MCInstBuilder(RISCV::VMNAND_MM) + .addOperand(Inst.getOperand(0)) + .addOperand(Inst.getOperand(0)) + .addOperand(Inst.getOperand(0))); + } else if (Inst.getNumOperands() == 4) { + // masked va >= x, vd != v0 + // + // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t + // expansion: vmslt{u}.vx vd, va, x, v0.t; vmxor.mm vd, vd, v0 + assert(Inst.getOperand(0).getReg() != RISCV::V0 && + "The destination register should not be V0."); + emitToStreamer(Out, MCInstBuilder(Opcode) + .addOperand(Inst.getOperand(0)) + .addOperand(Inst.getOperand(1)) + .addOperand(Inst.getOperand(2)) + .addOperand(Inst.getOperand(3))); + emitToStreamer(Out, MCInstBuilder(RISCV::VMXOR_MM) + .addOperand(Inst.getOperand(0)) + .addOperand(Inst.getOperand(0)) + .addReg(RISCV::V0)); + } else if (Inst.getNumOperands() == 5) { + // masked va >= x, vd == v0 + // + // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt + // expansion: vmslt{u}.vx vt, va, x; vmandnot.mm vd, vd, vt + assert(Inst.getOperand(0).getReg() == RISCV::V0 && + "The destination register should be V0."); + assert(Inst.getOperand(1).getReg() != RISCV::V0 && + "The temporary vector register should not be V0."); + emitToStreamer(Out, MCInstBuilder(Opcode) + .addOperand(Inst.getOperand(1)) + .addOperand(Inst.getOperand(2)) + .addOperand(Inst.getOperand(3)) + .addOperand(Inst.getOperand(4))); + emitToStreamer(Out, MCInstBuilder(RISCV::VMANDNOT_MM) + .addOperand(Inst.getOperand(0)) + .addOperand(Inst.getOperand(0)) + .addOperand(Inst.getOperand(1))); + } +} + bool RISCVAsmParser::checkPseudoAddTPRel(MCInst &Inst, OperandVector &Operands) { assert(Inst.getOpcode() == RISCV::PseudoAddTPRel && "Invalid instruction"); @@ -2432,6 +2488,16 @@ case RISCV::PseudoZEXT_W: emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/32, IDLoc, Out); return false; + case RISCV::PseudoVMSGEU_VX: + case RISCV::PseudoVMSGEU_VX_M: + case RISCV::PseudoVMSGEU_VX_M_T: + emitVMSGE(Inst, RISCV::VMSLTU_VX, IDLoc, Out); + return false; + case RISCV::PseudoVMSGE_VX: + case RISCV::PseudoVMSGE_VX_M: + case RISCV::PseudoVMSGE_VX_M_T: + emitVMSGE(Inst, RISCV::VMSLT_VX, IDLoc, Out); + return false; } emitToStreamer(Out, Inst); diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp @@ -60,10 +60,6 @@ SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; - void expandVMSGE(const MCInst &MI, raw_ostream &OS, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const; - /// TableGen'erated function for getting the binary encoding for an /// instruction. uint64_t getBinaryCodeForInstr(const MCInst &MI, @@ -191,92 +187,6 @@ support::endian::write(OS, Binary, support::little); } -void RISCVMCCodeEmitter::expandVMSGE(const MCInst &MI, raw_ostream &OS, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const { - MCInst TmpInst; - uint32_t Binary; - unsigned Opcode; - switch (MI.getOpcode()) { - default: - llvm_unreachable("Unexpacted opcode. It should be vmsgeu.vx or vmsge.vx."); - case RISCV::PseudoVMSGEU_VX: - case RISCV::PseudoVMSGEU_VX_M: - case RISCV::PseudoVMSGEU_VX_M_T: - Opcode = RISCV::VMSLTU_VX; - break; - case RISCV::PseudoVMSGE_VX: - case RISCV::PseudoVMSGE_VX_M: - case RISCV::PseudoVMSGE_VX_M_T: - Opcode = RISCV::VMSLT_VX; - break; - } - if (MI.getNumOperands() == 3) { - // unmasked va >= x - // - // pseudoinstruction: vmsge{u}.vx vd, va, x - // expansion: vmslt{u}.vx vd, va, x; vmnand.mm vd, vd, vd - TmpInst = MCInstBuilder(Opcode) - .addOperand(MI.getOperand(0)) - .addOperand(MI.getOperand(1)) - .addOperand(MI.getOperand(2)) - .addReg(RISCV::NoRegister); - Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); - support::endian::write(OS, Binary, support::little); - - TmpInst = MCInstBuilder(RISCV::VMNAND_MM) - .addOperand(MI.getOperand(0)) - .addOperand(MI.getOperand(0)) - .addOperand(MI.getOperand(0)); - Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); - support::endian::write(OS, Binary, support::little); - } else if (MI.getNumOperands() == 4) { - // masked va >= x, vd != v0 - // - // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t - // expansion: vmslt{u}.vx vd, va, x, v0.t; vmxor.mm vd, vd, v0 - assert(MI.getOperand(0).getReg() != RISCV::V0 && - "The destination register should not be V0."); - TmpInst = MCInstBuilder(Opcode) - .addOperand(MI.getOperand(0)) - .addOperand(MI.getOperand(1)) - .addOperand(MI.getOperand(2)) - .addOperand(MI.getOperand(3)); - Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); - support::endian::write(OS, Binary, support::little); - - TmpInst = MCInstBuilder(RISCV::VMXOR_MM) - .addOperand(MI.getOperand(0)) - .addOperand(MI.getOperand(0)) - .addReg(RISCV::V0); - Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); - support::endian::write(OS, Binary, support::little); - } else if (MI.getNumOperands() == 5) { - // masked va >= x, vd == v0 - // - // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt - // expansion: vmslt{u}.vx vt, va, x; vmandnot.mm vd, vd, vt - assert(MI.getOperand(0).getReg() == RISCV::V0 && - "The destination register should be V0."); - assert(MI.getOperand(1).getReg() != RISCV::V0 && - "The temporary vector register should not be V0."); - TmpInst = MCInstBuilder(Opcode) - .addOperand(MI.getOperand(1)) - .addOperand(MI.getOperand(2)) - .addOperand(MI.getOperand(3)) - .addOperand(MI.getOperand(4)); - Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); - support::endian::write(OS, Binary, support::little); - - TmpInst = MCInstBuilder(RISCV::VMANDNOT_MM) - .addOperand(MI.getOperand(0)) - .addOperand(MI.getOperand(0)) - .addOperand(MI.getOperand(1)); - Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); - support::endian::write(OS, Binary, support::little); - } -} - void RISCVMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { @@ -305,16 +215,6 @@ return; } - if (MI.getOpcode() == RISCV::PseudoVMSGEU_VX || - MI.getOpcode() == RISCV::PseudoVMSGE_VX || - MI.getOpcode() == RISCV::PseudoVMSGEU_VX_M || - MI.getOpcode() == RISCV::PseudoVMSGE_VX_M || - MI.getOpcode() == RISCV::PseudoVMSGEU_VX_M_T || - MI.getOpcode() == RISCV::PseudoVMSGE_VX_M_T) { - expandVMSGE(MI, OS, Fixups, STI); - return; - } - switch (Size) { default: llvm_unreachable("Unhandled encodeInstruction length!"); diff --git a/llvm/test/MC/RISCV/rvv/compare.s b/llvm/test/MC/RISCV/rvv/compare.s --- a/llvm/test/MC/RISCV/rvv/compare.s +++ b/llvm/test/MC/RISCV/rvv/compare.s @@ -353,7 +353,8 @@ vmsgeu.vx v8, v4, a0 # CHECK-INST: vmsltu.vx v8, v4, a0 # CHECK-INST: vmnot.m v8, v8 -# CHECK-ENCODING: [0x57,0x44,0x45,0x6a,0x57,0x24,0x84,0x76] +# CHECK-ENCODING: [0x57,0x44,0x45,0x6a] +# CHECK-ENCODING: [0x57,0x24,0x84,0x76] # CHECK-ERROR: instruction requires the following: 'V' (Vector Instructions) # CHECK-UNKNOWN: 57 44 45 6a # CHECK-UNKNOWN: 57 24 84 76 @@ -361,7 +362,8 @@ vmsge.vx v0, v4, a0 # CHECK-INST: vmslt.vx v0, v4, a0 # CHECK-INST: vmnot.m v0, v0 -# CHECK-ENCODING: [0x57,0x40,0x45,0x6e,0x57,0x20,0x00,0x76] +# CHECK-ENCODING: [0x57,0x40,0x45,0x6e] +# CHECK-ENCODING: [0x57,0x20,0x00,0x76] # CHECK-ERROR: instruction requires the following: 'V' (Vector Instructions) # CHECK-UNKNOWN: 57 40 45 6e # CHECK-UNKNOWN: 57 20 00 76 @@ -369,7 +371,8 @@ vmsge.vx v8, v4, a0 # CHECK-INST: vmslt.vx v8, v4, a0 # CHECK-INST: vmnot.m v8, v8 -# CHECK-ENCODING: [0x57,0x44,0x45,0x6e,0x57,0x24,0x84,0x76] +# CHECK-ENCODING: [0x57,0x44,0x45,0x6e] +# CHECK-ENCODING: [0x57,0x24,0x84,0x76] # CHECK-ERROR: instruction requires the following: 'V' (Vector Instructions) # CHECK-UNKNOWN: 57 44 45 6e # CHECK-UNKNOWN: 57 24 84 76 @@ -377,7 +380,8 @@ vmsgeu.vx v8, v4, a0, v0.t # CHECK-INST: vmsltu.vx v8, v4, a0, v0.t # CHECK-INST: vmxor.mm v8, v8, v0 -# CHECK-ENCODING: [0x57,0x44,0x45,0x68,0x57,0x24,0x80,0x6e] +# CHECK-ENCODING: [0x57,0x44,0x45,0x68] +# CHECK-ENCODING: [0x57,0x24,0x80,0x6e] # CHECK-ERROR: instruction requires the following: 'V' (Vector Instructions) # CHECK-UNKNOWN: 57 44 45 68 # CHECK-UNKNOWN: 57 24 80 6e @@ -385,7 +389,8 @@ vmsge.vx v8, v4, a0, v0.t # CHECK-INST: vmslt.vx v8, v4, a0, v0.t # CHECK-INST: vmxor.mm v8, v8, v0 -# CHECK-ENCODING: [0x57,0x44,0x45,0x6c,0x57,0x24,0x80,0x6e] +# CHECK-ENCODING: [0x57,0x44,0x45,0x6c] +# CHECK-ENCODING: [0x57,0x24,0x80,0x6e] # CHECK-ERROR: instruction requires the following: 'V' (Vector Instructions) # CHECK-UNKNOWN: 57 44 45 6c # CHECK-UNKNOWN: 57 24 80 6e @@ -393,7 +398,8 @@ vmsgeu.vx v0, v4, a0, v0.t, v2 # CHECK-INST: vmsltu.vx v2, v4, a0, v0.t # CHECK-INST: vmandnot.mm v0, v0, v2 -# CHECK-ENCODING: [0x57,0x41,0x45,0x68,0x57,0x20,0x01,0x62] +# CHECK-ENCODING: [0x57,0x41,0x45,0x68] +# CHECK-ENCODING: [0x57,0x20,0x01,0x62] # CHECK-ERROR: instruction requires the following: 'V' (Vector Instructions) # CHECK-UNKNOWN: 57 41 45 68 # CHECK-UNKNOWN: 57 20 01 62 @@ -401,7 +407,8 @@ vmsge.vx v0, v4, a0, v0.t, v2 # CHECK-INST: vmslt.vx v2, v4, a0, v0.t # CHECK-INST: vmandnot.mm v0, v0, v2 -# CHECK-ENCODING: [0x57,0x41,0x45,0x6c,0x57,0x20,0x01,0x62] +# CHECK-ENCODING: [0x57,0x41,0x45,0x6c] +# CHECK-ENCODING: [0x57,0x20,0x01,0x62] # CHECK-ERROR: instruction requires the following: 'V' (Vector Instructions) # CHECK-UNKNOWN: 57 41 45 6c # CHECK-UNKNOWN: 57 20 01 62