[RISCV] Custom legalize BITREVERSE with Zbkb.

With Zbkb, a bitreverse can be split into a rev8 and a brev8.

Reviewed By: VincentWu

Differential Revision: https://reviews.llvm.org/D118430
This commit is contained in:
Craig Topper 2022-01-28 22:55:37 -08:00
parent c95df64ce0
commit d8f929a567
4 changed files with 697 additions and 537 deletions

View File

@ -282,6 +282,9 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb())
? Legal
: Expand);
// Zbkb can use rev8+brev8 to implement bitreverse.
setOperationAction(ISD::BITREVERSE, XLenVT,
Subtarget.hasStdExtZbkb() ? Custom : Expand);
}
if (Subtarget.hasStdExtZbb()) {
@ -2955,17 +2958,23 @@ SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
return LowerINTRINSIC_VOID(Op, DAG);
case ISD::BSWAP:
case ISD::BITREVERSE: {
// Convert BSWAP/BITREVERSE to GREVI to enable GREVI combinining.
assert(Subtarget.hasStdExtZbp() && "Unexpected custom legalisation");
MVT VT = Op.getSimpleValueType();
SDLoc DL(Op);
// Start with the maximum immediate value which is the bitwidth - 1.
unsigned Imm = VT.getSizeInBits() - 1;
// If this is BSWAP rather than BITREVERSE, clear the lower 3 bits.
if (Op.getOpcode() == ISD::BSWAP)
Imm &= ~0x7U;
return DAG.getNode(RISCVISD::GREV, DL, VT, Op.getOperand(0),
DAG.getConstant(Imm, DL, VT));
if (Subtarget.hasStdExtZbp()) {
// Convert BSWAP/BITREVERSE to GREVI to enable GREVI combinining.
// Start with the maximum immediate value which is the bitwidth - 1.
unsigned Imm = VT.getSizeInBits() - 1;
// If this is BSWAP rather than BITREVERSE, clear the lower 3 bits.
if (Op.getOpcode() == ISD::BSWAP)
Imm &= ~0x7U;
return DAG.getNode(RISCVISD::GREV, DL, VT, Op.getOperand(0),
DAG.getConstant(Imm, DL, VT));
}
assert(Subtarget.hasStdExtZbkb() && "Unexpected custom legalization");
assert(Op.getOpcode() == ISD::BITREVERSE && "Unexpected opcode");
// Expand bitreverse to a bswap(rev8) followed by brev8.
SDValue BSwap = DAG.getNode(ISD::BSWAP, DL, VT, Op.getOperand(0));
return DAG.getNode(RISCVISD::BREV8, DL, VT, BSwap);
}
case ISD::FSHL:
case ISD::FSHR: {
@ -10097,6 +10106,7 @@ const char *RISCVTargetLowering::getTargetNodeName(unsigned Opcode) const {
NODE_NAME_CASE(STRICT_FCVT_W_RV64)
NODE_NAME_CASE(STRICT_FCVT_WU_RV64)
NODE_NAME_CASE(READ_CYCLE_WIDE)
NODE_NAME_CASE(BREV8)
NODE_NAME_CASE(GREV)
NODE_NAME_CASE(GREVW)
NODE_NAME_CASE(GORC)

View File

@ -99,6 +99,8 @@ enum NodeType : unsigned {
// READ_CYCLE_WIDE - A read of the 64-bit cycle CSR on a 32-bit target
// (returns (Lo, Hi)). It takes a chain operand.
READ_CYCLE_WIDE,
// Reverse bits in each byte.
BREV8,
// Generalized Reverse and Generalized Or-Combine - directly matching the
// semantics of the named RISC-V instructions. Lowered as custom nodes as
// TableGen chokes when faced with commutative permutations in deeply-nested

View File

@ -43,6 +43,7 @@ def riscv_fslw : SDNode<"RISCVISD::FSLW", SDT_RISCVIntShiftDOpW>;
def riscv_fsrw : SDNode<"RISCVISD::FSRW", SDT_RISCVIntShiftDOpW>;
def riscv_fsl : SDNode<"RISCVISD::FSL", SDTIntShiftDOp>;
def riscv_fsr : SDNode<"RISCVISD::FSR", SDTIntShiftDOp>;
def riscv_brev8 : SDNode<"RISCVISD::BREV8", SDTIntUnaryOp>;
def riscv_grev : SDNode<"RISCVISD::GREV", SDTIntBinOp>;
def riscv_grevw : SDNode<"RISCVISD::GREVW", SDT_RISCVIntBinOpW>;
def riscv_gorc : SDNode<"RISCVISD::GORC", SDTIntBinOp>;
@ -1190,6 +1191,7 @@ let Predicates = [HasStdExtZbf, IsRV64] in
def : PatGprGpr<riscv_bfpw, BFPW>;
let Predicates = [HasStdExtZbkb] in {
def : PatGpr<riscv_brev8, BREV8>;
def : PatGpr<int_riscv_brev8, BREV8>;
} // Predicates = [HasStdExtZbkb]

File diff suppressed because it is too large Load Diff