diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -161,8 +161,16 @@ 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 @@ 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 @@ 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; + } } } diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoB.td b/llvm/lib/Target/RISCV/RISCVInstrInfoB.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoB.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoB.td @@ -917,9 +917,6 @@ 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 { diff --git a/llvm/test/CodeGen/RISCV/rv64Zbp.ll b/llvm/test/CodeGen/RISCV/rv64Zbp.ll --- a/llvm/test/CodeGen/RISCV/rv64Zbp.ll +++ b/llvm/test/CodeGen/RISCV/rv64Zbp.ll @@ -1495,15 +1495,13 @@ ; ; 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 @@ ; ; 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)