-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[RISCV][SDAG] Fold select c, ~x, x
into xor -c, x
#82462
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
@llvm/pr-subscribers-backend-risc-v Author: Yingwei Zheng (dtcxzyw) ChangesThis patch lowers select of constants if NOTE: I initially implement it in Full diff: https://github.com/llvm/llvm-project/pull/82462.diff 2 Files Affected:
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 9ab6895aed521e..83c9b272963f46 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -7237,6 +7237,16 @@ static SDValue combineSelectToBinOp(SDNode *N, SelectionDAG &DAG,
}
}
+ // select c, ~x, x --> xor -c, x
+ if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV)) {
+ const APInt &TrueVal = TrueV->getAsAPIntVal();
+ const APInt &FalseVal = FalseV->getAsAPIntVal();
+ if (~TrueVal == FalseVal) {
+ SDValue Neg = DAG.getNegative(CondV, DL, VT);
+ return DAG.getNode(ISD::XOR, DL, VT, Neg, FalseV);
+ }
+ }
+
// Try to fold (select (setcc lhs, rhs, cc), truev, falsev) into bitwise ops
// when both truev and falsev are also setcc.
if (CondV.getOpcode() == ISD::SETCC && TrueV.getOpcode() == ISD::SETCC &&
diff --git a/llvm/test/CodeGen/RISCV/select.ll b/llvm/test/CodeGen/RISCV/select.ll
index 7dd223df5e557e..e01984b7c5843a 100644
--- a/llvm/test/CodeGen/RISCV/select.ll
+++ b/llvm/test/CodeGen/RISCV/select.ll
@@ -1449,3 +1449,180 @@ entry:
%res = select i1 %cond, i32 %a, i32 %c
ret i32 %res
}
+
+define i32 @select_cst_not1(i32 signext %a, i32 signext %b) {
+; CHECK-LABEL: select_cst_not1:
+; CHECK: # %bb.0:
+; CHECK-NEXT: slt a0, a0, a1
+; CHECK-NEXT: neg a0, a0
+; CHECK-NEXT: xori a0, a0, -6
+; CHECK-NEXT: ret
+ %cond = icmp slt i32 %a, %b
+ %ret = select i1 %cond, i32 5, i32 -6
+ ret i32 %ret
+}
+
+define i32 @select_cst_not2(i32 signext %a) {
+; CHECK-LABEL: select_cst_not2:
+; CHECK: # %bb.0:
+; CHECK-NEXT: srai a0, a0, 31
+; CHECK-NEXT: xori a0, a0, -6
+; CHECK-NEXT: ret
+ %cond = icmp slt i32 %a, 0
+ %ret = select i1 %cond, i32 5, i32 -6
+ ret i32 %ret
+}
+
+define i32 @select_cst_not3(i32 signext %a) {
+; CHECK-LABEL: select_cst_not3:
+; CHECK: # %bb.0:
+; CHECK-NEXT: srai a0, a0, 31
+; CHECK-NEXT: xori a0, a0, 5
+; CHECK-NEXT: ret
+ %cond = icmp sgt i32 %a, -1
+ %ret = select i1 %cond, i32 5, i32 -6
+ ret i32 %ret
+}
+
+define i32 @select_cst_not4(i32 signext %a, i32 signext %b) {
+; RV32IM-LABEL: select_cst_not4:
+; RV32IM: # %bb.0:
+; RV32IM-NEXT: slt a0, a0, a1
+; RV32IM-NEXT: lui a1, 524288
+; RV32IM-NEXT: addi a1, a1, -1
+; RV32IM-NEXT: add a0, a0, a1
+; RV32IM-NEXT: ret
+;
+; RV64IM-LABEL: select_cst_not4:
+; RV64IM: # %bb.0:
+; RV64IM-NEXT: slt a0, a0, a1
+; RV64IM-NEXT: neg a0, a0
+; RV64IM-NEXT: lui a1, 524288
+; RV64IM-NEXT: addiw a1, a1, -1
+; RV64IM-NEXT: xor a0, a0, a1
+; RV64IM-NEXT: ret
+;
+; RV64IMXVTCONDOPS-LABEL: select_cst_not4:
+; RV64IMXVTCONDOPS: # %bb.0:
+; RV64IMXVTCONDOPS-NEXT: slt a0, a0, a1
+; RV64IMXVTCONDOPS-NEXT: neg a0, a0
+; RV64IMXVTCONDOPS-NEXT: lui a1, 524288
+; RV64IMXVTCONDOPS-NEXT: addiw a1, a1, -1
+; RV64IMXVTCONDOPS-NEXT: xor a0, a0, a1
+; RV64IMXVTCONDOPS-NEXT: ret
+;
+; RV32IMZICOND-LABEL: select_cst_not4:
+; RV32IMZICOND: # %bb.0:
+; RV32IMZICOND-NEXT: slt a0, a0, a1
+; RV32IMZICOND-NEXT: lui a1, 524288
+; RV32IMZICOND-NEXT: addi a1, a1, -1
+; RV32IMZICOND-NEXT: add a0, a0, a1
+; RV32IMZICOND-NEXT: ret
+;
+; RV64IMZICOND-LABEL: select_cst_not4:
+; RV64IMZICOND: # %bb.0:
+; RV64IMZICOND-NEXT: slt a0, a0, a1
+; RV64IMZICOND-NEXT: neg a0, a0
+; RV64IMZICOND-NEXT: lui a1, 524288
+; RV64IMZICOND-NEXT: addiw a1, a1, -1
+; RV64IMZICOND-NEXT: xor a0, a0, a1
+; RV64IMZICOND-NEXT: ret
+ %cond = icmp slt i32 %a, %b
+ %ret = select i1 %cond, i32 -2147483648, i32 2147483647
+ ret i32 %ret
+}
+
+define i32 @select_cst_not5(i32 signext %a, i32 signext %b) {
+; RV32IM-LABEL: select_cst_not5:
+; RV32IM: # %bb.0:
+; RV32IM-NEXT: slt a0, a0, a1
+; RV32IM-NEXT: neg a0, a0
+; RV32IM-NEXT: lui a1, 16
+; RV32IM-NEXT: addi a1, a1, -5
+; RV32IM-NEXT: xor a0, a0, a1
+; RV32IM-NEXT: ret
+;
+; RV64IM-LABEL: select_cst_not5:
+; RV64IM: # %bb.0:
+; RV64IM-NEXT: slt a0, a0, a1
+; RV64IM-NEXT: neg a0, a0
+; RV64IM-NEXT: lui a1, 16
+; RV64IM-NEXT: addiw a1, a1, -5
+; RV64IM-NEXT: xor a0, a0, a1
+; RV64IM-NEXT: ret
+;
+; RV64IMXVTCONDOPS-LABEL: select_cst_not5:
+; RV64IMXVTCONDOPS: # %bb.0:
+; RV64IMXVTCONDOPS-NEXT: slt a0, a0, a1
+; RV64IMXVTCONDOPS-NEXT: neg a0, a0
+; RV64IMXVTCONDOPS-NEXT: lui a1, 16
+; RV64IMXVTCONDOPS-NEXT: addiw a1, a1, -5
+; RV64IMXVTCONDOPS-NEXT: xor a0, a0, a1
+; RV64IMXVTCONDOPS-NEXT: ret
+;
+; RV32IMZICOND-LABEL: select_cst_not5:
+; RV32IMZICOND: # %bb.0:
+; RV32IMZICOND-NEXT: slt a0, a0, a1
+; RV32IMZICOND-NEXT: neg a0, a0
+; RV32IMZICOND-NEXT: lui a1, 16
+; RV32IMZICOND-NEXT: addi a1, a1, -5
+; RV32IMZICOND-NEXT: xor a0, a0, a1
+; RV32IMZICOND-NEXT: ret
+;
+; RV64IMZICOND-LABEL: select_cst_not5:
+; RV64IMZICOND: # %bb.0:
+; RV64IMZICOND-NEXT: slt a0, a0, a1
+; RV64IMZICOND-NEXT: neg a0, a0
+; RV64IMZICOND-NEXT: lui a1, 16
+; RV64IMZICOND-NEXT: addiw a1, a1, -5
+; RV64IMZICOND-NEXT: xor a0, a0, a1
+; RV64IMZICOND-NEXT: ret
+ %cond = icmp slt i32 %a, %b
+ %ret = select i1 %cond, i32 -65532, i32 65531
+ ret i32 %ret
+}
+
+define i32 @select_cst_unknown(i32 signext %a, i32 signext %b) {
+; RV32IM-LABEL: select_cst_unknown:
+; RV32IM: # %bb.0:
+; RV32IM-NEXT: mv a2, a0
+; RV32IM-NEXT: li a0, 5
+; RV32IM-NEXT: blt a2, a1, .LBB42_2
+; RV32IM-NEXT: # %bb.1:
+; RV32IM-NEXT: li a0, -7
+; RV32IM-NEXT: .LBB42_2:
+; RV32IM-NEXT: ret
+;
+; RV64IM-LABEL: select_cst_unknown:
+; RV64IM: # %bb.0:
+; RV64IM-NEXT: mv a2, a0
+; RV64IM-NEXT: li a0, 5
+; RV64IM-NEXT: blt a2, a1, .LBB42_2
+; RV64IM-NEXT: # %bb.1:
+; RV64IM-NEXT: li a0, -7
+; RV64IM-NEXT: .LBB42_2:
+; RV64IM-NEXT: ret
+;
+; RV64IMXVTCONDOPS-LABEL: select_cst_unknown:
+; RV64IMXVTCONDOPS: # %bb.0:
+; RV64IMXVTCONDOPS-NEXT: slt a0, a0, a1
+; RV64IMXVTCONDOPS-NEXT: li a1, -7
+; RV64IMXVTCONDOPS-NEXT: vt.maskcn a1, a1, a0
+; RV64IMXVTCONDOPS-NEXT: li a2, 5
+; RV64IMXVTCONDOPS-NEXT: vt.maskc a0, a2, a0
+; RV64IMXVTCONDOPS-NEXT: or a0, a0, a1
+; RV64IMXVTCONDOPS-NEXT: ret
+;
+; CHECKZICOND-LABEL: select_cst_unknown:
+; CHECKZICOND: # %bb.0:
+; CHECKZICOND-NEXT: slt a0, a0, a1
+; CHECKZICOND-NEXT: li a1, -7
+; CHECKZICOND-NEXT: czero.nez a1, a1, a0
+; CHECKZICOND-NEXT: li a2, 5
+; CHECKZICOND-NEXT: czero.eqz a0, a2, a0
+; CHECKZICOND-NEXT: or a0, a0, a1
+; CHECKZICOND-NEXT: ret
+ %cond = icmp slt i32 %a, %b
+ %ret = select i1 %cond, i32 5, i32 -7
+ ret i32 %ret
+}
|
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.
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
This patch lowers select of constants if
TrueV == ~FalseV
.Address the comment in #82456 (comment).
NOTE: I initially implement it in
DAGCombiner::foldSelectOfConstants
. But it causes some regressions in X86/RISCV tests.