Index: llvm/lib/Target/RISCV/RISCVInstrInfoB.td =================================================================== --- llvm/lib/Target/RISCV/RISCVInstrInfoB.td +++ llvm/lib/Target/RISCV/RISCVInstrInfoB.td @@ -111,6 +111,32 @@ N->getValueType(0)); }]>; +// Check if (or r, imm) can be optimized to (BSETI (ORI r, i0), i1), +// in which imm = i0 | (1 << i1). +def BSETINVORIMask : PatLeaf<(imm), [{ + if (!N->hasOneUse()) + return false; + // The imm should not be a simm12. + if (isInt<12>(N->getSExtValue())) + return false; + // Bit 11 of imm must be 0, otherwise i0 will be negative. And all bits + // beyond bit 11 of r will be set. + uint64_t I = N->getZExtValue(); + if (I & (1 << 11)) + return false; + // There should be only one set bit from bit 12 to the top. + I = I & ~0xfff; + if (Subtarget->is64Bit()) + return isPowerOf2_64(I); + else + return isPowerOf2_32(I); +}]>; + +def BSETINVORIMaskLow : SDNodeXFormgetZExtValue(); + return CurDAG->getTargetConstant(I & 0xfff, SDLoc(N), N->getValueType(0)); +}]>; + //===----------------------------------------------------------------------===// // Instruction class templates //===----------------------------------------------------------------------===// @@ -754,6 +780,12 @@ def : Pat<(xor GPR:$r, BSETINVTwoBitsMask:$i), (BINVI (BINVI GPR:$r, (BSETINVTwoBitsMaskLow BSETINVTwoBitsMask:$i)), (BSETINVTwoBitsMaskHigh BSETINVTwoBitsMask:$i))>; +def : Pat<(or GPR:$r, BSETINVORIMask:$i), + (BSETI (ORI GPR:$r, (BSETINVORIMaskLow BSETINVORIMask:$i)), + (BSETINVTwoBitsMaskHigh BSETINVORIMask:$i))>; +def : Pat<(xor GPR:$r, BSETINVORIMask:$i), + (BINVI (XORI GPR:$r, (BSETINVORIMaskLow BSETINVORIMask:$i)), + (BSETINVTwoBitsMaskHigh BSETINVORIMask:$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 @@ -743,16 +743,14 @@ ; ; RV32IB-LABEL: xor_i32_4099: ; RV32IB: # %bb.0: -; RV32IB-NEXT: lui a1, 1 -; RV32IB-NEXT: addi a1, a1, 3 -; RV32IB-NEXT: xor a0, a0, a1 +; RV32IB-NEXT: xori a0, a0, 3 +; RV32IB-NEXT: binvi a0, a0, 12 ; RV32IB-NEXT: ret ; ; RV32IBS-LABEL: xor_i32_4099: ; RV32IBS: # %bb.0: -; RV32IBS-NEXT: lui a1, 1 -; RV32IBS-NEXT: addi a1, a1, 3 -; RV32IBS-NEXT: xor a0, a0, a1 +; RV32IBS-NEXT: xori a0, a0, 3 +; RV32IBS-NEXT: binvi a0, a0, 12 ; RV32IBS-NEXT: ret %xor = xor i32 %a, 4099 ret i32 %xor @@ -787,21 +785,45 @@ ; ; RV32IB-LABEL: xor_i32_66901: ; RV32IB: # %bb.0: -; RV32IB-NEXT: lui a1, 16 -; RV32IB-NEXT: addi a1, a1, 1365 -; RV32IB-NEXT: xor a0, a0, a1 +; RV32IB-NEXT: xori a0, a0, 1365 +; RV32IB-NEXT: binvi a0, a0, 16 ; RV32IB-NEXT: ret ; ; RV32IBS-LABEL: xor_i32_66901: ; RV32IBS: # %bb.0: -; RV32IBS-NEXT: lui a1, 16 -; RV32IBS-NEXT: addi a1, a1, 1365 -; RV32IBS-NEXT: xor a0, a0, a1 +; RV32IBS-NEXT: xori a0, a0, 1365 +; RV32IBS-NEXT: binvi a0, a0, 16 ; RV32IBS-NEXT: ret %xor = xor i32 %a, 66901 ret i32 %xor } +; This should not be optimized since bit 12 of 6145 is set. +define i32 @xor_i32_6145(i32 %a) nounwind { +; RV32I-LABEL: xor_i32_6145: +; RV32I: # %bb.0: +; RV32I-NEXT: lui a1, 2 +; RV32I-NEXT: addi a1, a1, -2047 +; RV32I-NEXT: xor a0, a0, a1 +; RV32I-NEXT: ret +; +; RV32IB-LABEL: xor_i32_6145: +; RV32IB: # %bb.0: +; RV32IB-NEXT: lui a1, 2 +; RV32IB-NEXT: addi a1, a1, -2047 +; RV32IB-NEXT: xor a0, a0, a1 +; RV32IB-NEXT: ret +; +; RV32IBS-LABEL: xor_i32_6145: +; RV32IBS: # %bb.0: +; RV32IBS-NEXT: lui a1, 2 +; RV32IBS-NEXT: addi a1, a1, -2047 +; RV32IBS-NEXT: xor a0, a0, a1 +; RV32IBS-NEXT: ret + %xor = xor i32 %a, 6145 + ret i32 %xor +} + define i32 @or_i32_4098(i32 %a) nounwind { ; RV32I-LABEL: or_i32_4098: ; RV32I: # %bb.0: @@ -835,16 +857,14 @@ ; ; RV32IB-LABEL: or_i32_4099: ; RV32IB: # %bb.0: -; RV32IB-NEXT: lui a1, 1 -; RV32IB-NEXT: addi a1, a1, 3 -; RV32IB-NEXT: or a0, a0, a1 +; RV32IB-NEXT: ori a0, a0, 3 +; RV32IB-NEXT: bseti a0, a0, 12 ; RV32IB-NEXT: ret ; ; RV32IBS-LABEL: or_i32_4099: ; RV32IBS: # %bb.0: -; RV32IBS-NEXT: lui a1, 1 -; RV32IBS-NEXT: addi a1, a1, 3 -; RV32IBS-NEXT: or a0, a0, a1 +; RV32IBS-NEXT: ori a0, a0, 3 +; RV32IBS-NEXT: bseti a0, a0, 12 ; RV32IBS-NEXT: ret %or = or i32 %a, 4099 ret i32 %or @@ -879,17 +899,41 @@ ; ; RV32IB-LABEL: or_i32_66901: ; RV32IB: # %bb.0: -; RV32IB-NEXT: lui a1, 16 -; RV32IB-NEXT: addi a1, a1, 1365 -; RV32IB-NEXT: or a0, a0, a1 +; RV32IB-NEXT: ori a0, a0, 1365 +; RV32IB-NEXT: bseti a0, a0, 16 ; RV32IB-NEXT: ret ; ; RV32IBS-LABEL: or_i32_66901: ; RV32IBS: # %bb.0: -; RV32IBS-NEXT: lui a1, 16 -; RV32IBS-NEXT: addi a1, a1, 1365 -; RV32IBS-NEXT: or a0, a0, a1 +; RV32IBS-NEXT: ori a0, a0, 1365 +; RV32IBS-NEXT: bseti a0, a0, 16 ; RV32IBS-NEXT: ret %or = or i32 %a, 66901 ret i32 %or } + +; This should not be optimized since bit 12 of 6145 is set. +define i32 @or_i32_6145(i32 %a) nounwind { +; RV32I-LABEL: or_i32_6145: +; RV32I: # %bb.0: +; RV32I-NEXT: lui a1, 2 +; RV32I-NEXT: addi a1, a1, -2047 +; RV32I-NEXT: or a0, a0, a1 +; RV32I-NEXT: ret +; +; RV32IB-LABEL: or_i32_6145: +; RV32IB: # %bb.0: +; RV32IB-NEXT: lui a1, 2 +; RV32IB-NEXT: addi a1, a1, -2047 +; RV32IB-NEXT: or a0, a0, a1 +; RV32IB-NEXT: ret +; +; RV32IBS-LABEL: or_i32_6145: +; RV32IBS: # %bb.0: +; RV32IBS-NEXT: lui a1, 2 +; RV32IBS-NEXT: addi a1, a1, -2047 +; RV32IBS-NEXT: or a0, a0, a1 +; RV32IBS-NEXT: ret + %or = or i32 %a, 6145 + ret i32 %or +} Index: llvm/test/CodeGen/RISCV/rv64zbs.ll =================================================================== --- llvm/test/CodeGen/RISCV/rv64zbs.ll +++ llvm/test/CodeGen/RISCV/rv64zbs.ll @@ -1244,16 +1244,14 @@ ; ; RV64IB-LABEL: xor_i64_4099: ; RV64IB: # %bb.0: -; RV64IB-NEXT: lui a1, 1 -; RV64IB-NEXT: addiw a1, a1, 3 -; RV64IB-NEXT: xor a0, a0, a1 +; RV64IB-NEXT: xori a0, a0, 3 +; RV64IB-NEXT: binvi a0, a0, 12 ; RV64IB-NEXT: ret ; ; RV64IBS-LABEL: xor_i64_4099: ; RV64IBS: # %bb.0: -; RV64IBS-NEXT: lui a1, 1 -; RV64IBS-NEXT: addiw a1, a1, 3 -; RV64IBS-NEXT: xor a0, a0, a1 +; RV64IBS-NEXT: xori a0, a0, 3 +; RV64IBS-NEXT: binvi a0, a0, 12 ; RV64IBS-NEXT: ret %xor = xor i64 %a, 4099 ret i64 %xor @@ -1312,21 +1310,45 @@ ; ; RV64IB-LABEL: xor_i64_66901: ; RV64IB: # %bb.0: -; RV64IB-NEXT: lui a1, 16 -; RV64IB-NEXT: addiw a1, a1, 1365 -; RV64IB-NEXT: xor a0, a0, a1 +; RV64IB-NEXT: xori a0, a0, 1365 +; RV64IB-NEXT: binvi a0, a0, 16 ; RV64IB-NEXT: ret ; ; RV64IBS-LABEL: xor_i64_66901: ; RV64IBS: # %bb.0: -; RV64IBS-NEXT: lui a1, 16 -; RV64IBS-NEXT: addiw a1, a1, 1365 -; RV64IBS-NEXT: xor a0, a0, a1 +; RV64IBS-NEXT: xori a0, a0, 1365 +; RV64IBS-NEXT: binvi a0, a0, 16 ; RV64IBS-NEXT: ret %xor = xor i64 %a, 66901 ret i64 %xor } +; This should not be optimized since bit 11 of 6145 is set. +define i64 @xor_i64_6145(i64 %a) nounwind { +; RV64I-LABEL: xor_i64_6145: +; RV64I: # %bb.0: +; RV64I-NEXT: lui a1, 2 +; RV64I-NEXT: addiw a1, a1, -2047 +; RV64I-NEXT: xor a0, a0, a1 +; RV64I-NEXT: ret +; +; RV64IB-LABEL: xor_i64_6145: +; RV64IB: # %bb.0: +; RV64IB-NEXT: lui a1, 2 +; RV64IB-NEXT: addiw a1, a1, -2047 +; RV64IB-NEXT: xor a0, a0, a1 +; RV64IB-NEXT: ret +; +; RV64IBS-LABEL: xor_i64_6145: +; RV64IBS: # %bb.0: +; RV64IBS-NEXT: lui a1, 2 +; RV64IBS-NEXT: addiw a1, a1, -2047 +; RV64IBS-NEXT: xor a0, a0, a1 +; RV64IBS-NEXT: ret + %xor = xor i64 %a, 6145 + ret i64 %xor +} + define i64 @or_i64_4099(i64 %a) nounwind { ; RV64I-LABEL: or_i64_4099: ; RV64I: # %bb.0: @@ -1337,16 +1359,14 @@ ; ; RV64IB-LABEL: or_i64_4099: ; RV64IB: # %bb.0: -; RV64IB-NEXT: lui a1, 1 -; RV64IB-NEXT: addiw a1, a1, 3 -; RV64IB-NEXT: or a0, a0, a1 +; RV64IB-NEXT: ori a0, a0, 3 +; RV64IB-NEXT: bseti a0, a0, 12 ; RV64IB-NEXT: ret ; ; RV64IBS-LABEL: or_i64_4099: ; RV64IBS: # %bb.0: -; RV64IBS-NEXT: lui a1, 1 -; RV64IBS-NEXT: addiw a1, a1, 3 -; RV64IBS-NEXT: or a0, a0, a1 +; RV64IBS-NEXT: ori a0, a0, 3 +; RV64IBS-NEXT: bseti a0, a0, 12 ; RV64IBS-NEXT: ret %or = or i64 %a, 4099 ret i64 %or @@ -1381,17 +1401,41 @@ ; ; RV64IB-LABEL: or_i64_66901: ; RV64IB: # %bb.0: -; RV64IB-NEXT: lui a1, 16 -; RV64IB-NEXT: addiw a1, a1, 1365 -; RV64IB-NEXT: or a0, a0, a1 +; RV64IB-NEXT: ori a0, a0, 1365 +; RV64IB-NEXT: bseti a0, a0, 16 ; RV64IB-NEXT: ret ; ; RV64IBS-LABEL: or_i64_66901: ; RV64IBS: # %bb.0: -; RV64IBS-NEXT: lui a1, 16 -; RV64IBS-NEXT: addiw a1, a1, 1365 -; RV64IBS-NEXT: or a0, a0, a1 +; RV64IBS-NEXT: ori a0, a0, 1365 +; RV64IBS-NEXT: bseti a0, a0, 16 ; RV64IBS-NEXT: ret %or = or i64 %a, 66901 ret i64 %or } + +; This should not be optimized since bit 11 of 6145 is set. +define i64 @or_i64_6145(i64 %a) nounwind { +; RV64I-LABEL: or_i64_6145: +; RV64I: # %bb.0: +; RV64I-NEXT: lui a1, 2 +; RV64I-NEXT: addiw a1, a1, -2047 +; RV64I-NEXT: or a0, a0, a1 +; RV64I-NEXT: ret +; +; RV64IB-LABEL: or_i64_6145: +; RV64IB: # %bb.0: +; RV64IB-NEXT: lui a1, 2 +; RV64IB-NEXT: addiw a1, a1, -2047 +; RV64IB-NEXT: or a0, a0, a1 +; RV64IB-NEXT: ret +; +; RV64IBS-LABEL: or_i64_6145: +; RV64IBS: # %bb.0: +; RV64IBS-NEXT: lui a1, 2 +; RV64IBS-NEXT: addiw a1, a1, -2047 +; RV64IBS-NEXT: or a0, a0, a1 +; RV64IBS-NEXT: ret + %xor = or i64 %a, 6145 + ret i64 %xor +}