diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -9693,6 +9693,23 @@ // fold (bitreverse (bitreverse x)) -> x if (N0.getOpcode() == ISD::BITREVERSE) return N0.getOperand(0); + + // Canonicalize (bitreverse (srl X, C)) -> (shl (bitreverse X), C) if X is a + // bswap. + if (N0.getOpcode() == ISD::SRL && N0.hasOneUse() && + isa(N0.getOperand(1)) && + N0.getOperand(0).getOpcode() == ISD::BSWAP) { + auto *N0C1 = cast(N0.getOperand(1)); + unsigned OpSizeInBits = VT.getScalarSizeInBits(); + if (N0C1->getAPIntValue().ult(OpSizeInBits)) { + unsigned C1 = N0C1->getZExtValue(); + SDLoc DL(N); + SDValue Rev = DAG.getNode(ISD::BITREVERSE, DL, VT, N0.getOperand(0)); + return DAG.getNode(ISD::SHL, DL, VT, Rev, + DAG.getConstant(C1, DL, VT)); + } + } + return SDValue(); } diff --git a/llvm/test/CodeGen/RISCV/bswap-bitreverse.ll b/llvm/test/CodeGen/RISCV/bswap-bitreverse.ll --- a/llvm/test/CodeGen/RISCV/bswap-bitreverse.ll +++ b/llvm/test/CodeGen/RISCV/bswap-bitreverse.ll @@ -848,19 +848,15 @@ ; ; 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: slli a0, a0, 16 ; 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: slli a0, a0, 48 ; RV64ZBKB-NEXT: srli a0, a0, 48 ; RV64ZBKB-NEXT: ret %tmp = call i16 @llvm.bswap.i16(i16 %a) @@ -977,10 +973,8 @@ ; ; 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: slli a0, a0, 32 ; RV64ZBKB-NEXT: srli a0, a0, 32 ; RV64ZBKB-NEXT: ret %tmp = call i32 @llvm.bswap.i32(i32 %a) @@ -1238,19 +1232,15 @@ ; ; 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: slli a0, a0, 16 ; 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: slli a0, a0, 48 ; RV64ZBKB-NEXT: srli a0, a0, 48 ; RV64ZBKB-NEXT: ret %tmp = call i16 @llvm.bitreverse.i16(i16 %a) @@ -1367,10 +1357,8 @@ ; ; 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: slli a0, a0, 32 ; RV64ZBKB-NEXT: srli a0, a0, 32 ; RV64ZBKB-NEXT: ret %tmp = call i32 @llvm.bitreverse.i32(i32 %a)