[llvm] c705b7b - [RISCV] Optimize bitwise and with constant for the Zbs extension

Ben Shi via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 7 16:26:09 PDT 2021


Author: Ben Shi
Date: 2021-06-08T07:26:00+08:00
New Revision: c705b7b04dba467a67871a1bbb77907d0ed7fc19

URL: https://github.com/llvm/llvm-project/commit/c705b7b04dba467a67871a1bbb77907d0ed7fc19
DIFF: https://github.com/llvm/llvm-project/commit/c705b7b04dba467a67871a1bbb77907d0ed7fc19.diff

LOG: [RISCV] Optimize bitwise and with constant for the Zbs extension

This patch optimizes (and r i) to
(BCLRI (BCLRI r, i0), i1) in which i = ~((1<<i0) | (1<<i1)).
or
(BCLRI (ANDI r, i0), i1) in which i = i0 & ~(1<<i1).

Reviewed By: craig.topper

Differential Revision: https://reviews.llvm.org/D103743

Added: 
    

Modified: 
    llvm/lib/Target/RISCV/RISCVInstrInfoB.td
    llvm/test/CodeGen/RISCV/rv32zbs.ll
    llvm/test/CodeGen/RISCV/rv64zbs.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/RISCVInstrInfoB.td b/llvm/lib/Target/RISCV/RISCVInstrInfoB.td
index 9d332e4e08700..b61c8c3285c88 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoB.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoB.td
@@ -128,6 +128,49 @@ def BSETINVORIMaskLow : SDNodeXForm<imm, [{
                                    SDLoc(N), N->getValueType(0));
 }]>;
 
+// Check if (and r, i) can be optimized to (BCLRI (BCLRI r, i0), i1),
+// in which i = ~((1<<i0) | (1<<i1)).
+def BCLRITwoBitsMask : 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 clear.
+  return countPopulation(N->getZExtValue()) == Subtarget->getXLen() - 2;
+}]>;
+
+def BCLRITwoBitsMaskLow : SDNodeXForm<imm, [{
+  return CurDAG->getTargetConstant(countTrailingZeros(~N->getZExtValue()),
+                                   SDLoc(N), N->getValueType(0));
+}]>;
+
+def BCLRITwoBitsMaskHigh : SDNodeXForm<imm, [{
+  uint64_t I = N->getSExtValue();
+  if (!Subtarget->is64Bit())
+    I |= 0xffffffffull << 32;
+  return CurDAG->getTargetConstant(63 - countLeadingZeros(~I), SDLoc(N),
+                                   N->getValueType(0));
+}]>;
+
+// Check if (and r, i) can be optimized to (BCLRI (ANDI r, i0), i1),
+// in which i = i0 & ~(1<<i1).
+def BCLRIANDIMask : PatLeaf<(imm), [{
+  if (!N->hasOneUse())
+    return false;
+  // The immediate should not be a simm12.
+  if (isInt<12>(N->getSExtValue()))
+    return false;
+  // There should be only one clear bit from bit 11 to the top.
+  uint64_t I = N->getZExtValue() | 0x7ff;
+  return Subtarget->is64Bit() ? isPowerOf2_64(~I) : isPowerOf2_32(~I);
+}]>;
+
+def BCLRIANDIMaskLow : SDNodeXForm<imm, [{
+  return CurDAG->getTargetConstant((N->getZExtValue() & 0x7ff) | ~0x7ffull,
+                                   SDLoc(N), N->getValueType(0));
+}]>;
+
 //===----------------------------------------------------------------------===//
 // Instruction class templates
 //===----------------------------------------------------------------------===//
@@ -777,6 +820,12 @@ def : Pat<(or GPR:$r, BSETINVORIMask:$i),
 def : Pat<(xor GPR:$r, BSETINVORIMask:$i),
           (BINVI (XORI GPR:$r, (BSETINVORIMaskLow BSETINVORIMask:$i)),
                  (BSETINVTwoBitsMaskHigh BSETINVORIMask:$i))>;
+def : Pat<(and GPR:$r, BCLRITwoBitsMask:$i),
+          (BCLRI (BCLRI GPR:$r, (BCLRITwoBitsMaskLow BCLRITwoBitsMask:$i)),
+                 (BCLRITwoBitsMaskHigh BCLRITwoBitsMask:$i))>;
+def : Pat<(and GPR:$r, BCLRIANDIMask:$i),
+          (BCLRI (ANDI GPR:$r, (BCLRIANDIMaskLow BCLRIANDIMask:$i)),
+                 (BCLRITwoBitsMaskHigh BCLRIANDIMask:$i))>;
 }
 
 // There's no encoding for roli in the the 'B' extension as it can be

diff  --git a/llvm/test/CodeGen/RISCV/rv32zbs.ll b/llvm/test/CodeGen/RISCV/rv32zbs.ll
index 92d2051982783..dce44f8c702ae 100644
--- a/llvm/test/CodeGen/RISCV/rv32zbs.ll
+++ b/llvm/test/CodeGen/RISCV/rv32zbs.ll
@@ -560,16 +560,14 @@ define i32 @sbclri_i32_large0(i32 %a) nounwind {
 ;
 ; RV32IB-LABEL: sbclri_i32_large0:
 ; RV32IB:       # %bb.0:
-; RV32IB-NEXT:    lui a1, 1044480
-; RV32IB-NEXT:    addi a1, a1, -256
-; RV32IB-NEXT:    and a0, a0, a1
+; RV32IB-NEXT:    andi a0, a0, -256
+; RV32IB-NEXT:    bclri a0, a0, 24
 ; RV32IB-NEXT:    ret
 ;
 ; RV32IBS-LABEL: sbclri_i32_large0:
 ; RV32IBS:       # %bb.0:
-; RV32IBS-NEXT:    lui a1, 1044480
-; RV32IBS-NEXT:    addi a1, a1, -256
-; RV32IBS-NEXT:    and a0, a0, a1
+; RV32IBS-NEXT:    andi a0, a0, -256
+; RV32IBS-NEXT:    bclri a0, a0, 24
 ; RV32IBS-NEXT:    ret
   %and = and i32 %a, -16777472
   ret i32 %and
@@ -585,21 +583,65 @@ define i32 @sbclri_i32_large1(i32 %a) nounwind {
 ;
 ; RV32IB-LABEL: sbclri_i32_large1:
 ; RV32IB:       # %bb.0:
-; RV32IB-NEXT:    lui a1, 1044464
-; RV32IB-NEXT:    addi a1, a1, -1
-; RV32IB-NEXT:    and a0, a0, a1
+; RV32IB-NEXT:    bclri a0, a0, 16
+; RV32IB-NEXT:    bclri a0, a0, 24
 ; RV32IB-NEXT:    ret
 ;
 ; RV32IBS-LABEL: sbclri_i32_large1:
 ; RV32IBS:       # %bb.0:
-; RV32IBS-NEXT:    lui a1, 1044464
-; RV32IBS-NEXT:    addi a1, a1, -1
-; RV32IBS-NEXT:    and a0, a0, a1
+; RV32IBS-NEXT:    bclri a0, a0, 16
+; RV32IBS-NEXT:    bclri a0, a0, 24
 ; RV32IBS-NEXT:    ret
   %and = and i32 %a, -16842753
   ret i32 %and
 }
 
+define i32 @sbclri_i32_large2(i32 %0) {
+; RV32I-LABEL: sbclri_i32_large2:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    lui a1, 524288
+; RV32I-NEXT:    addi a1, a1, -5
+; RV32I-NEXT:    and a0, a0, a1
+; RV32I-NEXT:    ret
+;
+; RV32IB-LABEL: sbclri_i32_large2:
+; RV32IB:       # %bb.0:
+; RV32IB-NEXT:    bclri a0, a0, 2
+; RV32IB-NEXT:    bclri a0, a0, 31
+; RV32IB-NEXT:    ret
+;
+; RV32IBS-LABEL: sbclri_i32_large2:
+; RV32IBS:       # %bb.0:
+; RV32IBS-NEXT:    bclri a0, a0, 2
+; RV32IBS-NEXT:    bclri a0, a0, 31
+; RV32IBS-NEXT:    ret
+  %2 = and i32 %0, 2147483643
+  ret i32 %2
+}
+
+define i32 @sbclri_i32_large3(i32 %0) {
+; RV32I-LABEL: sbclri_i32_large3:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    lui a1, 524288
+; RV32I-NEXT:    addi a1, a1, -6
+; RV32I-NEXT:    and a0, a0, a1
+; RV32I-NEXT:    ret
+;
+; RV32IB-LABEL: sbclri_i32_large3:
+; RV32IB:       # %bb.0:
+; RV32IB-NEXT:    andi a0, a0, -6
+; RV32IB-NEXT:    bclri a0, a0, 31
+; RV32IB-NEXT:    ret
+;
+; RV32IBS-LABEL: sbclri_i32_large3:
+; RV32IBS:       # %bb.0:
+; RV32IBS-NEXT:    andi a0, a0, -6
+; RV32IBS-NEXT:    bclri a0, a0, 31
+; RV32IBS-NEXT:    ret
+  %2 = and i32 %0, 2147483642
+  ret i32 %2
+}
+
 define i32 @sbseti_i32_10(i32 %a) nounwind {
 ; RV32I-LABEL: sbseti_i32_10:
 ; RV32I:       # %bb.0:

diff  --git a/llvm/test/CodeGen/RISCV/rv64zbs.ll b/llvm/test/CodeGen/RISCV/rv64zbs.ll
index 067fa52bbdaaa..a0a74752fb54c 100644
--- a/llvm/test/CodeGen/RISCV/rv64zbs.ll
+++ b/llvm/test/CodeGen/RISCV/rv64zbs.ll
@@ -810,16 +810,14 @@ define i64 @sbclri_i64_large0(i64 %a) nounwind {
 ;
 ; RV64IB-LABEL: sbclri_i64_large0:
 ; RV64IB:       # %bb.0:
-; RV64IB-NEXT:    lui a1, 1044480
-; RV64IB-NEXT:    addiw a1, a1, -256
-; RV64IB-NEXT:    and a0, a0, a1
+; RV64IB-NEXT:    andi a0, a0, -256
+; RV64IB-NEXT:    bclri a0, a0, 24
 ; RV64IB-NEXT:    ret
 ;
 ; RV64IBS-LABEL: sbclri_i64_large0:
 ; RV64IBS:       # %bb.0:
-; RV64IBS-NEXT:    lui a1, 1044480
-; RV64IBS-NEXT:    addiw a1, a1, -256
-; RV64IBS-NEXT:    and a0, a0, a1
+; RV64IBS-NEXT:    andi a0, a0, -256
+; RV64IBS-NEXT:    bclri a0, a0, 24
 ; RV64IBS-NEXT:    ret
   %and = and i64 %a, -16777472
   ret i64 %and
@@ -835,16 +833,14 @@ define i64 @sbclri_i64_large1(i64 %a) nounwind {
 ;
 ; RV64IB-LABEL: sbclri_i64_large1:
 ; RV64IB:       # %bb.0:
-; RV64IB-NEXT:    lui a1, 1044464
-; RV64IB-NEXT:    addiw a1, a1, -1
-; RV64IB-NEXT:    and a0, a0, a1
+; RV64IB-NEXT:    bclri a0, a0, 16
+; RV64IB-NEXT:    bclri a0, a0, 24
 ; RV64IB-NEXT:    ret
 ;
 ; RV64IBS-LABEL: sbclri_i64_large1:
 ; RV64IBS:       # %bb.0:
-; RV64IBS-NEXT:    lui a1, 1044464
-; RV64IBS-NEXT:    addiw a1, a1, -1
-; RV64IBS-NEXT:    and a0, a0, a1
+; RV64IBS-NEXT:    bclri a0, a0, 16
+; RV64IBS-NEXT:    bclri a0, a0, 24
 ; RV64IBS-NEXT:    ret
   %and = and i64 %a, -16842753
   ret i64 %and


        


More information about the llvm-commits mailing list