mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
[RISCV] Support vmsge.vx and vmsgeu.vx pseudo instructions in RVV.
Implement vmsge{u}.vx pseudo instruction. According to RISC-V V specification, there are different scenarios for this pseudo instruction. I list them below. unmasked va >= x pseudoinstruction: vmsge{u}.vx vd, va, x expansion: vmslt{u}.vx vd, va, x; vmnand.mm vd, vd, vd 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 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 Use pseudo instruction to model vmsge{u}.vx. The pseudo instruction will convert to different expansion according to the condition. Differential Revision: https://reviews.llvm.org/D84732
This commit is contained in:
parent
8d06bcf25b
commit
4adfe21466
@ -61,6 +61,10 @@ public:
|
||||
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,
|
||||
@ -188,6 +192,92 @@ void RISCVMCCodeEmitter::expandAddTPRel(const MCInst &MI, raw_ostream &OS,
|
||||
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 {
|
||||
@ -216,6 +306,16 @@ void RISCVMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
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!");
|
||||
|
@ -629,6 +629,46 @@ def : InstAlias<"vmsge.vi $vd, $va, $imm$vm",
|
||||
(VMSGT_VI VRegOp:$vd, VRegOp:$va, simm5_plus1:$imm,
|
||||
VMaskOp:$vm), 0>;
|
||||
|
||||
let isAsmParserOnly = 1, hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
|
||||
def PseudoVMSGEU_VX : Pseudo<(outs VRegOp:$vd),
|
||||
(ins VRegOp:$vs2, GPR:$rs1),
|
||||
[], "vmsgeu.vx", "$vd, $vs2, $rs1">;
|
||||
def PseudoVMSGE_VX : Pseudo<(outs VRegOp:$vd),
|
||||
(ins VRegOp:$vs2, GPR:$rs1),
|
||||
[], "vmsge.vx", "$vd, $vs2, $rs1">;
|
||||
def PseudoVMSGEU_VX_M : Pseudo<(outs VRNoV0:$vd),
|
||||
(ins VRegOp:$vs2, GPR:$rs1, VMaskOp:$vm),
|
||||
[], "vmsgeu.vx", "$vd, $vs2, $rs1$vm">;
|
||||
def PseudoVMSGE_VX_M : Pseudo<(outs VRNoV0:$vd),
|
||||
(ins VRegOp:$vs2, GPR:$rs1, VMaskOp:$vm),
|
||||
[], "vmsge.vx", "$vd, $vs2, $rs1$vm">;
|
||||
def PseudoVMSGEU_VX_M_T : Pseudo<(outs VMV0:$vd, VRegOp:$scratch),
|
||||
(ins VRegOp:$vs2, GPR:$rs1, VMaskOp:$vm),
|
||||
[], "vmsgeu.vx", "$vd, $vs2, $rs1$vm, $scratch">;
|
||||
def PseudoVMSGE_VX_M_T : Pseudo<(outs VMV0:$vd, VRegOp:$scratch),
|
||||
(ins VRegOp:$vs2, GPR:$rs1, VMaskOp:$vm),
|
||||
[], "vmsge.vx", "$vd, $vs2, $rs1$vm, $scratch">;
|
||||
}
|
||||
|
||||
// This apparently unnecessary alias prevents matching `vmsge{u}.vx vd, vs2, vs1` as if
|
||||
// it were an unmasked (i.e. $vm = RISCV::NoRegister) PseudoVMSGE{U}_VX_M.
|
||||
def : InstAlias<"vmsgeu.vx $vd, $va, $rs1",
|
||||
(PseudoVMSGEU_VX VRegOp:$vd, VRegOp:$va, GPR:$rs1), 0>;
|
||||
def : InstAlias<"vmsge.vx $vd, $va, $rs1",
|
||||
(PseudoVMSGE_VX VRegOp:$vd, VRegOp:$va, GPR:$rs1), 0>;
|
||||
def : InstAlias<"vmsgeu.vx v0, $va, $rs1, $vm, $vt",
|
||||
(PseudoVMSGEU_VX_M_T V0, VRegOp:$vt, VRegOp:$va, GPR:$rs1,
|
||||
VMaskOp:$vm), 0>;
|
||||
def : InstAlias<"vmsge.vx v0, $va, $rs1, $vm, $vt",
|
||||
(PseudoVMSGE_VX_M_T V0, VRegOp:$vt, VRegOp:$va, GPR:$rs1,
|
||||
VMaskOp:$vm), 0>;
|
||||
def : InstAlias<"vmsgeu.vx $vd, $va, $rs1, $vm",
|
||||
(PseudoVMSGEU_VX_M VRNoV0:$vd, VRegOp:$va, GPR:$rs1,
|
||||
VMaskOp:$vm), 0>;
|
||||
def : InstAlias<"vmsge.vx $vd, $va, $rs1, $vm",
|
||||
(PseudoVMSGE_VX_M VRNoV0:$vd, VRegOp:$va, GPR:$rs1,
|
||||
VMaskOp:$vm), 0>;
|
||||
|
||||
// Vector Integer Min/Max Instructions
|
||||
defm VMINU_V : VALU_IV_V_X<"vminu", 0b000100>;
|
||||
defm VMIN_V : VALU_IV_V_X<"vmin", 0b000101>;
|
||||
|
@ -296,7 +296,7 @@ class RegisterTypes<list<ValueType> reg_types> {
|
||||
// The order of registers represents the preferred allocation sequence,
|
||||
// meaning caller-save regs are listed before callee-save.
|
||||
def VR : RegisterClass<"RISCV", [nxv8i8, nxv4i16, nxv2i32, nxv1i64],
|
||||
64, (add
|
||||
64, (add
|
||||
(sequence "V%u", 25, 31),
|
||||
(sequence "V%u", 8, 24),
|
||||
(sequence "V%u", 0, 7)
|
||||
@ -304,6 +304,15 @@ def VR : RegisterClass<"RISCV", [nxv8i8, nxv4i16, nxv2i32, nxv1i64],
|
||||
let Size = 64;
|
||||
}
|
||||
|
||||
def VRNoV0 : RegisterClass<"RISCV", [nxv8i8, nxv4i16, nxv2i32, nxv1i64],
|
||||
64, (add
|
||||
(sequence "V%u", 25, 31),
|
||||
(sequence "V%u", 8, 24),
|
||||
(sequence "V%u", 1, 7)
|
||||
)> {
|
||||
let Size = 64;
|
||||
}
|
||||
|
||||
def VRM2 : RegisterClass<"RISCV", [nxv16i8, nxv8i16, nxv4i32, nxv2i64], 64,
|
||||
(add V26M2, V28M2, V30M2, V8M2, V10M2, V12M2, V14M2, V16M2,
|
||||
V18M2, V20M2, V22M2, V24M2, V0M2, V2M2, V4M2, V6M2)> {
|
||||
|
@ -1,5 +1,5 @@
|
||||
# RUN: llvm-mc -triple=riscv64 -show-encoding --mattr=+experimental-v %s \
|
||||
# RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
|
||||
# RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING
|
||||
# RUN: not llvm-mc -triple=riscv64 -show-encoding %s 2>&1 \
|
||||
# RUN: | FileCheck %s --check-prefix=CHECK-ERROR
|
||||
# RUN: llvm-mc -triple=riscv64 -filetype=obj --mattr=+experimental-v %s \
|
||||
@ -349,3 +349,59 @@ vmsge.vi v8, v4, 16
|
||||
# CHECK-ENCODING: [0x57,0xb4,0x47,0x7e]
|
||||
# CHECK-ERROR: instruction requires the following: 'V' (Vector Instructions)
|
||||
# CHECK-UNKNOWN: 57 b4 47 7e <unknown>
|
||||
|
||||
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-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-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-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-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-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-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-ERROR: instruction requires the following: 'V' (Vector Instructions)
|
||||
# CHECK-UNKNOWN: 57 41 45 6c <unknown>
|
||||
# CHECK-UNKNOWN: 57 20 01 62 <unknown>
|
||||
|
@ -590,3 +590,11 @@ vadd.vx v0, v2, a0, v0.t
|
||||
vadd.vi v0, v2, 1, v0.t
|
||||
# CHECK-ERROR: The destination vector register group cannot overlap the mask register.
|
||||
# CHECK-ERROR-LABEL: vadd.vi v0, v2, 1, v0.t
|
||||
|
||||
vmsge.vx v0, v4, a0, v0.t
|
||||
# CHECK-ERROR: too few operands for instruction
|
||||
# CHECK-ERROR-LABEL: vmsge.vx v0, v4, a0, v0.t
|
||||
|
||||
vmsge.vx v8, v4, a0, v0.t, v2
|
||||
# CHECK-ERROR: invalid operand for instruction
|
||||
# CHECK-ERROR-LABEL: vmsge.vx v8, v4, a0, v0.t, v2
|
||||
|
Loading…
Reference in New Issue
Block a user