[llvm] [llvm][RISCV] Tune lowerSelect on zicond for code size (PR #210026)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 16 03:43:04 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-risc-v

Author: Brandon Wu (4vtomat)

<details>
<summary>Changes</summary>

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.

---
Full diff: https://github.com/llvm/llvm-project/pull/210026.diff


2 Files Affected:

- (modified) llvm/lib/Target/RISCV/RISCVISelLowering.cpp (+2-1) 
- (modified) llvm/test/CodeGen/RISCV/zicond-opts.ll (+42) 


``````````diff
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
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/210026


More information about the llvm-commits mailing list