1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 18:42:46 +02: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:
Hsiangkai Wang 2020-07-28 14:45:28 +08:00
parent 8d06bcf25b
commit 4adfe21466
5 changed files with 215 additions and 2 deletions

View File

@ -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!");

View File

@ -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>;

View File

@ -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)> {

View File

@ -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>

View File

@ -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