[llvm] [RISCV] Lower (select c, x, -x) -> (sub (czero_eqz x, c), (czero_nez x, c)) with Zicond. (PR #217181)
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 18 17:57:07 PDT 2026
https://github.com/topperc created https://github.com/llvm/llvm-project/pull/217181
None
>From 60fc603f43fc5eadfdc8396b79225dfbda332b9d Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Tue, 18 Aug 2026 17:31:06 -0700
Subject: [PATCH 1/2] Pre-commit tests
---
llvm/test/CodeGen/RISCV/condops.ll | 149 +++++++++++++++++++++++++++++
1 file changed, 149 insertions(+)
diff --git a/llvm/test/CodeGen/RISCV/condops.ll b/llvm/test/CodeGen/RISCV/condops.ll
index 71af806811a4b..18d95b2612070 100644
--- a/llvm/test/CodeGen/RISCV/condops.ll
+++ b/llvm/test/CodeGen/RISCV/condops.ll
@@ -4554,3 +4554,152 @@ entry:
%cond = select i1 %tobool.not, i64 0, i64 %x
ret i64 %cond
}
+
+define i64 @neg1(i64 %rs1, i1 zeroext %rc) {
+; RV32I-LABEL: neg1:
+; RV32I: # %bb.0:
+; RV32I-NEXT: bnez a2, .LBB66_2
+; RV32I-NEXT: # %bb.1:
+; RV32I-NEXT: snez a2, a0
+; RV32I-NEXT: neg a1, a1
+; RV32I-NEXT: sub a1, a1, a2
+; RV32I-NEXT: neg a0, a0
+; RV32I-NEXT: .LBB66_2:
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: neg1:
+; RV64I: # %bb.0:
+; RV64I-NEXT: bnez a1, .LBB66_2
+; RV64I-NEXT: # %bb.1:
+; RV64I-NEXT: neg a0, a0
+; RV64I-NEXT: .LBB66_2:
+; RV64I-NEXT: ret
+;
+; RV32XVENTANACONDOPS-LABEL: neg1:
+; RV32XVENTANACONDOPS: # %bb.0:
+; RV32XVENTANACONDOPS-NEXT: neg a3, a1
+; RV32XVENTANACONDOPS-NEXT: snez a4, a0
+; RV32XVENTANACONDOPS-NEXT: sub a3, a3, a4
+; RV32XVENTANACONDOPS-NEXT: neg a4, a0
+; RV32XVENTANACONDOPS-NEXT: vt.maskc a0, a0, a2
+; RV32XVENTANACONDOPS-NEXT: vt.maskcn a4, a4, a2
+; RV32XVENTANACONDOPS-NEXT: vt.maskc a1, a1, a2
+; RV32XVENTANACONDOPS-NEXT: vt.maskcn a2, a3, a2
+; RV32XVENTANACONDOPS-NEXT: or a0, a0, a4
+; RV32XVENTANACONDOPS-NEXT: or a1, a1, a2
+; RV32XVENTANACONDOPS-NEXT: ret
+;
+; RV64XVENTANACONDOPS-LABEL: neg1:
+; RV64XVENTANACONDOPS: # %bb.0:
+; RV64XVENTANACONDOPS-NEXT: neg a2, a0
+; RV64XVENTANACONDOPS-NEXT: vt.maskc a0, a0, a1
+; RV64XVENTANACONDOPS-NEXT: vt.maskcn a1, a2, a1
+; RV64XVENTANACONDOPS-NEXT: or a0, a0, a1
+; RV64XVENTANACONDOPS-NEXT: ret
+;
+; RV64XTHEADCONDMOV-LABEL: neg1:
+; RV64XTHEADCONDMOV: # %bb.0:
+; RV64XTHEADCONDMOV-NEXT: neg a2, a0
+; RV64XTHEADCONDMOV-NEXT: th.mveqz a0, a2, a1
+; RV64XTHEADCONDMOV-NEXT: ret
+;
+; RV32ZICOND-LABEL: neg1:
+; RV32ZICOND: # %bb.0:
+; RV32ZICOND-NEXT: neg a3, a1
+; RV32ZICOND-NEXT: snez a4, a0
+; RV32ZICOND-NEXT: sub a3, a3, a4
+; RV32ZICOND-NEXT: neg a4, a0
+; RV32ZICOND-NEXT: czero.eqz a0, a0, a2
+; RV32ZICOND-NEXT: czero.nez a4, a4, a2
+; RV32ZICOND-NEXT: czero.eqz a1, a1, a2
+; RV32ZICOND-NEXT: czero.nez a2, a3, a2
+; RV32ZICOND-NEXT: or a0, a0, a4
+; RV32ZICOND-NEXT: or a1, a1, a2
+; RV32ZICOND-NEXT: ret
+;
+; RV64ZICOND-LABEL: neg1:
+; RV64ZICOND: # %bb.0:
+; RV64ZICOND-NEXT: neg a2, a0
+; RV64ZICOND-NEXT: czero.eqz a0, a0, a1
+; RV64ZICOND-NEXT: czero.nez a1, a2, a1
+; RV64ZICOND-NEXT: or a0, a0, a1
+; RV64ZICOND-NEXT: ret
+ %neg = sub i64 0, %rs1
+ %sel = select i1 %rc, i64 %rs1, i64 %neg
+ ret i64 %sel
+}
+
+define i64 @neg2(i64 %rs1, i1 zeroext %rc) {
+; RV32I-LABEL: neg2:
+; RV32I: # %bb.0:
+; RV32I-NEXT: beqz a2, .LBB67_2
+; RV32I-NEXT: # %bb.1:
+; RV32I-NEXT: snez a2, a0
+; RV32I-NEXT: neg a1, a1
+; RV32I-NEXT: sub a1, a1, a2
+; RV32I-NEXT: neg a0, a0
+; RV32I-NEXT: .LBB67_2:
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: neg2:
+; RV64I: # %bb.0:
+; RV64I-NEXT: beqz a1, .LBB67_2
+; RV64I-NEXT: # %bb.1:
+; RV64I-NEXT: neg a0, a0
+; RV64I-NEXT: .LBB67_2:
+; RV64I-NEXT: ret
+;
+; RV32XVENTANACONDOPS-LABEL: neg2:
+; RV32XVENTANACONDOPS: # %bb.0:
+; RV32XVENTANACONDOPS-NEXT: neg a3, a1
+; RV32XVENTANACONDOPS-NEXT: snez a4, a0
+; RV32XVENTANACONDOPS-NEXT: sub a3, a3, a4
+; RV32XVENTANACONDOPS-NEXT: neg a4, a0
+; RV32XVENTANACONDOPS-NEXT: vt.maskcn a0, a0, a2
+; RV32XVENTANACONDOPS-NEXT: vt.maskc a4, a4, a2
+; RV32XVENTANACONDOPS-NEXT: vt.maskcn a1, a1, a2
+; RV32XVENTANACONDOPS-NEXT: vt.maskc a2, a3, a2
+; RV32XVENTANACONDOPS-NEXT: or a0, a4, a0
+; RV32XVENTANACONDOPS-NEXT: or a1, a2, a1
+; RV32XVENTANACONDOPS-NEXT: ret
+;
+; RV64XVENTANACONDOPS-LABEL: neg2:
+; RV64XVENTANACONDOPS: # %bb.0:
+; RV64XVENTANACONDOPS-NEXT: neg a2, a0
+; RV64XVENTANACONDOPS-NEXT: vt.maskcn a0, a0, a1
+; RV64XVENTANACONDOPS-NEXT: vt.maskc a1, a2, a1
+; RV64XVENTANACONDOPS-NEXT: or a0, a1, a0
+; RV64XVENTANACONDOPS-NEXT: ret
+;
+; RV64XTHEADCONDMOV-LABEL: neg2:
+; RV64XTHEADCONDMOV: # %bb.0:
+; RV64XTHEADCONDMOV-NEXT: neg a2, a0
+; RV64XTHEADCONDMOV-NEXT: th.mvnez a0, a2, a1
+; RV64XTHEADCONDMOV-NEXT: ret
+;
+; RV32ZICOND-LABEL: neg2:
+; RV32ZICOND: # %bb.0:
+; RV32ZICOND-NEXT: neg a3, a1
+; RV32ZICOND-NEXT: snez a4, a0
+; RV32ZICOND-NEXT: sub a3, a3, a4
+; RV32ZICOND-NEXT: neg a4, a0
+; RV32ZICOND-NEXT: czero.nez a0, a0, a2
+; RV32ZICOND-NEXT: czero.eqz a4, a4, a2
+; RV32ZICOND-NEXT: czero.nez a1, a1, a2
+; RV32ZICOND-NEXT: czero.eqz a2, a3, a2
+; RV32ZICOND-NEXT: or a0, a4, a0
+; RV32ZICOND-NEXT: or a1, a2, a1
+; RV32ZICOND-NEXT: ret
+;
+; RV64ZICOND-LABEL: neg2:
+; RV64ZICOND: # %bb.0:
+; RV64ZICOND-NEXT: neg a2, a0
+; RV64ZICOND-NEXT: czero.nez a0, a0, a1
+; RV64ZICOND-NEXT: czero.eqz a1, a2, a1
+; RV64ZICOND-NEXT: or a0, a1, a0
+; RV64ZICOND-NEXT: ret
+ %neg = sub i64 0, %rs1
+ %sel = select i1 %rc, i64 %neg, i64 %rs1
+ ret i64 %sel
+}
+
>From 0c1ff91fe5249853ec055a58642e653494924b20 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Tue, 18 Aug 2026 17:38:46 -0700
Subject: [PATCH 2/2] [RISCV] Lower (select c, x, -x) -> (sub (czero_eqz x, c),
(czero_nez x, c)) with Zicond.
---
llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 24 +++++++++++--
llvm/test/CodeGen/RISCV/condops.ll | 40 +++++++++------------
2 files changed, 38 insertions(+), 26 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 2dbc048d8dc6b..b10f5a40ef4bd 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -10622,15 +10622,35 @@ SDValue RISCVTargetLowering::lowerSELECT(SDValue Op, SelectionDAG &DAG) const {
}
}
- // (select c, t, f) -> (or (czero_eqz t, c), (czero_nez f, c))
// Unless we have the short forward branch optimization, or we are
// optimizing for size.
- if (!Subtarget.hasConditionalMoveFusion() && !DAG.shouldOptForSize())
+ if (!Subtarget.hasConditionalMoveFusion() && !DAG.shouldOptForSize()) {
+ using namespace llvm::SDPatternMatch;
+
+ // (select c, x, -x) -> (sub (czero_eqz x, c), (czero_nez x, c))
+ if (sd_match(FalseV, m_Neg(m_Specific(TrueV)))) {
+ TrueV = DAG.getFreeze(TrueV);
+ return DAG.getNode(
+ ISD::SUB, DL, VT,
+ DAG.getNode(RISCVISD::CZERO_EQZ, DL, VT, TrueV, CondV),
+ DAG.getNode(RISCVISD::CZERO_NEZ, DL, VT, TrueV, CondV));
+ }
+ // (select c, -x, x) -> (sub (czero_nez x, c), (czero_eqz x, c))
+ if (sd_match(TrueV, m_Neg(m_Specific(FalseV)))) {
+ FalseV = DAG.getFreeze(FalseV);
+ return DAG.getNode(
+ ISD::SUB, DL, VT,
+ DAG.getNode(RISCVISD::CZERO_NEZ, DL, VT, FalseV, CondV),
+ DAG.getNode(RISCVISD::CZERO_EQZ, DL, VT, FalseV, CondV));
+ }
+
+ // (select c, t, f) -> (or (czero_eqz t, c), (czero_nez f, c))
return DAG.getNode(
ISD::OR, DL, VT,
DAG.getNode(RISCVISD::CZERO_EQZ, DL, VT, TrueV, CondV),
DAG.getNode(RISCVISD::CZERO_NEZ, DL, VT, FalseV, CondV),
SDNodeFlags::Disjoint);
+ }
}
if (Op.hasOneUse()) {
diff --git a/llvm/test/CodeGen/RISCV/condops.ll b/llvm/test/CodeGen/RISCV/condops.ll
index 18d95b2612070..3c62b322efece 100644
--- a/llvm/test/CodeGen/RISCV/condops.ll
+++ b/llvm/test/CodeGen/RISCV/condops.ll
@@ -4580,21 +4580,19 @@ define i64 @neg1(i64 %rs1, i1 zeroext %rc) {
; RV32XVENTANACONDOPS-NEXT: neg a3, a1
; RV32XVENTANACONDOPS-NEXT: snez a4, a0
; RV32XVENTANACONDOPS-NEXT: sub a3, a3, a4
-; RV32XVENTANACONDOPS-NEXT: neg a4, a0
+; RV32XVENTANACONDOPS-NEXT: vt.maskcn a4, a0, a2
; RV32XVENTANACONDOPS-NEXT: vt.maskc a0, a0, a2
-; RV32XVENTANACONDOPS-NEXT: vt.maskcn a4, a4, a2
; RV32XVENTANACONDOPS-NEXT: vt.maskc a1, a1, a2
; RV32XVENTANACONDOPS-NEXT: vt.maskcn a2, a3, a2
-; RV32XVENTANACONDOPS-NEXT: or a0, a0, a4
+; RV32XVENTANACONDOPS-NEXT: sub a0, a0, a4
; RV32XVENTANACONDOPS-NEXT: or a1, a1, a2
; RV32XVENTANACONDOPS-NEXT: ret
;
; RV64XVENTANACONDOPS-LABEL: neg1:
; RV64XVENTANACONDOPS: # %bb.0:
-; RV64XVENTANACONDOPS-NEXT: neg a2, a0
+; RV64XVENTANACONDOPS-NEXT: vt.maskcn a2, a0, a1
; RV64XVENTANACONDOPS-NEXT: vt.maskc a0, a0, a1
-; RV64XVENTANACONDOPS-NEXT: vt.maskcn a1, a2, a1
-; RV64XVENTANACONDOPS-NEXT: or a0, a0, a1
+; RV64XVENTANACONDOPS-NEXT: sub a0, a0, a2
; RV64XVENTANACONDOPS-NEXT: ret
;
; RV64XTHEADCONDMOV-LABEL: neg1:
@@ -4608,21 +4606,19 @@ define i64 @neg1(i64 %rs1, i1 zeroext %rc) {
; RV32ZICOND-NEXT: neg a3, a1
; RV32ZICOND-NEXT: snez a4, a0
; RV32ZICOND-NEXT: sub a3, a3, a4
-; RV32ZICOND-NEXT: neg a4, a0
+; RV32ZICOND-NEXT: czero.nez a4, a0, a2
; RV32ZICOND-NEXT: czero.eqz a0, a0, a2
-; RV32ZICOND-NEXT: czero.nez a4, a4, a2
; RV32ZICOND-NEXT: czero.eqz a1, a1, a2
; RV32ZICOND-NEXT: czero.nez a2, a3, a2
-; RV32ZICOND-NEXT: or a0, a0, a4
+; RV32ZICOND-NEXT: sub a0, a0, a4
; RV32ZICOND-NEXT: or a1, a1, a2
; RV32ZICOND-NEXT: ret
;
; RV64ZICOND-LABEL: neg1:
; RV64ZICOND: # %bb.0:
-; RV64ZICOND-NEXT: neg a2, a0
+; RV64ZICOND-NEXT: czero.nez a2, a0, a1
; RV64ZICOND-NEXT: czero.eqz a0, a0, a1
-; RV64ZICOND-NEXT: czero.nez a1, a2, a1
-; RV64ZICOND-NEXT: or a0, a0, a1
+; RV64ZICOND-NEXT: sub a0, a0, a2
; RV64ZICOND-NEXT: ret
%neg = sub i64 0, %rs1
%sel = select i1 %rc, i64 %rs1, i64 %neg
@@ -4654,21 +4650,19 @@ define i64 @neg2(i64 %rs1, i1 zeroext %rc) {
; RV32XVENTANACONDOPS-NEXT: neg a3, a1
; RV32XVENTANACONDOPS-NEXT: snez a4, a0
; RV32XVENTANACONDOPS-NEXT: sub a3, a3, a4
-; RV32XVENTANACONDOPS-NEXT: neg a4, a0
+; RV32XVENTANACONDOPS-NEXT: vt.maskc a4, a0, a2
; RV32XVENTANACONDOPS-NEXT: vt.maskcn a0, a0, a2
-; RV32XVENTANACONDOPS-NEXT: vt.maskc a4, a4, a2
; RV32XVENTANACONDOPS-NEXT: vt.maskcn a1, a1, a2
; RV32XVENTANACONDOPS-NEXT: vt.maskc a2, a3, a2
-; RV32XVENTANACONDOPS-NEXT: or a0, a4, a0
+; RV32XVENTANACONDOPS-NEXT: sub a0, a0, a4
; RV32XVENTANACONDOPS-NEXT: or a1, a2, a1
; RV32XVENTANACONDOPS-NEXT: ret
;
; RV64XVENTANACONDOPS-LABEL: neg2:
; RV64XVENTANACONDOPS: # %bb.0:
-; RV64XVENTANACONDOPS-NEXT: neg a2, a0
+; RV64XVENTANACONDOPS-NEXT: vt.maskc a2, a0, a1
; RV64XVENTANACONDOPS-NEXT: vt.maskcn a0, a0, a1
-; RV64XVENTANACONDOPS-NEXT: vt.maskc a1, a2, a1
-; RV64XVENTANACONDOPS-NEXT: or a0, a1, a0
+; RV64XVENTANACONDOPS-NEXT: sub a0, a0, a2
; RV64XVENTANACONDOPS-NEXT: ret
;
; RV64XTHEADCONDMOV-LABEL: neg2:
@@ -4682,21 +4676,19 @@ define i64 @neg2(i64 %rs1, i1 zeroext %rc) {
; RV32ZICOND-NEXT: neg a3, a1
; RV32ZICOND-NEXT: snez a4, a0
; RV32ZICOND-NEXT: sub a3, a3, a4
-; RV32ZICOND-NEXT: neg a4, a0
+; RV32ZICOND-NEXT: czero.eqz a4, a0, a2
; RV32ZICOND-NEXT: czero.nez a0, a0, a2
-; RV32ZICOND-NEXT: czero.eqz a4, a4, a2
; RV32ZICOND-NEXT: czero.nez a1, a1, a2
; RV32ZICOND-NEXT: czero.eqz a2, a3, a2
-; RV32ZICOND-NEXT: or a0, a4, a0
+; RV32ZICOND-NEXT: sub a0, a0, a4
; RV32ZICOND-NEXT: or a1, a2, a1
; RV32ZICOND-NEXT: ret
;
; RV64ZICOND-LABEL: neg2:
; RV64ZICOND: # %bb.0:
-; RV64ZICOND-NEXT: neg a2, a0
+; RV64ZICOND-NEXT: czero.eqz a2, a0, a1
; RV64ZICOND-NEXT: czero.nez a0, a0, a1
-; RV64ZICOND-NEXT: czero.eqz a1, a2, a1
-; RV64ZICOND-NEXT: or a0, a1, a0
+; RV64ZICOND-NEXT: sub a0, a0, a2
; RV64ZICOND-NEXT: ret
%neg = sub i64 0, %rs1
%sel = select i1 %rc, i64 %neg, i64 %rs1
More information about the llvm-commits
mailing list