Skip to content

Commit e1009fa

Browse files
committed
Skip Zicond for FP sel when we need to split regs
This patch disables the Zicond optimization for floating-point selects when the value type exceeds XLen (e.g., f64 on RV32 +zdinx). In these cases, using Zicond requires handling split registers, which results in a higher dynamic instruction count compared to the standard branch-based lowering (e.g., ~8 instructions vs ~5-7 instructions for appended sample code). Thus, there is no benefit to using Zicond here ```asm define double @select_f64_fcmp(double %a, double %b, double %c, double %d) nounwind { entry: %cmp = fcmp ogt double %a, %b %sel = select i1 %cmp, double %c, double %d ret double %sel } ``` Branch version: Executes 5 or 7 instruction ```asm ; RV32ZDINX_NOZICOND-LABEL: select_f64_fcmp: ; RV32ZDINX_NOZICOND: # %bb.0: # %entry ; RV32ZDINX_NOZICOND-NEXT: flt.d a0, a2, a0 ; RV32ZDINX_NOZICOND-NEXT: bnez a0, .LBB2_2 ; RV32ZDINX_NOZICOND-NEXT: # %bb.1: # %entry ; RV32ZDINX_NOZICOND-NEXT: mv a4, a6 ; RV32ZDINX_NOZICOND-NEXT: mv a5, a7 ; RV32ZDINX_NOZICOND-NEXT: .LBB2_2: # %entry ; RV32ZDINX_NOZICOND-NEXT: mv a0, a4 ; RV32ZDINX_NOZICOND-NEXT: mv a1, a5 ; RV32ZDINX_NOZICOND-NEXT: ret ``` Zicond version: Always executes 8 instructions. ```asm ; RV32ZDINX_ZICOND-LABEL: select_f64_fcmp: ; RV32ZDINX_ZICOND: # %bb.0: # %entry ; RV32ZDINX_ZICOND-NEXT: flt.d a0, a2, a0 ; RV32ZDINX_ZICOND-NEXT: czero.nez a1, a6, a0 ; RV32ZDINX_ZICOND-NEXT: czero.eqz a2, a4, a0 ; RV32ZDINX_ZICOND-NEXT: czero.nez a3, a7, a0 ; RV32ZDINX_ZICOND-NEXT: czero.eqz a4, a5, a0 ; RV32ZDINX_ZICOND-NEXT: or a0, a2, a1 ; RV32ZDINX_ZICOND-NEXT: or a1, a4, a3 ; RV32ZDINX_ZICOND-NEXT: ret ```
1 parent 6e40a9d commit e1009fa

File tree

2 files changed

+27
-34
lines changed

2 files changed

+27
-34
lines changed

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9558,31 +9558,16 @@ SDValue RISCVTargetLowering::lowerSELECT(SDValue Op, SelectionDAG &DAG) const {
95589558
// When there is no cost for GPR <-> FGPR, we can use zicond select for
95599559
// floating value when CondV is int type
95609560
bool FPinGPR = Subtarget.hasStdExtZfinx();
9561-
bool UseZicondForFPSel =
9562-
Subtarget.hasStdExtZicond() && FPinGPR && VT.isFloatingPoint();
95639561

9564-
if (UseZicondForFPSel) {
9565-
MVT XLenIntVT = Subtarget.getXLenVT();
9566-
9567-
// Handle RV32 with f64 (Zdinx): Split into two 32-bit integer selects.
9568-
if (VT == MVT::f64 && !Subtarget.is64Bit()) {
9569-
SDValue TrueSplit = DAG.getNode(RISCVISD::SplitF64, DL,
9570-
DAG.getVTList(MVT::i32, MVT::i32), TrueV);
9571-
SDValue FalseSplit = DAG.getNode(
9572-
RISCVISD::SplitF64, DL, DAG.getVTList(MVT::i32, MVT::i32), FalseV);
9573-
9574-
SDValue TrueLo = TrueSplit.getValue(0);
9575-
SDValue TrueHi = TrueSplit.getValue(1);
9576-
SDValue FalseLo = FalseSplit.getValue(0);
9577-
SDValue FalseHi = FalseSplit.getValue(1);
9562+
// We can handle FGPR without spliting into hi/lo parts
9563+
bool FitsInGPR = TypeSize::isKnownLE(VT.getSizeInBits(),
9564+
Subtarget.getXLenVT().getSizeInBits());
95789565

9579-
SDValue ResLo =
9580-
DAG.getNode(ISD::SELECT, DL, MVT::i32, CondV, TrueLo, FalseLo);
9581-
SDValue ResHi =
9582-
DAG.getNode(ISD::SELECT, DL, MVT::i32, CondV, TrueHi, FalseHi);
9566+
bool UseZicondForFPSel = Subtarget.hasStdExtZicond() && FPinGPR &&
9567+
VT.isFloatingPoint() && FitsInGPR;
95839568

9584-
return DAG.getNode(RISCVISD::BuildPairF64, DL, MVT::f64, ResLo, ResHi);
9585-
}
9569+
if (UseZicondForFPSel) {
9570+
MVT XLenIntVT = Subtarget.getXLenVT();
95869571

95879572
auto CastToInt = [&](SDValue V) -> SDValue {
95889573
if (VT == MVT::f16)

llvm/test/CodeGen/RISCV/zicond-fp-select-zfinx.ll

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -178,12 +178,19 @@ define double @select_f64_i1(i1 %cond, double %t, double %f) nounwind {
178178
; RV32ZDINX_ZICOND-LABEL: select_f64_i1:
179179
; RV32ZDINX_ZICOND: # %bb.0: # %entry
180180
; RV32ZDINX_ZICOND-NEXT: andi a0, a0, 1
181-
; RV32ZDINX_ZICOND-NEXT: czero.nez a3, a3, a0
182-
; RV32ZDINX_ZICOND-NEXT: czero.eqz a1, a1, a0
183-
; RV32ZDINX_ZICOND-NEXT: czero.nez a4, a4, a0
184-
; RV32ZDINX_ZICOND-NEXT: czero.eqz a2, a2, a0
185-
; RV32ZDINX_ZICOND-NEXT: or a0, a1, a3
186-
; RV32ZDINX_ZICOND-NEXT: or a1, a2, a4
181+
; RV32ZDINX_ZICOND-NEXT: bnez a0, .LBB1_2
182+
; RV32ZDINX_ZICOND-NEXT: # %bb.1: # %entry
183+
; RV32ZDINX_ZICOND-NEXT: mv a7, a4
184+
; RV32ZDINX_ZICOND-NEXT: mv a6, a3
185+
; RV32ZDINX_ZICOND-NEXT: mv a4, a6
186+
; RV32ZDINX_ZICOND-NEXT: mv a5, a7
187+
; RV32ZDINX_ZICOND-NEXT: j .LBB1_3
188+
; RV32ZDINX_ZICOND-NEXT: .LBB1_2:
189+
; RV32ZDINX_ZICOND-NEXT: mv a5, a2
190+
; RV32ZDINX_ZICOND-NEXT: mv a4, a1
191+
; RV32ZDINX_ZICOND-NEXT: .LBB1_3: # %entry
192+
; RV32ZDINX_ZICOND-NEXT: mv a0, a4
193+
; RV32ZDINX_ZICOND-NEXT: mv a1, a5
187194
; RV32ZDINX_ZICOND-NEXT: ret
188195
;
189196
; RV32ZDINX_NOZICOND-LABEL: select_f64_i1:
@@ -319,12 +326,13 @@ define double @select_f64_fcmp(double %a, double %b, double %c, double %d) nounw
319326
; RV32ZDINX_ZICOND-LABEL: select_f64_fcmp:
320327
; RV32ZDINX_ZICOND: # %bb.0: # %entry
321328
; RV32ZDINX_ZICOND-NEXT: flt.d a0, a2, a0
322-
; RV32ZDINX_ZICOND-NEXT: czero.nez a1, a6, a0
323-
; RV32ZDINX_ZICOND-NEXT: czero.eqz a2, a4, a0
324-
; RV32ZDINX_ZICOND-NEXT: czero.nez a3, a7, a0
325-
; RV32ZDINX_ZICOND-NEXT: czero.eqz a4, a5, a0
326-
; RV32ZDINX_ZICOND-NEXT: or a0, a2, a1
327-
; RV32ZDINX_ZICOND-NEXT: or a1, a4, a3
329+
; RV32ZDINX_ZICOND-NEXT: bnez a0, .LBB2_2
330+
; RV32ZDINX_ZICOND-NEXT: # %bb.1: # %entry
331+
; RV32ZDINX_ZICOND-NEXT: mv a4, a6
332+
; RV32ZDINX_ZICOND-NEXT: mv a5, a7
333+
; RV32ZDINX_ZICOND-NEXT: .LBB2_2: # %entry
334+
; RV32ZDINX_ZICOND-NEXT: mv a0, a4
335+
; RV32ZDINX_ZICOND-NEXT: mv a1, a5
328336
; RV32ZDINX_ZICOND-NEXT: ret
329337
;
330338
; RV32ZDINX_NOZICOND-LABEL: select_f64_fcmp:

0 commit comments

Comments
 (0)