-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[RISCV] Select (and (sra x, c2), c1) as (srli (srai x, c2-c3), c3). #101868
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
If c1 is a mask with c3 leading zeros and c3 is larger than c2. Fixes regression reported in llvm#101751.
@llvm/pr-subscribers-backend-risc-v Author: Craig Topper (topperc) ChangesIf c1 is a mask with c3 leading zeros and c3 is larger than c2. Fixes regression reported in #101751. Full diff: https://github.com/llvm/llvm-project/pull/101868.diff 3 Files Affected:
diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index 31f48a6ac24d7..f1f345d65854e 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -1449,6 +1449,31 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
}
}
+ // Turn (and (srl x, c2), c1) -> (srli (srai x, c2-c3)) if c1 is a mask with
+ // c3 leading zeros and c2 is larger than c3.
+ if (N0.getOpcode() == ISD::SRA && isa<ConstantSDNode>(N0.getOperand(1)) &&
+ N0.hasOneUse()) {
+ unsigned C2 = N0.getConstantOperandVal(1);
+ unsigned XLen = Subtarget->getXLen();
+ assert((C2 > 0 && C2 < XLen) && "Unexpected shift amount!");
+
+ SDValue X = N0.getOperand(0);
+
+ if (isMask_64(C1)) {
+ unsigned Leading = XLen - llvm::bit_width(C1);
+ if (C2 > Leading) {
+ SDNode *SRAI = CurDAG->getMachineNode(
+ RISCV::SRAI, DL, VT, X,
+ CurDAG->getTargetConstant(C2 - Leading, DL, VT));
+ SDNode *SRLI = CurDAG->getMachineNode(
+ RISCV::SRLI, DL, VT, SDValue(SRAI, 0),
+ CurDAG->getTargetConstant(Leading, DL, VT));
+ ReplaceNode(Node, SRLI);
+ return;
+ }
+ }
+ }
+
// If C1 masks off the upper bits only (but can't be formed as an
// ANDI), use an unsigned bitfield extract (e.g., th.extu), if
// available.
diff --git a/llvm/test/CodeGen/RISCV/lack-of-signed-truncation-check.ll b/llvm/test/CodeGen/RISCV/lack-of-signed-truncation-check.ll
index 6e3a50542939f..c7ba0e501fa44 100644
--- a/llvm/test/CodeGen/RISCV/lack-of-signed-truncation-check.ll
+++ b/llvm/test/CodeGen/RISCV/lack-of-signed-truncation-check.ll
@@ -24,25 +24,23 @@
define i1 @shifts_necmp_i16_i8(i16 %x) nounwind {
; RV32I-LABEL: shifts_necmp_i16_i8:
; RV32I: # %bb.0:
-; RV32I-NEXT: lui a1, 16
-; RV32I-NEXT: addi a1, a1, -1
-; RV32I-NEXT: and a2, a0, a1
+; RV32I-NEXT: slli a1, a0, 16
+; RV32I-NEXT: srli a1, a1, 16
; RV32I-NEXT: slli a0, a0, 24
-; RV32I-NEXT: srai a0, a0, 24
-; RV32I-NEXT: and a0, a0, a1
-; RV32I-NEXT: xor a0, a0, a2
+; RV32I-NEXT: srai a0, a0, 8
+; RV32I-NEXT: srli a0, a0, 16
+; RV32I-NEXT: xor a0, a0, a1
; RV32I-NEXT: snez a0, a0
; RV32I-NEXT: ret
;
; RV64I-LABEL: shifts_necmp_i16_i8:
; RV64I: # %bb.0:
-; RV64I-NEXT: lui a1, 16
-; RV64I-NEXT: addiw a1, a1, -1
-; RV64I-NEXT: and a2, a0, a1
+; RV64I-NEXT: slli a1, a0, 48
+; RV64I-NEXT: srli a1, a1, 48
; RV64I-NEXT: slli a0, a0, 56
-; RV64I-NEXT: srai a0, a0, 56
-; RV64I-NEXT: and a0, a0, a1
-; RV64I-NEXT: xor a0, a0, a2
+; RV64I-NEXT: srai a0, a0, 8
+; RV64I-NEXT: srli a0, a0, 48
+; RV64I-NEXT: xor a0, a0, a1
; RV64I-NEXT: snez a0, a0
; RV64I-NEXT: ret
;
diff --git a/llvm/test/CodeGen/RISCV/signed-truncation-check.ll b/llvm/test/CodeGen/RISCV/signed-truncation-check.ll
index de36bcdb91060..54b85fab757ca 100644
--- a/llvm/test/CodeGen/RISCV/signed-truncation-check.ll
+++ b/llvm/test/CodeGen/RISCV/signed-truncation-check.ll
@@ -24,25 +24,23 @@
define i1 @shifts_eqcmp_i16_i8(i16 %x) nounwind {
; RV32I-LABEL: shifts_eqcmp_i16_i8:
; RV32I: # %bb.0:
-; RV32I-NEXT: lui a1, 16
-; RV32I-NEXT: addi a1, a1, -1
-; RV32I-NEXT: and a2, a0, a1
+; RV32I-NEXT: slli a1, a0, 16
+; RV32I-NEXT: srli a1, a1, 16
; RV32I-NEXT: slli a0, a0, 24
-; RV32I-NEXT: srai a0, a0, 24
-; RV32I-NEXT: and a0, a0, a1
-; RV32I-NEXT: xor a0, a0, a2
+; RV32I-NEXT: srai a0, a0, 8
+; RV32I-NEXT: srli a0, a0, 16
+; RV32I-NEXT: xor a0, a0, a1
; RV32I-NEXT: seqz a0, a0
; RV32I-NEXT: ret
;
; RV64I-LABEL: shifts_eqcmp_i16_i8:
; RV64I: # %bb.0:
-; RV64I-NEXT: lui a1, 16
-; RV64I-NEXT: addiw a1, a1, -1
-; RV64I-NEXT: and a2, a0, a1
+; RV64I-NEXT: slli a1, a0, 48
+; RV64I-NEXT: srli a1, a1, 48
; RV64I-NEXT: slli a0, a0, 56
-; RV64I-NEXT: srai a0, a0, 56
-; RV64I-NEXT: and a0, a0, a1
-; RV64I-NEXT: xor a0, a0, a2
+; RV64I-NEXT: srai a0, a0, 8
+; RV64I-NEXT: srli a0, a0, 48
+; RV64I-NEXT: xor a0, a0, a1
; RV64I-NEXT: seqz a0, a0
; RV64I-NEXT: ret
;
|
@@ -1449,6 +1449,31 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) { | |||
} | |||
} | |||
|
|||
// Turn (and (srl x, c2), c1) -> (srli (srai x, c2-c3)) if c1 is a mask with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Turn (and (srl x, c2), c1) -> (srli (srai x, c2-c3)) if c1 is a mask with | |
// Turn (and (sra x, c2), c1) -> (srli (srai x, c2-c3), c3) if c1 is a mask with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
Please add the following regression test (extracted from quickjs): https://godbolt.org/z/n4GsEPh4d
define i64 @func000000000000000a(i32 signext %0, i32 signext %1) nounwind {
entry:
%3 = add i32 %0, %1
%4 = icmp sgt i32 %3, -1
%5 = select i1 %4, i64 0, i64 7
ret i64 %5
}
Before:
func000000000000000a: # @func000000000000000a
add a0, a0, a1
sraiw a0, a0, 31
andi a0, a0, 7
ret
After:
func000000000000000a: # @func000000000000000a
add a0, a0, a1
slli a0, a0, 32
srai a0, a0, 2
srli a0, a0, 61
ret
I wouldn't like to block this patch since the net effect looks good. We can fix this minor regression to avoid stacking too many patches :)
@@ -1449,6 +1449,31 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) { | |||
} | |||
} | |||
|
|||
// Turn (and (sra x, c2), c1) -> (srli (srai x, c2-c3)) if c1 is a mask with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Turn (and (sra x, c2), c1) -> (srli (srai x, c2-c3)) if c1 is a mask with | |
// Turn (and (sra x, c2), c1) -> (srli (srai x, c2-c3), c3) if c1 is a mask with |
If c1 is a mask with c3 leading zeros and c3 is larger than c2.
Fixes regression reported in #101751.