From fd4d584d6b5c8c1e8d4fd9cbf171247f72fa9b21 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Sat, 12 Mar 2022 16:23:17 -0800 Subject: [PATCH] [RISCV] Add DAGCombine to fold (bitreverse (bswap X)) to brev8 with Zbkb. If the type is less than XLenVT, type legalization will turn this into (srl (bitreverse (bswap (srl (bswap X), C))), C). We can't completely recover from these shifts. They introduce zeros into the upper bits of the result and we can't easily tell if they are needed. By doing a DAG combine early, we avoid introducing these shifts. --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 41 ++++++++++++++++++++++++----- llvm/test/CodeGen/RISCV/bswap-bitreverse.ll | 28 -------------------- 2 files changed, 35 insertions(+), 34 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index dc345b6..09151a0 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -1039,6 +1039,8 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM, setTargetDAGCombine(ISD::ROTL); setTargetDAGCombine(ISD::ROTR); } + if (Subtarget.hasStdExtZbkb()) + setTargetDAGCombine(ISD::BITREVERSE); setTargetDAGCombine(ISD::INTRINSIC_WO_CHAIN); if (Subtarget.hasStdExtZfh() || Subtarget.hasStdExtZbb()) setTargetDAGCombine(ISD::SIGN_EXTEND_INREG); @@ -6767,17 +6769,22 @@ void RISCVTargetLowering::ReplaceNodeResults(SDNode *N, } case RISCVISD::GREV: case RISCVISD::GORC: { - assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() && + MVT VT = N->getSimpleValueType(0); + MVT XLenVT = Subtarget.getXLenVT(); + assert((VT == MVT::i16 || (VT == MVT::i32 && Subtarget.is64Bit())) && "Unexpected custom legalisation"); assert(isa(N->getOperand(1)) && "Expected constant"); - SDValue NewOp0 = - DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(0)); + assert((Subtarget.hasStdExtZbp() || + (Subtarget.hasStdExtZbkb() && N->getOpcode() == RISCVISD::GREV && + N->getConstantOperandVal(1) == 7)) && + "Unexpected extension"); + SDValue NewOp0 = DAG.getNode(ISD::ANY_EXTEND, DL, XLenVT, N->getOperand(0)); SDValue NewOp1 = - DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, N->getOperand(1)); - SDValue NewRes = DAG.getNode(N->getOpcode(), DL, MVT::i64, NewOp0, NewOp1); + DAG.getNode(ISD::ZERO_EXTEND, DL, XLenVT, N->getOperand(1)); + SDValue NewRes = DAG.getNode(N->getOpcode(), DL, XLenVT, NewOp0, NewOp1); // ReplaceNodeResults requires we maintain the same type for the return // value. - Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, NewRes)); + Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NewRes)); break; } case RISCVISD::SHFL: { @@ -8051,6 +8058,26 @@ static SDValue performFP_TO_INT_SATCombine(SDNode *N, return DAG.getSelectCC(DL, Src, Src, ZeroInt, FpToInt, ISD::CondCode::SETUO); } +// Combine (bitreverse (bswap X)) to the BREV8 GREVI encoding if the type is +// smaller than XLenVT. +static SDValue performBITREVERSECombine(SDNode *N, SelectionDAG &DAG, + const RISCVSubtarget &Subtarget) { + assert(Subtarget.hasStdExtZbkb() && "Unexpected extension"); + + SDValue Src = N->getOperand(0); + if (Src.getOpcode() != ISD::BSWAP) + return SDValue(); + + EVT VT = N->getValueType(0); + if (!VT.isScalarInteger() || VT.getSizeInBits() >= Subtarget.getXLen() || + !isPowerOf2_32(VT.getSizeInBits())) + return SDValue(); + + SDLoc DL(N); + return DAG.getNode(RISCVISD::GREV, DL, VT, Src.getOperand(0), + DAG.getConstant(7, DL, VT)); +} + SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { SelectionDAG &DAG = DCI.DAG; @@ -8390,6 +8417,8 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N, } break; } + case ISD::BITREVERSE: + return performBITREVERSECombine(N, DAG, Subtarget); case ISD::FP_TO_SINT: case ISD::FP_TO_UINT: return performFP_TO_INTCombine(N, DCI, Subtarget); diff --git a/llvm/test/CodeGen/RISCV/bswap-bitreverse.ll b/llvm/test/CodeGen/RISCV/bswap-bitreverse.ll index 489e117..61543f5 100644 --- a/llvm/test/CodeGen/RISCV/bswap-bitreverse.ll +++ b/llvm/test/CodeGen/RISCV/bswap-bitreverse.ll @@ -822,7 +822,6 @@ define i64 @test_bitreverse_i64(i64 %a) nounwind { ret i64 %tmp } -; FIXME: Merge the away the two rev8s in the Zbkb code. define i16 @test_bswap_bitreverse_i16(i16 %a) nounwind { ; RV32I-LABEL: test_bswap_bitreverse_i16: ; RV32I: # %bb.0: @@ -926,20 +925,12 @@ define i16 @test_bswap_bitreverse_i16(i16 %a) nounwind { ; ; RV32ZBKB-LABEL: test_bswap_bitreverse_i16: ; RV32ZBKB: # %bb.0: -; RV32ZBKB-NEXT: rev8 a0, a0 -; RV32ZBKB-NEXT: srli a0, a0, 16 -; RV32ZBKB-NEXT: rev8 a0, a0 ; RV32ZBKB-NEXT: brev8 a0, a0 -; RV32ZBKB-NEXT: srli a0, a0, 16 ; RV32ZBKB-NEXT: ret ; ; RV64ZBKB-LABEL: test_bswap_bitreverse_i16: ; RV64ZBKB: # %bb.0: -; RV64ZBKB-NEXT: rev8 a0, a0 -; RV64ZBKB-NEXT: srli a0, a0, 48 -; RV64ZBKB-NEXT: rev8 a0, a0 ; RV64ZBKB-NEXT: brev8 a0, a0 -; RV64ZBKB-NEXT: srli a0, a0, 48 ; RV64ZBKB-NEXT: ret ; ; RV32ZBP-LABEL: test_bswap_bitreverse_i16: @@ -956,7 +947,6 @@ define i16 @test_bswap_bitreverse_i16(i16 %a) nounwind { ret i16 %tmp2 } -; FIXME: Merge the away the two rev8s in the Zbkb code. define i32 @test_bswap_bitreverse_i32(i32 %a) nounwind { ; RV32I-LABEL: test_bswap_bitreverse_i32: ; RV32I: # %bb.0: @@ -1065,11 +1055,7 @@ define i32 @test_bswap_bitreverse_i32(i32 %a) nounwind { ; ; RV64ZBKB-LABEL: test_bswap_bitreverse_i32: ; RV64ZBKB: # %bb.0: -; RV64ZBKB-NEXT: rev8 a0, a0 -; RV64ZBKB-NEXT: srli a0, a0, 32 -; RV64ZBKB-NEXT: rev8 a0, a0 ; RV64ZBKB-NEXT: brev8 a0, a0 -; RV64ZBKB-NEXT: srli a0, a0, 32 ; RV64ZBKB-NEXT: ret ; ; RV32ZBP-LABEL: test_bswap_bitreverse_i32: @@ -1243,7 +1229,6 @@ define i64 @test_bswap_bitreverse_i64(i64 %a) nounwind { ret i64 %tmp2 } -; FIXME: Merge the away the two rev8s in the Zbkb code. define i16 @test_bitreverse_bswap_i16(i16 %a) nounwind { ; RV32I-LABEL: test_bitreverse_bswap_i16: ; RV32I: # %bb.0: @@ -1347,20 +1332,12 @@ define i16 @test_bitreverse_bswap_i16(i16 %a) nounwind { ; ; RV32ZBKB-LABEL: test_bitreverse_bswap_i16: ; RV32ZBKB: # %bb.0: -; RV32ZBKB-NEXT: rev8 a0, a0 -; RV32ZBKB-NEXT: srli a0, a0, 16 -; RV32ZBKB-NEXT: rev8 a0, a0 ; RV32ZBKB-NEXT: brev8 a0, a0 -; RV32ZBKB-NEXT: srli a0, a0, 16 ; RV32ZBKB-NEXT: ret ; ; RV64ZBKB-LABEL: test_bitreverse_bswap_i16: ; RV64ZBKB: # %bb.0: -; RV64ZBKB-NEXT: rev8 a0, a0 -; RV64ZBKB-NEXT: srli a0, a0, 48 -; RV64ZBKB-NEXT: rev8 a0, a0 ; RV64ZBKB-NEXT: brev8 a0, a0 -; RV64ZBKB-NEXT: srli a0, a0, 48 ; RV64ZBKB-NEXT: ret ; ; RV32ZBP-LABEL: test_bitreverse_bswap_i16: @@ -1377,7 +1354,6 @@ define i16 @test_bitreverse_bswap_i16(i16 %a) nounwind { ret i16 %tmp2 } -; FIXME: Merge the away the two rev8s in the Zbkb code. define i32 @test_bitreverse_bswap_i32(i32 %a) nounwind { ; RV32I-LABEL: test_bitreverse_bswap_i32: ; RV32I: # %bb.0: @@ -1486,11 +1462,7 @@ define i32 @test_bitreverse_bswap_i32(i32 %a) nounwind { ; ; RV64ZBKB-LABEL: test_bitreverse_bswap_i32: ; RV64ZBKB: # %bb.0: -; RV64ZBKB-NEXT: rev8 a0, a0 -; RV64ZBKB-NEXT: srli a0, a0, 32 -; RV64ZBKB-NEXT: rev8 a0, a0 ; RV64ZBKB-NEXT: brev8 a0, a0 -; RV64ZBKB-NEXT: srli a0, a0, 32 ; RV64ZBKB-NEXT: ret ; ; RV32ZBP-LABEL: test_bitreverse_bswap_i32: -- 2.7.4