Index: llvm/lib/Target/RISCV/RISCVInstrInfoB.td =================================================================== --- llvm/lib/Target/RISCV/RISCVInstrInfoB.td +++ llvm/lib/Target/RISCV/RISCVInstrInfoB.td @@ -87,6 +87,30 @@ return !isInt<12>(Imm) && isPowerOf2_32(Imm); }], BSETINVXForm>; +// Check if (or r, i) can be optimized to (BSETI (BSETI r, i0), i1), +// in which i = (1 << i0) | (1 << i1). +def BSETINVTwoBitsMask : PatLeaf<(imm), [{ + if (!N->hasOneUse()) + return false; + // The immediate should not be a simm12. + if (isInt<12>(N->getSExtValue())) + return false; + // The immediate must have exactly two bits set. + return countPopulation(N->getZExtValue()) == 2; +}]>; + +def BSETINVTwoBitsMaskLow : SDNodeXFormgetZExtValue(); + return CurDAG->getTargetConstant(countTrailingZeros(I), SDLoc(N), + N->getValueType(0)); +}]>; + +def BSETINVTwoBitsMaskHigh : SDNodeXFormgetZExtValue(); + return CurDAG->getTargetConstant(63 - countLeadingZeros(I), SDLoc(N), + N->getValueType(0)); +}]>; + //===----------------------------------------------------------------------===// // Instruction class templates //===----------------------------------------------------------------------===// @@ -723,6 +747,13 @@ def : Pat<(and (srl GPR:$rs1, uimmlog2xlen:$shamt), (XLenVT 1)), (BEXTI GPR:$rs1, uimmlog2xlen:$shamt)>; + +def : Pat<(or GPR:$r, BSETINVTwoBitsMask:$i), + (BSETI (BSETI GPR:$r, (BSETINVTwoBitsMaskLow BSETINVTwoBitsMask:$i)), + (BSETINVTwoBitsMaskHigh BSETINVTwoBitsMask:$i))>; +def : Pat<(xor GPR:$r, BSETINVTwoBitsMask:$i), + (BINVI (BINVI GPR:$r, (BSETINVTwoBitsMaskLow BSETINVTwoBitsMask:$i)), + (BSETINVTwoBitsMaskHigh BSETINVTwoBitsMask:$i))>; } // There's no encoding for roli in the the 'B' extension as it can be Index: llvm/test/CodeGen/RISCV/rv32zbs.ll =================================================================== --- llvm/test/CodeGen/RISCV/rv32zbs.ll +++ llvm/test/CodeGen/RISCV/rv32zbs.ll @@ -720,16 +720,14 @@ ; ; RV32IB-LABEL: xor_i32_4098: ; RV32IB: # %bb.0: -; RV32IB-NEXT: lui a1, 1 -; RV32IB-NEXT: addi a1, a1, 2 -; RV32IB-NEXT: xor a0, a0, a1 +; RV32IB-NEXT: binvi a0, a0, 1 +; RV32IB-NEXT: binvi a0, a0, 12 ; RV32IB-NEXT: ret ; ; RV32IBS-LABEL: xor_i32_4098: ; RV32IBS: # %bb.0: -; RV32IBS-NEXT: lui a1, 1 -; RV32IBS-NEXT: addi a1, a1, 2 -; RV32IBS-NEXT: xor a0, a0, a1 +; RV32IBS-NEXT: binvi a0, a0, 1 +; RV32IBS-NEXT: binvi a0, a0, 12 ; RV32IBS-NEXT: ret %xor = xor i32 %a, 4098 ret i32 %xor @@ -789,16 +787,14 @@ ; ; RV32IB-LABEL: or_i32_4098: ; RV32IB: # %bb.0: -; RV32IB-NEXT: lui a1, 1 -; RV32IB-NEXT: addi a1, a1, 2 -; RV32IB-NEXT: or a0, a0, a1 +; RV32IB-NEXT: bseti a0, a0, 1 +; RV32IB-NEXT: bseti a0, a0, 12 ; RV32IB-NEXT: ret ; ; RV32IBS-LABEL: or_i32_4098: ; RV32IBS: # %bb.0: -; RV32IBS-NEXT: lui a1, 1 -; RV32IBS-NEXT: addi a1, a1, 2 -; RV32IBS-NEXT: or a0, a0, a1 +; RV32IBS-NEXT: bseti a0, a0, 1 +; RV32IBS-NEXT: bseti a0, a0, 12 ; RV32IBS-NEXT: ret %or = or i32 %a, 4098 ret i32 %or Index: llvm/test/CodeGen/RISCV/rv64zbs.ll =================================================================== --- llvm/test/CodeGen/RISCV/rv64zbs.ll +++ llvm/test/CodeGen/RISCV/rv64zbs.ll @@ -1221,18 +1221,14 @@ ; ; RV64IB-LABEL: xor_i64_large: ; RV64IB: # %bb.0: -; RV64IB-NEXT: addi a1, zero, 1 -; RV64IB-NEXT: slli a1, a1, 32 -; RV64IB-NEXT: addi a1, a1, 1 -; RV64IB-NEXT: xor a0, a0, a1 +; RV64IB-NEXT: binvi a0, a0, 0 +; RV64IB-NEXT: binvi a0, a0, 32 ; RV64IB-NEXT: ret ; ; RV64IBS-LABEL: xor_i64_large: ; RV64IBS: # %bb.0: -; RV64IBS-NEXT: addi a1, zero, 1 -; RV64IBS-NEXT: slli a1, a1, 32 -; RV64IBS-NEXT: addi a1, a1, 1 -; RV64IBS-NEXT: xor a0, a0, a1 +; RV64IBS-NEXT: binvi a0, a0, 0 +; RV64IBS-NEXT: binvi a0, a0, 32 ; RV64IBS-NEXT: ret %xor = xor i64 %a, 4294967297 ret i64 %xor @@ -1293,18 +1289,14 @@ ; ; RV64IB-LABEL: or_i64_large: ; RV64IB: # %bb.0: -; RV64IB-NEXT: addi a1, zero, 1 -; RV64IB-NEXT: slli a1, a1, 32 -; RV64IB-NEXT: addi a1, a1, 1 -; RV64IB-NEXT: or a0, a0, a1 +; RV64IB-NEXT: bseti a0, a0, 0 +; RV64IB-NEXT: bseti a0, a0, 32 ; RV64IB-NEXT: ret ; ; RV64IBS-LABEL: or_i64_large: ; RV64IBS: # %bb.0: -; RV64IBS-NEXT: addi a1, zero, 1 -; RV64IBS-NEXT: slli a1, a1, 32 -; RV64IBS-NEXT: addi a1, a1, 1 -; RV64IBS-NEXT: or a0, a0, a1 +; RV64IBS-NEXT: bseti a0, a0, 0 +; RV64IBS-NEXT: bseti a0, a0, 32 ; RV64IBS-NEXT: ret %or = or i64 %a, 4294967297 ret i64 %or