blob: 6acdcb83797306b6567965aa73bffd8679c3b2fe [file]
//===-- RISCVInstrInfoP.td - RISC-V 'P' instructions -------*- tablegen -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file describes the RISC-V instructions from the standard 'Base P'
// Packed SIMD instruction set extension.
//
// This version is still experimental as the 'P' extension hasn't been
// ratified yet.
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// Operand and SDNode transformation definitions.
//===----------------------------------------------------------------------===//
def SImm8PLI_BAsmOperand : SImmAsmOperand<8, "PLI_B"> {
let RenderMethod = "addSExtImmOperands<8>";
}
// A 8-bit signed immediate allowing range [-128, 255]
// but represented as [-128, 127].
def simm8_pli_b : RISCVOp {
let ParserMatchClass = SImm8PLI_BAsmOperand;
let EncoderMethod = "getImmOpValue";
let DecoderMethod = "decodeSImmOperand<8>";
let OperandType = "OPERAND_SIMM8";
let MCOperandPredicate = [{
int64_t Imm;
if (!MCOp.evaluateAsConstantImm(Imm))
return false;
return isInt<8>(Imm);
}];
}
def SImm10PLUIAsmOperand : SImmAsmOperand<10, "PLUI"> {
let RenderMethod = "addSExtImmOperands<10>";
}
// A 10-bit signed immediate allowing range [-512, 1023]
// but represented as [-512, 511].
def simm10_plui : RISCVOp {
let ParserMatchClass = SImm10PLUIAsmOperand;
let EncoderMethod = "getImmOpValue";
let DecoderMethod = "decodeSImmOperand<10>";
let OperandType = "OPERAND_SIMM10";
let MCOperandPredicate = [{
int64_t Imm;
if (!MCOp.evaluateAsConstantImm(Imm))
return false;
return isInt<10>(Imm);
}];
}
def SImm10PLI_HAsmOperand : SImmAsmOperand<10, "PLI_H"> {
let RenderMethod = "addSExtImmOperands<10>";
}
def SImm10PLI_WAsmOperand : SImmAsmOperand<10, "PLI_W"> {
let RenderMethod = "addSExtImmOperands<10>";
}
// A 10-bit signed immediate to be splatted to 16 bit elements allowing range
// [-512, 511] and [65025,65535] but represented as [-512, 511].
def simm10_pli_h : RISCVOp {
let ParserMatchClass = SImm10PLI_HAsmOperand;
let EncoderMethod = "getImmOpValue";
let DecoderMethod = "decodeSImmOperand<10>";
let OperandType = "OPERAND_SIMM10";
let MCOperandPredicate = [{
int64_t Imm;
if (!MCOp.evaluateAsConstantImm(Imm))
return false;
return isInt<10>(Imm);
}];
}
// A 10-bit signed immediate to be splatted to 32 bit elements allowing range
// [-512, 511] and [4294966784,4294967295]
def simm10_pli_w : RISCVOp {
let ParserMatchClass = SImm10PLI_WAsmOperand;
let EncoderMethod = "getImmOpValue";
let DecoderMethod = "decodeSImmOperand<10>";
let OperandType = "OPERAND_SIMM10";
let MCOperandPredicate = [{
int64_t Imm;
if (!MCOp.evaluateAsConstantImm(Imm))
return false;
return isInt<10>(Imm);
}];
}
class UImmPlus1AsmOperand<int width> : AsmOperandClass {
let Name = "UImm" # width # "Plus1";
let RenderMethod = "addImmOperands";
let DiagnosticType = "InvalidUImm" # width # "Plus1";
}
class RISCVUImmPlus1Op<int bitsNum>
: RISCVOp, ImmLeaf<XLenVT, "return Imm > 0 && isUInt<" # bitsNum # ">(Imm - 1);"> {
let ParserMatchClass = UImmPlus1AsmOperand<bitsNum>;
let EncoderMethod = "getImmOpValueMinus1";
let DecoderMethod = "decodeUImmPlus1Operand<" # bitsNum # ">";
let OperandType = "OPERAND_UIMM" # bitsNum # "_PLUS1";
let MCOperandPredicate = [{
int64_t Imm;
if (!MCOp.evaluateAsConstantImm(Imm))
return false;
return Imm > 0 && isUInt<}] # bitsNum # [{>(Imm - 1);
}];
}
def uimm4_plus1 : RISCVUImmPlus1Op<4>;
def uimm5_plus1 : RISCVUImmPlus1Op<5>;
def uimm6_plus1 : RISCVUImmPlus1Op<6>;
//===----------------------------------------------------------------------===//
// Instruction class templates
//===----------------------------------------------------------------------===//
// Common base for pli.b/h/w and plui.h/w
class RVPLoadImm_i<bits<7> funct7, dag ins, string opcodestr,
string argstr>
: RVInst<(outs GPR:$rd), ins, opcodestr, argstr, [],
InstFormatOther> {
bits<5> rd;
let Inst{31-25} = funct7;
let Inst{14-12} = 0b010;
let Inst{11-7} = rd;
let Inst{6-0} = OPC_OP_IMM_32.Value;
let hasSideEffects = 0;
let mayLoad = 0;
let mayStore = 0;
}
// Base for pli.h/w.
class PLI_i<bits<7> funct7, string opcodestr, DAGOperand imm>
: RVPLoadImm_i<funct7, (ins imm:$imm10), opcodestr, "$rd, $imm10"> {
bits<10> imm10;
let Inst{24-16} = imm10{8-0};
let Inst{15} = imm10{9};
}
// Base for plui.h/w.
class PLUI_i<bits<7> funct7, string opcodestr>
: RVPLoadImm_i<funct7, (ins simm10_plui:$imm10), opcodestr,
"$rd, $imm10"> {
bits<10> imm10;
let Inst{24} = imm10{0};
let Inst{23-15} = imm10{9-1};
}
// Common base for widening Binary/Ternary ops
class RVPWideningBase<bits<4> f, bits<2> w, bit arith_shift, dag outs, dag ins,
string opcodestr>
: RVInst<outs, ins, opcodestr, "$rd, $rs1, $rs2", [], InstFormatOther> {
bits<5> rs2;
bits<5> rs1;
bits<5> rd;
let Inst{31} = 0b0;
let Inst{30-27} = f;
let Inst{26-25} = w;
let Inst{24-20} = rs2;
let Inst{19-15} = rs1;
let Inst{14-12} = 0b010;
let Inst{11-8} = rd{4-1};
let Inst{7} = arith_shift;
let Inst{6-0} = OPC_OP_IMM_32.Value;
}
// Common base for narrowing ops
class RVPNarrowingBase<bits<3> f, bit r, bits<4> funct4, dag outs, dag ins,
string opcodestr, string argstr, bit DefVXSAT = 0>
: RVInst<outs, ins, opcodestr, argstr, [], InstFormatOther> {
bits<5> rs1;
bits<5> rd;
let Inst{31} = 0b0;
let Inst{30-28} = f;
let Inst{27} = r;
let Inst{19-16} = rs1{4-1};
let Inst{15-12} = funct4;
let Inst{11-7} = rd;
let Inst{6-0} = OPC_OP_IMM_32.Value;
let Defs = !if(DefVXSAT, [VXSAT], []);
}
// Common base for pair ops (non-widening nor narrowing)
class RVPPairBase<bits<4> f, bit bit15, dag outs, dag ins,
string opcodestr, string argstr, bit DefVXSAT>
: RVInst<outs, ins, opcodestr, argstr, [], InstFormatOther> {
bits<5> rs1;
bits<5> rd;
let Inst{30-27} = f;
let Inst{19-16} = rs1{4-1};
let Inst{15} = bit15;
let Inst{14-12} = 0b110;
let Inst{11-8} = rd{4-1};
let Inst{7} = 0b0;
let Inst{6-0} = OPC_OP_IMM_32.Value;
let Defs = !if(DefVXSAT, [VXSAT], []);
}
// Common base for pair binary ops
class RVPPairBinaryBase_rr<bits<4> f, bits<2> w, bit bit20, bit bit15,
string opcodestr, bit DefVXSAT = 0>
: RVPPairBase<f, bit15, (outs GPRPairRV32:$rd),
(ins GPRPairRV32:$rs1, GPRPairRV32:$rs2), opcodestr,
"$rd, $rs1, $rs2", DefVXSAT> {
bits<5> rs2;
let Inst{31} = 0b1;
let Inst{26-25} = w;
let Inst{24-21} = rs2{4-1};
let Inst{20} = bit20;
}
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
class RVPShift_ri<bits<3> f, bits<3> funct3, string opcodestr, Operand ImmType,
bit DefVXSAT = 0>
: RVInstIBase<funct3, OPC_OP_IMM_32, (outs GPR:$rd),
(ins GPR:$rs1, ImmType:$shamt), opcodestr,
"$rd, $rs1, $shamt"> {
let Inst{31} = 0b1;
let Inst{30-28} = f;
let Inst{27} = 0b0;
let Defs = !if(DefVXSAT, [VXSAT], []);
}
class RVPShiftD_ri<bits<3> f, bits<3> funct3, string opcodestr,
Operand ImmType = uimm6, bit DefVXSAT = 0>
: RVPShift_ri<f, funct3, opcodestr, ImmType, DefVXSAT> {
bits<6> shamt;
let Inst{26} = 0b1;
let Inst{25-20} = shamt;
}
class RVPShiftW_ri<bits<3> f, bits<3> funct3, string opcodestr,
Operand ImmType = uimm5, bit DefVXSAT = 0>
: RVPShift_ri<f, funct3, opcodestr, ImmType, DefVXSAT> {
bits<5> shamt;
let Inst{26-25} = 0b01;
let Inst{24-20} = shamt;
}
class RVPShiftH_ri<bits<3> f, bits<3> funct3, string opcodestr,
Operand ImmType = uimm4, bit DefVXSAT = 0>
: RVPShift_ri<f, funct3, opcodestr, ImmType, DefVXSAT> {
bits<4> shamt;
let Inst{26-24} = 0b001;
let Inst{23-20} = shamt;
}
class RVPShiftB_ri<bits<3> f, bits<3> funct3, string opcodestr,
Operand ImmType = uimm3>
: RVPShift_ri<f, funct3, opcodestr, ImmType> {
bits<3> shamt;
let Inst{26-23} = 0b0001;
let Inst{22-20} = shamt;
}
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
class RVPWideningShift_ri<bits<3> f, string opcodestr, Operand ImmType>
: RVInst<(outs GPRPairRV32:$rd), (ins GPR:$rs1, ImmType:$shamt), opcodestr,
"$rd, $rs1, $shamt", [], InstFormatOther> {
bits<5> rs1;
bits<5> rd;
let Inst{31} = 0b0;
let Inst{30-28} = f;
let Inst{27} = 0b0;
let Inst{19-15} = rs1;
let Inst{14-12} = 0b010;
let Inst{11-8} = rd{4-1};
let Inst{7} = 0b0;
let Inst{6-0} = OPC_OP_IMM_32.Value;
}
class RVPWideningShiftW_ri<bits<3> f, string opcodestr>
: RVPWideningShift_ri<f, opcodestr, uimm6> {
bits<6> shamt;
let Inst{26} = 0b1;
let Inst{25-20} = shamt;
}
class RVPWideningShiftH_ri<bits<3> f, string opcodestr>
: RVPWideningShift_ri<f, opcodestr, uimm5> {
bits<5> shamt;
let Inst{26-25} = 0b01;
let Inst{24-20} = shamt;
}
class RVPWideningShiftB_ri<bits<3> f, string opcodestr>
: RVPWideningShift_ri<f, opcodestr, uimm4> {
bits<4> shamt;
let Inst{26-24} = 0b001;
let Inst{23-20} = shamt;
}
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
class RVPNarrowingShift_ri<bits<3> f, string opcodestr, Operand ImmType,
bit DefVXSAT>
: RVPNarrowingBase<f, 0b0, 0b1100, (outs GPR:$rd),
(ins GPRPairRV32:$rs1, ImmType:$shamt), opcodestr,
"$rd, $rs1, $shamt", DefVXSAT>;
class RVPNarrowingShiftW_ri<bits<3> f, string opcodestr, bit DefVXSAT = 0>
: RVPNarrowingShift_ri<f, opcodestr, uimm6, DefVXSAT> {
bits<6> shamt;
let Inst{26} = 0b1;
let Inst{25-20} = shamt;
}
class RVPNarrowingShiftH_ri<bits<3> f, string opcodestr, bit DefVXSAT = 0>
: RVPNarrowingShift_ri<f, opcodestr, uimm5, DefVXSAT> {
bits<5> shamt;
let Inst{26-25} = 0b01;
let Inst{24-20} = shamt;
}
class RVPNarrowingShiftB_ri<bits<3> f, string opcodestr, bit DefVXSAT = 0>
: RVPNarrowingShift_ri<f, opcodestr, uimm4, DefVXSAT> {
bits<4> shamt;
let Inst{26-24} = 0b001;
let Inst{23-20} = shamt;
}
// direction is bit 15 and is usually 0 for left shifts and 1 for right shifts.
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
class RVPPairShift_ri<bits<3> f, bit direction, string opcodestr,
Operand ImmType, bit DefVXSAT = 0>
: RVPPairBase<{f, 0b0}, direction, (outs GPRPairRV32:$rd),
(ins GPRPairRV32:$rs1, ImmType:$shamt), opcodestr,
"$rd, $rs1, $shamt", DefVXSAT> {
let Inst{31} = 0b0;
}
class RVPPairShiftW_ri<bits<3> f, bit direction, string opcodestr,
bit DefVXSAT = 0>
: RVPPairShift_ri<f, direction, opcodestr, uimm5, DefVXSAT> {
bits<5> shamt;
let Inst{26-25} = 0b01;
let Inst{24-20} = shamt;
}
class RVPPairShiftH_ri<bits<3> f, bit direction, string opcodestr,
bit DefVXSAT = 0>
: RVPPairShift_ri<f, direction, opcodestr, uimm4, DefVXSAT> {
bits<4> shamt;
let Inst{26-24} = 0b001;
let Inst{23-20} = shamt;
}
class RVPPairShiftB_ri<bits<3> f, bit direction, string opcodestr>
: RVPPairShift_ri<f, direction, opcodestr, uimm3> {
bits<3> shamt;
let Inst{26-23} = 0b0001;
let Inst{22-20} = shamt;
}
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
class RVPNarrowingShift_rr<bits<3> f, bits<2> w, string opcodestr,
bit DefVXSAT = 0>
: RVPNarrowingBase<f, 0b1, 0b1100, (outs GPR:$rd),
(ins GPRPairRV32:$rs1, GPR:$rs2), opcodestr,
"$rd, $rs1, $rs2", DefVXSAT> {
bits<5> rs2;
let Inst{26-25} = w;
let Inst{24-20} = rs2;
}
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
class RVPWideningShift_rr<bits<3> f, bits<2> w, string opcodestr>
: RVPWideningBase<{f, 0b1}, w, 0b0, (outs GPRPairRV32:$rd),
(ins GPR:$rs1, GPR:$rs2), opcodestr>;
// direction is bit 15 and is usually 0 for left shifts and 1 for right shifts.
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
class RVPPairShift_rr<bits<3> f, bits<2> w, bit direction, string opcodestr,
bit DefVXSAT = 0>
: RVPPairBase<{f, 0b1}, direction, (outs GPRPairRV32:$rd),
(ins GPRPairRV32:$rs1, GPR:$rs2), opcodestr,
"$rd, $rs1, $rs2", DefVXSAT> {
bits<5> rs2;
let Inst{31} = 0b0;
let Inst{26-25} = w;
let Inst{24-20} = rs2;
}
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
class RVPUnary_ri<bits<2> w, bits<5> uf, string opcodestr, bit DefVXSAT = 0>
: RVInstIBase<0b010, OPC_OP_IMM_32, (outs GPR:$rd), (ins GPR:$rs1),
opcodestr, "$rd, $rs1"> {
let Inst{31-27} = 0b11100;
let Inst{26-25} = w;
let Inst{24-20} = uf;
let Defs = !if(DefVXSAT, [VXSAT], []);
}
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
class RVPPairUnary_r<bits<2> w, bits<5> uf, string opcodestr, bit DefVXSAT = 0>
: RVPPairBase<0b1100, 0b0, (outs GPRPairRV32:$rd),
(ins GPRPairRV32:$rs1), opcodestr, "$rd, $rs1", DefVXSAT> {
let Inst{31} = 0b0;
let Inst{26-25} = w;
let Inst{24-20} = uf;
}
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
class RVPBinaryScalar_rr<bits<3> f, bits<2> w, bits<3> funct3, string opcodestr,
bit DefVXSAT = 0>
: RVInstRBase<funct3, OPC_OP_IMM_32, (outs GPR:$rd),
(ins GPR:$rs1, GPR:$rs2), opcodestr, "$rd, $rs1, $rs2"> {
let Inst{31} = 0b1;
let Inst{30-28} = f;
let Inst{27} = 0b1;
let Inst{26-25} = w;
let Defs = !if(DefVXSAT, [VXSAT], []);
}
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
class RVPBinary_rr<bits<4> f, bits<2> w, bits<3> funct3, string opcodestr,
bit Commutable = 0, bit DefVXSAT = 0>
: RVInstRBase<funct3, OPC_OP_32, (outs GPR:$rd),
(ins GPR:$rs1, GPR:$rs2), opcodestr, "$rd, $rs1, $rs2"> {
assert !or(!eq(funct3{0}, 0), !eq(f{0}, 0)),
"LSB of f should be zero if LSB of funct3 is one";
let Inst{31} = 0b1;
let Inst{30-27} = f;
let Inst{26-25} = w;
let isCommutable = Commutable;
let Defs = !if(DefVXSAT, [VXSAT], []);
}
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
class RVPWideningBinary_rr<bits<4> f, bits<2> w, string opcodestr,
bit Commutable = 0>
: RVPWideningBase<f, w, 0b1, (outs GPRPairRV32:$rd),
(ins GPR:$rs1, GPR:$rs2), opcodestr> {
assert !eq(f{0}, 0), "LSB of f should be zero";
let isCommutable = Commutable;
}
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
class RVPNarrowingBinary_rr<bits<3> f, bits<2> w, string opcodestr>
: RVPNarrowingBase<f, 0b1, 0b0100, (outs GPR:$rd),
(ins GPRPairRV32:$rs1, GPR:$rs2), opcodestr,
"$rd, $rs1, $rs2"> {
bits<5> rs2;
let Inst{26-25} = w;
let Inst{24-20} = rs2;
}
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
class RVPPairBinary_rr<bits<4> f, bits<2> w, string opcodestr,
bit Commutable = 0, bit DefVXSAT = 0>
: RVPPairBinaryBase_rr<f, w, 0b0, 0b0, opcodestr, DefVXSAT> {
let isCommutable = Commutable;
}
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
class RVPPairBinaryShift_rr<bits<3> f, bits<2> w, string opcodestr,
bit DefVXSAT = 0>
: RVPPairBinaryBase_rr<{f, 0b0}, w, 0b1, 0b0, opcodestr, DefVXSAT>;
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
class RVPPairBinaryPack_rr<bits<3> f, bits<2> w, string opcodestr>
: RVPPairBinaryBase_rr<{f, 0b0}, w, 0b0, 0b1, opcodestr>;
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
class RVPPairBinaryExchanged_rr<bits<4> f, bits<2> w, string opcodestr,
bit Commutable = 0, bit DefVXSAT = 0>
: RVPPairBinaryBase_rr<f, w, 0b1, 0b1, opcodestr, DefVXSAT> {
let isCommutable = Commutable;
}
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
class RVPTernary_rrr<bits<4> f, bits<2> w, bits<3> funct3, string opcodestr>
: RVInstRBase<funct3, OPC_OP_32, (outs GPR:$rd_wb),
(ins GPR:$rd, GPR:$rs1, GPR:$rs2), opcodestr,
"$rd, $rs1, $rs2"> {
assert !eq(funct3{0}, 1), "LSB of funct3 should be one";
assert !eq(f{0}, 1), "LSB of f should be one";
let Inst{31} = 0b1;
let Inst{30-27} = f;
let Inst{26-25} = w;
let Constraints = "$rd = $rd_wb";
}
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
class RVPWideningTernary_rrr<bits<4> f, bits<2> w, string opcodestr>
: RVPWideningBase<f, w, 0b1, (outs GPRPairRV32:$rd_wb),
(ins GPRPairRV32:$rd, GPR:$rs1, GPR:$rs2), opcodestr> {
assert !eq(f{0}, 1), "LSB of f should be one";
let Constraints = "$rd = $rd_wb";
}
// Common base for pli.db/h/w and plui.dh/w
class RVPPairLoadImm_i<bits<7> funct7, dag ins, string opcodestr,
string argstr>
: RVInst<(outs GPRPairRV32:$rd), ins, opcodestr, argstr, [],
InstFormatOther> {
bits<5> rd;
let Inst{31-25} = funct7;
let Inst{14-12} = 0b010;
let Inst{11-8} = rd{4-1};
let Inst{7} = 0b0;
let Inst{6-0} = OPC_OP_IMM_32.Value;
let hasSideEffects = 0;
let mayLoad = 0;
let mayStore = 0;
}
//===----------------------------------------------------------------------===//
// Instructions
//===----------------------------------------------------------------------===//
let Predicates = [HasStdExtP] in {
let IsSignExtendingOpW = 1 in
def CLS : Unary_r<0b011000000011, 0b001, "cls">;
def ABS : Unary_r<0b011000000111, 0b001, "abs">;
let append Predicates = [IsRV32] in {
def REV_RV32 : Unary_r<0b011010011111, 0b101, "rev">;
} // Predicates = [IsRV32]
let append Predicates = [IsRV64] in {
def REV16_RV64 : Unary_r<0b011010110000, 0b101, "rev16">;
def REV_RV64 : Unary_r<0b011010111111, 0b101, "rev">;
let IsSignExtendingOpW = 1 in {
def CLSW : UnaryW_r<0b011000000011, 0b001, "clsw">;
def ABSW : UnaryW_r<0b011000000111, 0b001, "absw">;
}
} // append Predicates = [IsRV64]
def PSLLI_B : RVPShiftB_ri<0b000, 0b010, "pslli.b">;
def PSLLI_H : RVPShiftH_ri<0b000, 0b010, "pslli.h">;
def PSSLAI_H : RVPShiftH_ri<0b101, 0b010, "psslai.h", DefVXSAT=1>;
let append Predicates = [IsRV32], DecoderNamespace = "RV32Only" in {
def SSLAI : RVPShiftW_ri<0b101, 0b010, "sslai", DefVXSAT=1>;
} // append Predicates = [IsRV32], DecoderNamespace = "RV32Only"
let append Predicates = [IsRV64] in {
def PSLLI_W : RVPShiftW_ri<0b000, 0b010, "pslli.w">;
def PSSLAI_W : RVPShiftW_ri<0b101, 0b010, "psslai.w", DefVXSAT=1>;
} // append Predicates = [IsRV64]
let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
def PLI_H : PLI_i<0b1011000, "pli.h", simm10_pli_h>;
let append Predicates = [IsRV64] in
def PLI_W : PLI_i<0b1011001, "pli.w", simm10_pli_w>;
def PLI_B : RVPLoadImm_i<0b1011010, (ins simm8_pli_b:$imm8), "pli.b",
"$rd, $imm8"> {
bits<8> imm8;
let Inst{24} = 0b0;
let Inst{23-16} = imm8;
let Inst{15} = 0b0;
}
} // isReMaterializable = 1, isAsCheapAsAMove = 1
def PSEXT_H_B : RVPUnary_ri<0b00, 0b00100, "psext.h.b">;
def PSABS_H : RVPUnary_ri<0b00, 0b00111, "psabs.h", DefVXSAT=1>;
def PSABS_B : RVPUnary_ri<0b10, 0b00111, "psabs.b", DefVXSAT=1>;
let append Predicates = [IsRV64] in {
def PSEXT_W_B : RVPUnary_ri<0b01, 0b00100, "psext.w.b">;
def PSEXT_W_H : RVPUnary_ri<0b01, 0b00101, "psext.w.h">;
} // append Predicates = [IsRV64]
let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
def PLUI_H : PLUI_i<0b1111000, "plui.h">;
let append Predicates = [IsRV64] in
def PLUI_W : PLUI_i<0b1111001, "plui.w">;
} // isReMaterializable = 1, isAsCheapAsAMove = 1
def PSLL_HS : RVPBinaryScalar_rr<0b000, 0b00, 0b010, "psll.hs">;
def PSLL_BS : RVPBinaryScalar_rr<0b000, 0b10, 0b010, "psll.bs">;
def PADD_HS : RVPBinaryScalar_rr<0b001, 0b00, 0b010, "padd.hs">;
def PADD_BS : RVPBinaryScalar_rr<0b001, 0b10, 0b010, "padd.bs">;
def PSSHL_HS : RVPBinaryScalar_rr<0b010, 0b00, 0b010, "psshl.hs", DefVXSAT=1>;
def PSSHLR_HS : RVPBinaryScalar_rr<0b011, 0b00, 0b010, "psshlr.hs", DefVXSAT=1>;
def PSSHA_HS : RVPBinaryScalar_rr<0b110, 0b00, 0b010, "pssha.hs", DefVXSAT=1>;
def PSSHAR_HS : RVPBinaryScalar_rr<0b111, 0b00, 0b010, "psshar.hs", DefVXSAT=1>;
let append Predicates = [IsRV32], DecoderNamespace = "RV32Only" in {
def SSHL : RVPBinaryScalar_rr<0b010, 0b01, 0b010, "sshl", DefVXSAT=1>;
def SSHLR : RVPBinaryScalar_rr<0b011, 0b01, 0b010, "sshlr", DefVXSAT=1>;
def SSHA : RVPBinaryScalar_rr<0b110, 0b01, 0b010, "ssha", DefVXSAT=1>;
def SSHAR : RVPBinaryScalar_rr<0b111, 0b01, 0b010, "sshar", DefVXSAT=1>;
} // append Predicates = [IsRV32], DecoderNamespace = "RV32Only"
let append Predicates = [IsRV64] in {
def PSLL_WS : RVPBinaryScalar_rr<0b000, 0b01, 0b010, "psll.ws">;
def PADD_WS : RVPBinaryScalar_rr<0b001, 0b01, 0b010, "padd.ws">;
def PSSHL_WS : RVPBinaryScalar_rr<0b010, 0b01, 0b010, "psshl.ws", DefVXSAT=1>;
def SHL : RVPBinaryScalar_rr<0b010, 0b11, 0b010, "shl">;
def PSSHLR_WS : RVPBinaryScalar_rr<0b011, 0b01, 0b010, "psshlr.ws", DefVXSAT=1>;
def SHLR : RVPBinaryScalar_rr<0b011, 0b11, 0b010, "shlr">;
def PSSHA_WS : RVPBinaryScalar_rr<0b110, 0b01, 0b010, "pssha.ws", DefVXSAT=1>;
def SHA : RVPBinaryScalar_rr<0b110, 0b11, 0b010, "sha">;
def PSSHAR_WS : RVPBinaryScalar_rr<0b111, 0b01, 0b010, "psshar.ws", DefVXSAT=1>;
def SHAR : RVPBinaryScalar_rr<0b111, 0b11, 0b010, "shar">;
} // append Predicates = [IsRV64]
def PSRLI_B : RVPShiftB_ri<0b000, 0b100, "psrli.b">;
def PSRLI_H : RVPShiftH_ri<0b000, 0b100, "psrli.h">;
def PUSATI_H : RVPShiftH_ri<0b010, 0b100, "pusati.h", DefVXSAT=1>;
def PSRAI_B : RVPShiftB_ri<0b100, 0b100, "psrai.b">;
def PSRAI_H : RVPShiftH_ri<0b100, 0b100, "psrai.h">;
def PSRARI_H : RVPShiftH_ri<0b101, 0b100, "psrari.h">;
def PSATI_H : RVPShiftH_ri<0b110, 0b100, "psati.h", uimm4_plus1, DefVXSAT=1>;
let append Predicates = [IsRV32], DecoderNamespace = "RV32Only" in {
def USATI_RV32 : RVPShiftW_ri<0b010, 0b100, "usati", DefVXSAT=1>;
def SRARI_RV32 : RVPShiftW_ri<0b101, 0b100, "srari">;
def SATI_RV32 : RVPShiftW_ri<0b110, 0b100, "sati", uimm5_plus1, DefVXSAT=1>;
} // append Predicates = [IsRV32], DecoderNamespace = "RV32Only"
let append Predicates = [IsRV64] in {
def PSRLI_W : RVPShiftW_ri<0b000, 0b100, "psrli.w">;
def PSRAI_W : RVPShiftW_ri<0b100, 0b100, "psrai.w">;
def PUSATI_W : RVPShiftW_ri<0b010, 0b100, "pusati.w", DefVXSAT=1>;
def USATI_RV64 : RVPShiftD_ri<0b010, 0b100, "usati", DefVXSAT=1>;
def PSRARI_W : RVPShiftW_ri<0b101, 0b100, "psrari.w">;
def SRARI_RV64 : RVPShiftD_ri<0b101, 0b100, "srari">;
def PSATI_W : RVPShiftW_ri<0b110, 0b100, "psati.w", uimm5_plus1, DefVXSAT=1>;
def SATI_RV64 : RVPShiftD_ri<0b110, 0b100, "sati", uimm6_plus1, DefVXSAT=1>;
} // append Predicates = [IsRV64]
def PSRL_HS : RVPBinaryScalar_rr<0b000, 0b00, 0b100, "psrl.hs">;
def PSRL_BS : RVPBinaryScalar_rr<0b000, 0b10, 0b100, "psrl.bs">;
def PREDSUM_HS : RVPBinaryScalar_rr<0b001, 0b00, 0b100, "predsum.hs">;
def PREDSUM_BS : RVPBinaryScalar_rr<0b001, 0b10, 0b100, "predsum.bs">;
def PREDSUMU_HS : RVPBinaryScalar_rr<0b011, 0b00, 0b100, "predsumu.hs">;
def PREDSUMU_BS : RVPBinaryScalar_rr<0b011, 0b10, 0b100, "predsumu.bs">;
def PSRA_HS : RVPBinaryScalar_rr<0b100, 0b00, 0b100, "psra.hs">;
def PSRA_BS : RVPBinaryScalar_rr<0b100, 0b10, 0b100, "psra.bs">;
let append Predicates = [IsRV64] in {
def PSRL_WS : RVPBinaryScalar_rr<0b000, 0b01, 0b100, "psrl.ws">;
def PREDSUM_WS : RVPBinaryScalar_rr<0b001, 0b01, 0b100, "predsum.ws">;
def PREDSUMU_WS : RVPBinaryScalar_rr<0b011, 0b01, 0b100, "predsumu.ws">;
def PSRA_WS : RVPBinaryScalar_rr<0b100, 0b01, 0b100, "psra.ws">;
} // append Predicates = [IsRV64]
def PADD_H : RVPBinary_rr<0b0000, 0b00, 0b000, "padd.h", Commutable=1>;
def PADD_B : RVPBinary_rr<0b0000, 0b10, 0b000, "padd.b", Commutable=1>;
def PSADD_H : RVPBinary_rr<0b0010, 0b00, 0b000, "psadd.h", Commutable=1, DefVXSAT=1>;
def PSADD_B : RVPBinary_rr<0b0010, 0b10, 0b000, "psadd.b", Commutable=1, DefVXSAT=1>;
def PAADD_H : RVPBinary_rr<0b0011, 0b00, 0b000, "paadd.h", Commutable=1>;
def PAADD_B : RVPBinary_rr<0b0011, 0b10, 0b000, "paadd.b", Commutable=1>;
def PSADDU_H : RVPBinary_rr<0b0110, 0b00, 0b000, "psaddu.h", Commutable=1, DefVXSAT=1>;
def PSADDU_B : RVPBinary_rr<0b0110, 0b10, 0b000, "psaddu.b", Commutable=1, DefVXSAT=1>;
def PAADDU_H : RVPBinary_rr<0b0111, 0b00, 0b000, "paaddu.h", Commutable=1>;
def PAADDU_B : RVPBinary_rr<0b0111, 0b10, 0b000, "paaddu.b", Commutable=1>;
def PSUB_H : RVPBinary_rr<0b1000, 0b00, 0b000, "psub.h">;
def PSUB_B : RVPBinary_rr<0b1000, 0b10, 0b000, "psub.b">;
def PABD_H : RVPBinary_rr<0b1001, 0b00, 0b000, "pabd.h", Commutable=1>;
def PABD_B : RVPBinary_rr<0b1001, 0b10, 0b000, "pabd.b", Commutable=1>;
def PSSUB_H : RVPBinary_rr<0b1010, 0b00, 0b000, "pssub.h", DefVXSAT=1>;
def PSSUB_B : RVPBinary_rr<0b1010, 0b10, 0b000, "pssub.b", DefVXSAT=1>;
def PASUB_H : RVPBinary_rr<0b1011, 0b00, 0b000, "pasub.h">;
def PASUB_B : RVPBinary_rr<0b1011, 0b10, 0b000, "pasub.b">;
def PABDU_H : RVPBinary_rr<0b1101, 0b00, 0b000, "pabdu.h", Commutable=1>;
def PABDU_B : RVPBinary_rr<0b1101, 0b10, 0b000, "pabdu.b", Commutable=1>;
def PSSUBU_H : RVPBinary_rr<0b1110, 0b00, 0b000, "pssubu.h", DefVXSAT=1>;
def PSSUBU_B : RVPBinary_rr<0b1110, 0b10, 0b000, "pssubu.b", DefVXSAT=1>;
def PASUBU_H : RVPBinary_rr<0b1111, 0b00, 0b000, "pasubu.h">;
def PASUBU_B : RVPBinary_rr<0b1111, 0b10, 0b000, "pasubu.b">;
let append Predicates = [IsRV32], DecoderNamespace = "RV32Only" in {
def SADD : RVPBinary_rr<0b0010, 0b01, 0b000, "sadd", Commutable=1, DefVXSAT=1>;
def AADD : RVPBinary_rr<0b0011, 0b01, 0b000, "aadd", Commutable=1>;
def SADDU : RVPBinary_rr<0b0110, 0b01, 0b000, "saddu", Commutable=1, DefVXSAT=1>;
def AADDU : RVPBinary_rr<0b0111, 0b01, 0b000, "aaddu", Commutable=1>;
def SSUB : RVPBinary_rr<0b1010, 0b01, 0b000, "ssub", DefVXSAT=1>;
def ASUB : RVPBinary_rr<0b1011, 0b01, 0b000, "asub">;
def SSUBU : RVPBinary_rr<0b1110, 0b01, 0b000, "ssubu", DefVXSAT=1>;
def ASUBU : RVPBinary_rr<0b1111, 0b01, 0b000, "asubu">;
} // append Predicates = [IsRV32], DecoderNamespace = "RV32Only"
let append Predicates = [IsRV64] in {
def PADD_W : RVPBinary_rr<0b0000, 0b01, 0b000, "padd.w", Commutable=1>;
def PSADD_W : RVPBinary_rr<0b0010, 0b01, 0b000, "psadd.w", Commutable=1, DefVXSAT=1>;
def PAADD_W : RVPBinary_rr<0b0011, 0b01, 0b000, "paadd.w", Commutable=1>;
def PSADDU_W : RVPBinary_rr<0b0110, 0b01, 0b000, "psaddu.w", Commutable=1, DefVXSAT=1>;
def PAADDU_W : RVPBinary_rr<0b0111, 0b01, 0b000, "paaddu.w", Commutable=1>;
def PSUB_W : RVPBinary_rr<0b1000, 0b01, 0b000, "psub.w">;
def PSSUB_W : RVPBinary_rr<0b1010, 0b01, 0b000, "pssub.w", DefVXSAT=1>;
def PASUB_W : RVPBinary_rr<0b1011, 0b01, 0b000, "pasub.w">;
def PSSUBU_W : RVPBinary_rr<0b1110, 0b01, 0b000, "pssubu.w", DefVXSAT=1>;
def PASUBU_W : RVPBinary_rr<0b1111, 0b01, 0b000, "pasubu.w">;
} // append Predicates = [IsRV64]
def SLX : RVPTernary_rrr<0b0001, 0b11, 0b001, "slx">;
def PMUL_H_B01 : RVPBinary_rr<0b0010, 0b00, 0b001, "pmul.h.b01">;
def MVM : RVPTernary_rrr<0b0101, 0b00, 0b001, "mvm">;
def MVMN : RVPTernary_rrr<0b0101, 0b01, 0b001, "mvmn">;
def MERGE : RVPTernary_rrr<0b0101, 0b10, 0b001, "merge">;
def SRX : RVPTernary_rrr<0b0101, 0b11, 0b001, "srx">;
def PMULU_H_B01 : RVPBinary_rr<0b0110, 0b00, 0b001, "pmulu.h.b01">;
def PABDSUMU_B : RVPBinary_rr<0b0110, 0b10, 0b001, "pabdsumu.b">;
def PABDSUMAU_B : RVPTernary_rrr<0b0111, 0b10, 0b001, "pabdsumau.b">;
let append Predicates = [IsRV32], DecoderNamespace = "RV32Only" in {
def MUL_H01 : RVPBinary_rr<0b0010, 0b01, 0b001, "mul.h01">;
def MACC_H01 : RVPTernary_rrr<0b0011, 0b01, 0b001, "macc.h01">;
def MULU_H01 : RVPBinary_rr<0b0110, 0b01, 0b001, "mulu.h01">;
def MACCU_H01 : RVPTernary_rrr<0b0111, 0b01, 0b001, "maccu.h01">;
} // append Predicates = [IsRV32], DecoderNamespace = "RV32Only"
let append Predicates = [IsRV64] in {
def PMUL_W_H01 : RVPBinary_rr<0b0010, 0b01, 0b001, "pmul.w.h01">;
def MUL_W01 : RVPBinary_rr<0b0010, 0b11, 0b001, "mul.w01">;
def PMACC_W_H01 : RVPTernary_rrr<0b0011, 0b01, 0b001, "pmacc.w.h01">;
def MACC_W01 : RVPTernary_rrr<0b0011, 0b11, 0b001, "macc.w01">;
def PMULU_W_H01 : RVPBinary_rr<0b0110, 0b01, 0b001, "pmulu.w.h01">;
def MULU_W01 : RVPBinary_rr<0b0110, 0b11, 0b001, "mulu.w01">;
def PMACCU_W_H01 : RVPTernary_rrr<0b0111, 0b01, 0b001, "pmaccu.w.h01">;
def MACCU_W01 : RVPTernary_rrr<0b0111, 0b11, 0b001, "maccu.w01">;
} // append Predicates = [IsRV64]
// Note the spec has a 3-bit f field in bits 30:28 with 0 in bit 27.
// Here we include the 0 in the f field to reduce number of tablegen classes.
def PSH1ADD_H : RVPBinary_rr<0b0100, 0b00, 0b010, "psh1add.h">;
def PSSH1SADD_H : RVPBinary_rr<0b0110, 0b00, 0b010, "pssh1sadd.h", DefVXSAT=1>;
let append Predicates = [IsRV32], DecoderNamespace = "RV32Only" in {
def SSH1SADD : RVPBinary_rr<0b0110, 0b01, 0b010, "ssh1sadd", DefVXSAT=1>;
} // append Predicates = [IsRV32], DecoderNamespace = "RV32Only"
let append Predicates = [IsRV64] in {
def PNCLIPUP_B : RVPBinary_rr<0b0000, 0b00, 0b010, "pnclipup.b", DefVXSAT=1>;
def PNCLIPUP_H : RVPBinary_rr<0b0000, 0b01, 0b010, "pnclipup.h", DefVXSAT=1>;
def PNCLIPUP_W : RVPBinary_rr<0b0000, 0b11, 0b010, "pnclipup.w", DefVXSAT=1>;
def PSH1ADD_W : RVPBinary_rr<0b0100, 0b01, 0b010, "psh1add.w">;
def PSSH1SADD_W : RVPBinary_rr<0b0110, 0b01, 0b010, "pssh1sadd.w", DefVXSAT=1>;
def PNCLIPP_B : RVPBinary_rr<0b1000, 0b00, 0b010, "pnclipp.b", DefVXSAT=1>;
def PNCLIPP_H : RVPBinary_rr<0b1000, 0b01, 0b010, "pnclipp.h", DefVXSAT=1>;
def PNCLIPP_W : RVPBinary_rr<0b1000, 0b11, 0b010, "pnclipp.w", DefVXSAT=1>;
def UNZIP8P : RVPBinary_rr<0b1100, 0b00, 0b010, "unzip8p">;
def UNZIP16P : RVPBinary_rr<0b1100, 0b01, 0b010, "unzip16p">;
def UNZIP8HP : RVPBinary_rr<0b1100, 0b10, 0b010, "unzip8hp">;
def UNZIP16HP : RVPBinary_rr<0b1100, 0b11, 0b010, "unzip16hp">;
def ZIP8P : RVPBinary_rr<0b1110, 0b00, 0b010, "zip8p">;
def ZIP16P : RVPBinary_rr<0b1110, 0b01, 0b010, "zip16p">;
def ZIP8HP : RVPBinary_rr<0b1110, 0b10, 0b010, "zip8hp">;
def ZIP16HP : RVPBinary_rr<0b1110, 0b11, 0b010, "zip16hp">;
} // append Predicates = [IsRV64]
def PMUL_H_B00 : RVPBinary_rr<0b0000, 0b00, 0b011, "pmul.h.b00", Commutable=1>;
def PMUL_H_B11 : RVPBinary_rr<0b0010, 0b00, 0b011, "pmul.h.b11", Commutable=1>;
def PMULU_H_B00 : RVPBinary_rr<0b0100, 0b00, 0b011, "pmulu.h.b00", Commutable=1>;
def PMULU_H_B11 : RVPBinary_rr<0b0110, 0b00, 0b011, "pmulu.h.b11", Commutable=1>;
def PMULSU_H_B00 : RVPBinary_rr<0b1100, 0b00, 0b011, "pmulsu.h.b00">;
def PMULSU_H_B11 : RVPBinary_rr<0b1110, 0b00, 0b011, "pmulsu.h.b11">;
let append Predicates = [IsRV32], DecoderNamespace = "RV32Only" in {
def MUL_H00 : RVPBinary_rr<0b0000, 0b01, 0b011, "mul.h00", Commutable=1>;
def MACC_H00 : RVPTernary_rrr<0b0001, 0b01, 0b011, "macc.h00">;
def MUL_H11 : RVPBinary_rr<0b0010, 0b01, 0b011, "mul.h11", Commutable=1>;
def MACC_H11 : RVPTernary_rrr<0b0011, 0b01, 0b011, "macc.h11">;
def MULU_H00 : RVPBinary_rr<0b0100, 0b01, 0b011, "mulu.h00", Commutable=1>;
def MACCU_H00 : RVPTernary_rrr<0b0101, 0b01, 0b011, "maccu.h00">;
def MULU_H11 : RVPBinary_rr<0b0110, 0b01, 0b011, "mulu.h11", Commutable=1>;
def MACCU_H11 : RVPTernary_rrr<0b0111, 0b01, 0b011, "maccu.h11">;
def MULSU_H00 : RVPBinary_rr<0b1100, 0b01, 0b011, "mulsu.h00">;
def MACCSU_H00 : RVPTernary_rrr<0b1101, 0b01, 0b011, "maccsu.h00">;
def MULSU_H11 : RVPBinary_rr<0b1110, 0b01, 0b011, "mulsu.h11">;
def MACCSU_H11 : RVPTernary_rrr<0b1111, 0b01, 0b011, "maccsu.h11">;
} // append Predicates = [IsRV32], DecoderNamespace = "RV32Only"
let append Predicates = [IsRV64] in {
def PMUL_W_H00 : RVPBinary_rr<0b0000, 0b01, 0b011, "pmul.w.h00", Commutable=1>;
def MUL_W00 : RVPBinary_rr<0b0000, 0b11, 0b011, "mul.w00", Commutable=1>;
def PMACC_W_H00 : RVPTernary_rrr<0b0001, 0b01, 0b011, "pmacc.w.h00">;
def MACC_W00 : RVPTernary_rrr<0b0001, 0b11, 0b011, "macc.w00">;
def PMUL_W_H11 : RVPBinary_rr<0b0010, 0b01, 0b011, "pmul.w.h11", Commutable=1>;
def MUL_W11 : RVPBinary_rr<0b0010, 0b11, 0b011, "mul.w11", Commutable=1>;
def PMACC_W_H11 : RVPTernary_rrr<0b0011, 0b01, 0b011, "pmacc.w.h11">;
def MACC_W11 : RVPTernary_rrr<0b0011, 0b11, 0b011, "macc.w11">;
def PMULU_W_H00 : RVPBinary_rr<0b0100, 0b01, 0b011, "pmulu.w.h00", Commutable=1>;
def MULU_W00 : RVPBinary_rr<0b0100, 0b11, 0b011, "mulu.w00", Commutable=1>;
def PMACCU_W_H00 : RVPTernary_rrr<0b0101, 0b01, 0b011, "pmaccu.w.h00">;
def MACCU_W00 : RVPTernary_rrr<0b0101, 0b11, 0b011, "maccu.w00">;
def PMULU_W_H11 : RVPBinary_rr<0b0110, 0b01, 0b011, "pmulu.w.h11", Commutable=1>;
def MULU_W11 : RVPBinary_rr<0b0110, 0b11, 0b011, "mulu.w11", Commutable=1>;
def PMACCU_W_H11 : RVPTernary_rrr<0b0111, 0b01, 0b011, "pmaccu.w.h11">;
def MACCU_W11 : RVPTernary_rrr<0b0111, 0b11, 0b011, "maccu.w11">;
def PMULSU_W_H00 : RVPBinary_rr<0b1100, 0b01, 0b011, "pmulsu.w.h00">;
def MULSU_W00 : RVPBinary_rr<0b1100, 0b11, 0b011, "mulsu.w00">;
def PMACCSU_W_H00 : RVPTernary_rrr<0b1101, 0b01, 0b011, "pmaccsu.w.h00">;
def MACCSU_W00 : RVPTernary_rrr<0b1101, 0b11, 0b011, "maccsu.w00">;
def PMULSU_W_H11 : RVPBinary_rr<0b1110, 0b01, 0b011, "pmulsu.w.h11">;
def MULSU_W11 : RVPBinary_rr<0b1110, 0b11, 0b011, "mulsu.w11">;
def PMACCSU_W_H11 : RVPTernary_rrr<0b1111, 0b01, 0b011, "pmaccsu.w.h11">;
def MACCSU_W11 : RVPTernary_rrr<0b1111, 0b11, 0b011, "maccsu.w11">;
} // append Predicates = [IsRV64]
// Note the spec has a 3-bit f field in bits 30:28 with 0 in bit 27.
// Here we include the 0 in the f field to reduce number of tablegen classes.
def PPAIRE_B : RVPBinary_rr<0b0000, 0b00, 0b100, "ppaire.b">;
def PPAIREO_B : RVPBinary_rr<0b0010, 0b00, 0b100, "ppaireo.b">;
def PPAIREO_H : RVPBinary_rr<0b0010, 0b01, 0b100, "ppaireo.h">;
def PPAIROE_B : RVPBinary_rr<0b0100, 0b00, 0b100, "ppairoe.b">;
def PPAIROE_H : RVPBinary_rr<0b0100, 0b01, 0b100, "ppairoe.h">;
def PPAIRO_B : RVPBinary_rr<0b0110, 0b00, 0b100, "ppairo.b">;
def PPAIRO_H : RVPBinary_rr<0b0110, 0b01, 0b100, "ppairo.h">;
let append Predicates = [IsRV32] in {
// This should be a MnemonicAlias, but InstAlias produces better errors.
def : InstAlias<"ppaire.h $rd, $rs1, $rs2", (PACK GPR:$rd, GPR:$rs1, GPR:$rs2), 0>;
}
let append Predicates = [IsRV64] in {
def PPAIRE_H : RVPBinary_rr<0b0000, 0b01, 0b100, "ppaire.h">;
// This should be a MnemonicAlias, but InstAlias produces better errors.
def : InstAlias<"ppaire.w $rd, $rs1, $rs2", (PACK GPR:$rd, GPR:$rs1, GPR:$rs2), 0>;
def PPAIREO_W : RVPBinary_rr<0b0010, 0b11, 0b100, "ppaireo.w">;
def PPAIROE_W : RVPBinary_rr<0b0100, 0b11, 0b100, "ppairoe.w">;
def PPAIRO_W : RVPBinary_rr<0b0110, 0b11, 0b100, "ppairo.w">;
} // append Predicates = [IsRV64]
def PM2ADD_H : RVPBinary_rr<0b0000, 0b00, 0b101, "pm2add.h", Commutable=1>;
def PM4ADD_B : RVPBinary_rr<0b0000, 0b10, 0b101, "pm4add.b", Commutable=1>;
def PM2ADDA_H : RVPTernary_rrr<0b0001, 0b00, 0b101, "pm2adda.h">;
def PM4ADDA_B : RVPTernary_rrr<0b0001, 0b10, 0b101, "pm4adda.b">;
def PM2ADD_HX : RVPBinary_rr<0b0010, 0b00, 0b101, "pm2add.hx", Commutable=1>;
def PM2ADDA_HX : RVPTernary_rrr<0b0011, 0b00, 0b101, "pm2adda.hx">;
def PM2ADDU_H : RVPBinary_rr<0b0100, 0b00, 0b101, "pm2addu.h", Commutable=1>;
def PM4ADDU_B : RVPBinary_rr<0b0100, 0b10, 0b101, "pm4addu.b", Commutable=1>;
def PM2ADDAU_H : RVPTernary_rrr<0b0101, 0b00, 0b101, "pm2addau.h">;
def PM4ADDAU_B : RVPTernary_rrr<0b0101, 0b10, 0b101, "pm4addau.b">;
def PMQ2ADD_H : RVPBinary_rr<0b0110, 0b00, 0b101, "pmq2add.h", Commutable=1>;
def PMQR2ADD_H : RVPBinary_rr<0b0110, 0b10, 0b101, "pmqr2add.h", Commutable=1>;
def PMQ2ADDA_H : RVPTernary_rrr<0b0111, 0b00, 0b101, "pmq2adda.h">;
def PMQR2ADDA_H : RVPTernary_rrr<0b0111, 0b10, 0b101, "pmqr2adda.h">;
def PM2SUB_H : RVPBinary_rr<0b1000, 0b00, 0b101, "pm2sub.h">;
def PM2SADD_H : RVPBinary_rr<0b1000, 0b10, 0b101, "pm2sadd.h", Commutable=1, DefVXSAT=1>;
def PM2SUBA_H : RVPTernary_rrr<0b1001, 0b00, 0b101, "pm2suba.h">;
def PM2SUB_HX : RVPBinary_rr<0b1010, 0b00, 0b101, "pm2sub.hx">;
def PM2SADD_HX : RVPBinary_rr<0b1010, 0b10, 0b101, "pm2sadd.hx", Commutable=1, DefVXSAT=1>;
def PM2SUBA_HX : RVPTernary_rrr<0b1011, 0b00, 0b101, "pm2suba.hx">;
def PM2ADDSU_H : RVPBinary_rr<0b1100, 0b00, 0b101, "pm2addsu.h">;
def PM4ADDSU_B : RVPBinary_rr<0b1100, 0b10, 0b101, "pm4addsu.b">;
def PM2ADDASU_H : RVPTernary_rrr<0b1101, 0b00, 0b101, "pm2addasu.h">;
def PM4ADDASU_B : RVPTernary_rrr<0b1101, 0b10, 0b101, "pm4addasu.b">;
let append Predicates = [IsRV32], DecoderNamespace = "RV32Only" in {
def MQACC_H01 : RVPTernary_rrr<0b1111, 0b00, 0b101, "mqacc.h01">;
def MQRACC_H01 : RVPTernary_rrr<0b1111, 0b10, 0b101, "mqracc.h01">;
} // append Predicates = [IsRV32], DecoderNamespace = "RV32Only"
let append Predicates = [IsRV64] in {
def PM2ADD_W : RVPBinary_rr<0b0000, 0b01, 0b101, "pm2add.w", Commutable=1>;
def PM4ADD_H : RVPBinary_rr<0b0000, 0b11, 0b101, "pm4add.h", Commutable=1>;
def PM2ADDA_W : RVPTernary_rrr<0b0001, 0b01, 0b101, "pm2adda.w">;
def PM4ADDA_H : RVPTernary_rrr<0b0001, 0b11, 0b101, "pm4adda.h">;
def PM2ADD_WX : RVPBinary_rr<0b0010, 0b01, 0b101, "pm2add.wx", Commutable=1>;
def PM2ADDA_WX : RVPTernary_rrr<0b0011, 0b01, 0b101, "pm2adda.wx">;
def PM2ADDU_W : RVPBinary_rr<0b0100, 0b01, 0b101, "pm2addu.w", Commutable=1>;
def PM4ADDU_H : RVPBinary_rr<0b0100, 0b11, 0b101, "pm4addu.h", Commutable=1>;
def PM2ADDAU_W : RVPTernary_rrr<0b0101, 0b01, 0b101, "pm2addau.w">;
def PM4ADDAU_H : RVPTernary_rrr<0b0101, 0b11, 0b101, "pm4addau.h">;
def PMQ2ADD_W : RVPBinary_rr<0b0110, 0b01, 0b101, "pmq2add.w", Commutable=1>;
def PMQR2ADD_W : RVPBinary_rr<0b0110, 0b11, 0b101, "pmqr2add.w", Commutable=1>;
def PMQ2ADDA_W : RVPTernary_rrr<0b0111, 0b01, 0b101, "pmq2adda.w">;
def PMQR2ADDA_W : RVPTernary_rrr<0b0111, 0b11, 0b101, "pmqr2adda.w">;
def PM2SUB_W : RVPBinary_rr<0b1000, 0b01, 0b101, "pm2sub.w">;
def PM2SUBA_W : RVPTernary_rrr<0b1001, 0b01, 0b101, "pm2suba.w">;
def PM2SUB_WX : RVPBinary_rr<0b1010, 0b01, 0b101, "pm2sub.wx">;
def PM2SUBA_WX : RVPTernary_rrr<0b1011, 0b01, 0b101, "pm2suba.wx">;
def PM2ADDSU_W : RVPBinary_rr<0b1100, 0b01, 0b101, "pm2addsu.w">;
def PM4ADDSU_H : RVPBinary_rr<0b1100, 0b11, 0b101, "pm4addsu.h">;
def PM2ADDASU_W : RVPTernary_rrr<0b1101, 0b01, 0b101, "pm2addasu.w">;
def PM4ADDASU_H : RVPTernary_rrr<0b1101, 0b11, 0b101, "pm4addasu.h">;
def PMQACC_W_H01 : RVPTernary_rrr<0b1111, 0b00, 0b101, "pmqacc.w.h01">;
def MQACC_W01 : RVPTernary_rrr<0b1111, 0b01, 0b101, "mqacc.w01">;
def PMQRACC_W_H01 : RVPTernary_rrr<0b1111, 0b10, 0b101, "pmqracc.w.h01">;
def MQRACC_W01 : RVPTernary_rrr<0b1111, 0b11, 0b101, "mqracc.w01">;
} // append Predicates = [IsRV64]
def PAS_HX : RVPBinary_rr<0b0000, 0b00, 0b110, "pas.hx">;
def PSA_HX : RVPBinary_rr<0b0000, 0b10, 0b110, "psa.hx">;
def PSAS_HX : RVPBinary_rr<0b0010, 0b00, 0b110, "psas.hx", DefVXSAT=1>;
def PSSA_HX : RVPBinary_rr<0b0010, 0b10, 0b110, "pssa.hx", DefVXSAT=1>;
def PAAS_HX : RVPBinary_rr<0b0011, 0b00, 0b110, "paas.hx">;
def PASA_HX : RVPBinary_rr<0b0011, 0b10, 0b110, "pasa.hx">;
def PMSEQ_H : RVPBinary_rr<0b1000, 0b00, 0b110, "pmseq.h", Commutable=1>;
def PMSEQ_B : RVPBinary_rr<0b1000, 0b10, 0b110, "pmseq.b", Commutable=1>;
def PMSLT_H : RVPBinary_rr<0b1010, 0b00, 0b110, "pmslt.h">;
def PMSLT_B : RVPBinary_rr<0b1010, 0b10, 0b110, "pmslt.b">;
def PMSLTU_H : RVPBinary_rr<0b1011, 0b00, 0b110, "pmsltu.h">;
def PMSLTU_B : RVPBinary_rr<0b1011, 0b10, 0b110, "pmsltu.b">;
def PMIN_H : RVPBinary_rr<0b1100, 0b00, 0b110, "pmin.h", Commutable=1>;
def PMIN_B : RVPBinary_rr<0b1100, 0b10, 0b110, "pmin.b", Commutable=1>;
def PMINU_H : RVPBinary_rr<0b1101, 0b00, 0b110, "pminu.h", Commutable=1>;
def PMINU_B : RVPBinary_rr<0b1101, 0b10, 0b110, "pminu.b", Commutable=1>;
def PMAX_H : RVPBinary_rr<0b1110, 0b00, 0b110, "pmax.h", Commutable=1>;
def PMAX_B : RVPBinary_rr<0b1110, 0b10, 0b110, "pmax.b", Commutable=1>;
def PMAXU_H : RVPBinary_rr<0b1111, 0b00, 0b110, "pmaxu.h", Commutable=1>;
def PMAXU_B : RVPBinary_rr<0b1111, 0b10, 0b110, "pmaxu.b", Commutable=1>;
let append Predicates = [IsRV32], DecoderNamespace = "RV32Only" in {
def MSEQ : RVPBinary_rr<0b1000, 0b01, 0b110, "mseq", Commutable=1>;
def MSLT : RVPBinary_rr<0b1010, 0b01, 0b110, "mslt">;
def MSLTU : RVPBinary_rr<0b1011, 0b01, 0b110, "msltu">;
} // append Predicates = [IsRV32], DecoderNamespace = "RV32Only"
let append Predicates = [IsRV64] in {
def PAS_WX : RVPBinary_rr<0b0000, 0b01, 0b110, "pas.wx">;
def PSA_WX : RVPBinary_rr<0b0000, 0b11, 0b110, "psa.wx">;
def PSAS_WX : RVPBinary_rr<0b0010, 0b01, 0b110, "psas.wx", DefVXSAT=1>;
def PSSA_WX : RVPBinary_rr<0b0010, 0b11, 0b110, "pssa.wx", DefVXSAT=1>;
def PAAS_WX : RVPBinary_rr<0b0011, 0b01, 0b110, "paas.wx">;
def PASA_WX : RVPBinary_rr<0b0011, 0b11, 0b110, "pasa.wx">;
def PMSEQ_W : RVPBinary_rr<0b1000, 0b01, 0b110, "pmseq.w", Commutable=1>;
def PMSLT_W : RVPBinary_rr<0b1010, 0b01, 0b110, "pmslt.w">;
def PMSLTU_W : RVPBinary_rr<0b1011, 0b01, 0b110, "pmsltu.w">;
def PMIN_W : RVPBinary_rr<0b1100, 0b01, 0b110, "pmin.w", Commutable=1>;
def PMINU_W : RVPBinary_rr<0b1101, 0b01, 0b110, "pminu.w", Commutable=1>;
def PMAX_W : RVPBinary_rr<0b1110, 0b01, 0b110, "pmax.w", Commutable=1>;
def PMAXU_W : RVPBinary_rr<0b1111, 0b01, 0b110, "pmaxu.w", Commutable=1>;
} // append Predicates = [IsRV64]
def PMULH_H : RVPBinary_rr<0b0000, 0b00, 0b111, "pmulh.h", Commutable=1>;
def PMULHR_H : RVPBinary_rr<0b0000, 0b10, 0b111, "pmulhr.h", Commutable=1>;
def PMHACC_H : RVPTernary_rrr<0b0001, 0b00, 0b111, "pmhacc.h">;
def PMHRACC_H : RVPTernary_rrr<0b0001, 0b10, 0b111, "pmhracc.h">;
def PMULHU_H : RVPBinary_rr<0b0010, 0b00, 0b111, "pmulhu.h", Commutable=1>;
def PMULHRU_H : RVPBinary_rr<0b0010, 0b10, 0b111, "pmulhru.h", Commutable=1>;
def PMHACCU_H : RVPTernary_rrr<0b0011, 0b00, 0b111, "pmhaccu.h">;
def PMHRACCU_H : RVPTernary_rrr<0b0011, 0b10, 0b111, "pmhraccu.h">;
def PMULH_H_B0 : RVPBinary_rr<0b0100, 0b00, 0b111, "pmulh.h.b0">;
def PMULHSU_H_B0 : RVPBinary_rr<0b0100, 0b10, 0b111, "pmulhsu.h.b0">;
def PMHACC_H_B0 : RVPTernary_rrr<0b0101, 0b00, 0b111, "pmhacc.h.b0">;
def PMHACCSU_H_B0 : RVPTernary_rrr<0b0101, 0b10, 0b111, "pmhaccsu.h.b0">;
def PMULH_H_B1 : RVPBinary_rr<0b0110, 0b00, 0b111, "pmulh.h.b1">;
def PMULHSU_H_B1 : RVPBinary_rr<0b0110, 0b10, 0b111, "pmulhsu.h.b1">;
def PMHACC_H_B1 : RVPTernary_rrr<0b0111, 0b00, 0b111, "pmhacc.h.b1">;
def PMHACCSU_H_B1 : RVPTernary_rrr<0b0111, 0b10, 0b111, "pmhaccsu.h.b1">;
def PMULHSU_H : RVPBinary_rr<0b1000, 0b00, 0b111, "pmulhsu.h">;
def PMULHRSU_H : RVPBinary_rr<0b1000, 0b10, 0b111, "pmulhrsu.h">;
def PMHACCSU_H : RVPTernary_rrr<0b1001, 0b00, 0b111, "pmhaccsu.h">;
def PMHRACCSU_H : RVPTernary_rrr<0b1001, 0b10, 0b111, "pmhraccsu.h">;
def PMULQ_H : RVPBinary_rr<0b1010, 0b00, 0b111, "pmulq.h", Commutable=1, DefVXSAT=1>;
def PMULQR_H : RVPBinary_rr<0b1010, 0b10, 0b111, "pmulqr.h", Commutable=1, DefVXSAT=1>;
let append Predicates = [IsRV32], DecoderNamespace = "RV32Only" in {
def MULHR : RVPBinary_rr<0b0000, 0b11, 0b111, "mulhr", Commutable=1>;
def MHACC : RVPTernary_rrr<0b0001, 0b01, 0b111, "mhacc">;
def MHRACC : RVPTernary_rrr<0b0001, 0b11, 0b111, "mhracc">;
def MULHRU : RVPBinary_rr<0b0010, 0b11, 0b111, "mulhru", Commutable=1>;
def MHACCU : RVPTernary_rrr<0b0011, 0b01, 0b111, "mhaccu">;
def MHRACCU : RVPTernary_rrr<0b0011, 0b11, 0b111, "mhraccu">;
def MULH_H0 : RVPBinary_rr<0b0100, 0b01, 0b111, "mulh.h0">;
def MULHSU_H0 : RVPBinary_rr<0b0100, 0b11, 0b111, "mulhsu.h0">;
def MHACC_H0 : RVPTernary_rrr<0b0101, 0b01, 0b111, "mhacc.h0">;
def MHACCSU_H0 : RVPTernary_rrr<0b0101, 0b11, 0b111, "mhaccsu.h0">;
def MULH_H1 : RVPBinary_rr<0b0110, 0b01, 0b111, "mulh.h1">;
def MULHSU_H1 : RVPBinary_rr<0b0110, 0b11, 0b111, "mulhsu.h1">;
def MHACC_H1 : RVPTernary_rrr<0b0111, 0b01, 0b111, "mhacc.h1">;
def MHACCSU_H1 : RVPTernary_rrr<0b0111, 0b11, 0b111, "mhaccsu.h1">;
def MULHRSU : RVPBinary_rr<0b1000, 0b11, 0b111, "mulhrsu">;
def MHACCSU : RVPTernary_rrr<0b1001, 0b01, 0b111, "mhaccsu">;
def MHRACCSU : RVPTernary_rrr<0b1001, 0b11, 0b111, "mhraccsu">;
def MULQ : RVPBinary_rr<0b1010, 0b01, 0b111, "mulq", Commutable=1, DefVXSAT=1>;
def MULQR : RVPBinary_rr<0b1010, 0b11, 0b111, "mulqr", Commutable=1, DefVXSAT=1>;
def MQACC_H00 : RVPTernary_rrr<0b1101, 0b00, 0b111, "mqacc.h00">;
def MQRACC_H00 : RVPTernary_rrr<0b1101, 0b10, 0b111, "mqracc.h00">;
def MQACC_H11 : RVPTernary_rrr<0b1111, 0b00, 0b111, "mqacc.h11">;
def MQRACC_H11 : RVPTernary_rrr<0b1111, 0b10, 0b111, "mqracc.h11">;
} // append Predicates = [IsRV32], DecoderNamespace = "RV32Only" in
let append Predicates = [IsRV64] in {
def PMULH_W : RVPBinary_rr<0b0000, 0b01, 0b111, "pmulh.w", Commutable=1>;
def PMULHR_W : RVPBinary_rr<0b0000, 0b11, 0b111, "pmulhr.w", Commutable=1>;
def PMHACC_W : RVPTernary_rrr<0b0001, 0b01, 0b111, "pmhacc.w">;
def PMHRACC_W : RVPTernary_rrr<0b0001, 0b11, 0b111, "pmhracc.w">;
def PMULHU_W : RVPBinary_rr<0b0010, 0b01, 0b111, "pmulhu.w", Commutable=1>;
def PMULHRU_W : RVPBinary_rr<0b0010, 0b11, 0b111, "pmulhru.w", Commutable=1>;
def PMHACCU_W : RVPTernary_rrr<0b0011, 0b01, 0b111, "pmhaccu.w">;
def PMHRACCU_W : RVPTernary_rrr<0b0011, 0b11, 0b111, "pmhraccu.w">;
def PMULH_W_H0 : RVPBinary_rr<0b0100, 0b01, 0b111, "pmulh.w.h0">;
def PMULHSU_W_H0 : RVPBinary_rr<0b0100, 0b11, 0b111, "pmulhsu.w.h0">;
def PMHACC_W_H0 : RVPTernary_rrr<0b0101, 0b01, 0b111, "pmhacc.w.h0">;
def PMHACCSU_W_H0 : RVPTernary_rrr<0b0101, 0b11, 0b111, "pmhaccsu.w.h0">;
def PMULH_W_H1 : RVPBinary_rr<0b0110, 0b01, 0b111, "pmulh.w.h1">;
def PMULHSU_W_H1 : RVPBinary_rr<0b0110, 0b11, 0b111, "pmulhsu.w.h1">;
def PMHACC_W_H1 : RVPTernary_rrr<0b0111, 0b01, 0b111, "pmhacc.w.h1">;
def PMHACCSU_W_H1 : RVPTernary_rrr<0b0111, 0b11, 0b111, "pmhaccsu.w.h1">;
def PMULHSU_W : RVPBinary_rr<0b1000, 0b01, 0b111, "pmulhsu.w">;
def PMULHRSU_W : RVPBinary_rr<0b1000, 0b11, 0b111, "pmulhrsu.w">;
def PMHACCSU_W : RVPTernary_rrr<0b1001, 0b01, 0b111, "pmhaccsu.w">;
def PMHRACCSU_W : RVPTernary_rrr<0b1001, 0b11, 0b111, "pmhraccsu.w">;
def PMULQ_W : RVPBinary_rr<0b1010, 0b01, 0b111, "pmulq.w", Commutable=1, DefVXSAT=1>;
def PMULQR_W : RVPBinary_rr<0b1010, 0b11, 0b111, "pmulqr.w", Commutable=1, DefVXSAT=1>;
def PMQACC_W_H00 : RVPTernary_rrr<0b1101, 0b00, 0b111, "pmqacc.w.h00">;
def MQACC_W00 : RVPTernary_rrr<0b1101, 0b01, 0b111, "mqacc.w00">;
def PMQRACC_W_H00 : RVPTernary_rrr<0b1101, 0b10, 0b111, "pmqracc.w.h00">;
def MQRACC_W00 : RVPTernary_rrr<0b1101, 0b11, 0b111, "mqracc.w00">;
def PMQACC_W_H11 : RVPTernary_rrr<0b1111, 0b00, 0b111, "pmqacc.w.h11">;
def MQACC_W11 : RVPTernary_rrr<0b1111, 0b01, 0b111, "mqacc.w11">;
def PMQRACC_W_H11 : RVPTernary_rrr<0b1111, 0b10, 0b111, "pmqracc.w.h11">;
def MQRACC_W11 : RVPTernary_rrr<0b1111, 0b11, 0b111, "mqracc.w11">;
} // append Predicates = [IsRV64]
let append Predicates = [IsRV32] in {
def PLI_DH : RVPPairLoadImm_i<0b0011000, (ins simm10_pli_h:$imm10), "pli.dh",
"$rd, $imm10"> {
bits<10> imm10;
let Inst{24-16} = imm10{8-0};
let Inst{15} = imm10{9};
}
def PLI_DB : RVPPairLoadImm_i<0b0011010, (ins simm8_pli_b:$imm8), "pli.db",
"$rd, $imm8"> {
bits<8> imm8;
let Inst{24} = 0b0;
let Inst{23-16} = imm8;
let Inst{15} = 0b0;
}
def PLUI_DH : RVPPairLoadImm_i<0b0111000, (ins simm10_plui:$imm10),
"plui.dh", "$rd, $imm10"> {
bits<10> imm10;
let Inst{24} = imm10{0};
let Inst{23-15} = imm10{9-1};
}
def PWSLLI_B : RVPWideningShiftB_ri<0b000, "pwslli.b">;
def PWSLLI_H : RVPWideningShiftH_ri<0b000, "pwslli.h">;
def WSLLI : RVPWideningShiftW_ri<0b000, "wslli">;
def PWSLAI_B : RVPWideningShiftB_ri<0b100, "pwslai.b">;
def PWSLAI_H : RVPWideningShiftH_ri<0b100, "pwslai.h">;
def WSLAI : RVPWideningShiftW_ri<0b100, "wslai">;
def PWSLL_BS : RVPWideningShift_rr<0b000, 0b00, "pwsll.bs">;
def PWSLL_HS : RVPWideningShift_rr<0b000, 0b01, "pwsll.hs">;
def WSLL : RVPWideningShift_rr<0b000, 0b11, "wsll">;
def PWSLA_BS : RVPWideningShift_rr<0b100, 0b00, "pwsla.bs">;
def PWSLA_HS : RVPWideningShift_rr<0b100, 0b01, "pwsla.hs">;
def WSLA : RVPWideningShift_rr<0b100, 0b11, "wsla">;
def WZIP8P : RVPWideningShift_rr<0b111, 0b00, "wzip8p">;
def WZIP16P : RVPWideningShift_rr<0b111, 0b01, "wzip16p">;
def PWADD_H : RVPWideningBinary_rr<0b0000, 0b00, "pwadd.h", Commutable=1>;
def WADD : RVPWideningBinary_rr<0b0000, 0b01, "wadd", Commutable=1>;
def PWADD_B : RVPWideningBinary_rr<0b0000, 0b10, "pwadd.b", Commutable=1>;
def PM2WADD_H : RVPWideningBinary_rr<0b0000, 0b11, "pm2wadd.h", Commutable=1>;
def PWADDA_H : RVPWideningTernary_rrr<0b0001, 0b00, "pwadda.h">;
def WADDA : RVPWideningTernary_rrr<0b0001, 0b01, "wadda">;
def PWADDA_B : RVPWideningTernary_rrr<0b0001, 0b10, "pwadda.b">;
def PM2WADDA_H : RVPWideningTernary_rrr<0b0001, 0b11, "pm2wadda.h">;
def PWADDU_H : RVPWideningBinary_rr<0b0010, 0b00, "pwaddu.h", Commutable=1>;
def WADDU : RVPWideningBinary_rr<0b0010, 0b01, "waddu", Commutable=1>;
def PWADDU_B : RVPWideningBinary_rr<0b0010, 0b10, "pwaddu.b", Commutable=1>;
def PM2WADD_HX : RVPWideningBinary_rr<0b0010, 0b11, "pm2wadd.hx", Commutable=1>;
def PWADDAU_H : RVPWideningTernary_rrr<0b0011, 0b00, "pwaddau.h">;
def WADDAU : RVPWideningTernary_rrr<0b0011, 0b01, "waddau">;
def PWADDAU_B : RVPWideningTernary_rrr<0b0011, 0b10, "pwaddau.b">;
def PM2WADDA_HX : RVPWideningTernary_rrr<0b0011, 0b11, "pm2wadda.hx">;
def PWMUL_H : RVPWideningBinary_rr<0b0100, 0b00, "pwmul.h", Commutable=1>;
def WMUL : RVPWideningBinary_rr<0b0100, 0b01, "wmul", Commutable=1>;
def PWMUL_B : RVPWideningBinary_rr<0b0100, 0b10, "pwmul.b", Commutable=1>;
def PM2WADDU_H : RVPWideningBinary_rr<0b0100, 0b11, "pm2waddu.h", Commutable=1>;
def PWMACC_H : RVPWideningTernary_rrr<0b0101, 0b00, "pwmacc.h">;
def WMACC : RVPWideningTernary_rrr<0b0101, 0b01, "wmacc">;
def PM2WADDAU_H : RVPWideningTernary_rrr<0b0101, 0b11, "pm2waddau.h">;
def PWMULU_H : RVPWideningBinary_rr<0b0110, 0b00, "pwmulu.h", Commutable=1>;
def WMULU : RVPWideningBinary_rr<0b0110, 0b01, "wmulu", Commutable=1>;
def PWMULU_B : RVPWideningBinary_rr<0b0110, 0b10, "pwmulu.b", Commutable=1>;
def PWMACCU_H : RVPWideningTernary_rrr<0b0111, 0b00, "pwmaccu.h">;
def WMACCU : RVPWideningTernary_rrr<0b0111, 0b01, "wmaccu">;
def PWSUB_H : RVPWideningBinary_rr<0b1000, 0b00, "pwsub.h">;
def WSUB : RVPWideningBinary_rr<0b1000, 0b01, "wsub">;
def PWSUB_B : RVPWideningBinary_rr<0b1000, 0b10, "pwsub.b">;
def PM2WSUB_H : RVPWideningBinary_rr<0b1000, 0b11, "pm2wsub.h">;
def PWSUBA_H : RVPWideningTernary_rrr<0b1001, 0b00, "pwsuba.h">;
def WSUBA : RVPWideningTernary_rrr<0b1001, 0b01, "wsuba">;
def PWSUBA_B : RVPWideningTernary_rrr<0b1001, 0b10, "pwsuba.b">;
def PM2WSUBA_H : RVPWideningTernary_rrr<0b1001, 0b11, "pm2wsuba.h">;
def PWSUBU_H : RVPWideningBinary_rr<0b1010, 0b00, "pwsubu.h">;
def WSUBU : RVPWideningBinary_rr<0b1010, 0b01, "wsubu">;
def PWSUBU_B : RVPWideningBinary_rr<0b1010, 0b10, "pwsubu.b">;
def PM2WSUB_HX : RVPWideningBinary_rr<0b1010, 0b11, "pm2wsub.hx">;
def PWSUBAU_H : RVPWideningTernary_rrr<0b1011, 0b00, "pwsubau.h">;
def WSUBAU : RVPWideningTernary_rrr<0b1011, 0b01, "wsubau">;
def PWSUBAU_B : RVPWideningTernary_rrr<0b1011, 0b10, "pwsubau.b">;
def PM2WSUBA_HX : RVPWideningTernary_rrr<0b1011, 0b11, "pm2wsuba.hx">;
def PWMULSU_H : RVPWideningBinary_rr<0b1100, 0b00, "pwmulsu.h">;
def WMULSU : RVPWideningBinary_rr<0b1100, 0b01, "wmulsu">;
def PWMULSU_B : RVPWideningBinary_rr<0b1100, 0b10, "pwmulsu.b">;
def PM2WADDSU_H : RVPWideningBinary_rr<0b1100, 0b11, "pm2waddsu.h">;
def PWMACCSU_H : RVPWideningTernary_rrr<0b1101, 0b00, "pwmaccsu.h">;
def WMACCSU : RVPWideningTernary_rrr<0b1101, 0b01, "wmaccsu">;
def PM2WADDASU_H : RVPWideningTernary_rrr<0b1101, 0b11, "pm2waddasu.h">;
def PMQWACC_H : RVPWideningTernary_rrr<0b1111, 0b00, "pmqwacc.h">;
def MQWACC : RVPWideningTernary_rrr<0b1111, 0b01, "mqwacc">;
def PMQRWACC_H : RVPWideningTernary_rrr<0b1111, 0b10, "pmqrwacc.h">;
def MQRWACC : RVPWideningTernary_rrr<0b1111, 0b11, "mqrwacc">;
def PREDSUM_DHS : RVPNarrowingBinary_rr<0b001, 0b00, "predsum.dhs">;
def PREDSUM_DBS : RVPNarrowingBinary_rr<0b001, 0b10, "predsum.dbs">;
def PREDSUMU_DHS : RVPNarrowingBinary_rr<0b011, 0b00, "predsumu.dhs">;
def PREDSUMU_DBS : RVPNarrowingBinary_rr<0b011, 0b10, "predsumu.dbs">;
def PNSRLI_B : RVPNarrowingShiftB_ri<0b000, "pnsrli.b">;
def PNSRLI_H : RVPNarrowingShiftH_ri<0b000, "pnsrli.h">;
def NSRLI : RVPNarrowingShiftW_ri<0b000, "nsrli">;
def PNCLIPIU_B : RVPNarrowingShiftB_ri<0b010, "pnclipiu.b", DefVXSAT=1>;
def PNCLIPIU_H : RVPNarrowingShiftH_ri<0b010, "pnclipiu.h", DefVXSAT=1>;
def NCLIPIU : RVPNarrowingShiftW_ri<0b010, "nclipiu", DefVXSAT=1>;
def PNCLIPRIU_B : RVPNarrowingShiftB_ri<0b011, "pnclipriu.b", DefVXSAT=1>;
def PNCLIPRIU_H : RVPNarrowingShiftH_ri<0b011, "pnclipriu.h", DefVXSAT=1>;
def NCLIPRIU : RVPNarrowingShiftW_ri<0b011, "nclipriu", DefVXSAT=1>;
def PNSRAI_B : RVPNarrowingShiftB_ri<0b100, "pnsrai.b">;
def PNSRAI_H : RVPNarrowingShiftH_ri<0b100, "pnsrai.h">;
def NSRAI : RVPNarrowingShiftW_ri<0b100, "nsrai">;
def PNSRARI_B : RVPNarrowingShiftB_ri<0b101, "pnsrari.b">;
def PNSRARI_H : RVPNarrowingShiftH_ri<0b101, "pnsrari.h">;
def NSRARI : RVPNarrowingShiftW_ri<0b101, "nsrari">;
def PNCLIPI_B : RVPNarrowingShiftB_ri<0b110, "pnclipi.b", DefVXSAT=1>;
def PNCLIPI_H : RVPNarrowingShiftH_ri<0b110, "pnclipi.h", DefVXSAT=1>;
def NCLIPI : RVPNarrowingShiftW_ri<0b110, "nclipi", DefVXSAT=1>;
def PNCLIPRI_B : RVPNarrowingShiftB_ri<0b111, "pnclipri.b", DefVXSAT=1>;
def PNCLIPRI_H : RVPNarrowingShiftH_ri<0b111, "pnclipri.h", DefVXSAT=1>;
def NCLIPRI : RVPNarrowingShiftW_ri<0b111, "nclipri", DefVXSAT=1>;
def PNSRL_BS : RVPNarrowingShift_rr<0b000, 0b00, "pnsrl.bs">;
def PNSRL_HS : RVPNarrowingShift_rr<0b000, 0b01, "pnsrl.hs">;
def NSRL : RVPNarrowingShift_rr<0b000, 0b11, "nsrl">;
def PNCLIPU_BS : RVPNarrowingShift_rr<0b010, 0b00, "pnclipu.bs", DefVXSAT=1>;
def PNCLIPU_HS : RVPNarrowingShift_rr<0b010, 0b01, "pnclipu.hs", DefVXSAT=1>;
def NCLIPU : RVPNarrowingShift_rr<0b010, 0b11, "nclipu", DefVXSAT=1>;
def PNCLIPRU_BS : RVPNarrowingShift_rr<0b011, 0b00, "pnclipru.bs", DefVXSAT=1>;
def PNCLIPRU_HS : RVPNarrowingShift_rr<0b011, 0b01, "pnclipru.hs", DefVXSAT=1>;
def NCLIPRU : RVPNarrowingShift_rr<0b011, 0b11, "nclipru", DefVXSAT=1>;
def PNSRA_BS : RVPNarrowingShift_rr<0b100, 0b00, "pnsra.bs">;
def PNSRA_HS : RVPNarrowingShift_rr<0b100, 0b01, "pnsra.hs">;
def NSRA : RVPNarrowingShift_rr<0b100, 0b11, "nsra">;
def PNSRAR_BS : RVPNarrowingShift_rr<0b101, 0b00, "pnsrar.bs">;
def PNSRAR_HS : RVPNarrowingShift_rr<0b101, 0b01, "pnsrar.hs">;
def NSRAR : RVPNarrowingShift_rr<0b101, 0b11, "nsrar">;
def PNCLIP_BS : RVPNarrowingShift_rr<0b110, 0b00, "pnclip.bs", DefVXSAT=1>;
def PNCLIP_HS : RVPNarrowingShift_rr<0b110, 0b01, "pnclip.hs", DefVXSAT=1>;
def NCLIP : RVPNarrowingShift_rr<0b110, 0b11, "nclip", DefVXSAT=1>;
def PNCLIPR_BS : RVPNarrowingShift_rr<0b111, 0b00, "pnclipr.bs", DefVXSAT=1>;
def PNCLIPR_HS : RVPNarrowingShift_rr<0b111, 0b01, "pnclipr.hs", DefVXSAT=1>;
def NCLIPR : RVPNarrowingShift_rr<0b111, 0b11, "nclipr", DefVXSAT=1>;
def PSLLI_DB : RVPPairShiftB_ri<0b000, 0b0, "pslli.db">;
def PSLLI_DH : RVPPairShiftH_ri<0b000, 0b0, "pslli.dh">;
def PSLLI_DW : RVPPairShiftW_ri<0b000, 0b0, "pslli.dw">;
def PSSLAI_DH : RVPPairShiftH_ri<0b101, 0b0, "psslai.dh", DefVXSAT=1>;
def PSSLAI_DW : RVPPairShiftW_ri<0b101, 0b0, "psslai.dw", DefVXSAT=1>;
def PSEXT_DH_B : RVPPairUnary_r<0b00, 0b00100, "psext.dh.b">;
def PSEXT_DW_B : RVPPairUnary_r<0b01, 0b00100, "psext.dw.b">;
def PSEXT_DW_H : RVPPairUnary_r<0b01, 0b00101, "psext.dw.h">;
def PSABS_DH : RVPPairUnary_r<0b00, 0b00111, "psabs.dh", DefVXSAT=1>;
def PSABS_DB : RVPPairUnary_r<0b10, 0b00111, "psabs.db", DefVXSAT=1>;
def PSLL_DHS : RVPPairShift_rr<0b000, 0b00, 0b0, "psll.dhs">;
def PSLL_DWS : RVPPairShift_rr<0b000, 0b01, 0b0, "psll.dws">;
def PSLL_DBS : RVPPairShift_rr<0b000, 0b10, 0b0, "psll.dbs">;
def PADD_DHS : RVPPairShift_rr<0b001, 0b00, 0b0, "padd.dhs">;
def PADD_DWS : RVPPairShift_rr<0b001, 0b01, 0b0, "padd.dws">;
def PADD_DBS : RVPPairShift_rr<0b001, 0b10, 0b0, "padd.dbs">;
def PSSHL_DHS : RVPPairShift_rr<0b010, 0b00, 0b0, "psshl.dhs", DefVXSAT=1>;
def PSSHL_DWS : RVPPairShift_rr<0b010, 0b01, 0b0, "psshl.dws", DefVXSAT=1>;
def PSSHLR_DHS : RVPPairShift_rr<0b011, 0b00, 0b0, "psshlr.dhs", DefVXSAT=1>;
def PSSHLR_DWS : RVPPairShift_rr<0b011, 0b01, 0b0, "psshlr.dws", DefVXSAT=1>;
def PSSHA_DHS : RVPPairShift_rr<0b110, 0b00, 0b0, "pssha.dhs", DefVXSAT=1>;
def PSSHA_DWS : RVPPairShift_rr<0b110, 0b01, 0b0, "pssha.dws", DefVXSAT=1>;
def PSSHAR_DHS : RVPPairShift_rr<0b111, 0b00, 0b0, "psshar.dhs", DefVXSAT=1>;
def PSSHAR_DWS : RVPPairShift_rr<0b111, 0b01, 0b0, "psshar.dws", DefVXSAT=1>;
def PSRLI_DB : RVPPairShiftB_ri<0b000, 0b1, "psrli.db">;
def PSRLI_DH : RVPPairShiftH_ri<0b000, 0b1, "psrli.dh">;
def PSRLI_DW : RVPPairShiftW_ri<0b000, 0b1, "psrli.dw">;
def PUSATI_DH : RVPPairShiftH_ri<0b010, 0b1, "pusati.dh", DefVXSAT=1>;
def PUSATI_DW : RVPPairShiftW_ri<0b010, 0b1, "pusati.dw", DefVXSAT=1>;
def PSRAI_DB : RVPPairShiftB_ri<0b100, 0b1, "psrai.db">;
def PSRAI_DH : RVPPairShiftH_ri<0b100, 0b1, "psrai.dh">;
def PSRAI_DW : RVPPairShiftW_ri<0b100, 0b1, "psrai.dw">;
def PSRARI_DH : RVPPairShiftH_ri<0b101, 0b1, "psrari.dh">;
def PSRARI_DW : RVPPairShiftW_ri<0b101, 0b1, "psrari.dw">;
def PSATI_DH : RVPPairShiftH_ri<0b110, 0b1, "psati.dh", DefVXSAT=1>;
def PSATI_DW : RVPPairShiftW_ri<0b110, 0b1, "psati.dw", DefVXSAT=1>;
def PSRL_DHS : RVPPairShift_rr<0b000, 0b00, 0b1, "psrl.dhs">;
def PSRL_DWS : RVPPairShift_rr<0b000, 0b01, 0b1, "psrl.dws">;
def PSRL_DBS : RVPPairShift_rr<0b000, 0b10, 0b1, "psrl.dbs">;
def PSRA_DHS : RVPPairShift_rr<0b100, 0b00, 0b1, "psra.dhs">;
def PSRA_DWS : RVPPairShift_rr<0b100, 0b01, 0b1, "psra.dws">;
def PSRA_DBS : RVPPairShift_rr<0b100, 0b10, 0b1, "psra.dbs">;
def PADD_DH : RVPPairBinary_rr<0b0000, 0b00, "padd.dh", Commutable=1>;
def PADD_DW : RVPPairBinary_rr<0b0000, 0b01, "padd.dw", Commutable=1>;
def PADD_DB : RVPPairBinary_rr<0b0000, 0b10, "padd.db", Commutable=1>;
def ADDD : RVPPairBinary_rr<0b0000, 0b11, "addd", Commutable=1>;
def PSADD_DH : RVPPairBinary_rr<0b0010, 0b00, "psadd.dh", Commutable=1, DefVXSAT=1>;
def PSADD_DW : RVPPairBinary_rr<0b0010, 0b01, "psadd.dw", Commutable=1, DefVXSAT=1>;
def PSADD_DB : RVPPairBinary_rr<0b0010, 0b10, "psadd.db", Commutable=1, DefVXSAT=1>;
def PAADD_DH : RVPPairBinary_rr<0b0011, 0b00, "paadd.dh", Commutable=1>;
def PAADD_DW : RVPPairBinary_rr<0b0011, 0b01, "paadd.dw", Commutable=1>;
def PAADD_DB : RVPPairBinary_rr<0b0011, 0b10, "paadd.db", Commutable=1>;
def PSADDU_DH : RVPPairBinary_rr<0b0110, 0b00, "psaddu.dh", Commutable=1, DefVXSAT=1>;
def PSADDU_DW : RVPPairBinary_rr<0b0110, 0b01, "psaddu.dw", Commutable=1, DefVXSAT=1>;
def PSADDU_DB : RVPPairBinary_rr<0b0110, 0b10, "psaddu.db", Commutable=1, DefVXSAT=1>;
def PAADDU_DH : RVPPairBinary_rr<0b0111, 0b00, "paaddu.dh", Commutable=1>;
def PAADDU_DW : RVPPairBinary_rr<0b0111, 0b01, "paaddu.dw", Commutable=1>;
def PAADDU_DB : RVPPairBinary_rr<0b0111, 0b10, "paaddu.db", Commutable=1>;
def PSUB_DH : RVPPairBinary_rr<0b1000, 0b00, "psub.dh">;
def PSUB_DW : RVPPairBinary_rr<0b1000, 0b01, "psub.dw">;
def PSUB_DB : RVPPairBinary_rr<0b1000, 0b10, "psub.db">;
def SUBD : RVPPairBinary_rr<0b1000, 0b11, "subd">;
def PABD_DH : RVPPairBinary_rr<0b1001, 0b00, "pabd.dh", Commutable=1>;
def PABD_DB : RVPPairBinary_rr<0b1001, 0b10, "pabd.db", Commutable=1>;
def PSSUB_DH : RVPPairBinary_rr<0b1010, 0b00, "pssub.dh", DefVXSAT=1>;
def PSSUB_DW : RVPPairBinary_rr<0b1010, 0b01, "pssub.dw", DefVXSAT=1>;
def PSSUB_DB : RVPPairBinary_rr<0b1010, 0b10, "pssub.db", DefVXSAT=1>;
def PASUB_DH : RVPPairBinary_rr<0b1011, 0b00, "pasub.dh">;
def PASUB_DW : RVPPairBinary_rr<0b1011, 0b01, "pasub.dw">;
def PASUB_DB : RVPPairBinary_rr<0b1011, 0b10, "pasub.db">;
def PABDU_DH : RVPPairBinary_rr<0b1101, 0b00, "pabdu.dh", Commutable=1>;
def PABDU_DB : RVPPairBinary_rr<0b1101, 0b10, "pabdu.db", Commutable=1>;
def PSSUBU_DH : RVPPairBinary_rr<0b1110, 0b00, "pssubu.dh", DefVXSAT=1>;
def PSSUBU_DW : RVPPairBinary_rr<0b1110, 0b01, "pssubu.dw", DefVXSAT=1>;
def PSSUBU_DB : RVPPairBinary_rr<0b1110, 0b10, "pssubu.db", DefVXSAT=1>;
def PASUBU_DH : RVPPairBinary_rr<0b1111, 0b00, "pasubu.dh">;
def PASUBU_DW : RVPPairBinary_rr<0b1111, 0b01, "pasubu.dw">;
def PASUBU_DB : RVPPairBinary_rr<0b1111, 0b10, "pasubu.db">;
def PSH1ADD_DH : RVPPairBinaryShift_rr<0b010, 0b00, "psh1add.dh">;
def PSH1ADD_DW : RVPPairBinaryShift_rr<0b010, 0b01, "psh1add.dw">;
def PSSH1SADD_DH : RVPPairBinaryShift_rr<0b011, 0b00, "pssh1sadd.dh", DefVXSAT=1>;
def PSSH1SADD_DW : RVPPairBinaryShift_rr<0b011, 0b01, "pssh1sadd.dw", DefVXSAT=1>;
def PPAIRE_DB : RVPPairBinaryPack_rr<0b000, 0b00, "ppaire.db">;
def PPAIRE_DH : RVPPairBinaryPack_rr<0b000, 0b01, "ppaire.dh">;
def PPAIREO_DB : RVPPairBinaryPack_rr<0b001, 0b00, "ppaireo.db">;
def PPAIREO_DH : RVPPairBinaryPack_rr<0b001, 0b01, "ppaireo.dh">;
def PPAIROE_DB : RVPPairBinaryPack_rr<0b010, 0b00, "ppairoe.db">;
def PPAIROE_DH : RVPPairBinaryPack_rr<0b010, 0b01, "ppairoe.dh">;
def PPAIRO_DB : RVPPairBinaryPack_rr<0b011, 0b00, "ppairo.db">;
def PPAIRO_DH : RVPPairBinaryPack_rr<0b011, 0b01, "ppairo.dh">;
def PAS_DHX : RVPPairBinaryExchanged_rr<0b0000, 0b00, "pas.dhx">;
def PSA_DHX : RVPPairBinaryExchanged_rr<0b0000, 0b10, "psa.dhx">;
def PSAS_DHX : RVPPairBinaryExchanged_rr<0b0010, 0b00, "psas.dhx", DefVXSAT=1>;
def PSSA_DHX : RVPPairBinaryExchanged_rr<0b0010, 0b10, "pssa.dhx", DefVXSAT=1>;
def PAAS_DHX : RVPPairBinaryExchanged_rr<0b0011, 0b00, "paas.dhx">;
def PASA_DHX : RVPPairBinaryExchanged_rr<0b0011, 0b10, "pasa.dhx">;
def PMSEQ_DH : RVPPairBinaryExchanged_rr<0b1000, 0b00, "pmseq.dh", Commutable=1>;
def PMSEQ_DW : RVPPairBinaryExchanged_rr<0b1000, 0b01, "pmseq.dw", Commutable=1>;
def PMSEQ_DB : RVPPairBinaryExchanged_rr<0b1000, 0b10, "pmseq.db", Commutable=1>;
def PMSLT_DH : RVPPairBinaryExchanged_rr<0b1010, 0b00, "pmslt.dh">;
def PMSLT_DW : RVPPairBinaryExchanged_rr<0b1010, 0b01, "pmslt.dw">;
def PMSLT_DB : RVPPairBinaryExchanged_rr<0b1010, 0b10, "pmslt.db">;
def PMSLTU_DH : RVPPairBinaryExchanged_rr<0b1011, 0b00, "pmsltu.dh">;
def PMSLTU_DW : RVPPairBinaryExchanged_rr<0b1011, 0b01, "pmsltu.dw">;
def PMSLTU_DB : RVPPairBinaryExchanged_rr<0b1011, 0b10, "pmsltu.db">;
def PMIN_DH : RVPPairBinaryExchanged_rr<0b1100, 0b00, "pmin.dh", Commutable=1>;
def PMIN_DW : RVPPairBinaryExchanged_rr<0b1100, 0b01, "pmin.dw", Commutable=1>;
def PMIN_DB : RVPPairBinaryExchanged_rr<0b1100, 0b10, "pmin.db", Commutable=1>;
def PMINU_DH : RVPPairBinaryExchanged_rr<0b1101, 0b00, "pminu.dh", Commutable=1>;
def PMINU_DW : RVPPairBinaryExchanged_rr<0b1101, 0b01, "pminu.dw", Commutable=1>;
def PMINU_DB : RVPPairBinaryExchanged_rr<0b1101, 0b10, "pminu.db", Commutable=1>;
def PMAX_DH : RVPPairBinaryExchanged_rr<0b1110, 0b00, "pmax.dh", Commutable=1>;
def PMAX_DW : RVPPairBinaryExchanged_rr<0b1110, 0b01, "pmax.dw", Commutable=1>;
def PMAX_DB : RVPPairBinaryExchanged_rr<0b1110, 0b10, "pmax.db", Commutable=1>;
def PMAXU_DH : RVPPairBinaryExchanged_rr<0b1111, 0b00, "pmaxu.dh", Commutable=1>;
def PMAXU_DW : RVPPairBinaryExchanged_rr<0b1111, 0b01, "pmaxu.dw", Commutable=1>;
def PMAXU_DB : RVPPairBinaryExchanged_rr<0b1111, 0b10, "pmaxu.db", Commutable=1>;
} // append Predicates = [IsRV32]
} // Predicates = [HasStdExtP]
//===----------------------------------------------------------------------===//
// Assembler Pseudo Instructions
//===----------------------------------------------------------------------===//
let Predicates = [HasStdExtP] in {
def : InstAlias<"pmv.bs $rd, $rs", (PADD_BS GPR:$rd, X0, GPR:$rs)>;
def : InstAlias<"pmv.hs $rd, $rs", (PADD_HS GPR:$rd, X0, GPR:$rs)>;
def : InstAlias<"pneg.b $rd, $rs", (PSUB_B GPR:$rd, X0, GPR:$rs)>;
def : InstAlias<"pneg.h $rd, $rs", (PSUB_H GPR:$rd, X0, GPR:$rs)>;
def : InstAlias<"pabs.b $rd, $rs", (PABD_B GPR:$rd, GPR:$rs, X0)>;
def : InstAlias<"pabs.h $rd, $rs", (PABD_H GPR:$rd, GPR:$rs, X0)>;
// No pabd.w instruction
def : InstAlias<"pzext.h.b $rd, $rs", (PPAIRE_B GPR:$rd, GPR:$rs, X0)>;
def : InstAlias<"pmseqz.b $rd, $rs", (PMSEQ_B GPR:$rd, GPR:$rs, X0)>;
def : InstAlias<"pmseqz.h $rd, $rs", (PMSEQ_H GPR:$rd, GPR:$rs, X0)>;
def : InstAlias<"pmsnez.b $rd, $rs", (PMSLTU_B GPR:$rd, X0, GPR:$rs)>;
def : InstAlias<"pmsnez.h $rd, $rs", (PMSLTU_H GPR:$rd, X0, GPR:$rs)>;
def : InstAlias<"pmsltz.b $rd, $rs", (PMSLT_B GPR:$rd, GPR:$rs, X0)>;
def : InstAlias<"pmsltz.h $rd, $rs", (PMSLT_H GPR:$rd, GPR:$rs, X0)>;
def : InstAlias<"pmsgtz.b $rd, $rs", (PMSLT_B GPR:$rd, X0, GPR:$rs)>;
def : InstAlias<"pmsgtz.h $rd, $rs", (PMSLT_H GPR:$rd, X0, GPR:$rs)>;
// The canonical pmslt(u) form will always be printed. Therefore,
// set a zero weight.
def : InstAlias<"pmsgt.b $rd, $rs, $rt", (PMSLT_B GPR:$rd, GPR:$rt, GPR:$rs), 0>;
def : InstAlias<"pmsgt.h $rd, $rs, $rt", (PMSLT_H GPR:$rd, GPR:$rt, GPR:$rs), 0>;
def : InstAlias<"pmsgtu.b $rd, $rs, $rt", (PMSLTU_B GPR:$rd, GPR:$rt, GPR:$rs), 0>;
def : InstAlias<"pmsgtu.h $rd, $rs, $rt", (PMSLTU_H GPR:$rd, GPR:$rt, GPR:$rs), 0>;
let append Predicates = [IsRV32] in {
def : InstAlias<"mseqz $rd, $rs", (MSEQ GPR:$rd, GPR:$rs, X0)>;
def : InstAlias<"msnez $rd, $rs", (MSLTU GPR:$rd, X0, GPR:$rs)>;
def : InstAlias<"msltz $rd, $rs", (MSLT GPR:$rd, GPR:$rs, X0)>;
def : InstAlias<"msgtz $rd, $rs", (MSLT GPR:$rd, X0, GPR:$rs)>;
// The canonical mslt(u) form will always be printed. Therefore,
// set a zero weight.
def : InstAlias<"msgt $rd, $rs, $rt", (MSLT GPR:$rd, GPR:$rt, GPR:$rs), 0>;
def : InstAlias<"msgtu $rd, $rs, $rt", (MSLTU GPR:$rd, GPR:$rt, GPR:$rs), 0>;
} // append Predicates = [IsRV32]
let append Predicates = [IsRV64] in {
def : InstAlias<"pmv.ws $rd, $rs", (PADD_WS GPR:$rd, X0, GPR:$rs)>;
def : InstAlias<"pneg.w $rd, $rs", (PSUB_W GPR:$rd, X0, GPR:$rs)>;
def : InstAlias<"pzext.w.h $rd, $rs", (PPAIRE_H GPR:$rd, GPR:$rs, X0)>;
def : InstAlias<"pmseqz.w $rd, $rs", (PMSEQ_W GPR:$rd, GPR:$rs, X0)>;
def : InstAlias<"pmsnez.w $rd, $rs", (PMSLTU_W GPR:$rd, X0, GPR:$rs)>;
def : InstAlias<"pmsltz.w $rd, $rs", (PMSLT_W GPR:$rd, GPR:$rs, X0)>;
def : InstAlias<"pmsgtz.w $rd, $rs", (PMSLT_W GPR:$rd, X0, GPR:$rs)>;
// The canonical pmslt(u) form will always be printed. Therefore,
// set a zero weight.
def : InstAlias<"pmsgt.w $rd, $rs, $rt", (PMSLT_W GPR:$rd, GPR:$rt, GPR:$rs), 0>;
def : InstAlias<"pmsgtu.w $rd, $rs, $rt", (PMSLTU_W GPR:$rd, GPR:$rt, GPR:$rs), 0>;
def : InstAlias<"pwcvtu.wb $rd, $rs", (ZIP8P GPR:$rd, GPR:$rs, X0)>;
def : InstAlias<"pwcvtu.wh $rd, $rs", (ZIP16P GPR:$rd, GPR:$rs, X0)>;
def : InstAlias<"pwcvth.wb $rd, $rs", (ZIP8P GPR:$rd, X0, GPR:$rs)>;
def : InstAlias<"pwcvth.wh $rd, $rs", (ZIP16P GPR:$rd, X0, GPR:$rs)>;
def : InstAlias<"pncvt.wb $rd, $rs", (UNZIP8P GPR:$rd, GPR:$rs, X0)>;
def : InstAlias<"pncvt.wh $rd, $rs", (UNZIP16P GPR:$rd, GPR:$rs, X0)>;
def : InstAlias<"pncvth.wb $rd, $rs", (UNZIP8HP GPR:$rd, GPR:$rs, X0)>;
def : InstAlias<"pncvth.wh $rd, $rs", (UNZIP16HP GPR:$rd, GPR:$rs, X0)>;
} // append Predicates = [IsRV64]
let append Predicates = [IsRV32] in {
def : InstAlias<"pmv.dbs $rd, $rs",
(PADD_DBS GPRPairRV32:$rd, X0_Pair, GPR:$rs)>;
def : InstAlias<"pmv.dhs $rd, $rs",
(PADD_DHS GPRPairRV32:$rd, X0_Pair, GPR:$rs)>;
def : InstAlias<"pmv.dws $rd, $rs",
(PADD_DWS GPRPairRV32:$rd, X0_Pair, GPR:$rs)>;
def : InstAlias<"pneg.db $rd, $rs",
(PSUB_DB GPRPairRV32:$rd, X0_Pair, GPRPairRV32:$rs)>;
def : InstAlias<"pneg.dh $rd, $rs",
(PSUB_DH GPRPairRV32:$rd, X0_Pair, GPRPairRV32:$rs)>;
def : InstAlias<"pneg.dw $rd, $rs",
(PSUB_DW GPRPairRV32:$rd, X0_Pair, GPRPairRV32:$rs)>;
def : InstAlias<"negd $rd, $rs",
(SUBD GPRPairRV32:$rd, X0_Pair, GPRPairRV32:$rs)>;
def : InstAlias<"pabs.db $rd, $rs",
(PABD_DB GPRPairRV32:$rd, GPRPairRV32:$rs, X0_Pair)>;
def : InstAlias<"pabs.dh $rd, $rs",
(PABD_DH GPRPairRV32:$rd, GPRPairRV32:$rs, X0_Pair)>;
// No pabd.dw instruction
def : InstAlias<"pzext.dh.b $rd, $rs",
(PPAIRE_DB GPRPairRV32:$rd, GPRPairRV32:$rs, X0_Pair)>;
def : InstAlias<"pzext.dw.h $rd, $rs",
(PPAIRE_DH GPRPairRV32:$rd, GPRPairRV32:$rs, X0_Pair)>;
def : InstAlias<"pmseqz.db $rd, $rs",
(PMSEQ_DB GPRPairRV32:$rd, GPRPairRV32:$rs, X0_Pair)>;
def : InstAlias<"pmseqz.dh $rd, $rs",
(PMSEQ_DH GPRPairRV32:$rd, GPRPairRV32:$rs, X0_Pair)>;
def : InstAlias<"pmseqz.dw $rd, $rs",
(PMSEQ_DW GPRPairRV32:$rd, GPRPairRV32:$rs, X0_Pair)>;
def : InstAlias<"pmsnez.db $rd, $rs",
(PMSLTU_DB GPRPairRV32:$rd, X0_Pair, GPRPairRV32:$rs)>;
def : InstAlias<"pmsnez.dh $rd, $rs",
(PMSLTU_DH GPRPairRV32:$rd, X0_Pair, GPRPairRV32:$rs)>;
def : InstAlias<"pmsnez.dw $rd, $rs",
(PMSLTU_DW GPRPairRV32:$rd, X0_Pair, GPRPairRV32:$rs)>;
def : InstAlias<"pmsltz.db $rd, $rs",
(PMSLT_DB GPRPairRV32:$rd, GPRPairRV32:$rs, X0_Pair)>;
def : InstAlias<"pmsltz.dh $rd, $rs",
(PMSLT_DH GPRPairRV32:$rd, GPRPairRV32:$rs, X0_Pair)>;
def : InstAlias<"pmsltz.dw $rd, $rs",
(PMSLT_DW GPRPairRV32:$rd, GPRPairRV32:$rs, X0_Pair)>;
def : InstAlias<"pmsgtz.db $rd, $rs",
(PMSLT_DB GPRPairRV32:$rd, X0_Pair, GPRPairRV32:$rs)>;
def : InstAlias<"pmsgtz.dh $rd, $rs",
(PMSLT_DH GPRPairRV32:$rd, X0_Pair, GPRPairRV32:$rs)>;
def : InstAlias<"pmsgtz.dw $rd, $rs",
(PMSLT_DW GPRPairRV32:$rd, X0_Pair, GPRPairRV32:$rs)>;
// The canonical pmslt(u) form will always be printed. Therefore,
// set a zero weight.
def : InstAlias<"pmsgt.db $rd, $rs, $rt",
(PMSLT_DB GPRPairRV32:$rd, GPRPairRV32:$rt, GPRPairRV32:$rs), 0>;
def : InstAlias<"pmsgt.dh $rd, $rs, $rt",
(PMSLT_DH GPRPairRV32:$rd, GPRPairRV32:$rt, GPRPairRV32:$rs), 0>;
def : InstAlias<"pmsgt.dw $rd, $rs, $rt",
(PMSLT_DW GPRPairRV32:$rd, GPRPairRV32:$rt, GPRPairRV32:$rs), 0>;
def : InstAlias<"pmsgtu.db $rd, $rs, $rt",
(PMSLTU_DB GPRPairRV32:$rd, GPRPairRV32:$rt, GPRPairRV32:$rs), 0>;
def : InstAlias<"pmsgtu.dh $rd, $rs, $rt",
(PMSLTU_DH GPRPairRV32:$rd, GPRPairRV32:$rt, GPRPairRV32:$rs), 0>;
def : InstAlias<"pmsgtu.dw $rd, $rs, $rt",
(PMSLTU_DW GPRPairRV32:$rd, GPRPairRV32:$rt, GPRPairRV32:$rs), 0>;
def : InstAlias<"pwcvt.b $rd, $rs", (PWADD_B GPRPairRV32:$rd, GPR:$rs, X0)>;
def : InstAlias<"pwcvt.h $rd, $rs", (PWADD_H GPRPairRV32:$rd, GPR:$rs, X0)>;
def : InstAlias<"pwcvtu.b $rd, $rs", (WZIP8P GPRPairRV32:$rd, GPR:$rs, X0)>;
def : InstAlias<"pwcvtu.h $rd, $rs", (WZIP16P GPRPairRV32:$rd, GPR:$rs, X0)>;
def : InstAlias<"pwcvth.b $rd, $rs", (WZIP8P GPRPairRV32:$rd, X0, GPR:$rs)>;
def : InstAlias<"pwcvth.h $rd, $rs", (WZIP16P GPRPairRV32:$rd, X0, GPR:$rs)>;
def : InstAlias<"pncvt.b $rd, $rs", (PNSRLI_B GPR:$rd, GPRPairRV32:$rs, 0)>;
def : InstAlias<"pncvt.h $rd, $rs", (PNSRLI_H GPR:$rd, GPRPairRV32:$rs, 0)>;
def : InstAlias<"pncvth.b $rd, $rs", (PNSRLI_B GPR:$rd, GPRPairRV32:$rs, 8)>;
def : InstAlias<"pncvth.h $rd, $rs", (PNSRLI_H GPR:$rd, GPRPairRV32:$rs, 16)>;
def : InstAlias<"mvd $rd, $rs", (PADD_DW GPRPairRV32:$rd, X0_Pair, GPRPairRV32:$rs)>;
} // append Predicates = [IsRV32]
} // Predicates = [HasStdExtP]
//===----------------------------------------------------------------------===//
// Codegen patterns
//===----------------------------------------------------------------------===//
class PatGprSplatGpr<SDPatternOperator OpNode, RVInst Inst, ValueType VecVT,
ValueType ScalarVT = XLenVT>
: Pat<(VecVT (OpNode GPR:$rs1, (splat_vector (ScalarVT GPR:$rs2)))),
(Inst GPR:$rs1, GPR:$rs2)>;
// Similar to PatGprShiftMask, but without the mask. Shift amount is a scalar.
class PatGprShift<SDPatternOperator OpNode, RVInst Inst, ValueType VecVT,
ValueType ScalarVT = XLenVT>
: Pat<(VecVT (OpNode (VecVT GPR:$rs1), (ScalarVT GPR:$rs2))),
(Inst GPR:$rs1, GPR:$rs2)>;
// Pattern classes for GPRPair operations
class PatGprPairGprPair<SDPatternOperator OpNode, RVInst Inst, ValueType vt>
: Pat<(vt (OpNode (vt GPRPair:$rs1), (vt GPRPair:$rs2))),
(Inst GPRPair:$rs1, GPRPair:$rs2)>;
// Reduction sum. PatRedSum is the single-GPR source (predsum.bs/hs/ws), result
// XLenVT; PatRedSumPair is the RV32 paired source (predsum.dbs/dhs), result i32.
// Target-illegal results (i32 accumulator on RV64, i64 on RV32) don't reach
// isel and are split in ReplaceNodeResults.
class PatRedSum<SDPatternOperator OpNode, RVInst Inst, ValueType VecVT>
: Pat<(XLenVT (OpNode (VecVT GPR:$rs1), (XLenVT GPR:$rs2))),
(Inst GPR:$rs1, GPR:$rs2)>;
class PatRedSumPair<SDPatternOperator OpNode, RVInst Inst, ValueType VecVT>
: Pat<(i32 (OpNode (VecVT GPRPair:$rs1), (i32 GPR:$rs2))),
(Inst GPRPair:$rs1, GPR:$rs2)>;
class PatGprPairImm<SDPatternOperator OpNode, RVInst Inst,
SDPatternOperator ImmType, ValueType vt>
: Pat<(vt (OpNode (vt GPRPair:$rs1), ImmType:$imm)),
(Inst GPRPair:$rs1, ImmType:$imm)>;
class PatGprPairShiftMask<SDPatternOperator OpNode, RVInst Inst,
ComplexPattern ShiftMask, ValueType vt>
: Pat<(vt (OpNode GPRPair:$rs1, ShiftMask:$rs2)),
(Inst GPRPair:$rs1, ShiftMask:$rs2)>;
class PatGprPairSplatGpr<SDPatternOperator OpNode, RVInst Inst, ValueType VecVT,
ValueType ScalarVT = XLenVT>
: Pat<(VecVT (OpNode GPRPair:$rs1, (splat_vector (ScalarVT GPR:$rs2)))),
(Inst GPRPair:$rs1, GPR:$rs2)>;
// Similar to PatGprPairShiftMask, but without the mask. Shift amount is a
// scalar.
class PatGprPairShift<SDPatternOperator OpNode, RVInst Inst, ValueType VecVT,
ValueType ScalarVT = XLenVT>
: Pat<(VecVT (OpNode (VecVT GPRPair:$rs1), (ScalarVT GPR:$rs2))),
(Inst GPRPair:$rs1, GPR:$rs2)>;
def riscv_absw : RVSDNode<"ABSW", SDT_RISCVIntUnaryOpW>;
def riscv_clsw : RVSDNode<"CLSW", SDT_RISCVIntUnaryOpW>;
def SDT_RISCVIntBinOpD : SDTypeProfile<2, 4, [SDTCisVT<0, i32>,
SDTCisVT<1, i32>,
SDTCisSameAs<0, 2>,
SDTCisSameAs<1, 3>,
SDTCisSameAs<0, 4>,
SDTCisSameAs<1, 5>]>;
def riscv_addd : RVSDNode<"ADDD", SDT_RISCVIntBinOpD,
[SDNPCommutative, SDNPAssociative]>;
def riscv_subd : RVSDNode<"SUBD", SDT_RISCVIntBinOpD>;
def SDT_RISCVWideningAddSubAccumulate : SDTypeProfile<2, 4, [SDTCisVT<0, i32>,
SDTCisVT<1, i32>,
SDTCisSameAs<0, 2>,
SDTCisSameAs<1, 3>,
SDTCisSameAs<0, 4>,
SDTCisSameAs<0, 5>]>;
// Widening add accumulate unsigned: rd = rd + zext(rs1) + zext(rs2)
def riscv_waddau : RVSDNode<"WADDAU", SDT_RISCVWideningAddSubAccumulate>;
// Widening sub accumulate unsigned: rd = rd + zext(rs1) - zext(rs2)
def riscv_wsubau : RVSDNode<"WSUBAU", SDT_RISCVWideningAddSubAccumulate>;
// Widening add accumulate signed: rd = rd + sext(rs1) + sext(rs2)
def riscv_wadda : RVSDNode<"WADDA", SDT_RISCVWideningAddSubAccumulate>;
// Widening sub accumulate signed: rd = rd + sext(rs1) - sext(rs2)
def riscv_wsuba : RVSDNode<"WSUBA", SDT_RISCVWideningAddSubAccumulate>;
def riscv_waddu : RVSDNode<"WADDU", SDTIntBinHiLoOp, [SDNPCommutative]>;
def riscv_wsubu : RVSDNode<"WSUBU", SDTIntBinHiLoOp>;
def riscv_wmulsu : RVSDNode<"WMULSU", SDTIntBinHiLoOp>;
def SDT_RISCVPackedWideningMul : SDTypeProfile<1, 2, [SDTCisVec<0>,
SDTCisSameAs<1, 2>,
SDTCisOpSmallerThanOp<1, 0>,
SDTCisSameNumEltsAs<0, 1>]>;
def riscv_pwmul : RVSDNode<"PWMUL", SDT_RISCVPackedWideningMul, [SDNPCommutative]>;
def riscv_pwmulu : RVSDNode<"PWMULU", SDT_RISCVPackedWideningMul, [SDNPCommutative]>;
def riscv_pwmulsu : RVSDNode<"PWMULSU", SDT_RISCVPackedWideningMul>;
def SDT_RISCVWideningShiftLeft : SDTypeProfile<2, 2, [SDTCisVT<0, i32>,
SDTCisSameAs<0, 1>,
SDTCisSameAs<0, 2>,
SDTCisSameAs<0, 3>]>;
def riscv_wsll : RVSDNode<"WSLL", SDT_RISCVWideningShiftLeft>;
def riscv_wsla : RVSDNode<"WSLA", SDT_RISCVWideningShiftLeft>;
// Narrowing shift: res = nsrl(lo, hi, shamt) is equivalent to
// res = truncate (srl (build_pair lo, hi), shamt), XLenVT
def SDT_RISCVNarrowingShift : SDTypeProfile<1, 3, [SDTCisVT<0, i32>,
SDTCisSameAs<0, 1>,
SDTCisSameAs<0, 2>,
SDTCisSameAs<0, 3>]>;
def riscv_nsrl : RVSDNode<"NSRL", SDT_RISCVNarrowingShift>;
def riscv_nsra : RVSDNode<"NSRA", SDT_RISCVNarrowingShift>;
// ComplexPattern for 64-bit shift mask (NSRL/NSRA only read 6 bits).
def shiftMask64 : ComplexPattern<XLenVT, 1, "selectShiftMask<64>", [], [], 0>;
def shiftMask8 : ComplexPattern<XLenVT, 1, "selectShiftMask<8>", [], [], 0>;
def shiftMask16 : ComplexPattern<XLenVT, 1, "selectShiftMask<16>", [], [], 0>;
// Build a GPRPair from two GPR registers for narrowing shift instructions.
def BuildGPRPair : OutPatFrag<(ops node:$lo, node:$hi),
(REG_SEQUENCE GPRPair, $lo, sub_gpr_even, $hi, sub_gpr_odd)>;
// Averaging subtraction, (a - b) >> 2
def riscv_asub : RVSDNode<"ASUB", SDTIntBinOp>;
def riscv_asubu : RVSDNode<"ASUBU", SDTIntBinOp>;
// MULH/MULHU/MULHSU with rounding.
def riscv_mulhr : RVSDNode<"MULHR", SDTIntBinOp>;
def riscv_mulhru : RVSDNode<"MULHRU", SDTIntBinOp>;
def riscv_mulhrsu : RVSDNode<"MULHRSU", SDTIntBinOp>;
def SDT_RISCVPackedShift : SDTypeProfile<1, 2, [SDTCisVec<0>,
SDTCisSameAs<0, 1>,
SDTCisVT<2, XLenVT>]>;
def riscv_pshl : RVSDNode<"PSHL", SDT_RISCVPackedShift>;
def riscv_psrl : RVSDNode<"PSRL", SDT_RISCVPackedShift>;
def riscv_psra : RVSDNode<"PSRA", SDT_RISCVPackedShift>;
def riscv_pssha : RVSDNode<"PSSHA", SDT_RISCVPackedShift>;
// The immediate for these is the number of trailing ones in the max value.
def riscv_sati : RVSDNode<"SATI", SDTIntBinOp>;
def riscv_usati : RVSDNode<"USATI", SDTIntBinOp>;
// Bitwise merge: res = (~op0 & op1) | (op0 & op2)
def SDT_RISCVMERGE : SDTypeProfile<1, 3, [SDTCisInt<0>,
SDTCisSameAs<0, 1>,
SDTCisSameAs<0, 2>,
SDTCisSameAs<0, 3>]>;
def riscv_merge : RVSDNode<"MERGE", SDT_RISCVMERGE>;
// (rdlo, rdhi) PPAIRE_DB (rs1plo, rs1phi, rs2plo, rs2phi)
def SDT_RISCVPPairE_DB : SDTypeProfile<2, 4, [SDTCisVT<0, v4i8>,
SDTCisSameAs<0, 1>,
SDTCisSameAs<0, 2>,
SDTCisSameAs<0, 3>,
SDTCisSameAs<0, 4>,
SDTCisSameAs<0, 5>]>;
def riscv_ppaire_db : RVSDNode<"PPAIRE_DB", SDT_RISCVPPairE_DB>;
// Add one to the immediate. Used by RISCVISD::SATI.
def IncImm : SDNodeXForm<imm, [{
return CurDAG->getTargetConstant(N->getZExtValue() + 1, SDLoc(N),
N->getValueType(0));
}]>;
def SDT_RISCVBuildPairGPRVec : SDTypeProfile<1, 2, [SDTCisVec<0>,
SDTCisVT<1, i32>,
SDTCisSameAs<1, 2>]>;
def SDT_RISCVSplitGPRVec : SDTypeProfile<2, 1, [SDTCisVT<0, i32>,
SDTCisSameAs<0, 1>,
SDTCisVec<2>]>;
// These nodes are used to handle 64-bit vector arguments and returns on RV32.
// One side is a pair of i32 GPRs, the other is a 64-bit vector.
// TOD: We might be able to use 32-bit vectors with concat_vectors/build_vector
// and extract_subvector/extract_vectorelt instead. Using custom nodes prevents
// 64-bit vector aithmetic operations in our lit tests from being split until
// we can tune some generic combines.
def RISCVBuildPairGPRVec : RVSDNode<"BuildPairGPRVec",
SDT_RISCVBuildPairGPRVec>;
def RISCVSplitGPRVec : RVSDNode<"SplitGPRVec", SDT_RISCVSplitGPRVec>;
// (rs1 << 1) + rs2
class PatPSh1Add<RVInst Inst, ValueType vt>
: Pat<(vt (add (riscv_pshl (vt GPR:$rs1), (XLenVT 1)), (vt GPR:$rs2))),
(Inst GPR:$rs1, GPR:$rs2)>;
class PatPSh1AddPair<RVInst Inst, ValueType vt>
: Pat<(vt (add (riscv_pshl (vt GPRPair:$rs1), (XLenVT 1)), (vt GPRPair:$rs2))),
(Inst GPRPair:$rs1, GPRPair:$rs2)>;
// Vector sshlsat is custom-lowered to riscv_pssha before isel; saddsat(a, a)
// is an equivalent shape via the signed sshlsat(a, 1) identity.
def saturating_shl1 : PatFrags<(ops node:$a),
[(riscv_pssha node:$a, (XLenVT 1)),
(saddsat node:$a, node:$a)]>;
class PatPSSh1SAdd<RVInst Inst, ValueType vt>
: Pat<(vt (saddsat (saturating_shl1 (vt GPR:$rs1)), (vt GPR:$rs2))),
(Inst GPR:$rs1, GPR:$rs2)>;
class PatPSSh1SAddPair<RVInst Inst, ValueType vt>
: Pat<(vt (saddsat (saturating_shl1 (vt GPRPair:$rs1)), (vt GPRPair:$rs2))),
(Inst GPRPair:$rs1, GPRPair:$rs2)>;
let Predicates = [HasStdExtP] in {
def : PatGpr<abs, ABS>;
def : PatGpr<ctls, CLS>;
def : Pat<(XLenVT (fshl GPR:$rd, GPR:$rs1, shiftMaskXLen:$rs2)),
(SLX GPR:$rd, GPR:$rs1, shiftMaskXLen:$rs2)>;
def : Pat<(XLenVT (fshr GPR:$rs1, GPR:$rd, shiftMaskXLen:$rs2)),
(SRX GPR:$rd, GPR:$rs1, shiftMaskXLen:$rs2)>;
// Pseudo version of MERGE without the tied constraint. Will be expanded to
// MERGE, MVM, or MVMN after register allocation.
// dst = (~rd & rs1) | (rd & rs2)
def PseudoMERGE : Pseudo<(outs GPR:$dst), (ins GPR:$rd, GPR:$rs1, GPR:$rs2),
[]>;
def : Pat<(XLenVT (or (and GPR:$rd, GPR:$rs2), (and (not GPR:$rd), GPR:$rs1))),
(PseudoMERGE GPR:$rd, GPR:$rs1, GPR:$rs2)>;
// Pattern for insert_vector_elt
def : Pat<(XLenVT (riscv_merge GPR:$rd, GPR:$rs1, GPR:$rs2)),
(PseudoMERGE GPR:$rd, GPR:$rs1, GPR:$rs2)>;
// Match a pattern of 2 bytes being inserted into bits [15:8] when only the
// upper 16 bits are being demanded.
def : Pat<(binop_allhusers<or> (shl GPR:$rs2, (XLenVT 8)),
zexti8:$rs1),
(PPAIRE_B zexti8:$rs1, GPR:$rs2)>;
// Basic 8-bit arithmetic patterns
def : PatGprGpr<add, PADD_B, XLenVecI8VT>;
def : PatGprGpr<sub, PSUB_B, XLenVecI8VT>;
def : PatGprSplatGpr<add, PADD_BS, XLenVecI8VT>;
// Basic 16-bit arithmetic patterns
def : PatGprGpr<add, PADD_H, XLenVecI16VT>;
def : PatGprGpr<sub, PSUB_H, XLenVecI16VT>;
def : PatGprSplatGpr<add, PADD_HS, XLenVecI16VT>;
// 8-bit bitwise operation patterns
def : PatGprGpr<and, AND, XLenVecI8VT>;
def : PatGprGpr<or, OR, XLenVecI8VT>;
def : PatGprGpr<xor, XOR, XLenVecI8VT>;
def : Pat<(XLenVecI8VT (vnot GPR:$rs1)), (XORI GPR:$rs1, -1)>;
// P implies Zbb so we can select ANDN/ORN/XNOR.
def : Pat<(XLenVecI8VT (and GPR:$rs1, (vnot GPR:$rs2))), (ANDN GPR:$rs1, GPR:$rs2)>;
def : Pat<(XLenVecI8VT (or GPR:$rs1, (vnot GPR:$rs2))), (ORN GPR:$rs1, GPR:$rs2)>;
def : Pat<(XLenVecI8VT (vnot (xor GPR:$rs1, GPR:$rs2))), (XNOR GPR:$rs1, GPR:$rs2)>;
// 16-bit bitwise operation patterns
def : PatGprGpr<and, AND, XLenVecI16VT>;
def : PatGprGpr<or, OR, XLenVecI16VT>;
def : PatGprGpr<xor, XOR, XLenVecI16VT>;
def : Pat<(XLenVecI16VT (vnot GPR:$rs1)), (XORI GPR:$rs1, -1)>;
// P implies Zbb so we can select ANDN/ORN/XNOR.
def : Pat<(XLenVecI16VT (and GPR:$rs1, (vnot GPR:$rs2))), (ANDN GPR:$rs1, GPR:$rs2)>;
def : Pat<(XLenVecI16VT (or GPR:$rs1, (vnot GPR:$rs2))), (ORN GPR:$rs1, GPR:$rs2)>;
def : Pat<(XLenVecI16VT (vnot (xor GPR:$rs1, GPR:$rs2))), (XNOR GPR:$rs1, GPR:$rs2)>;
// 8-bit saturating add/sub patterns
def : PatGprGpr<saddsat, PSADD_B, XLenVecI8VT>;
def : PatGprGpr<uaddsat, PSADDU_B, XLenVecI8VT>;
def : PatGprGpr<ssubsat, PSSUB_B, XLenVecI8VT>;
def : PatGprGpr<usubsat, PSSUBU_B, XLenVecI8VT>;
// 16-bit saturating add/sub patterns
def : PatGprGpr<saddsat, PSADD_H, XLenVecI16VT>;
def : PatGprGpr<uaddsat, PSADDU_H, XLenVecI16VT>;
def : PatGprGpr<ssubsat, PSSUB_H, XLenVecI16VT>;
def : PatGprGpr<usubsat, PSSUBU_H, XLenVecI16VT>;
// 16-bit shift-add patterns
def : PatPSh1Add<PSH1ADD_H, XLenVecI16VT>;
def : PatPSSh1SAdd<PSSH1SADD_H, XLenVecI16VT>;
// 16-bit exchanged add/sub patterns
def : PatGprGpr<int_riscv_pas, PAS_HX, XLenVecI16VT>;
def : PatGprGpr<int_riscv_psa, PSA_HX, XLenVecI16VT>;
def : PatGprGpr<int_riscv_psas, PSAS_HX, XLenVecI16VT>;
def : PatGprGpr<int_riscv_pssa, PSSA_HX, XLenVecI16VT>;
def : PatGprGpr<int_riscv_paas, PAAS_HX, XLenVecI16VT>;
def : PatGprGpr<int_riscv_pasa, PASA_HX, XLenVecI16VT>;
// 8-bit averaging patterns
def : PatGprGpr<avgfloors, PAADD_B, XLenVecI8VT>;
def : PatGprGpr<avgflooru, PAADDU_B, XLenVecI8VT>;
def : PatGprGpr<riscv_asub, PASUB_B, XLenVecI8VT>;
def : PatGprGpr<riscv_asubu, PASUBU_B, XLenVecI8VT>;
// 16-bit averaging patterns
def : PatGprGpr<avgfloors, PAADD_H, XLenVecI16VT>;
def : PatGprGpr<avgflooru, PAADDU_H, XLenVecI16VT>;
def : PatGprGpr<riscv_asub, PASUB_H, XLenVecI16VT>;
def : PatGprGpr<riscv_asubu, PASUBU_H, XLenVecI16VT>;
// 8-bit absolute difference patterns
def : Pat<(XLenVecI8VT (abs GPR:$rs1)), (PABD_B GPR:$rs1, (XLenVecI8VT X0))>;
def : PatGprGpr<abds, PABD_B, XLenVecI8VT>;
def : PatGprGpr<abdu, PABDU_B, XLenVecI8VT>;
// 16-bit absolute difference patterns
def : Pat<(XLenVecI16VT (abs GPR:$rs1)), (PABD_H GPR:$rs1, (XLenVecI16VT X0))>;
def : PatGprGpr<abds, PABD_H, XLenVecI16VT>;
def : PatGprGpr<abdu, PABDU_H, XLenVecI16VT>;
// 16-bit multiply high patterns
def : PatGprGpr<mulhs, PMULH_H, XLenVecI16VT>;
def : PatGprGpr<mulhu, PMULHU_H, XLenVecI16VT>;
def : PatGprGpr<riscv_mulhsu, PMULHSU_H, XLenVecI16VT>;
// 16-bit multiply high rounding patterns
def : PatGprGpr<riscv_mulhr, PMULHR_H, XLenVecI16VT>;
def : PatGprGpr<riscv_mulhru, PMULHRU_H, XLenVecI16VT>;
def : PatGprGpr<riscv_mulhrsu, PMULHRSU_H, XLenVecI16VT>;
// 8-bit logical shift left/right patterns
def : PatGprImm<riscv_pshl, PSLLI_B, uimm3, XLenVecI8VT>;
def : PatGprImm<riscv_psrl, PSRLI_B, uimm3, XLenVecI8VT>;
// 16-bit logical shift left/right patterns
def : PatGprImm<riscv_pshl, PSLLI_H, uimm4, XLenVecI16VT>;
def : PatGprImm<riscv_psrl, PSRLI_H, uimm4, XLenVecI16VT>;
// 8-bit arithmetic shift right patterns
def : PatGprImm<riscv_psra, PSRAI_B, uimm3, XLenVecI8VT>;
// 16-bit arithmetic shift right patterns
def : PatGprImm<riscv_psra, PSRAI_H, uimm4, XLenVecI16VT>;
// 16-bit signed saturation shift left patterns
def : PatGprImm<riscv_pssha, PSSLAI_H, uimm4, XLenVecI16VT>;
def : PatGprShift<riscv_pssha, PSSHA_HS, XLenVecI16VT>;
// 8-bit logical shift left/right
def : PatGprShiftMask<riscv_pshl, PSLL_BS, shiftMask8, XLenVecI8VT>;
def : PatGprShiftMask<riscv_psrl, PSRL_BS, shiftMask8, XLenVecI8VT>;
// 8-bit arithmetic shift left/right
def : PatGprShiftMask<riscv_psra, PSRA_BS, shiftMask8, XLenVecI8VT>;
// 16-bit logical shift left/right
def : PatGprShiftMask<riscv_pshl, PSLL_HS, shiftMask16, XLenVecI16VT>;
def : PatGprShiftMask<riscv_psrl, PSRL_HS, shiftMask16, XLenVecI16VT>;
// 16-bit arithmetic shift left/right
def : PatGprShiftMask<riscv_psra, PSRA_HS, shiftMask16, XLenVecI16VT>;
// // splat pattern
def : Pat<(XLenVecI8VT (splat_vector (XLenVT GPR:$rs2))),
(PADD_BS (XLenVecI8VT X0), GPR:$rs2)>;
def : Pat<(XLenVecI16VT (splat_vector (XLenVT GPR:$rs2))),
(PADD_HS (XLenVecI16VT X0), GPR:$rs2)>;
// 8/16-bit comparison patterns (result is all 1s or all 0s per element)
// a == b
def : PatGprGpr<seteq, PMSEQ_B, XLenVecI8VT>;
def : PatGprGpr<seteq, PMSEQ_H, XLenVecI16VT>;
// a < b
def : PatGprGpr<setlt, PMSLT_B, XLenVecI8VT>;
def : PatGprGpr<setult, PMSLTU_B, XLenVecI8VT>;
def : PatGprGpr<setlt, PMSLT_H, XLenVecI16VT>;
def : PatGprGpr<setult, PMSLTU_H, XLenVecI16VT>;
// 8/16-bit [s|u]min/[s|u]max patterns
def : PatGprGpr<smin, PMIN_B, XLenVecI8VT>;
def : PatGprGpr<umin, PMINU_B, XLenVecI8VT>;
def : PatGprGpr<smin, PMIN_H, XLenVecI16VT>;
def : PatGprGpr<umin, PMINU_H, XLenVecI16VT>;
def : PatGprGpr<smax, PMAX_B, XLenVecI8VT>;
def : PatGprGpr<umax, PMAXU_B, XLenVecI8VT>;
def : PatGprGpr<smax, PMAX_H, XLenVecI16VT>;
def : PatGprGpr<umax, PMAXU_H, XLenVecI16VT>;
// 8/16-bit vselect patterns
def : Pat<(XLenVecI8VT (vselect (XLenVecI8VT GPR:$mask), GPR:$true_v, GPR:$false_v)),
(MERGE GPR:$mask, GPR:$false_v, GPR:$true_v)>;
def : Pat<(XLenVecI16VT (vselect (XLenVecI16VT GPR:$mask), GPR:$true_v, GPR:$false_v)),
(MERGE GPR:$mask, GPR:$false_v, GPR:$true_v)>;
// 16-bit bswap patterns
def : Pat<(XLenVecI16VT (bswap GPR:$rs)),
(PPAIROE_B GPR:$rs, GPR:$rs)>;
let append Predicates = [IsRV32] in {
def : PatGpr<bitreverse, REV_RV32>;
def : Pat<(XLenVT (riscv_sati GPR:$rs1, timm:$imm)),
(SATI_RV32 GPR:$rs1, (IncImm timm:$imm))>;
def : Pat<(XLenVT (riscv_usati GPR:$rs1, timm:$imm)),
(USATI_RV32 GPR:$rs1, timm:$imm)>;
def : PatGprGpr<saddsat, SADD>;
def : PatGprGpr<ssubsat, SSUB>;
def : PatGprGpr<uaddsat, SADDU>;
def : PatGprGpr<usubsat, SSUBU>;
def : PatGprGpr<sshlsat, SSHA>;
def : PatGprGpr<ushlsat, SSHL>;
def : PatGprUimmLog2XLen<sshlsat, SSLAI>;
// No SSLLI
def : Pat<(XLenVT (saddsat (sshlsat GPR:$rs1, (XLenVT 1)), GPR:$rs2)),
(SSH1SADD GPR:$rs1, GPR:$rs2)>;
def : Pat<(XLenVT (saddsat (saddsat GPR:$rs1, GPR:$rs1), GPR:$rs2)),
(SSH1SADD GPR:$rs1, GPR:$rs2)>;
// 32-bit averaging patterns
def : PatGprGpr<avgfloors, AADD, i32>;
def : PatGprGpr<avgflooru, AADDU, i32>;
def : PatGprGpr<riscv_asub, ASUB, i32>;
def : PatGprGpr<riscv_asubu, ASUBU, i32>;
// 32-bit multiply high rounding patterns
def : PatGprGpr<riscv_mulhr, MULHR, i32>;
def : PatGprGpr<riscv_mulhru, MULHRU, i32>;
def : PatGprGpr<riscv_mulhrsu, MULHRSU, i32>;
// Halfword multiply patterns where one operand is a sext.h or zext.h and
// the other is a sext.h or zext.h or is known to be sign/zero-extended. We
// prefer plain mul when both operands are known to be sign/zero-extended.
def : Pat<(i32 (mul sexti16:$rs1, (sext_inreg GPR:$rs2, i16))),
(MUL_H00 sexti16:$rs1, GPR:$rs2)>;
def : Pat<(i32 (mul zexti16:$rs1, (and GPR:$rs2, 0xffff))),
(MULU_H00 zexti16:$rs1, GPR:$rs2)>;
def : Pat<(i32 (mul sexti16:$rs1, (and GPR:$rs2, 0xffff))),
(MULSU_H00 sexti16:$rs1, GPR:$rs2)>;
def : Pat<(i32 (mul (sext_inreg GPR:$rs1, i16), zexti16:$rs2)),
(MULSU_H00 GPR:$rs1, zexti16:$rs2)>;
def : Pat<(i32 (add GPR:$rd, (mul_oneuse sexti16:$rs1, sexti16:$rs2))),
(MACC_H00 GPR:$rd, sexti16:$rs1, sexti16:$rs2)>;
def : Pat<(i32 (add GPR:$rd, (mul_oneuse zexti16:$rs1, zexti16:$rs2))),
(MACCU_H00 GPR:$rd, zexti16:$rs1, zexti16:$rs2)>;
def : Pat<(i32 (add GPR:$rd, (mul_oneuse sexti16:$rs1, zexti16:$rs2))),
(MACCSU_H00 GPR:$rd, sexti16:$rs1, zexti16:$rs2)>;
def : Pat<(i32 (add GPR:$rd, (binop_oneuse<mulhs> GPR:$rs1, GPR:$rs2))),
(MHACC GPR:$rd, GPR:$rs1, GPR:$rs2)>;
def : Pat<(i32 (add GPR:$rd, (binop_oneuse<mulhu> GPR:$rs1, GPR:$rs2))),
(MHACCU GPR:$rd, GPR:$rs1, GPR:$rs2)>;
def : Pat<(i32 (add GPR:$rd, (binop_oneuse<riscv_mulhsu> GPR:$rs1, GPR:$rs2))),
(MHACCSU GPR:$rd, GPR:$rs1, GPR:$rs2)>;
// Narrowing shift patterns (NSRL/NSRA)
// Immediate shift amount patterns
def : Pat<(riscv_nsrl GPR:$lo, GPR:$hi, uimm6:$shamt),
(NSRLI (BuildGPRPair GPR:$lo, GPR:$hi), uimm6:$shamt)>;
def : Pat<(riscv_nsra GPR:$lo, GPR:$hi, uimm6:$shamt),
(NSRAI (BuildGPRPair GPR:$lo, GPR:$hi), uimm6:$shamt)>;
// Register shift amount patterns
def : Pat<(riscv_nsrl GPR:$lo, GPR:$hi, shiftMask64:$shamt),
(NSRL (BuildGPRPair GPR:$lo, GPR:$hi), shiftMask64:$shamt)>;
def : Pat<(riscv_nsra GPR:$lo, GPR:$hi, shiftMask64:$shamt),
(NSRA (BuildGPRPair GPR:$lo, GPR:$hi), shiftMask64:$shamt)>;
// Match a pattern of 2 bytes being inserted into bits [31:16], with bits
// bits [15:0] coming from a zero extended value. We can use pack with
// ppaire.b for bits [31:16]. If bits [15:0] can also be a ppaire.b, it can be
// matched separately.
def : Pat<(i32 (or (or (shl GPR:$op1rs2, (XLenVT 24)),
(shl zexti8:$op1rs1, (XLenVT 16))),
zexti16:$rs1)),
(PACK zexti16:$rs1,
(XLenVT (PPAIRE_B zexti8:$op1rs1, GPR:$op1rs2)))>;
// Packed widening multiply patterns.
// The v2i32 patterns are not needed yet.
def : Pat<(v4i16 (riscv_pwmul (v4i8 GPR:$rs1), (v4i8 GPR:$rs2))),
(PWMUL_B GPR:$rs1, GPR:$rs2)>;
def : Pat<(v2i32 (riscv_pwmul (v2i16 GPR:$rs1), (v2i16 GPR:$rs2))),
(PWMUL_H GPR:$rs1, GPR:$rs2)>;
def : Pat<(v4i16 (riscv_pwmulu (v4i8 GPR:$rs1), (v4i8 GPR:$rs2))),
(PWMULU_B GPR:$rs1, GPR:$rs2)>;
//def : Pat<(v2i32 (riscv_pwmulu (v2i16 GPR:$rs1), (v2i16 GPR:$rs2))),
// (PWMULU_H GPR:$rs1, GPR:$rs2)>;
def : Pat<(v4i16 (riscv_pwmulsu (v4i8 GPR:$rs1), (v4i8 GPR:$rs2))),
(PWMULSU_B GPR:$rs1, GPR:$rs2)>;
//def : Pat<(v2i32 (riscv_pwmulsu (v2i16 GPR:$rs1), (v2i16 GPR:$rs2))),
// (PWMULSU_H GPR:$rs1, GPR:$rs2)>;
// 8/16-bit bitreverse patterns
// FIXME: Use BREV8 with Zbkb.
def : Pat<(v4i8 (bitreverse GPR:$rs)),
(REV8_RV32 (REV_RV32 GPR:$rs))>;
def : Pat<(v2i16 (bitreverse GPR:$rs)),
(PPAIROE_H (REV_RV32 GPR:$rs), (REV_RV32 GPR:$rs))>;
// Load/Store patterns
def : StPat<store, SW, GPR, v4i8>;
def : StPat<store, SW, GPR, v2i16>;
def : LdPat<load, LW, v4i8>;
def : LdPat<load, LW, v2i16>;
// Zero-extend patterns using wzip*p with zero
def : Pat<(v4i16 (zext (v4i8 GPR:$rs))), (WZIP8P GPR:$rs, (v4i8 X0))>;
def : Pat<(v2i32 (zext (v2i16 GPR:$rs))), (WZIP16P GPR:$rs, (v2i16 X0))>;
// Sign-extend patterns using pwadd with zero
def : Pat<(v4i16 (sext (v4i8 GPR:$rs))), (PWADD_B GPR:$rs, (v4i8 X0))>;
def : Pat<(v2i32 (sext (v2i16 GPR:$rs))), (PWADD_H GPR:$rs, (v2i16 X0))>;
// Build vector patterns
def : Pat<(v2i16 (build_vector (XLenVT GPR:$a), (XLenVT GPR:$b))),
(PACK GPR:$a, GPR:$b)>;
// Truncate patterns using pnsrli.
// FIXME: Support general shift+trunc
def : Pat<(v4i8 (trunc (v4i16 GPRPair:$rs))), (PNSRLI_B GPRPair:$rs, 0)>;
def : Pat<(v2i16 (trunc (v2i32 GPRPair:$rs))), (PNSRLI_H GPRPair:$rs, 0)>;
def : Pat<(v4i8 (trunc (v4i16 (riscv_psrl GPRPair:$rs1, uimm4:$imm)))),
(PNSRLI_B GPRPair:$rs1, uimm4:$imm)>;
def : Pat<(v2i16 (trunc (v2i32 (riscv_psrl GPRPair:$rs1, uimm5:$imm)))),
(PNSRLI_H GPRPair:$rs1, uimm5:$imm)>;
def : Pat<(v4i8 (trunc (v4i16 (riscv_psra GPRPair:$rs1, uimm4:$imm)))),
(PNSRAI_B GPRPair:$rs1, uimm4:$imm)>;
def : Pat<(v2i16 (trunc (v2i32 (riscv_psra GPRPair:$rs1, uimm5:$imm)))),
(PNSRAI_H GPRPair:$rs1, uimm5:$imm)>;
def : Pat<(v4i8 (trunc (v4i16 (riscv_psrl GPRPair:$rs1, shiftMask16:$rs2)))),
(PNSRL_BS GPRPair:$rs1, shiftMask16:$rs2)>;
def : Pat<(v2i16 (trunc (v2i32 (riscv_psrl GPRPair:$rs1, shiftMask32:$rs2)))),
(PNSRL_HS GPRPair:$rs1, shiftMask32:$rs2)>;
def : Pat<(v4i8 (trunc (v4i16 (riscv_psra GPRPair:$rs1, shiftMask16:$rs2)))),
(PNSRA_BS GPRPair:$rs1, shiftMask16:$rs2)>;
def : Pat<(v2i16 (trunc (v2i32 (riscv_psra GPRPair:$rs1, shiftMask32:$rs2)))),
(PNSRA_HS GPRPair:$rs1, shiftMask32:$rs2)>;
// Basic 8-bit arithmetic patterns
def : PatGprPairGprPair<add, PADD_DB, v8i8>;
def : PatGprPairGprPair<sub, PSUB_DB, v8i8>;
def : PatGprPairSplatGpr<add, PADD_DBS, v8i8>;
// Basic 16-bit arithmetic patterns
def : PatGprPairGprPair<add, PADD_DH, v4i16>;
def : PatGprPairGprPair<sub, PSUB_DH, v4i16>;
def : PatGprPairSplatGpr<add, PADD_DHS, v4i16>;
// Basic 32-bit arithmetic patterns
def : PatGprPairGprPair<add, PADD_DW, v2i32>;
def : PatGprPairGprPair<sub, PSUB_DW, v2i32>;
def : PatGprPairSplatGpr<add, PADD_DWS, v2i32>;
// 8-bit saturating add/sub patterns
def : PatGprPairGprPair<saddsat, PSADD_DB, v8i8>;
def : PatGprPairGprPair<uaddsat, PSADDU_DB, v8i8>;
def : PatGprPairGprPair<ssubsat, PSSUB_DB, v8i8>;
def : PatGprPairGprPair<usubsat, PSSUBU_DB, v8i8>;
// 16-bit saturating add/sub patterns
def : PatGprPairGprPair<saddsat, PSADD_DH, v4i16>;
def : PatGprPairGprPair<uaddsat, PSADDU_DH, v4i16>;
def : PatGprPairGprPair<ssubsat, PSSUB_DH, v4i16>;
def : PatGprPairGprPair<usubsat, PSSUBU_DH, v4i16>;
// 32-bit saturating add/sub patterns
def : PatGprPairGprPair<saddsat, PSADD_DW, v2i32>;
def : PatGprPairGprPair<uaddsat, PSADDU_DW, v2i32>;
def : PatGprPairGprPair<ssubsat, PSSUB_DW, v2i32>;
def : PatGprPairGprPair<usubsat, PSSUBU_DW, v2i32>;
// 16-bit shift-add patterns
def : PatPSh1AddPair<PSH1ADD_DH, v4i16>;
def : PatPSSh1SAddPair<PSSH1SADD_DH, v4i16>;
// 32-bit shift-add patterns
def : PatPSh1AddPair<PSH1ADD_DW, v2i32>;
def : PatPSSh1SAddPair<PSSH1SADD_DW, v2i32>;
// 16-bit exchanged add/sub patterns
def : PatGprPairGprPair<int_riscv_pas, PAS_DHX, v4i16>;
def : PatGprPairGprPair<int_riscv_psa, PSA_DHX, v4i16>;
def : PatGprPairGprPair<int_riscv_psas, PSAS_DHX, v4i16>;
def : PatGprPairGprPair<int_riscv_pssa, PSSA_DHX, v4i16>;
def : PatGprPairGprPair<int_riscv_paas, PAAS_DHX, v4i16>;
def : PatGprPairGprPair<int_riscv_pasa, PASA_DHX, v4i16>;
// 8-bit averaging patterns
def : PatGprPairGprPair<avgfloors, PAADD_DB, v8i8>;
def : PatGprPairGprPair<avgflooru, PAADDU_DB, v8i8>;
def : PatGprPairGprPair<riscv_asub, PASUB_DB, v8i8>;
def : PatGprPairGprPair<riscv_asubu, PASUBU_DB, v8i8>;
// 16-bit averaging patterns
def : PatGprPairGprPair<avgfloors, PAADD_DH, v4i16>;
def : PatGprPairGprPair<avgflooru, PAADDU_DH, v4i16>;
def : PatGprPairGprPair<riscv_asub, PASUB_DH, v4i16>;
def : PatGprPairGprPair<riscv_asubu, PASUBU_DH, v4i16>;
// 32-bit averaging patterns
def : PatGprPairGprPair<avgfloors, PAADD_DW, v2i32>;
def : PatGprPairGprPair<avgflooru, PAADDU_DW, v2i32>;
def : PatGprPairGprPair<riscv_asub, PASUB_DW, v2i32>;
def : PatGprPairGprPair<riscv_asubu, PASUBU_DW, v2i32>;
// 8-bit absolute difference patterns
def : Pat<(v8i8 (abs GPRPair:$rs1)), (PABD_DB GPRPair:$rs1, (v8i8 X0_Pair))>;
def : PatGprPairGprPair<abds, PABD_DB, v8i8>;
def : PatGprPairGprPair<abdu, PABDU_DB, v8i8>;
// 16-bit absolute difference patterns
def : Pat<(v4i16 (abs GPRPair:$rs1)), (PABD_DH GPRPair:$rs1, (v4i16 X0_Pair))>;
def : PatGprPairGprPair<abds, PABD_DH, v4i16>;
def : PatGprPairGprPair<abdu, PABDU_DH, v4i16>;
// 8-bit logical shift left/right patterns
def : PatGprPairImm<riscv_pshl, PSLLI_DB, uimm3, v8i8>;
def : PatGprPairImm<riscv_psrl, PSRLI_DB, uimm3, v8i8>;
// 16-bit logical shift left/right patterns
def : PatGprPairImm<riscv_pshl, PSLLI_DH, uimm4, v4i16>;
def : PatGprPairImm<riscv_psrl, PSRLI_DH, uimm4, v4i16>;
// 32-bit logical shift left/right patterns
def : PatGprPairImm<riscv_pshl, PSLLI_DW, uimm5, v2i32>;
def : PatGprPairImm<riscv_psrl, PSRLI_DW, uimm5, v2i32>;
// 8-bit arithmetic shift right patterns
def : PatGprPairImm<riscv_psra, PSRAI_DB, uimm3, v8i8>;
// 16-bit arithmetic shift right patterns
def : PatGprPairImm<riscv_psra, PSRAI_DH, uimm4, v4i16>;
// 32-bit arithmetic shift left/right patterns
def : PatGprPairImm<riscv_psra, PSRAI_DW, uimm5, v2i32>;
// 16-bit signed saturation shift left patterns
def : PatGprPairImm<riscv_pssha, PSSLAI_DH, uimm4, v4i16>;
def : PatGprPairShift<riscv_pssha, PSSHA_DHS, v4i16>;
// 32-bit signed saturation shift left patterns
def : PatGprPairImm<riscv_pssha, PSSLAI_DW, uimm5, v2i32>;
def : PatGprPairShift<riscv_pssha, PSSHA_DWS, v2i32>;
// 8-bit logical shift left/right
def : PatGprPairShiftMask<riscv_pshl, PSLL_DBS, shiftMask8, v8i8>;
def : PatGprPairShiftMask<riscv_psrl, PSRL_DBS, shiftMask8, v8i8>;
// 8-bit arithmetic shift left/right
def : PatGprPairShiftMask<riscv_psra, PSRA_DBS, shiftMask8, v8i8>;
// 16-bit logical shift left/right
def : PatGprPairShiftMask<riscv_pshl, PSLL_DHS, shiftMask16, v4i16>;
def : PatGprPairShiftMask<riscv_psrl, PSRL_DHS, shiftMask16, v4i16>;
// 16-bit arithmetic shift left/right
def : PatGprPairShiftMask<riscv_psra, PSRA_DHS, shiftMask16, v4i16>;
// 32-bit logical shift left/right
def : PatGprPairShiftMask<riscv_pshl, PSLL_DWS, shiftMask32, v2i32>;
def : PatGprPairShiftMask<riscv_psrl, PSRL_DWS, shiftMask32, v2i32>;
// 32-bit arithmetic shift left/right
def : PatGprPairShiftMask<riscv_psra, PSRA_DWS, shiftMask32, v2i32>;
// 8/16/32-bit comparison patterns (result is all 1s or all 0s per element)
// a == b
def : PatGprPairGprPair<seteq, PMSEQ_DB, v8i8>;
def : PatGprPairGprPair<seteq, PMSEQ_DH, v4i16>;
def : PatGprPairGprPair<seteq, PMSEQ_DW, v2i32>;
// a < b
def : PatGprPairGprPair<setlt, PMSLT_DB, v8i8>;
def : PatGprPairGprPair<setlt, PMSLT_DH, v4i16>;
def : PatGprPairGprPair<setlt, PMSLT_DW, v2i32>;
def : PatGprPairGprPair<setult, PMSLTU_DB, v8i8>;
def : PatGprPairGprPair<setult, PMSLTU_DH, v4i16>;
def : PatGprPairGprPair<setult, PMSLTU_DW, v2i32>;
// 8-bit reduction sum patterns
def : PatRedSum<int_riscv_predsum, PREDSUM_BS, v4i8>;
def : PatRedSum<int_riscv_predsumu, PREDSUMU_BS, v4i8>;
def : PatRedSumPair<int_riscv_predsum, PREDSUM_DBS, v8i8>;
def : PatRedSumPair<int_riscv_predsumu, PREDSUMU_DBS, v8i8>;
// 16-bit reduction sum patterns
def : PatRedSum<int_riscv_predsum, PREDSUM_HS, v2i16>;
def : PatRedSum<int_riscv_predsumu, PREDSUMU_HS, v2i16>;
def : PatRedSumPair<int_riscv_predsum, PREDSUM_DHS, v4i16>;
def : PatRedSumPair<int_riscv_predsumu, PREDSUMU_DHS, v4i16>;
// [s|u]min/[s|u]max patterns
def : PatGprPairGprPair<smin, PMIN_DB, v8i8>;
def : PatGprPairGprPair<umin, PMINU_DB, v8i8>;
def : PatGprPairGprPair<smin, PMIN_DH, v4i16>;
def : PatGprPairGprPair<umin, PMINU_DH, v4i16>;
def : PatGprPairGprPair<smin, PMIN_DW, v2i32>;
def : PatGprPairGprPair<umin, PMINU_DW, v2i32>;
def : PatGprPairGprPair<smax, PMAX_DB, v8i8>;
def : PatGprPairGprPair<umax, PMAXU_DB, v8i8>;
def : PatGprPairGprPair<smax, PMAX_DH, v4i16>;
def : PatGprPairGprPair<umax, PMAXU_DH, v4i16>;
def : PatGprPairGprPair<smax, PMAX_DW, v2i32>;
def : PatGprPairGprPair<umax, PMAXU_DW, v2i32>;
// 16-bit bswap patterns
def : Pat<(v4i16 (bswap GPRPair:$rs)),
(PPAIROE_DB GPRPair:$rs, GPRPair:$rs)>;
// 8/16-bit bitreverse patterns
// FIXME: Custom lower?
def : Pat<(v8i8 (bitreverse GPRPair:$rs)),
(BuildGPRPair (REV8_RV32 (REV_RV32 (EXTRACT_SUBREG GPRPair:$rs, sub_gpr_even))),
(REV8_RV32 (REV_RV32 (EXTRACT_SUBREG GPRPair:$rs, sub_gpr_odd))))>;
def : Pat<(v4i16 (bitreverse GPRPair:$rs)),
(PPAIROE_DH (BuildGPRPair (REV_RV32 (EXTRACT_SUBREG GPRPair:$rs, sub_gpr_even)),
(REV_RV32 (EXTRACT_SUBREG GPRPair:$rs, sub_gpr_odd))),
(BuildGPRPair (REV_RV32 (EXTRACT_SUBREG GPRPair:$rs, sub_gpr_even)),
(REV_RV32 (EXTRACT_SUBREG GPRPair:$rs, sub_gpr_odd))))>;
// splat pattern
def : Pat<(v8i8 (splat_vector (XLenVT GPR:$rs2))),
(PADD_DBS (v8i8 X0_Pair), GPR:$rs2)>;
def : Pat<(v4i16 (splat_vector (XLenVT GPR:$rs2))),
(PADD_DHS (v4i16 X0_Pair), GPR:$rs2)>;
def : Pat<(v2i32 (splat_vector (XLenVT GPR:$rs2))),
(BuildGPRPair GPR:$rs2, GPR:$rs2)>;
// Build vector patterns
def : Pat<(v8i8 (build_vector (XLenVT GPR:$a), (XLenVT GPR:$b),
(XLenVT GPR:$c), (XLenVT GPR:$d),
(XLenVT GPR:$e), (XLenVT GPR:$f),
(XLenVT GPR:$g), (XLenVT GPR:$h))),
(BuildGPRPair (PACK (PPAIRE_B GPR:$a, GPR:$b),
(PPAIRE_B GPR:$c, GPR:$d)),
(PACK (PPAIRE_B GPR:$e, GPR:$f),
(PPAIRE_B GPR:$g, GPR:$h)))>;
def : Pat<(v4i16 (build_vector (XLenVT GPR:$a), (XLenVT GPR:$b),
(XLenVT GPR:$c), (XLenVT GPR:$d))),
(BuildGPRPair (PACK GPR:$a, GPR:$b), (PACK GPR:$c, GPR:$d))>;
def : Pat<(v2i32 (build_vector (XLenVT GPR:$a), (XLenVT GPR:$b))),
(BuildGPRPair GPR:$a, GPR:$b)>;
// Concat vector patterns
def : Pat<(v8i8 (concat_vectors (v4i8 GPR:$a), (v4i8 GPR:$b))),
(BuildGPRPair GPR:$a, GPR:$b)>;
def : Pat<(v4i16 (concat_vectors (v2i16 GPR:$a), (v2i16 GPR:$b))),
(BuildGPRPair GPR:$a, GPR:$b)>;
def : Pat<(i32 (extractelt (v2i32 GPRPair:$vec), (i32 0))),
(EXTRACT_SUBREG GPRPair:$vec, sub_gpr_even)>;
def : Pat<(i32 (extractelt (v2i32 GPRPair:$vec), (i32 1))),
(EXTRACT_SUBREG GPRPair:$vec, sub_gpr_odd)>;
} // append Predicates = [IsRV32]
let append Predicates = [IsRV64] in {
def : PatGpr<riscv_absw, ABSW>;
def : PatGpr<riscv_clsw, CLSW>;
def : PatGpr<bitreverse, REV_RV64>;
def : Pat<(XLenVT (riscv_sati GPR:$rs1, timm:$imm)),
(SATI_RV64 GPR:$rs1, (IncImm timm:$imm))>;
def : Pat<(XLenVT (riscv_usati GPR:$rs1, timm:$imm)),
(USATI_RV64 GPR:$rs1, timm:$imm)>;
// Word multiply patterns where one operand is a sext.w or zext.w and
// the other is a sext.w or zext.w or is known to be sign/zero-extended. We
// prefer plain mul when both operands are known to be sign/zero-extended.
def : Pat<(i64 (mul sexti32:$rs1, (sext_inreg GPR:$rs2, i32))),
(MUL_W00 sexti32:$rs1, GPR:$rs2)>;
def : Pat<(i64 (mul zexti32:$rs1, (and GPR:$rs2, 0xffffffff))),
(MULU_W00 zexti32:$rs1, GPR:$rs2)>;
def : Pat<(i64 (mul sexti32:$rs1, (and GPR:$rs2, 0xffffffff))),
(MULSU_W00 sexti32:$rs1, GPR:$rs2)>;
def : Pat<(i64 (mul (sext_inreg GPR:$rs1, i32), zexti32:$rs2)),
(MULSU_W00 GPR:$rs1, zexti32:$rs2)>;
def : Pat<(i64 (add GPR:$rd, (mul_oneuse sexti32:$rs1, sexti32:$rs2))),
(MACC_W00 GPR:$rd, sexti32:$rs1, sexti32:$rs2)>;
def : Pat<(i64 (add GPR:$rd, (mul_oneuse zexti32:$rs1, zexti32:$rs2))),
(MACCU_W00 GPR:$rd, zexti32:$rs1, zexti32:$rs2)>;
def : Pat<(i64 (add GPR:$rd, (mul_oneuse sexti32:$rs1, zexti32:$rs2))),
(MACCSU_W00 GPR:$rd, sexti32:$rs1, zexti32:$rs2)>;
// Match a pattern of 2 bytes being inserted into bits [31:16], with bits
// bits [15:0] coming from a zero extended value, and bits [63:32] being
// ignored. We can use ppaire.h with ppaire.b for bits [31:16]. If bits [15:0]
// can also be a ppaire.b, it can be matched separately.
def : Pat<(binop_allwusers<or>
(or (shl GPR:$op1rs2, (XLenVT 24)),
(shl zexti8:$op1rs1, (XLenVT 16))),
zexti16:$rs1),
(PPAIRE_H zexti16:$rs1,
(XLenVT (PPAIRE_B zexti8:$op1rs1, GPR:$op1rs2)))>;
// Basic 32-bit arithmetic patterns
def : PatGprGpr<add, PADD_W, v2i32>;
def : PatGprGpr<sub, PSUB_W, v2i32>;
def : PatGprSplatGpr<add, PADD_WS, v2i32>;
// 32-bit bitwise operation patterns
def : PatGprGpr<and, AND, v2i32>;
def : PatGprGpr<or, OR, v2i32>;
def : PatGprGpr<xor, XOR, v2i32>;
def : Pat<(v2i32 (vnot GPR:$rs1)), (XORI GPR:$rs1, -1)>;
// P implies Zbb so we can select ANDN/ORN/XNOR.
def : Pat<(v2i32 (and GPR:$rs1, (vnot GPR:$rs2))), (ANDN GPR:$rs1, GPR:$rs2)>;
def : Pat<(v2i32 (or GPR:$rs1, (vnot GPR:$rs2))), (ORN GPR:$rs1, GPR:$rs2)>;
def : Pat<(v2i32 (vnot (xor GPR:$rs1, GPR:$rs2))), (XNOR GPR:$rs1, GPR:$rs2)>;
// 32-bit saturating add/sub patterns
def : PatGprGpr<saddsat, PSADD_W, v2i32>;
def : PatGprGpr<uaddsat, PSADDU_W, v2i32>;
def : PatGprGpr<ssubsat, PSSUB_W, v2i32>;
def : PatGprGpr<usubsat, PSSUBU_W, v2i32>;
// 32-bit shift-add patterns
def : PatPSh1Add<PSH1ADD_W, v2i32>;
def : PatPSSh1SAdd<PSSH1SADD_W, v2i32>;
// 32-bit exchanged add/sub patterns
def : PatGprGpr<int_riscv_pas, PAS_WX, v2i32>;
def : PatGprGpr<int_riscv_psa, PSA_WX, v2i32>;
def : PatGprGpr<int_riscv_psas, PSAS_WX, v2i32>;
def : PatGprGpr<int_riscv_pssa, PSSA_WX, v2i32>;
def : PatGprGpr<int_riscv_paas, PAAS_WX, v2i32>;
def : PatGprGpr<int_riscv_pasa, PASA_WX, v2i32>;
// 32-bit averaging patterns
def : PatGprGpr<avgfloors, PAADD_W, v2i32>;
def : PatGprGpr<avgflooru, PAADDU_W, v2i32>;
// 32-bit averaging-sub patterns
def : PatGprGpr<riscv_asub, PASUB_W, v2i32>;
def : PatGprGpr<riscv_asubu, PASUBU_W, v2i32>;
// 32-bit multiply high patterns
def : PatGprGpr<mulhs, PMULH_W, v2i32>;
def : PatGprGpr<mulhu, PMULHU_W, v2i32>;
def : PatGprGpr<riscv_mulhsu, PMULHSU_W, v2i32>;
// 32-bit multiply high rounding patterns
def : PatGprGpr<riscv_mulhr, PMULHR_W, v2i32>;
def : PatGprGpr<riscv_mulhru, PMULHRU_W, v2i32>;
def : PatGprGpr<riscv_mulhrsu, PMULHRSU_W, v2i32>;
// 8/16/32-bit multiply low patterns
// FIXME custom lower
def : Pat<(v8i8 (mul GPR:$rs1, GPR:$rs2)),
(PPAIRE_B (PMUL_H_B00 GPR:$rs1, GPR:$rs2),
(PMUL_H_B11 GPR:$rs1, GPR:$rs2))>;
def : Pat<(v4i16 (mul GPR:$rs1, GPR:$rs2)),
(PPAIRE_H (PMUL_W_H00 GPR:$rs1, GPR:$rs2),
(PMUL_W_H11 GPR:$rs1, GPR:$rs2))>;
def : Pat<(v2i32 (mul GPR:$rs1, GPR:$rs2)),
(PACK (MUL_W00 GPR:$rs1, GPR:$rs2), (MUL_W11 GPR:$rs1, GPR:$rs2))>;
// 8-bit multiply high patterns
// FIXME custom lower
def : Pat<(v8i8 (mulhs GPR:$rs1, GPR:$rs2)),
(PPAIRO_B (PMUL_H_B00 GPR:$rs1, GPR:$rs2),
(PMUL_H_B11 GPR:$rs1, GPR:$rs2))>;
def : Pat<(v8i8 (mulhu GPR:$rs1, GPR:$rs2)),
(PPAIRO_B (PMULU_H_B00 GPR:$rs1, GPR:$rs2),
(PMULU_H_B11 GPR:$rs1, GPR:$rs2))>;
def : Pat<(v8i8 (riscv_mulhsu GPR:$rs1, GPR:$rs2)),
(PPAIRO_B (PMULSU_H_B00 GPR:$rs1, GPR:$rs2),
(PMULSU_H_B11 GPR:$rs1, GPR:$rs2))>;
// 32-bit logical shift left/right patterns
def : PatGprImm<riscv_pshl, PSLLI_W, uimm5, v2i32>;
def : PatGprImm<riscv_psrl, PSRLI_W, uimm5, v2i32>;
// 32-bit arithmetic shift left/right patterns
def : PatGprImm<riscv_psra, PSRAI_W, uimm5, v2i32>;
// 32-bit signed saturation shift left patterns
def : PatGprImm<riscv_pssha, PSSLAI_W, uimm5, v2i32>;
def : PatGprShift<riscv_pssha, PSSHA_WS, v2i32>;
// 32-bit logical shift left/right
def : PatGprShiftMask<riscv_pshl, PSLL_WS, shiftMask32, v2i32>;
def : PatGprShiftMask<riscv_psrl, PSRL_WS, shiftMask32, v2i32>;
// 32-bit arithmetic shift left/right
def : PatGprShiftMask<riscv_psra, PSRA_WS, shiftMask32, v2i32>;
// splat pattern
def : Pat<(v2i32 (splat_vector (XLenVT GPR:$rs2))), (PADD_WS (v2i32 X0), GPR:$rs2)>;
// 32-bit comparison patterns (result is all 1s or all 0s per element)
// a == b
def : PatGprGpr<seteq, PMSEQ_W, v2i32>;
// a < b
def : PatGprGpr<setlt, PMSLT_W, v2i32>;
def : PatGprGpr<setult, PMSLTU_W, v2i32>;
// 8-bit reduction sum patterns
def : PatRedSum<int_riscv_predsum, PREDSUM_BS, v8i8>;
def : PatRedSum<int_riscv_predsumu, PREDSUMU_BS, v8i8>;
// 16-bit reduction sum patterns
def : PatRedSum<int_riscv_predsum, PREDSUM_HS, v4i16>;
def : PatRedSum<int_riscv_predsumu, PREDSUMU_HS, v4i16>;
// 32-bit reduction sum patterns
def : PatRedSum<int_riscv_predsum, PREDSUM_WS, v2i32>;
def : PatRedSum<int_riscv_predsumu, PREDSUMU_WS, v2i32>;
// 32-bit [s|u]min/[s|u]max patterns
def : PatGprGpr<smin, PMIN_W, v2i32>;
def : PatGprGpr<umin, PMINU_W, v2i32>;
def : PatGprGpr<smax, PMAX_W, v2i32>;
def : PatGprGpr<umax, PMAXU_W, v2i32>;
// 32-bit vselect patterns
def : Pat<(v2i32 (vselect (v2i32 GPR:$mask), GPR:$true_v, GPR:$false_v)),
(MERGE GPR:$mask, GPR:$false_v, GPR:$true_v)>;
// 32-bit bswap patterns
def : Pat<(v2i32 (bswap GPR:$rs)),
(PPAIROE_W (REV8_RV64 GPR:$rs), (REV8_RV64 GPR:$rs))>;
// 8/16/32-bit bitreverse patterns
def : Pat<(v8i8 (bitreverse GPR:$rs)),
(REV8_RV64 (REV_RV64 GPR:$rs))>;
def : Pat<(v4i16 (bitreverse GPR:$rs)),
(REV16_RV64 (REV_RV64 GPR:$rs))>;
def : Pat<(v2i32 (bitreverse GPR:$rs)),
(PPAIROE_W (REV_RV64 GPR:$rs), (REV_RV64 GPR:$rs))>;
// Load/Store patterns
def : StPat<store, SD, GPR, v8i8>;
def : StPat<store, SD, GPR, v4i16>;
def : StPat<store, SD, GPR, v2i32>;
def : LdPat<load, LD, v8i8>;
def : LdPat<load, LD, v4i16>;
def : LdPat<load, LD, v2i32>;
// Build vector patterns
def : Pat<(v8i8 (build_vector (XLenVT GPR:$a), (XLenVT GPR:$b),
(XLenVT GPR:$c), (XLenVT GPR:$d),
(XLenVT undef), (XLenVT undef),
(XLenVT undef), (XLenVT undef))),
(PPAIRE_H (PPAIRE_B GPR:$a, GPR:$b), (PPAIRE_B GPR:$c, GPR:$d))>;
def : Pat<(v8i8 (build_vector (XLenVT GPR:$a), (XLenVT GPR:$b),
(XLenVT GPR:$c), (XLenVT GPR:$d),
(XLenVT GPR:$e), (XLenVT GPR:$f),
(XLenVT GPR:$g), (XLenVT GPR:$h))),
(PACK (PPAIRE_H (PPAIRE_B GPR:$a, GPR:$b), (PPAIRE_B GPR:$c, GPR:$d)),
(PPAIRE_H (PPAIRE_B GPR:$e, GPR:$f), (PPAIRE_B GPR:$g, GPR:$h)))>;
def : Pat<(v4i16 (build_vector (XLenVT GPR:$a), (XLenVT GPR:$b),
(XLenVT undef), (XLenVT undef))),
(PPAIRE_H GPR:$a, GPR:$b)>;
def : Pat<(v4i16 (build_vector (XLenVT GPR:$a), (XLenVT GPR:$b),
(XLenVT GPR:$c), (XLenVT GPR:$d))),
(PACK (PPAIRE_H GPR:$a, GPR:$b), (PPAIRE_H GPR:$c, GPR:$d))>;
def : Pat<(v2i32 (build_vector (XLenVT GPR:$a), (XLenVT GPR:$b))),
(PACK GPR:$a, GPR:$b)>;
// Zero-extend patterns using zip*p with zero
def : Pat<(v4i16 (zext_invec (v8i8 GPR:$rs))), (ZIP8P GPR:$rs, (v8i8 X0))>;
def : Pat<(v2i32 (zext_invec (v4i16 GPR:$rs))), (ZIP16P GPR:$rs, (v4i16 X0))>;
// Sign extend inreg patterns using psext. sext_invec is lowered to
// zext_invec+sext_inreg.
def : Pat<(v4i16 (sext_inreg GPR:$rs1, v4i8)), (PSEXT_H_B GPR:$rs1)>;
def : Pat<(v2i32 (sext_inreg GPR:$rs1, v2i16)), (PSEXT_W_H GPR:$rs1)>;
} // append Predicates = [IsRV64]
} // Predicates = [HasStdExtP]