[llvm] [llvm][RISCV] Tune lowerSelect on zicond for code size (PR #210026)
Brandon Wu via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 16 03:42:24 PDT 2026
https://github.com/4vtomat created https://github.com/llvm/llvm-project/pull/210026
Selecting 2 non-constant value will be lowered using 2 czero + 1 or if zicond is enabled, when optimizing for code size, it's at least 10 bytes depending on whether or can be compressed or not.
However if we care about code size > performance we can just keep branch instruction to reduce the code sequence to only 1 mv + 1 branch which is at most 8 bytes.
>From 095c2d29ea440566717d0255acf0368dbbe48021 Mon Sep 17 00:00:00 2001
From: Brandon Wu <brandon.wu at sifive.com>
Date: Thu, 16 Jul 2026 03:36:33 -0700
Subject: [PATCH] [llvm][RISCV] Tune lowerSelect on zicond for code size
Selecting 2 non-constant value will be lowered using 2 czero + 1 or if
zicond is enabled, when optimizing for code size, it's at least 10 bytes
depending on whether or can be compressed or not.
However if we care about code size > performance we can just keep branch
instruction to reduce the code sequence to only 1 mv + 1 branch which is
at most 8 bytes.
---
llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 3 +-
llvm/test/CodeGen/RISCV/zicond-opts.ll | 42 +++++++++++++++++++++
2 files changed, 44 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 2df58fc2ca9f0..c8eadec987edc 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -10484,7 +10484,8 @@ 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.
- if (!Subtarget.hasConditionalMoveFusion())
+ if (!Subtarget.hasConditionalMoveFusion() &&
+ !DAG.getMachineFunction().getFunction().hasMinSize())
return DAG.getNode(
ISD::OR, DL, VT,
DAG.getNode(RISCVISD::CZERO_EQZ, DL, VT, TrueV, CondV),
diff --git a/llvm/test/CodeGen/RISCV/zicond-opts.ll b/llvm/test/CodeGen/RISCV/zicond-opts.ll
index 0568b0e1fae05..2909803f8adb3 100644
--- a/llvm/test/CodeGen/RISCV/zicond-opts.ll
+++ b/llvm/test/CodeGen/RISCV/zicond-opts.ll
@@ -401,3 +401,45 @@ entry:
%clzg = select i1 %iszero, i32 -9, i32 %cast
ret i32 %clzg
}
+
+define i64 @select_wo_minsize(i64 %true, i64 %false, i1 zeroext %c) {
+; RV32ZICOND-LABEL: select_wo_minsize:
+; RV32ZICOND: # %bb.0:
+; RV32ZICOND-NEXT: czero.nez a2, a2, a4
+; RV32ZICOND-NEXT: czero.eqz a0, a0, a4
+; RV32ZICOND-NEXT: czero.nez a3, a3, a4
+; RV32ZICOND-NEXT: czero.eqz a1, a1, a4
+; RV32ZICOND-NEXT: or a0, a0, a2
+; RV32ZICOND-NEXT: or a1, a1, a3
+; RV32ZICOND-NEXT: ret
+;
+; RV64ZICOND-LABEL: select_wo_minsize:
+; RV64ZICOND: # %bb.0:
+; RV64ZICOND-NEXT: czero.nez a1, a1, a2
+; RV64ZICOND-NEXT: czero.eqz a0, a0, a2
+; RV64ZICOND-NEXT: or a0, a0, a1
+; RV64ZICOND-NEXT: ret
+ %r = select i1 %c, i64 %true, i64 %false
+ ret i64 %r
+}
+
+define i64 @select_w_minsize(i64 %true, i64 %false, i1 zeroext %c) minsize {
+; RV32ZICOND-LABEL: select_w_minsize:
+; RV32ZICOND: # %bb.0:
+; RV32ZICOND-NEXT: bnez a4, .LBB16_2
+; RV32ZICOND-NEXT: # %bb.1:
+; RV32ZICOND-NEXT: mv a0, a2
+; RV32ZICOND-NEXT: mv a1, a3
+; RV32ZICOND-NEXT: .LBB16_2:
+; RV32ZICOND-NEXT: ret
+;
+; RV64ZICOND-LABEL: select_w_minsize:
+; RV64ZICOND: # %bb.0:
+; RV64ZICOND-NEXT: bnez a2, .LBB16_2
+; RV64ZICOND-NEXT: # %bb.1:
+; RV64ZICOND-NEXT: mv a0, a1
+; RV64ZICOND-NEXT: .LBB16_2:
+; RV64ZICOND-NEXT: ret
+ %r = select i1 %c, i64 %true, i64 %false
+ ret i64 %r
+}
More information about the llvm-commits
mailing list