Skip to content

Commit dafc8b5

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 23f5ad7 commit dafc8b5

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
@@ -9587,31 +9587,16 @@ SDValue RISCVTargetLowering::lowerSELECT(SDValue Op, SelectionDAG &DAG) const {
95879587
// When there is no cost for GPR <-> FGPR, we can use zicond select for
95889588
// floating value when CondV is int type
95899589
bool FPinGPR = Subtarget.hasStdExtZfinx();
9590-
bool UseZicondForFPSel =
9591-
Subtarget.hasStdExtZicond() && FPinGPR && VT.isFloatingPoint();
95929590

9593-
if (UseZicondForFPSel) {
9594-
MVT XLenIntVT = Subtarget.getXLenVT();
9595-
9596-
// Handle RV32 with f64 (Zdinx): Split into two 32-bit integer selects.
9597-
if (VT == MVT::f64 && !Subtarget.is64Bit()) {
9598-
SDValue TrueSplit = DAG.getNode(RISCVISD::SplitF64, DL,
9599-
DAG.getVTList(MVT::i32, MVT::i32), TrueV);
9600-
SDValue FalseSplit = DAG.getNode(
9601-
RISCVISD::SplitF64, DL, DAG.getVTList(MVT::i32, MVT::i32), FalseV);
9602-
9603-
SDValue TrueLo = TrueSplit.getValue(0);
9604-
SDValue TrueHi = TrueSplit.getValue(1);
9605-
SDValue FalseLo = FalseSplit.getValue(0);
9606-
SDValue FalseHi = FalseSplit.getValue(1);
9591+
// We can handle FGPR without spliting into hi/lo parts
9592+
bool FitsInGPR = TypeSize::isKnownLE(VT.getSizeInBits(),
9593+
Subtarget.getXLenVT().getSizeInBits());
96079594

9608-
SDValue ResLo =
9609-
DAG.getNode(ISD::SELECT, DL, MVT::i32, CondV, TrueLo, FalseLo);
9610-
SDValue ResHi =
9611-
DAG.getNode(ISD::SELECT, DL, MVT::i32, CondV, TrueHi, FalseHi);
9595+
bool UseZicondForFPSel = Subtarget.hasStdExtZicond() && FPinGPR &&
9596+
VT.isFloatingPoint() && FitsInGPR;
96129597

9613-
return DAG.getNode(RISCVISD::BuildPairF64, DL, MVT::f64, ResLo, ResHi);
9614-
}
9598+
if (UseZicondForFPSel) {
9599+
MVT XLenIntVT = Subtarget.getXLenVT();
96159600

96169601
auto CastToInt = [&](SDValue V) -> SDValue {
96179602
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)