[llvm] [RISCV] Lower (select c, (1 << X) + 1, 0) -> (shXadd c, c) (PR #158969)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 16 04:04:37 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-risc-v
Author: Piotr Fusik (pfusik)
<details>
<summary>Changes</summary>
---
Full diff: https://github.com/llvm/llvm-project/pull/158969.diff
4 Files Affected:
- (modified) llvm/lib/Target/RISCV/RISCVISelLowering.cpp (+16-4)
- (modified) llvm/test/CodeGen/RISCV/rv32zba.ll (+129)
- (modified) llvm/test/CodeGen/RISCV/rv64zba.ll (+60)
- (modified) llvm/test/CodeGen/RISCV/xqciac.ll (+20)
``````````diff
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 9d90eb0a65218..cb20959e9dcc8 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -9150,10 +9150,22 @@ static SDValue lowerSelectToBinOp(SDNode *N, SelectionDAG &DAG,
DAG.getNode(ISD::ADD, DL, VT, CondV, DAG.getAllOnesConstant(DL, VT));
return DAG.getNode(ISD::AND, DL, VT, Neg, DAG.getFreeze(FalseV));
}
- // (select c, y, 0) -> -c & y
- if (isNullConstant(FalseV) && (!HasCZero || isSimm12Constant(TrueV))) {
- SDValue Neg = DAG.getNegative(CondV, DL, VT);
- return DAG.getNode(ISD::AND, DL, VT, Neg, DAG.getFreeze(TrueV));
+ if (isNullConstant(FalseV)) {
+ // (select c, (1 << ShAmount) + 1, 0) -> (c << ShAmount) + c
+ if (auto *TrueC = dyn_cast<ConstantSDNode>(TrueV)) {
+ uint64_t TrueM1 = TrueC->getZExtValue() - 1;
+ if (isPowerOf2_64(TrueM1)) {
+ unsigned ShAmount = Log2_64(TrueM1);
+ if (Subtarget.hasShlAdd(ShAmount))
+ return DAG.getNode(RISCVISD::SHL_ADD, DL, VT, CondV,
+ DAG.getConstant(ShAmount, DL, VT), CondV);
+ }
+ }
+ // (select c, y, 0) -> -c & y
+ if (!HasCZero || isSimm12Constant(TrueV)) {
+ SDValue Neg = DAG.getNegative(CondV, DL, VT);
+ return DAG.getNode(ISD::AND, DL, VT, Neg, DAG.getFreeze(TrueV));
+ }
}
}
diff --git a/llvm/test/CodeGen/RISCV/rv32zba.ll b/llvm/test/CodeGen/RISCV/rv32zba.ll
index ab099103b4216..0d490682d1ff3 100644
--- a/llvm/test/CodeGen/RISCV/rv32zba.ll
+++ b/llvm/test/CodeGen/RISCV/rv32zba.ll
@@ -1136,3 +1136,132 @@ define i32 @mul_neg8(i32 %a) {
%c = mul i32 %a, -8
ret i32 %c
}
+
+define i32 @select3i32(i1 zeroext %x) {
+; RV32I-LABEL: select3i32:
+; RV32I: # %bb.0:
+; RV32I-NEXT: neg a0, a0
+; RV32I-NEXT: andi a0, a0, 3
+; RV32I-NEXT: ret
+;
+; RV32ZBA-LABEL: select3i32:
+; RV32ZBA: # %bb.0:
+; RV32ZBA-NEXT: sh1add a0, a0, a0
+; RV32ZBA-NEXT: ret
+;
+; RV32XANDESPERF-LABEL: select3i32:
+; RV32XANDESPERF: # %bb.0:
+; RV32XANDESPERF-NEXT: nds.lea.h a0, a0, a0
+; RV32XANDESPERF-NEXT: ret
+ %select = select i1 %x, i32 3, i32 0
+ ret i32 %select
+}
+
+define i32 @select5i32(i1 zeroext %x) {
+; RV32I-LABEL: select5i32:
+; RV32I: # %bb.0:
+; RV32I-NEXT: neg a0, a0
+; RV32I-NEXT: andi a0, a0, 5
+; RV32I-NEXT: ret
+;
+; RV32ZBA-LABEL: select5i32:
+; RV32ZBA: # %bb.0:
+; RV32ZBA-NEXT: sh2add a0, a0, a0
+; RV32ZBA-NEXT: ret
+;
+; RV32XANDESPERF-LABEL: select5i32:
+; RV32XANDESPERF: # %bb.0:
+; RV32XANDESPERF-NEXT: nds.lea.w a0, a0, a0
+; RV32XANDESPERF-NEXT: ret
+ %select = select i1 %x, i32 5, i32 0
+ ret i32 %select
+}
+
+define i32 @select9i32(i1 zeroext %x) {
+; RV32I-LABEL: select9i32:
+; RV32I: # %bb.0:
+; RV32I-NEXT: neg a0, a0
+; RV32I-NEXT: andi a0, a0, 9
+; RV32I-NEXT: ret
+;
+; RV32ZBA-LABEL: select9i32:
+; RV32ZBA: # %bb.0:
+; RV32ZBA-NEXT: sh3add a0, a0, a0
+; RV32ZBA-NEXT: ret
+;
+; RV32XANDESPERF-LABEL: select9i32:
+; RV32XANDESPERF: # %bb.0:
+; RV32XANDESPERF-NEXT: nds.lea.d a0, a0, a0
+; RV32XANDESPERF-NEXT: ret
+ %select = select i1 %x, i32 9, i32 0
+ ret i32 %select
+}
+
+define i64 @select3i64(i1 zeroext %x) {
+; RV32I-LABEL: select3i64:
+; RV32I: # %bb.0:
+; RV32I-NEXT: neg a0, a0
+; RV32I-NEXT: andi a0, a0, 3
+; RV32I-NEXT: li a1, 0
+; RV32I-NEXT: ret
+;
+; RV32ZBA-LABEL: select3i64:
+; RV32ZBA: # %bb.0:
+; RV32ZBA-NEXT: sh1add a0, a0, a0
+; RV32ZBA-NEXT: li a1, 0
+; RV32ZBA-NEXT: ret
+;
+; RV32XANDESPERF-LABEL: select3i64:
+; RV32XANDESPERF: # %bb.0:
+; RV32XANDESPERF-NEXT: nds.lea.h a0, a0, a0
+; RV32XANDESPERF-NEXT: li a1, 0
+; RV32XANDESPERF-NEXT: ret
+ %select = select i1 %x, i64 3, i64 0
+ ret i64 %select
+}
+
+define i64 @select5i64(i1 zeroext %x) {
+; RV32I-LABEL: select5i64:
+; RV32I: # %bb.0:
+; RV32I-NEXT: neg a0, a0
+; RV32I-NEXT: andi a0, a0, 5
+; RV32I-NEXT: li a1, 0
+; RV32I-NEXT: ret
+;
+; RV32ZBA-LABEL: select5i64:
+; RV32ZBA: # %bb.0:
+; RV32ZBA-NEXT: sh2add a0, a0, a0
+; RV32ZBA-NEXT: li a1, 0
+; RV32ZBA-NEXT: ret
+;
+; RV32XANDESPERF-LABEL: select5i64:
+; RV32XANDESPERF: # %bb.0:
+; RV32XANDESPERF-NEXT: nds.lea.w a0, a0, a0
+; RV32XANDESPERF-NEXT: li a1, 0
+; RV32XANDESPERF-NEXT: ret
+ %select = select i1 %x, i64 5, i64 0
+ ret i64 %select
+}
+
+define i64 @select9i64(i1 zeroext %x) {
+; RV32I-LABEL: select9i64:
+; RV32I: # %bb.0:
+; RV32I-NEXT: neg a0, a0
+; RV32I-NEXT: andi a0, a0, 9
+; RV32I-NEXT: li a1, 0
+; RV32I-NEXT: ret
+;
+; RV32ZBA-LABEL: select9i64:
+; RV32ZBA: # %bb.0:
+; RV32ZBA-NEXT: sh3add a0, a0, a0
+; RV32ZBA-NEXT: li a1, 0
+; RV32ZBA-NEXT: ret
+;
+; RV32XANDESPERF-LABEL: select9i64:
+; RV32XANDESPERF: # %bb.0:
+; RV32XANDESPERF-NEXT: nds.lea.d a0, a0, a0
+; RV32XANDESPERF-NEXT: li a1, 0
+; RV32XANDESPERF-NEXT: ret
+ %select = select i1 %x, i64 9, i64 0
+ ret i64 %select
+}
diff --git a/llvm/test/CodeGen/RISCV/rv64zba.ll b/llvm/test/CodeGen/RISCV/rv64zba.ll
index b46f7cc440b7a..95f9f7116fe68 100644
--- a/llvm/test/CodeGen/RISCV/rv64zba.ll
+++ b/llvm/test/CodeGen/RISCV/rv64zba.ll
@@ -4576,3 +4576,63 @@ define i64 @append_32ones(i64 %x) {
%o = or i64 %s, 4294967295
ret i64 %o
}
+
+define i32 @select3(i1 zeroext %x) {
+; RV64I-LABEL: select3:
+; RV64I: # %bb.0:
+; RV64I-NEXT: neg a0, a0
+; RV64I-NEXT: andi a0, a0, 3
+; RV64I-NEXT: ret
+;
+; RV64ZBA-LABEL: select3:
+; RV64ZBA: # %bb.0:
+; RV64ZBA-NEXT: sh1add a0, a0, a0
+; RV64ZBA-NEXT: ret
+;
+; RV64XANDESPERF-LABEL: select3:
+; RV64XANDESPERF: # %bb.0:
+; RV64XANDESPERF-NEXT: nds.lea.h a0, a0, a0
+; RV64XANDESPERF-NEXT: ret
+ %select = select i1 %x, i32 3, i32 0
+ ret i32 %select
+}
+
+define i32 @select5(i1 zeroext %x) {
+; RV64I-LABEL: select5:
+; RV64I: # %bb.0:
+; RV64I-NEXT: neg a0, a0
+; RV64I-NEXT: andi a0, a0, 5
+; RV64I-NEXT: ret
+;
+; RV64ZBA-LABEL: select5:
+; RV64ZBA: # %bb.0:
+; RV64ZBA-NEXT: sh2add a0, a0, a0
+; RV64ZBA-NEXT: ret
+;
+; RV64XANDESPERF-LABEL: select5:
+; RV64XANDESPERF: # %bb.0:
+; RV64XANDESPERF-NEXT: nds.lea.w a0, a0, a0
+; RV64XANDESPERF-NEXT: ret
+ %select = select i1 %x, i32 5, i32 0
+ ret i32 %select
+}
+
+define i32 @select9(i1 zeroext %x) {
+; RV64I-LABEL: select9:
+; RV64I: # %bb.0:
+; RV64I-NEXT: neg a0, a0
+; RV64I-NEXT: andi a0, a0, 9
+; RV64I-NEXT: ret
+;
+; RV64ZBA-LABEL: select9:
+; RV64ZBA: # %bb.0:
+; RV64ZBA-NEXT: sh3add a0, a0, a0
+; RV64ZBA-NEXT: ret
+;
+; RV64XANDESPERF-LABEL: select9:
+; RV64XANDESPERF: # %bb.0:
+; RV64XANDESPERF-NEXT: nds.lea.d a0, a0, a0
+; RV64XANDESPERF-NEXT: ret
+ %select = select i1 %x, i32 9, i32 0
+ ret i32 %select
+}
diff --git a/llvm/test/CodeGen/RISCV/xqciac.ll b/llvm/test/CodeGen/RISCV/xqciac.ll
index ec83fd7a28f32..918468bdf03d3 100644
--- a/llvm/test/CodeGen/RISCV/xqciac.ll
+++ b/llvm/test/CodeGen/RISCV/xqciac.ll
@@ -599,3 +599,23 @@ define i32 @add_shl_moreOneUse_4(i32 %x) {
%add = add i32 %mul, %or
ret i32 %add
}
+
+define i32 @select65(i1 zeroext %x) {
+; RV32IM-LABEL: select65:
+; RV32IM: # %bb.0:
+; RV32IM-NEXT: neg a0, a0
+; RV32IM-NEXT: andi a0, a0, 65
+; RV32IM-NEXT: ret
+;
+; RV32IMXQCIAC-LABEL: select65:
+; RV32IMXQCIAC: # %bb.0:
+; RV32IMXQCIAC-NEXT: qc.shladd a0, a0, a0, 6
+; RV32IMXQCIAC-NEXT: ret
+;
+; RV32IZBAMXQCIAC-LABEL: select65:
+; RV32IZBAMXQCIAC: # %bb.0:
+; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a0, a0, 6
+; RV32IZBAMXQCIAC-NEXT: ret
+ %select = select i1 %x, i32 65, i32 0
+ ret i32 %select
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/158969
More information about the llvm-commits
mailing list