[RISCV] Custom type legalize i32 bswap/bitreverse to GREVIW on RV64 with Zbp extension

Previously we required a sra to pattern match these properly in isel. If the consumer didn't need the result sign extended we'll have an srl instead of sra and fail to match.

This patch switches to custom legalizing to GREVIW using portions of D91259.

Differential Revision: https://reviews.llvm.org/D91457
This commit is contained in:
Craig Topper 2020-11-20 10:29:01 -08:00
parent f3c445697d
commit 6a1d8b91ed
3 changed files with 28 additions and 15 deletions

View File

@ -161,8 +161,16 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::ROTR, XLenVT, Expand);
}
if (!Subtarget.hasStdExtZbp())
if (Subtarget.hasStdExtZbp()) {
setOperationAction(ISD::BITREVERSE, XLenVT, Legal);
if (Subtarget.is64Bit()) {
setOperationAction(ISD::BITREVERSE, MVT::i32, Custom);
setOperationAction(ISD::BSWAP, MVT::i32, Custom);
}
} else {
setOperationAction(ISD::BSWAP, XLenVT, Expand);
}
if (!Subtarget.hasStdExtZbb()) {
setOperationAction(ISD::CTTZ, XLenVT, Expand);
@ -170,9 +178,6 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::CTPOP, XLenVT, Expand);
}
if (Subtarget.hasStdExtZbp())
setOperationAction(ISD::BITREVERSE, XLenVT, Legal);
if (Subtarget.hasStdExtZbt()) {
setOperationAction(ISD::FSHL, XLenVT, Legal);
setOperationAction(ISD::FSHR, XLenVT, Legal);
@ -1067,6 +1072,21 @@ void RISCVTargetLowering::ReplaceNodeResults(SDNode *N,
Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, NewRes));
break;
}
case ISD::BSWAP:
case ISD::BITREVERSE: {
assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
Subtarget.hasStdExtZbp() && "Unexpected custom legalisation");
SDValue NewOp0 = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64,
N->getOperand(0));
unsigned Imm = N->getOpcode() == ISD::BITREVERSE ? 31 : 24;
SDValue GREVIW = DAG.getNode(RISCVISD::GREVIW, DL, MVT::i64, NewOp0,
DAG.getTargetConstant(Imm, DL,
Subtarget.getXLenVT()));
// ReplaceNodeResults requires we maintain the same type for the return
// value.
Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, GREVIW));
break;
}
}
}

View File

@ -917,9 +917,6 @@ def : Pat<(SROIWPat GPR:$rs1, uimmlog2xlen:$shamt),
let Predicates = [HasStdExtZbp, IsRV64] in {
def : Pat<(riscv_greviw GPR:$rs1, timm:$shamt), (GREVIW GPR:$rs1, timm:$shamt)>;
def : Pat<(riscv_gorciw GPR:$rs1, timm:$shamt), (GORCIW GPR:$rs1, timm:$shamt)>;
def : Pat<(sra (bswap GPR:$rs1), (i64 32)), (GREVIW GPR:$rs1, (i64 24))>;
def : Pat<(sra (bitreverse GPR:$rs1), (i64 32)), (GREVIW GPR:$rs1, (i64 31))>;
} // Predicates = [HasStdExtZbp, IsRV64]
let Predicates = [HasStdExtZbt, IsRV64] in {

View File

@ -1495,15 +1495,13 @@ define void @bswap_i32_nosext(i32 signext %a, i32* %x) nounwind {
;
; RV64IB-LABEL: bswap_i32_nosext:
; RV64IB: # %bb.0:
; RV64IB-NEXT: rev8 a0, a0
; RV64IB-NEXT: srli a0, a0, 32
; RV64IB-NEXT: greviw a0, a0, 24
; RV64IB-NEXT: sw a0, 0(a1)
; RV64IB-NEXT: ret
;
; RV64IBP-LABEL: bswap_i32_nosext:
; RV64IBP: # %bb.0:
; RV64IBP-NEXT: rev8 a0, a0
; RV64IBP-NEXT: srli a0, a0, 32
; RV64IBP-NEXT: greviw a0, a0, 24
; RV64IBP-NEXT: sw a0, 0(a1)
; RV64IBP-NEXT: ret
%1 = tail call i32 @llvm.bswap.i32(i32 %a)
@ -1756,15 +1754,13 @@ define void @bitreverse_i32_nosext(i32 signext %a, i32* %x) nounwind {
;
; RV64IB-LABEL: bitreverse_i32_nosext:
; RV64IB: # %bb.0:
; RV64IB-NEXT: rev a0, a0
; RV64IB-NEXT: srli a0, a0, 32
; RV64IB-NEXT: greviw a0, a0, 31
; RV64IB-NEXT: sw a0, 0(a1)
; RV64IB-NEXT: ret
;
; RV64IBP-LABEL: bitreverse_i32_nosext:
; RV64IBP: # %bb.0:
; RV64IBP-NEXT: rev a0, a0
; RV64IBP-NEXT: srli a0, a0, 32
; RV64IBP-NEXT: greviw a0, a0, 31
; RV64IBP-NEXT: sw a0, 0(a1)
; RV64IBP-NEXT: ret
%1 = tail call i32 @llvm.bitreverse.i32(i32 %a)