[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