[llvm] [RISCV][SDAG] Fold `select c, ~x, x` into `xor -c, x` (PR #82462)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 20 22:25:05 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-risc-v
Author: Yingwei Zheng (dtcxzyw)
<details>
<summary>Changes</summary>
This patch lowers select of constants if `TrueV == ~FalseV`.
Address the comment in https://github.com/llvm/llvm-project/pull/82456#discussion_r1496881603.
NOTE: I initially implement it in `DAGCombiner::foldSelectOfConstants`. But it causes some regressions in X86/RISCV tests.
---
Full diff: https://github.com/llvm/llvm-project/pull/82462.diff
2 Files Affected:
- (modified) llvm/lib/Target/RISCV/RISCVISelLowering.cpp (+10)
- (modified) llvm/test/CodeGen/RISCV/select.ll (+177)
``````````diff
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
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/82462
More information about the llvm-commits
mailing list