[llvm] 5836e52 - [RISCV] Add isel patterns to use SBSET for (1 << X) by using X0 as the input.

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 26 15:53:04 PST 2020


Author: Craig Topper
Date: 2020-11-26T15:35:13-08:00
New Revision: 5836e52063763e5d1e5f6e08b84a5bf832d0da5d

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

LOG: [RISCV] Add isel patterns to use SBSET for (1 << X) by using X0 as the input.

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 e80ef9987b45..7a8a1bc364e1 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoB.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoB.td
@@ -689,6 +689,9 @@ def : Pat<(xor (shiftop<shl> 1, GPR:$rs2), GPR:$rs1),
           (SBINV GPR:$rs1, GPR:$rs2)>;
 def : Pat<(and (shiftop<srl> GPR:$rs1, GPR:$rs2), 1),
           (SBEXT GPR:$rs1, GPR:$rs2)>;
+
+def : Pat<(shiftop<shl> 1, GPR:$rs2),
+          (SBSET X0, GPR:$rs2)>;
 }
 
 let Predicates = [HasStdExtZbb] in {
@@ -905,6 +908,9 @@ def : Pat<(sext_inreg (xor (riscv_sllw 1, GPR:$rs2), GPR:$rs1), i32),
           (SBINVW GPR:$rs1, GPR:$rs2)>;
 def : Pat<(and (riscv_srlw GPR:$rs1, GPR:$rs2), 1),
           (SBEXTW GPR:$rs1, GPR:$rs2)>;
+
+def : Pat<(riscv_sllw 1, GPR:$rs2),
+          (SBSETW X0, GPR:$rs2)>;
 } // Predicates = [HasStdExtZbs, IsRV64]
 
 let Predicates = [HasStdExtZbb, IsRV64] in {

diff  --git a/llvm/test/CodeGen/RISCV/rv32Zbs.ll b/llvm/test/CodeGen/RISCV/rv32Zbs.ll
index 56e8ac57bc7c..355389340da5 100644
--- a/llvm/test/CodeGen/RISCV/rv32Zbs.ll
+++ b/llvm/test/CodeGen/RISCV/rv32Zbs.ll
@@ -79,36 +79,34 @@ define i64 @sbclr_i64(i64 %a, i64 %b) nounwind {
 ; RV32IB-LABEL: sbclr_i64:
 ; RV32IB:       # %bb.0:
 ; RV32IB-NEXT:    andi a3, a2, 63
-; RV32IB-NEXT:    addi a4, a3, -32
-; RV32IB-NEXT:    addi a3, zero, 1
-; RV32IB-NEXT:    bltz a4, .LBB2_2
+; RV32IB-NEXT:    addi a3, a3, -32
+; RV32IB-NEXT:    bltz a3, .LBB2_2
 ; RV32IB-NEXT:  # %bb.1:
 ; RV32IB-NEXT:    mv a2, zero
-; RV32IB-NEXT:    sll a4, a3, a4
+; RV32IB-NEXT:    sbset a3, zero, a3
 ; RV32IB-NEXT:    j .LBB2_3
 ; RV32IB-NEXT:  .LBB2_2:
-; RV32IB-NEXT:    mv a4, zero
-; RV32IB-NEXT:    sll a2, a3, a2
+; RV32IB-NEXT:    mv a3, zero
+; RV32IB-NEXT:    sbset a2, zero, a2
 ; RV32IB-NEXT:  .LBB2_3:
 ; RV32IB-NEXT:    andn a0, a0, a2
-; RV32IB-NEXT:    andn a1, a1, a4
+; RV32IB-NEXT:    andn a1, a1, a3
 ; RV32IB-NEXT:    ret
 ;
 ; RV32IBS-LABEL: sbclr_i64:
 ; RV32IBS:       # %bb.0:
 ; RV32IBS-NEXT:    andi a3, a2, 63
-; RV32IBS-NEXT:    addi a4, a3, -32
-; RV32IBS-NEXT:    addi a3, zero, 1
-; RV32IBS-NEXT:    bltz a4, .LBB2_2
+; RV32IBS-NEXT:    addi a3, a3, -32
+; RV32IBS-NEXT:    bltz a3, .LBB2_2
 ; RV32IBS-NEXT:  # %bb.1:
 ; RV32IBS-NEXT:    mv a2, zero
-; RV32IBS-NEXT:    sll a4, a3, a4
+; RV32IBS-NEXT:    sbset a3, zero, a3
 ; RV32IBS-NEXT:    j .LBB2_3
 ; RV32IBS-NEXT:  .LBB2_2:
-; RV32IBS-NEXT:    mv a4, zero
-; RV32IBS-NEXT:    sll a2, a3, a2
+; RV32IBS-NEXT:    mv a3, zero
+; RV32IBS-NEXT:    sbset a2, zero, a2
 ; RV32IBS-NEXT:  .LBB2_3:
-; RV32IBS-NEXT:    not a3, a4
+; RV32IBS-NEXT:    not a3, a3
 ; RV32IBS-NEXT:    not a2, a2
 ; RV32IBS-NEXT:    and a0, a2, a0
 ; RV32IBS-NEXT:    and a1, a3, a1
@@ -165,6 +163,27 @@ define i32 @sbset_i32_no_mask(i32 %a, i32 %b) nounwind {
   ret i32 %or
 }
 
+; We can use sbsetw for 1 << x by setting the first source to zero.
+define signext i32 @sbset_i32_zero(i32 signext %a) nounwind {
+; RV32I-LABEL: sbset_i32_zero:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    addi a1, zero, 1
+; RV32I-NEXT:    sll a0, a1, a0
+; RV32I-NEXT:    ret
+;
+; RV32IB-LABEL: sbset_i32_zero:
+; RV32IB:       # %bb.0:
+; RV32IB-NEXT:    sbset a0, zero, a0
+; RV32IB-NEXT:    ret
+;
+; RV32IBS-LABEL: sbset_i32_zero:
+; RV32IBS:       # %bb.0:
+; RV32IBS-NEXT:    sbset a0, zero, a0
+; RV32IBS-NEXT:    ret
+  %shl = shl i32 1, %a
+  ret i32 %shl
+}
+
 ; As we are not matching directly i64 code patterns on RV32 some i64 patterns
 ; don't have yet any matching bit manipulation instructions on RV32.
 ; This test is presented here in case future expansions of the experimental-b
@@ -182,8 +201,7 @@ define i64 @sbset_i64(i64 %a, i64 %b) nounwind {
 ;
 ; RV32IB-LABEL: sbset_i64:
 ; RV32IB:       # %bb.0:
-; RV32IB-NEXT:    addi a3, zero, 1
-; RV32IB-NEXT:    sll a3, a3, a2
+; RV32IB-NEXT:    sbset a3, zero, a2
 ; RV32IB-NEXT:    srai a3, a3, 31
 ; RV32IB-NEXT:    sbset a0, a0, a2
 ; RV32IB-NEXT:    or a1, a3, a1
@@ -191,8 +209,7 @@ define i64 @sbset_i64(i64 %a, i64 %b) nounwind {
 ;
 ; RV32IBS-LABEL: sbset_i64:
 ; RV32IBS:       # %bb.0:
-; RV32IBS-NEXT:    addi a3, zero, 1
-; RV32IBS-NEXT:    sll a3, a3, a2
+; RV32IBS-NEXT:    sbset a3, zero, a2
 ; RV32IBS-NEXT:    srai a3, a3, 31
 ; RV32IBS-NEXT:    sbset a0, a0, a2
 ; RV32IBS-NEXT:    or a1, a3, a1
@@ -205,6 +222,50 @@ define i64 @sbset_i64(i64 %a, i64 %b) nounwind {
   ret i64 %or
 }
 
+define signext i64 @sbset_i64_zero(i64 signext %a) nounwind {
+; RV32I-LABEL: sbset_i64_zero:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    addi a1, a0, -32
+; RV32I-NEXT:    addi a2, zero, 1
+; RV32I-NEXT:    bltz a1, .LBB7_2
+; RV32I-NEXT:  # %bb.1:
+; RV32I-NEXT:    mv a0, zero
+; RV32I-NEXT:    sll a1, a2, a1
+; RV32I-NEXT:    ret
+; RV32I-NEXT:  .LBB7_2:
+; RV32I-NEXT:    mv a1, zero
+; RV32I-NEXT:    sll a0, a2, a0
+; RV32I-NEXT:    ret
+;
+; RV32IB-LABEL: sbset_i64_zero:
+; RV32IB:       # %bb.0:
+; RV32IB-NEXT:    addi a1, a0, -32
+; RV32IB-NEXT:    bltz a1, .LBB7_2
+; RV32IB-NEXT:  # %bb.1:
+; RV32IB-NEXT:    mv a0, zero
+; RV32IB-NEXT:    sbset a1, zero, a1
+; RV32IB-NEXT:    ret
+; RV32IB-NEXT:  .LBB7_2:
+; RV32IB-NEXT:    mv a1, zero
+; RV32IB-NEXT:    sbset a0, zero, a0
+; RV32IB-NEXT:    ret
+;
+; RV32IBS-LABEL: sbset_i64_zero:
+; RV32IBS:       # %bb.0:
+; RV32IBS-NEXT:    addi a1, a0, -32
+; RV32IBS-NEXT:    bltz a1, .LBB7_2
+; RV32IBS-NEXT:  # %bb.1:
+; RV32IBS-NEXT:    mv a0, zero
+; RV32IBS-NEXT:    sbset a1, zero, a1
+; RV32IBS-NEXT:    ret
+; RV32IBS-NEXT:  .LBB7_2:
+; RV32IBS-NEXT:    mv a1, zero
+; RV32IBS-NEXT:    sbset a0, zero, a0
+; RV32IBS-NEXT:    ret
+  %shl = shl i64 1, %a
+  ret i64 %shl
+}
+
 define i32 @sbinv_i32(i32 %a, i32 %b) nounwind {
 ; RV32I-LABEL: sbinv_i32:
 ; RV32I:       # %bb.0:
@@ -245,8 +306,7 @@ define i64 @sbinv_i64(i64 %a, i64 %b) nounwind {
 ;
 ; RV32IB-LABEL: sbinv_i64:
 ; RV32IB:       # %bb.0:
-; RV32IB-NEXT:    addi a3, zero, 1
-; RV32IB-NEXT:    sll a3, a3, a2
+; RV32IB-NEXT:    sbset a3, zero, a2
 ; RV32IB-NEXT:    srai a3, a3, 31
 ; RV32IB-NEXT:    sbinv a0, a0, a2
 ; RV32IB-NEXT:    xor a1, a3, a1
@@ -254,8 +314,7 @@ define i64 @sbinv_i64(i64 %a, i64 %b) nounwind {
 ;
 ; RV32IBS-LABEL: sbinv_i64:
 ; RV32IBS:       # %bb.0:
-; RV32IBS-NEXT:    addi a3, zero, 1
-; RV32IBS-NEXT:    sll a3, a3, a2
+; RV32IBS-NEXT:    sbset a3, zero, a2
 ; RV32IBS-NEXT:    srai a3, a3, 31
 ; RV32IBS-NEXT:    sbinv a0, a0, a2
 ; RV32IBS-NEXT:    xor a1, a3, a1
@@ -321,18 +380,18 @@ define i64 @sbext_i64(i64 %a, i64 %b) nounwind {
 ; RV32I:       # %bb.0:
 ; RV32I-NEXT:    andi a3, a2, 63
 ; RV32I-NEXT:    addi a4, a3, -32
-; RV32I-NEXT:    bltz a4, .LBB10_2
+; RV32I-NEXT:    bltz a4, .LBB12_2
 ; RV32I-NEXT:  # %bb.1:
 ; RV32I-NEXT:    srl a0, a1, a4
-; RV32I-NEXT:    j .LBB10_3
-; RV32I-NEXT:  .LBB10_2:
+; RV32I-NEXT:    j .LBB12_3
+; RV32I-NEXT:  .LBB12_2:
 ; RV32I-NEXT:    srl a0, a0, a2
 ; RV32I-NEXT:    addi a2, zero, 31
 ; RV32I-NEXT:    sub a2, a2, a3
 ; RV32I-NEXT:    slli a1, a1, 1
 ; RV32I-NEXT:    sll a1, a1, a2
 ; RV32I-NEXT:    or a0, a0, a1
-; RV32I-NEXT:  .LBB10_3:
+; RV32I-NEXT:  .LBB12_3:
 ; RV32I-NEXT:    andi a0, a0, 1
 ; RV32I-NEXT:    mv a1, zero
 ; RV32I-NEXT:    ret
@@ -341,18 +400,18 @@ define i64 @sbext_i64(i64 %a, i64 %b) nounwind {
 ; RV32IB:       # %bb.0:
 ; RV32IB-NEXT:    andi a3, a2, 63
 ; RV32IB-NEXT:    addi a4, a3, -32
-; RV32IB-NEXT:    bltz a4, .LBB10_2
+; RV32IB-NEXT:    bltz a4, .LBB12_2
 ; RV32IB-NEXT:  # %bb.1:
 ; RV32IB-NEXT:    srl a0, a1, a4
-; RV32IB-NEXT:    j .LBB10_3
-; RV32IB-NEXT:  .LBB10_2:
+; RV32IB-NEXT:    j .LBB12_3
+; RV32IB-NEXT:  .LBB12_2:
 ; RV32IB-NEXT:    srl a0, a0, a2
 ; RV32IB-NEXT:    addi a2, zero, 31
 ; RV32IB-NEXT:    sub a2, a2, a3
 ; RV32IB-NEXT:    slli a1, a1, 1
 ; RV32IB-NEXT:    sll a1, a1, a2
 ; RV32IB-NEXT:    or a0, a0, a1
-; RV32IB-NEXT:  .LBB10_3:
+; RV32IB-NEXT:  .LBB12_3:
 ; RV32IB-NEXT:    andi a0, a0, 1
 ; RV32IB-NEXT:    mv a1, zero
 ; RV32IB-NEXT:    ret
@@ -361,18 +420,18 @@ define i64 @sbext_i64(i64 %a, i64 %b) nounwind {
 ; RV32IBS:       # %bb.0:
 ; RV32IBS-NEXT:    andi a3, a2, 63
 ; RV32IBS-NEXT:    addi a4, a3, -32
-; RV32IBS-NEXT:    bltz a4, .LBB10_2
+; RV32IBS-NEXT:    bltz a4, .LBB12_2
 ; RV32IBS-NEXT:  # %bb.1:
 ; RV32IBS-NEXT:    srl a0, a1, a4
-; RV32IBS-NEXT:    j .LBB10_3
-; RV32IBS-NEXT:  .LBB10_2:
+; RV32IBS-NEXT:    j .LBB12_3
+; RV32IBS-NEXT:  .LBB12_2:
 ; RV32IBS-NEXT:    srl a0, a0, a2
 ; RV32IBS-NEXT:    addi a2, zero, 31
 ; RV32IBS-NEXT:    sub a2, a2, a3
 ; RV32IBS-NEXT:    slli a1, a1, 1
 ; RV32IBS-NEXT:    sll a1, a1, a2
 ; RV32IBS-NEXT:    or a0, a0, a1
-; RV32IBS-NEXT:  .LBB10_3:
+; RV32IBS-NEXT:  .LBB12_3:
 ; RV32IBS-NEXT:    andi a0, a0, 1
 ; RV32IBS-NEXT:    mv a1, zero
 ; RV32IBS-NEXT:    ret

diff  --git a/llvm/test/CodeGen/RISCV/rv64Zbs.ll b/llvm/test/CodeGen/RISCV/rv64Zbs.ll
index 85d1bd5b3c2f..e50b7a24c536 100644
--- a/llvm/test/CodeGen/RISCV/rv64Zbs.ll
+++ b/llvm/test/CodeGen/RISCV/rv64Zbs.ll
@@ -205,6 +205,27 @@ define signext i32 @sbset_i32_load(i32* %p, i32 signext %b) nounwind {
   ret i32 %or
 }
 
+; We can use sbsetw for 1 << x by setting the first source to zero.
+define signext i32 @sbset_i32_zero(i32 signext %a) nounwind {
+; RV64I-LABEL: sbset_i32_zero:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    addi a1, zero, 1
+; RV64I-NEXT:    sllw a0, a1, a0
+; RV64I-NEXT:    ret
+;
+; RV64IB-LABEL: sbset_i32_zero:
+; RV64IB:       # %bb.0:
+; RV64IB-NEXT:    sbsetw a0, zero, a0
+; RV64IB-NEXT:    ret
+;
+; RV64IBS-LABEL: sbset_i32_zero:
+; RV64IBS:       # %bb.0:
+; RV64IBS-NEXT:    sbsetw a0, zero, a0
+; RV64IBS-NEXT:    ret
+  %shl = shl i32 1, %a
+  ret i32 %shl
+}
+
 define i64 @sbset_i64(i64 %a, i64 %b) nounwind {
 ; RV64I-LABEL: sbset_i64:
 ; RV64I:       # %bb.0:
@@ -250,6 +271,27 @@ define i64 @sbset_i64_no_mask(i64 %a, i64 %b) nounwind {
   ret i64 %or
 }
 
+; We can use sbsetw for 1 << x by setting the first source to zero.
+define signext i64 @sbset_i64_zero(i64 signext %a) nounwind {
+; RV64I-LABEL: sbset_i64_zero:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    addi a1, zero, 1
+; RV64I-NEXT:    sll a0, a1, a0
+; RV64I-NEXT:    ret
+;
+; RV64IB-LABEL: sbset_i64_zero:
+; RV64IB:       # %bb.0:
+; RV64IB-NEXT:    sbset a0, zero, a0
+; RV64IB-NEXT:    ret
+;
+; RV64IBS-LABEL: sbset_i64_zero:
+; RV64IBS:       # %bb.0:
+; RV64IBS-NEXT:    sbset a0, zero, a0
+; RV64IBS-NEXT:    ret
+  %shl = shl i64 1, %a
+  ret i64 %shl
+}
+
 define signext i32 @sbinv_i32(i32 signext %a, i32 signext %b) nounwind {
 ; RV64I-LABEL: sbinv_i32:
 ; RV64I:       # %bb.0:


        


More information about the llvm-commits mailing list