[llvm] 6a54776 - [RISCV] Select SRLI+SLLI for AND with leading ones mask

Ben Shi via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 15 19:11:12 PDT 2022


Author: Haocong.Lu
Date: 2022-03-16T02:10:57Z
New Revision: 6a54776fe0092c251ee3783c0c25d14699467896

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

LOG: [RISCV] Select SRLI+SLLI for AND with leading ones mask

Select SRLI+SLLI for and i64 %x, imm if the imm is a leading ones mask.
It's useful in RV64 when the mask exceeds simm32 (cannot be generated by LUI).

Reviewed By: craig.topper

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

Added: 
    

Modified: 
    llvm/lib/Target/RISCV/RISCVInstrInfo.td
    llvm/test/CodeGen/RISCV/and.ll
    llvm/test/CodeGen/RISCV/copysign-casts.ll
    llvm/test/CodeGen/RISCV/double-arith.ll
    llvm/test/CodeGen/RISCV/double-bitmanip-dagcombines.ll
    llvm/test/CodeGen/RISCV/double-intrinsics.ll
    llvm/test/CodeGen/RISCV/rv64zbp.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index b7fd6ab409333..8362cb4c6bb8b 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -415,6 +415,11 @@ def AddiPairImmB : SDNodeXForm<imm, [{
                                    N->getValueType(0));
 }]>;
 
+def TrailingZeros : SDNodeXForm<imm, [{
+  return CurDAG->getTargetConstant(N->getAPIntValue().countTrailingZeros(),
+                                   SDLoc(N), N->getValueType(0));
+}]>;
+
 def XLenSubTrailingOnes : SDNodeXForm<imm, [{
   uint64_t XLen = Subtarget->getXLen();
   uint64_t TrailingOnes = N->getAPIntValue().countTrailingOnes();
@@ -423,7 +428,13 @@ def XLenSubTrailingOnes : SDNodeXForm<imm, [{
 }]>;
 
 // Checks if this mask is a non-empty sequence of ones starting at the
-// least significant bit with the remainder zero and exceeds simm12.
+// most/least significant bit with the remainder zero and exceeds simm32/simm12.
+def LeadingOnesMask : PatLeaf<(imm), [{
+  if (!N->hasOneUse())
+    return false;
+  return !isInt<32>(N->getSExtValue()) && isMask_64(~N->getSExtValue());
+}], TrailingZeros>;
+
 def TrailingOnesMask : PatLeaf<(imm), [{
   if (!N->hasOneUse())
     return false;
@@ -1134,7 +1145,9 @@ def : PatGprUimmLog2XLen<shl, SLLI>;
 def : PatGprUimmLog2XLen<srl, SRLI>;
 def : PatGprUimmLog2XLen<sra, SRAI>;
 
-// AND with trailing ones mask exceeding simm12.
+// AND with leading/trailing ones mask exceeding simm32/simm12.
+def : Pat<(i64 (and GPR:$rs, LeadingOnesMask:$mask)),
+          (SLLI (SRLI $rs, LeadingOnesMask:$mask), LeadingOnesMask:$mask)>;
 def : Pat<(XLenVT (and GPR:$rs, TrailingOnesMask:$mask)),
           (SRLI (SLLI $rs, TrailingOnesMask:$mask), TrailingOnesMask:$mask)>;
 

diff  --git a/llvm/test/CodeGen/RISCV/and.ll b/llvm/test/CodeGen/RISCV/and.ll
index 825354114c5a7..ccf937a4bd5cd 100644
--- a/llvm/test/CodeGen/RISCV/and.ll
+++ b/llvm/test/CodeGen/RISCV/and.ll
@@ -70,6 +70,26 @@ define i64 @and64_0xfff(i64 %x) {
   ret i64 %a
 }
 
+; Test for handling of AND with constant. If this constant exceeds simm32 and
+; also is a non-empty sequence of ones starting at the most significant bit
+; with the remainder zero, we can replace it with SRLI + SLLI.
+
+define i32 @and32_0x7ffff000(i32 %x) {
+; RV32I-LABEL: and32_0x7ffff000:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    lui a1, 524287
+; RV32I-NEXT:    and a0, a0, a1
+; RV32I-NEXT:    ret
+;
+; RV64I-LABEL: and32_0x7ffff000:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    lui a1, 524287
+; RV64I-NEXT:    and a0, a0, a1
+; RV64I-NEXT:    ret
+  %a = and i32 %x, 2147479552
+  ret i32 %a
+}
+
 define i32 @and32_0xfffff000(i32 %x) {
 ; RV32I-LABEL: and32_0xfffff000:
 ; RV32I:       # %bb.0:
@@ -99,3 +119,102 @@ define i32 @and32_0xfffffa00(i32 %x) {
   %a = and i32 %x, -1536
   ret i32 %a
 }
+
+define i64 @and64_0x7ffffffffffff000(i64 %x) {
+; RV32I-LABEL: and64_0x7ffffffffffff000:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    lui a2, 1048575
+; RV32I-NEXT:    and a0, a0, a2
+; RV32I-NEXT:    slli a1, a1, 1
+; RV32I-NEXT:    srli a1, a1, 1
+; RV32I-NEXT:    ret
+;
+; RV64I-LABEL: and64_0x7ffffffffffff000:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    lui a1, 1048574
+; RV64I-NEXT:    srli a1, a1, 1
+; RV64I-NEXT:    and a0, a0, a1
+; RV64I-NEXT:    ret
+  %a = and i64 %x, 9223372036854771712
+  ret i64 %a
+}
+
+define i64 @and64_0xfffffffffffff000(i64 %x) {
+; RV32I-LABEL: and64_0xfffffffffffff000:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    lui a2, 1048575
+; RV32I-NEXT:    and a0, a0, a2
+; RV32I-NEXT:    ret
+;
+; RV64I-LABEL: and64_0xfffffffffffff000:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    lui a1, 1048575
+; RV64I-NEXT:    and a0, a0, a1
+; RV64I-NEXT:    ret
+  %a = and i64 %x, -4096
+  ret i64 %a
+}
+
+define i64 @and64_0xfffffffffffffa00(i64 %x) {
+; RV32I-LABEL: and64_0xfffffffffffffa00:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    andi a0, a0, -1536
+; RV32I-NEXT:    ret
+;
+; RV64I-LABEL: and64_0xfffffffffffffa00:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    andi a0, a0, -1536
+; RV64I-NEXT:    ret
+  %a = and i64 %x, -1536
+  ret i64 %a
+}
+
+define i64 @and64_0xffffffff00000000(i64 %x) {
+; RV32I-LABEL: and64_0xffffffff00000000:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    li a0, 0
+; RV32I-NEXT:    ret
+;
+; RV64I-LABEL: and64_0xffffffff00000000:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    srli a0, a0, 32
+; RV64I-NEXT:    slli a0, a0, 32
+; RV64I-NEXT:    ret
+  %a = and i64 %x, -4294967296
+  ret i64 %a
+}
+
+define i64 @and64_0x7fffffff00000000(i64 %x) {
+; RV32I-LABEL: and64_0x7fffffff00000000:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    slli a0, a1, 1
+; RV32I-NEXT:    srli a1, a0, 1
+; RV32I-NEXT:    li a0, 0
+; RV32I-NEXT:    ret
+;
+; RV64I-LABEL: and64_0x7fffffff00000000:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    lui a1, 524288
+; RV64I-NEXT:    addiw a1, a1, -1
+; RV64I-NEXT:    slli a1, a1, 32
+; RV64I-NEXT:    and a0, a0, a1
+; RV64I-NEXT:    ret
+  %a = and i64 %x, 9223372032559808512
+  ret i64 %a
+}
+
+define i64 @and64_0xffffffff80000000(i64 %x) {
+; RV32I-LABEL: and64_0xffffffff80000000:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    lui a2, 524288
+; RV32I-NEXT:    and a0, a0, a2
+; RV32I-NEXT:    ret
+;
+; RV64I-LABEL: and64_0xffffffff80000000:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    lui a1, 524288
+; RV64I-NEXT:    and a0, a0, a1
+; RV64I-NEXT:    ret
+  %a = and i64 %x, -2147483648
+  ret i64 %a
+}

diff  --git a/llvm/test/CodeGen/RISCV/copysign-casts.ll b/llvm/test/CodeGen/RISCV/copysign-casts.ll
index 01ddd45783038..42ea6958a9d1b 100644
--- a/llvm/test/CodeGen/RISCV/copysign-casts.ll
+++ b/llvm/test/CodeGen/RISCV/copysign-casts.ll
@@ -280,12 +280,11 @@ define float @fold_demote_s_d(float %a, double %b) nounwind {
 ;
 ; RV64I-LABEL: fold_demote_s_d:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    li a2, -1
-; RV64I-NEXT:    slli a2, a2, 63
-; RV64I-NEXT:    and a1, a1, a2
-; RV64I-NEXT:    srli a1, a1, 32
 ; RV64I-NEXT:    slli a0, a0, 33
 ; RV64I-NEXT:    srli a0, a0, 33
+; RV64I-NEXT:    srli a1, a1, 63
+; RV64I-NEXT:    slli a1, a1, 63
+; RV64I-NEXT:    srli a1, a1, 32
 ; RV64I-NEXT:    or a0, a0, a1
 ; RV64I-NEXT:    ret
 ;
@@ -431,12 +430,11 @@ define half @fold_demote_h_d(half %a, double %b) nounwind {
 ;
 ; RV64I-LABEL: fold_demote_h_d:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    li a2, -1
-; RV64I-NEXT:    slli a2, a2, 63
-; RV64I-NEXT:    and a1, a1, a2
-; RV64I-NEXT:    srli a1, a1, 48
 ; RV64I-NEXT:    slli a0, a0, 49
 ; RV64I-NEXT:    srli a0, a0, 49
+; RV64I-NEXT:    srli a1, a1, 63
+; RV64I-NEXT:    slli a1, a1, 63
+; RV64I-NEXT:    srli a1, a1, 48
 ; RV64I-NEXT:    or a0, a0, a1
 ; RV64I-NEXT:    ret
 ;
@@ -474,15 +472,14 @@ define half @fold_demote_h_d(half %a, double %b) nounwind {
 ;
 ; RV64IFD-LABEL: fold_demote_h_d:
 ; RV64IFD:       # %bb.0:
-; RV64IFD-NEXT:    fmv.x.w a0, fa0
-; RV64IFD-NEXT:    fmv.x.d a1, fa1
-; RV64IFD-NEXT:    li a2, -1
-; RV64IFD-NEXT:    slli a2, a2, 63
-; RV64IFD-NEXT:    and a1, a1, a2
-; RV64IFD-NEXT:    srli a1, a1, 48
-; RV64IFD-NEXT:    slli a0, a0, 49
-; RV64IFD-NEXT:    srli a0, a0, 49
-; RV64IFD-NEXT:    or a0, a0, a1
+; RV64IFD-NEXT:    fmv.x.d a0, fa1
+; RV64IFD-NEXT:    fmv.x.w a1, fa0
+; RV64IFD-NEXT:    slli a1, a1, 49
+; RV64IFD-NEXT:    srli a1, a1, 49
+; RV64IFD-NEXT:    srli a0, a0, 63
+; RV64IFD-NEXT:    slli a0, a0, 63
+; RV64IFD-NEXT:    srli a0, a0, 48
+; RV64IFD-NEXT:    or a0, a1, a0
 ; RV64IFD-NEXT:    lui a1, 1048560
 ; RV64IFD-NEXT:    or a0, a0, a1
 ; RV64IFD-NEXT:    fmv.w.x fa0, a0

diff  --git a/llvm/test/CodeGen/RISCV/double-arith.ll b/llvm/test/CodeGen/RISCV/double-arith.ll
index 55c710dbf95d9..9e476a7db2f94 100644
--- a/llvm/test/CodeGen/RISCV/double-arith.ll
+++ b/llvm/test/CodeGen/RISCV/double-arith.ll
@@ -199,9 +199,8 @@ define double @fsgnj_d(double %a, double %b) nounwind {
 ;
 ; RV64I-LABEL: fsgnj_d:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    li a2, -1
-; RV64I-NEXT:    slli a2, a2, 63
-; RV64I-NEXT:    and a1, a1, a2
+; RV64I-NEXT:    srli a1, a1, 63
+; RV64I-NEXT:    slli a1, a1, 63
 ; RV64I-NEXT:    slli a0, a0, 1
 ; RV64I-NEXT:    srli a0, a0, 1
 ; RV64I-NEXT:    or a0, a0, a1
@@ -291,11 +290,10 @@ define double @fsgnjn_d(double %a, double %b) nounwind {
 ; RV64I-LABEL: fsgnjn_d:
 ; RV64I:       # %bb.0:
 ; RV64I-NEXT:    not a1, a1
-; RV64I-NEXT:    li a2, -1
-; RV64I-NEXT:    slli a2, a2, 63
-; RV64I-NEXT:    and a1, a1, a2
 ; RV64I-NEXT:    slli a0, a0, 1
 ; RV64I-NEXT:    srli a0, a0, 1
+; RV64I-NEXT:    srli a1, a1, 63
+; RV64I-NEXT:    slli a1, a1, 63
 ; RV64I-NEXT:    or a0, a0, a1
 ; RV64I-NEXT:    ret
   %1 = fsub double -0.0, %b

diff  --git a/llvm/test/CodeGen/RISCV/double-bitmanip-dagcombines.ll b/llvm/test/CodeGen/RISCV/double-bitmanip-dagcombines.ll
index 1b1c2620f0462..25ffd32f5ccbb 100644
--- a/llvm/test/CodeGen/RISCV/double-bitmanip-dagcombines.ll
+++ b/llvm/test/CodeGen/RISCV/double-bitmanip-dagcombines.ll
@@ -113,11 +113,10 @@ define double @fcopysign_fneg(double %a, double %b) nounwind {
 ; RV64I-LABEL: fcopysign_fneg:
 ; RV64I:       # %bb.0:
 ; RV64I-NEXT:    not a1, a1
-; RV64I-NEXT:    li a2, -1
-; RV64I-NEXT:    slli a2, a2, 63
-; RV64I-NEXT:    and a1, a1, a2
 ; RV64I-NEXT:    slli a0, a0, 1
 ; RV64I-NEXT:    srli a0, a0, 1
+; RV64I-NEXT:    srli a1, a1, 63
+; RV64I-NEXT:    slli a1, a1, 63
 ; RV64I-NEXT:    or a0, a0, a1
 ; RV64I-NEXT:    ret
 ;

diff  --git a/llvm/test/CodeGen/RISCV/double-intrinsics.ll b/llvm/test/CodeGen/RISCV/double-intrinsics.ll
index 303d503af7f77..84b9c27bcee46 100644
--- a/llvm/test/CodeGen/RISCV/double-intrinsics.ll
+++ b/llvm/test/CodeGen/RISCV/double-intrinsics.ll
@@ -735,9 +735,8 @@ define double @copysign_f64(double %a, double %b) nounwind {
 ;
 ; RV64I-LABEL: copysign_f64:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    li a2, -1
-; RV64I-NEXT:    slli a2, a2, 63
-; RV64I-NEXT:    and a1, a1, a2
+; RV64I-NEXT:    srli a1, a1, 63
+; RV64I-NEXT:    slli a1, a1, 63
 ; RV64I-NEXT:    slli a0, a0, 1
 ; RV64I-NEXT:    srli a0, a0, 1
 ; RV64I-NEXT:    or a0, a0, a1

diff  --git a/llvm/test/CodeGen/RISCV/rv64zbp.ll b/llvm/test/CodeGen/RISCV/rv64zbp.ll
index a14053a260b84..8dc9816a6087a 100644
--- a/llvm/test/CodeGen/RISCV/rv64zbp.ll
+++ b/llvm/test/CodeGen/RISCV/rv64zbp.ll
@@ -3279,9 +3279,8 @@ define i64 @packu_i64(i64 %a, i64 %b) nounwind {
 ; RV64I-LABEL: packu_i64:
 ; RV64I:       # %bb.0:
 ; RV64I-NEXT:    srli a0, a0, 32
-; RV64I-NEXT:    li a2, -1
-; RV64I-NEXT:    slli a2, a2, 32
-; RV64I-NEXT:    and a1, a1, a2
+; RV64I-NEXT:    srli a1, a1, 32
+; RV64I-NEXT:    slli a1, a1, 32
 ; RV64I-NEXT:    or a0, a1, a0
 ; RV64I-NEXT:    ret
 ;


        


More information about the llvm-commits mailing list