We could expand vmsge{u}.vx pseudo instructions in RISCVAsmParser.
It is more appropriate to expand it before encoding.
Differential Revision: https://reviews.llvm.org/D93968
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
.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");
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);
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
- void expandVMSGE(const MCInst &MI, raw_ostream &OS,
- SmallVectorImpl<MCFixup> &Fixups,
- const MCSubtargetInfo &STI) const;
-
/// TableGen'erated function for getting the binary encoding for an
/// instruction.
uint64_t getBinaryCodeForInstr(const MCInst &MI,
support::endian::write(OS, Binary, support::little);
}
-void RISCVMCCodeEmitter::expandVMSGE(const MCInst &MI, raw_ostream &OS,
- SmallVectorImpl<MCFixup> &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<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
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!");
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 <unknown>
# CHECK-UNKNOWN: 57 24 84 76 <unknown>
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 <unknown>
# CHECK-UNKNOWN: 57 20 00 76 <unknown>
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 <unknown>
# CHECK-UNKNOWN: 57 24 84 76 <unknown>
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 <unknown>
# CHECK-UNKNOWN: 57 24 80 6e <unknown>
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 <unknown>
# CHECK-UNKNOWN: 57 24 80 6e <unknown>
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 <unknown>
# CHECK-UNKNOWN: 57 20 01 62 <unknown>
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 <unknown>
# CHECK-UNKNOWN: 57 20 01 62 <unknown>