[RISCV] Select SRLI+SLLI for AND with leading ones mask
authorHaocong.Lu <Haocong.Lu@streamcomputing.com>
Wed, 16 Mar 2022 02:07:21 +0000 (02:07 +0000)
committerBen Shi <ben.shi@streamcomputing.com>
Wed, 16 Mar 2022 02:10:57 +0000 (02:10 +0000)
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

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

index b7fd6ab..8362cb4 100644 (file)
@@ -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)>;
 
index 8253541..ccf937a 100644 (file)
@@ -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
+}
index 01ddd45..42ea695 100644 (file)
@@ -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
index 55c710d..9e476a7 100644 (file)
@@ -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
index 1b1c262..25ffd32 100644 (file)
@@ -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
 ;
index 303d503..84b9c27 100644 (file)
@@ -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
index a14053a..8dc9816 100644 (file)
@@ -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
 ;