[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