[llvm] 2e21bb8 - [RISCV][ISelLowering] Use Zicond for FP selects on Zfinx/Zdinx (#169299)

via llvm-commits llvm-commits at lists.llvm.org
Sun Nov 30 18:20:00 PST 2025


Author: fennecJ
Date: 2025-12-01T10:19:56+08:00
New Revision: 2e21bb815d527ebbe4d53f0396d1e40aae9e2146

URL: https://github.com/llvm/llvm-project/commit/2e21bb815d527ebbe4d53f0396d1e40aae9e2146
DIFF: https://github.com/llvm/llvm-project/commit/2e21bb815d527ebbe4d53f0396d1e40aae9e2146.diff

LOG: [RISCV][ISelLowering] Use Zicond for FP selects on Zfinx/Zdinx (#169299)

### Summary

This patch let RISCVTargetLowering::lowerSELECT to lower some
floating-point select operations through an integer zicond select when:
* Zicond is available, and 
* FP values live in GPRs (Zfinx/Zdinx), and
* Select condition is an integer type.

In that scenario there is no extra cost for GPR <-> "FP GPR" moves, so
we can implement FP selects with a CZERO-based sequence instead of a
branch.

For example, for  
```c
float foo(int cond, float x) {
    return (cond != 0) ? x : 0.0f;
}
```
the current lowering produces:
```asm
foo:
  mv    a2, a0
  li    a0, 0
  beqz  a2, .LBB0_2
.LBB0_1:
  mv    a0, a1
.LBB0_2:
  ret
```

With this patch, when targeting rv64ima_zicond_zfinx we instead get:  

```asm
foo:
  czero.nez  a2, zero, a0
  czero.eqz  a0, a1, a0
  or         a0, a2, a0
  ret
```


The existing branch-based lowering is preserved for:
* targets without Zicond
* targets where FP registers are separate (+f, +d without zfinx/zdinx)

### Testing

Adds llvm/test/CodeGen/RISCV/zicond-fp-select-zfinx.ll to cover:
* RV64 Zfinx/Zicond vs Zfinx without Zicond
* RV64 Zdinx/Zicond vs Zdinx without Zicond
* RV32 Zfinx/Zicond vs Zfinx without Zicond

Also adds baseline RV32F/RV64F/RV64D cases to ensure we still use
branches when FP registers are separate.

The tests check that:
* With Zicond + Zfinx/Zdinx, FP select lowers to a CZERO+OR sequence
with no conditional branches.
* Without Zicond (or without Zfinx/Zdinx), we still get branch-based
code and no czero.* instructions.

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

Modified: 
    llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 4550e40166525..d2e4bb4199a7a 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -9584,6 +9584,50 @@ SDValue RISCVTargetLowering::lowerSELECT(SDValue Op, SelectionDAG &DAG) const {
   if (SDValue V = lowerSelectToBinOp(Op.getNode(), DAG, Subtarget))
     return V;
 
+  // When there is no cost for GPR <-> FPR, we can use zicond select for
+  // floating value when CondV is int type
+  bool FPinGPR = Subtarget.hasStdExtZfinx();
+
+  // We can handle FGPR without spliting into hi/lo parts
+  bool FitsInGPR = TypeSize::isKnownLE(VT.getSizeInBits(),
+                                       Subtarget.getXLenVT().getSizeInBits());
+
+  bool UseZicondForFPSel = Subtarget.hasStdExtZicond() && FPinGPR &&
+                           VT.isFloatingPoint() && FitsInGPR;
+
+  if (UseZicondForFPSel) {
+
+    auto CastToInt = [&](SDValue V) -> SDValue {
+      // Treat +0.0 as int 0 to enable single 'czero' instruction generation.
+      if (isNullFPConstant(V))
+        return DAG.getConstant(0, DL, XLenVT);
+
+      if (VT == MVT::f16)
+        return DAG.getNode(RISCVISD::FMV_X_ANYEXTH, DL, XLenVT, V);
+
+      if (VT == MVT::f32 && Subtarget.is64Bit())
+        return DAG.getNode(RISCVISD::FMV_X_ANYEXTW_RV64, DL, XLenVT, V);
+
+      return DAG.getBitcast(XLenVT, V);
+    };
+
+    SDValue TrueVInt = CastToInt(TrueV);
+    SDValue FalseVInt = CastToInt(FalseV);
+
+    // Emit integer SELECT (lowers to Zicond)
+    SDValue ResultInt =
+        DAG.getNode(ISD::SELECT, DL, XLenVT, CondV, TrueVInt, FalseVInt);
+
+    // Convert back to floating VT
+    if (VT == MVT::f32 && Subtarget.is64Bit())
+      return DAG.getNode(RISCVISD::FMV_W_X_RV64, DL, VT, ResultInt);
+
+    if (VT == MVT::f16)
+      return DAG.getNode(RISCVISD::FMV_H_X, DL, VT, ResultInt);
+
+    return DAG.getBitcast(VT, ResultInt);
+  }
+
   // When Zicond or XVentanaCondOps is present, emit CZERO_EQZ and CZERO_NEZ
   // nodes to implement the SELECT. Performing the lowering here allows for
   // greater control over when CZERO_{EQZ/NEZ} are used vs another branchless

diff  --git a/llvm/test/CodeGen/RISCV/zicond-fp-select-zfinx.ll b/llvm/test/CodeGen/RISCV/zicond-fp-select-zfinx.ll
new file mode 100644
index 0000000000000..b505c84166eb1
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/zicond-fp-select-zfinx.ll
@@ -0,0 +1,798 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; Zicond with zfinx(implies by zdinx)
+; RUN: llc -mtriple=riscv64 -mattr=+zdinx,+zicond -verify-machineinstrs < %s | FileCheck %s --check-prefix=RV64ZDINX_ZICOND
+; RUN: llc -mtriple=riscv64 -mattr=+zdinx         -verify-machineinstrs < %s | FileCheck %s --check-prefix=RV64ZDINX_NOZICOND
+
+; Zicond with zfinx(implies by zhinx)
+; RUN: llc -mtriple=riscv64 -mattr=+zhinx,+zicond -verify-machineinstrs < %s | FileCheck %s --check-prefix=RV64ZHINX_ZICOND
+
+; Baseline with classic FP registers (no *inx); zicond select should NOT trigger
+; RUN: llc -mtriple=riscv64 -mattr=+f,+d          -verify-machineinstrs < %s | FileCheck %s --check-prefix=RV64FD
+
+; Check same optimize work on 32bit machine
+; RUN: llc -mtriple=riscv32 -mattr=+zfinx,+zicond -verify-machineinstrs < %s | FileCheck %s --check-prefix=RV32ZFINX_ZICOND
+; RUN: llc -mtriple=riscv32 -mattr=+zfinx         -verify-machineinstrs < %s | FileCheck %s --check-prefix=RV32ZFINX_NOZICOND
+; RUN: llc -mtriple=riscv32 -mattr=+zdinx,+zicond -verify-machineinstrs < %s | FileCheck %s --check-prefix=RV32ZDINX_ZICOND
+; RUN: llc -mtriple=riscv32 -mattr=+zdinx         -verify-machineinstrs < %s | FileCheck %s --check-prefix=RV32ZDINX_NOZICOND
+
+; This test checks that floating-point SELECT is lowered through integer
+; SELECT (and thus to Zicond czero.* sequence) when FP values live in GPRs
+; (Zfinx/Zdinx) and Zicond is enabled. When Zicond is disabled, we expect
+; a branch-based lowering instead.
+
+; -----------------------------------------------------------------------------
+; float select with i1 condition (Zfinx)
+; -----------------------------------------------------------------------------
+
+define float @select_f32_i1(i1 %cond, float %t, float %f) nounwind {
+; RV64ZDINX_ZICOND-LABEL: select_f32_i1:
+; RV64ZDINX_ZICOND:       # %bb.0: # %entry
+; RV64ZDINX_ZICOND-NEXT:    # kill: def $x12_w killed $x12_w def $x12
+; RV64ZDINX_ZICOND-NEXT:    # kill: def $x11_w killed $x11_w def $x11
+; RV64ZDINX_ZICOND-NEXT:    andi a0, a0, 1
+; RV64ZDINX_ZICOND-NEXT:    czero.nez a2, a2, a0
+; RV64ZDINX_ZICOND-NEXT:    czero.eqz a0, a1, a0
+; RV64ZDINX_ZICOND-NEXT:    or a0, a0, a2
+; RV64ZDINX_ZICOND-NEXT:    # kill: def $x10_w killed $x10_w killed $x10
+; RV64ZDINX_ZICOND-NEXT:    ret
+;
+; RV64ZDINX_NOZICOND-LABEL: select_f32_i1:
+; RV64ZDINX_NOZICOND:       # %bb.0: # %entry
+; RV64ZDINX_NOZICOND-NEXT:    andi a3, a0, 1
+; RV64ZDINX_NOZICOND-NEXT:    mv a0, a1
+; RV64ZDINX_NOZICOND-NEXT:    bnez a3, .LBB0_2
+; RV64ZDINX_NOZICOND-NEXT:  # %bb.1: # %entry
+; RV64ZDINX_NOZICOND-NEXT:    mv a0, a2
+; RV64ZDINX_NOZICOND-NEXT:  .LBB0_2: # %entry
+; RV64ZDINX_NOZICOND-NEXT:    ret
+;
+; RV64ZHINX_ZICOND-LABEL: select_f32_i1:
+; RV64ZHINX_ZICOND:       # %bb.0: # %entry
+; RV64ZHINX_ZICOND-NEXT:    # kill: def $x12_w killed $x12_w def $x12
+; RV64ZHINX_ZICOND-NEXT:    # kill: def $x11_w killed $x11_w def $x11
+; RV64ZHINX_ZICOND-NEXT:    andi a0, a0, 1
+; RV64ZHINX_ZICOND-NEXT:    czero.nez a2, a2, a0
+; RV64ZHINX_ZICOND-NEXT:    czero.eqz a0, a1, a0
+; RV64ZHINX_ZICOND-NEXT:    or a0, a0, a2
+; RV64ZHINX_ZICOND-NEXT:    # kill: def $x10_w killed $x10_w killed $x10
+; RV64ZHINX_ZICOND-NEXT:    ret
+;
+; RV64FD-LABEL: select_f32_i1:
+; RV64FD:       # %bb.0: # %entry
+; RV64FD-NEXT:    andi a0, a0, 1
+; RV64FD-NEXT:    bnez a0, .LBB0_2
+; RV64FD-NEXT:  # %bb.1: # %entry
+; RV64FD-NEXT:    fmv.s fa0, fa1
+; RV64FD-NEXT:  .LBB0_2: # %entry
+; RV64FD-NEXT:    ret
+;
+; RV32ZFINX_ZICOND-LABEL: select_f32_i1:
+; RV32ZFINX_ZICOND:       # %bb.0: # %entry
+; RV32ZFINX_ZICOND-NEXT:    # kill: def $x12_w killed $x12_w def $x12
+; RV32ZFINX_ZICOND-NEXT:    # kill: def $x11_w killed $x11_w def $x11
+; RV32ZFINX_ZICOND-NEXT:    andi a0, a0, 1
+; RV32ZFINX_ZICOND-NEXT:    czero.nez a2, a2, a0
+; RV32ZFINX_ZICOND-NEXT:    czero.eqz a0, a1, a0
+; RV32ZFINX_ZICOND-NEXT:    or a0, a0, a2
+; RV32ZFINX_ZICOND-NEXT:    # kill: def $x10_w killed $x10_w killed $x10
+; RV32ZFINX_ZICOND-NEXT:    ret
+;
+; RV32ZFINX_NOZICOND-LABEL: select_f32_i1:
+; RV32ZFINX_NOZICOND:       # %bb.0: # %entry
+; RV32ZFINX_NOZICOND-NEXT:    andi a3, a0, 1
+; RV32ZFINX_NOZICOND-NEXT:    mv a0, a1
+; RV32ZFINX_NOZICOND-NEXT:    bnez a3, .LBB0_2
+; RV32ZFINX_NOZICOND-NEXT:  # %bb.1: # %entry
+; RV32ZFINX_NOZICOND-NEXT:    mv a0, a2
+; RV32ZFINX_NOZICOND-NEXT:  .LBB0_2: # %entry
+; RV32ZFINX_NOZICOND-NEXT:    ret
+;
+; RV32ZDINX_ZICOND-LABEL: select_f32_i1:
+; RV32ZDINX_ZICOND:       # %bb.0: # %entry
+; RV32ZDINX_ZICOND-NEXT:    # kill: def $x12_w killed $x12_w def $x12
+; RV32ZDINX_ZICOND-NEXT:    # kill: def $x11_w killed $x11_w def $x11
+; RV32ZDINX_ZICOND-NEXT:    andi a0, a0, 1
+; RV32ZDINX_ZICOND-NEXT:    czero.nez a2, a2, a0
+; RV32ZDINX_ZICOND-NEXT:    czero.eqz a0, a1, a0
+; RV32ZDINX_ZICOND-NEXT:    or a0, a0, a2
+; RV32ZDINX_ZICOND-NEXT:    # kill: def $x10_w killed $x10_w killed $x10
+; RV32ZDINX_ZICOND-NEXT:    ret
+;
+; RV32ZDINX_NOZICOND-LABEL: select_f32_i1:
+; RV32ZDINX_NOZICOND:       # %bb.0: # %entry
+; RV32ZDINX_NOZICOND-NEXT:    andi a3, a0, 1
+; RV32ZDINX_NOZICOND-NEXT:    mv a0, a1
+; RV32ZDINX_NOZICOND-NEXT:    bnez a3, .LBB0_2
+; RV32ZDINX_NOZICOND-NEXT:  # %bb.1: # %entry
+; RV32ZDINX_NOZICOND-NEXT:    mv a0, a2
+; RV32ZDINX_NOZICOND-NEXT:  .LBB0_2: # %entry
+; RV32ZDINX_NOZICOND-NEXT:    ret
+entry:
+  %sel = select i1 %cond, float %t, float %f
+  ret float %sel
+}
+
+; -----------------------------------------------------------------------------
+; double select with i1 condition (Zdinx)
+; -----------------------------------------------------------------------------
+
+define double @select_f64_i1(i1 %cond, double %t, double %f) nounwind {
+; RV64ZDINX_ZICOND-LABEL: select_f64_i1:
+; RV64ZDINX_ZICOND:       # %bb.0: # %entry
+; RV64ZDINX_ZICOND-NEXT:    andi a0, a0, 1
+; RV64ZDINX_ZICOND-NEXT:    czero.nez a2, a2, a0
+; RV64ZDINX_ZICOND-NEXT:    czero.eqz a0, a1, a0
+; RV64ZDINX_ZICOND-NEXT:    or a0, a0, a2
+; RV64ZDINX_ZICOND-NEXT:    ret
+;
+; RV64ZDINX_NOZICOND-LABEL: select_f64_i1:
+; RV64ZDINX_NOZICOND:       # %bb.0: # %entry
+; RV64ZDINX_NOZICOND-NEXT:    andi a3, a0, 1
+; RV64ZDINX_NOZICOND-NEXT:    mv a0, a1
+; RV64ZDINX_NOZICOND-NEXT:    bnez a3, .LBB1_2
+; RV64ZDINX_NOZICOND-NEXT:  # %bb.1: # %entry
+; RV64ZDINX_NOZICOND-NEXT:    mv a0, a2
+; RV64ZDINX_NOZICOND-NEXT:  .LBB1_2: # %entry
+; RV64ZDINX_NOZICOND-NEXT:    ret
+;
+; RV64ZHINX_ZICOND-LABEL: select_f64_i1:
+; RV64ZHINX_ZICOND:       # %bb.0: # %entry
+; RV64ZHINX_ZICOND-NEXT:    andi a0, a0, 1
+; RV64ZHINX_ZICOND-NEXT:    czero.nez a2, a2, a0
+; RV64ZHINX_ZICOND-NEXT:    czero.eqz a0, a1, a0
+; RV64ZHINX_ZICOND-NEXT:    or a0, a0, a2
+; RV64ZHINX_ZICOND-NEXT:    ret
+;
+; RV64FD-LABEL: select_f64_i1:
+; RV64FD:       # %bb.0: # %entry
+; RV64FD-NEXT:    andi a0, a0, 1
+; RV64FD-NEXT:    bnez a0, .LBB1_2
+; RV64FD-NEXT:  # %bb.1: # %entry
+; RV64FD-NEXT:    fmv.d fa0, fa1
+; RV64FD-NEXT:  .LBB1_2: # %entry
+; RV64FD-NEXT:    ret
+;
+; RV32ZFINX_ZICOND-LABEL: select_f64_i1:
+; RV32ZFINX_ZICOND:       # %bb.0: # %entry
+; RV32ZFINX_ZICOND-NEXT:    andi a0, a0, 1
+; RV32ZFINX_ZICOND-NEXT:    czero.nez a3, a3, a0
+; RV32ZFINX_ZICOND-NEXT:    czero.eqz a1, a1, a0
+; RV32ZFINX_ZICOND-NEXT:    czero.nez a4, a4, a0
+; RV32ZFINX_ZICOND-NEXT:    czero.eqz a2, a2, a0
+; RV32ZFINX_ZICOND-NEXT:    or a0, a1, a3
+; RV32ZFINX_ZICOND-NEXT:    or a1, a2, a4
+; RV32ZFINX_ZICOND-NEXT:    ret
+;
+; RV32ZFINX_NOZICOND-LABEL: select_f64_i1:
+; RV32ZFINX_NOZICOND:       # %bb.0: # %entry
+; RV32ZFINX_NOZICOND-NEXT:    andi a5, a0, 1
+; RV32ZFINX_NOZICOND-NEXT:    mv a0, a1
+; RV32ZFINX_NOZICOND-NEXT:    bnez a5, .LBB1_2
+; RV32ZFINX_NOZICOND-NEXT:  # %bb.1: # %entry
+; RV32ZFINX_NOZICOND-NEXT:    mv a0, a3
+; RV32ZFINX_NOZICOND-NEXT:    mv a2, a4
+; RV32ZFINX_NOZICOND-NEXT:  .LBB1_2: # %entry
+; RV32ZFINX_NOZICOND-NEXT:    mv a1, a2
+; RV32ZFINX_NOZICOND-NEXT:    ret
+;
+; RV32ZDINX_ZICOND-LABEL: select_f64_i1:
+; RV32ZDINX_ZICOND:       # %bb.0: # %entry
+; RV32ZDINX_ZICOND-NEXT:    andi a0, a0, 1
+; RV32ZDINX_ZICOND-NEXT:    bnez a0, .LBB1_2
+; RV32ZDINX_ZICOND-NEXT:  # %bb.1: # %entry
+; RV32ZDINX_ZICOND-NEXT:    mv a7, a4
+; RV32ZDINX_ZICOND-NEXT:    mv a6, a3
+; RV32ZDINX_ZICOND-NEXT:    fmv.d a4, a6
+; RV32ZDINX_ZICOND-NEXT:    j .LBB1_3
+; RV32ZDINX_ZICOND-NEXT:  .LBB1_2:
+; RV32ZDINX_ZICOND-NEXT:    mv a5, a2
+; RV32ZDINX_ZICOND-NEXT:    mv a4, a1
+; RV32ZDINX_ZICOND-NEXT:  .LBB1_3: # %entry
+; RV32ZDINX_ZICOND-NEXT:    mv a0, a4
+; RV32ZDINX_ZICOND-NEXT:    mv a1, a5
+; RV32ZDINX_ZICOND-NEXT:    ret
+;
+; RV32ZDINX_NOZICOND-LABEL: select_f64_i1:
+; RV32ZDINX_NOZICOND:       # %bb.0: # %entry
+; RV32ZDINX_NOZICOND-NEXT:    andi a0, a0, 1
+; RV32ZDINX_NOZICOND-NEXT:    bnez a0, .LBB1_2
+; RV32ZDINX_NOZICOND-NEXT:  # %bb.1: # %entry
+; RV32ZDINX_NOZICOND-NEXT:    mv a7, a4
+; RV32ZDINX_NOZICOND-NEXT:    mv a6, a3
+; RV32ZDINX_NOZICOND-NEXT:    fmv.d a4, a6
+; RV32ZDINX_NOZICOND-NEXT:    j .LBB1_3
+; RV32ZDINX_NOZICOND-NEXT:  .LBB1_2:
+; RV32ZDINX_NOZICOND-NEXT:    mv a5, a2
+; RV32ZDINX_NOZICOND-NEXT:    mv a4, a1
+; RV32ZDINX_NOZICOND-NEXT:  .LBB1_3: # %entry
+; RV32ZDINX_NOZICOND-NEXT:    mv a0, a4
+; RV32ZDINX_NOZICOND-NEXT:    mv a1, a5
+; RV32ZDINX_NOZICOND-NEXT:    ret
+entry:
+  %sel = select i1 %cond, double %t, double %f
+  ret double %sel
+}
+
+; -----------------------------------------------------------------------------
+; double select with floating-point compare condition (a > b ? c : d), Zdinx
+; -----------------------------------------------------------------------------
+
+define double @select_f64_fcmp(double %a, double %b, double %c, double %d) nounwind {
+; RV64ZDINX_ZICOND-LABEL: select_f64_fcmp:
+; RV64ZDINX_ZICOND:       # %bb.0: # %entry
+; RV64ZDINX_ZICOND-NEXT:    flt.d a0, a1, a0
+; RV64ZDINX_ZICOND-NEXT:    czero.nez a1, a3, a0
+; RV64ZDINX_ZICOND-NEXT:    czero.eqz a0, a2, a0
+; RV64ZDINX_ZICOND-NEXT:    or a0, a0, a1
+; RV64ZDINX_ZICOND-NEXT:    ret
+;
+; RV64ZDINX_NOZICOND-LABEL: select_f64_fcmp:
+; RV64ZDINX_NOZICOND:       # %bb.0: # %entry
+; RV64ZDINX_NOZICOND-NEXT:    flt.d a1, a1, a0
+; RV64ZDINX_NOZICOND-NEXT:    mv a0, a2
+; RV64ZDINX_NOZICOND-NEXT:    bnez a1, .LBB2_2
+; RV64ZDINX_NOZICOND-NEXT:  # %bb.1: # %entry
+; RV64ZDINX_NOZICOND-NEXT:    mv a0, a3
+; RV64ZDINX_NOZICOND-NEXT:  .LBB2_2: # %entry
+; RV64ZDINX_NOZICOND-NEXT:    ret
+;
+; RV64ZHINX_ZICOND-LABEL: select_f64_fcmp:
+; RV64ZHINX_ZICOND:       # %bb.0: # %entry
+; RV64ZHINX_ZICOND-NEXT:    addi sp, sp, -32
+; RV64ZHINX_ZICOND-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
+; RV64ZHINX_ZICOND-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
+; RV64ZHINX_ZICOND-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
+; RV64ZHINX_ZICOND-NEXT:    mv s0, a3
+; RV64ZHINX_ZICOND-NEXT:    mv s1, a2
+; RV64ZHINX_ZICOND-NEXT:    call __gtdf2
+; RV64ZHINX_ZICOND-NEXT:    sgtz a0, a0
+; RV64ZHINX_ZICOND-NEXT:    czero.nez a1, s0, a0
+; RV64ZHINX_ZICOND-NEXT:    czero.eqz a0, s1, a0
+; RV64ZHINX_ZICOND-NEXT:    or a0, a0, a1
+; RV64ZHINX_ZICOND-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
+; RV64ZHINX_ZICOND-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
+; RV64ZHINX_ZICOND-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
+; RV64ZHINX_ZICOND-NEXT:    addi sp, sp, 32
+; RV64ZHINX_ZICOND-NEXT:    ret
+;
+; RV64FD-LABEL: select_f64_fcmp:
+; RV64FD:       # %bb.0: # %entry
+; RV64FD-NEXT:    flt.d a0, fa1, fa0
+; RV64FD-NEXT:    fmv.d fa0, fa2
+; RV64FD-NEXT:    bnez a0, .LBB2_2
+; RV64FD-NEXT:  # %bb.1: # %entry
+; RV64FD-NEXT:    fmv.d fa0, fa3
+; RV64FD-NEXT:  .LBB2_2: # %entry
+; RV64FD-NEXT:    ret
+;
+; RV32ZFINX_ZICOND-LABEL: select_f64_fcmp:
+; RV32ZFINX_ZICOND:       # %bb.0: # %entry
+; RV32ZFINX_ZICOND-NEXT:    addi sp, sp, -32
+; RV32ZFINX_ZICOND-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
+; RV32ZFINX_ZICOND-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
+; RV32ZFINX_ZICOND-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
+; RV32ZFINX_ZICOND-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
+; RV32ZFINX_ZICOND-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
+; RV32ZFINX_ZICOND-NEXT:    mv s0, a7
+; RV32ZFINX_ZICOND-NEXT:    mv s1, a6
+; RV32ZFINX_ZICOND-NEXT:    mv s2, a5
+; RV32ZFINX_ZICOND-NEXT:    mv s3, a4
+; RV32ZFINX_ZICOND-NEXT:    call __gtdf2
+; RV32ZFINX_ZICOND-NEXT:    sgtz a0, a0
+; RV32ZFINX_ZICOND-NEXT:    czero.nez a1, s1, a0
+; RV32ZFINX_ZICOND-NEXT:    czero.eqz a2, s3, a0
+; RV32ZFINX_ZICOND-NEXT:    czero.nez a3, s0, a0
+; RV32ZFINX_ZICOND-NEXT:    czero.eqz a4, s2, a0
+; RV32ZFINX_ZICOND-NEXT:    or a0, a2, a1
+; RV32ZFINX_ZICOND-NEXT:    or a1, a4, a3
+; RV32ZFINX_ZICOND-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
+; RV32ZFINX_ZICOND-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
+; RV32ZFINX_ZICOND-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
+; RV32ZFINX_ZICOND-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
+; RV32ZFINX_ZICOND-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
+; RV32ZFINX_ZICOND-NEXT:    addi sp, sp, 32
+; RV32ZFINX_ZICOND-NEXT:    ret
+;
+; RV32ZFINX_NOZICOND-LABEL: select_f64_fcmp:
+; RV32ZFINX_NOZICOND:       # %bb.0: # %entry
+; RV32ZFINX_NOZICOND-NEXT:    addi sp, sp, -32
+; RV32ZFINX_NOZICOND-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
+; RV32ZFINX_NOZICOND-NEXT:    sw s0, 24(sp) # 4-byte Folded Spill
+; RV32ZFINX_NOZICOND-NEXT:    sw s1, 20(sp) # 4-byte Folded Spill
+; RV32ZFINX_NOZICOND-NEXT:    sw s2, 16(sp) # 4-byte Folded Spill
+; RV32ZFINX_NOZICOND-NEXT:    sw s3, 12(sp) # 4-byte Folded Spill
+; RV32ZFINX_NOZICOND-NEXT:    mv s1, a7
+; RV32ZFINX_NOZICOND-NEXT:    mv s3, a6
+; RV32ZFINX_NOZICOND-NEXT:    mv s0, a5
+; RV32ZFINX_NOZICOND-NEXT:    mv s2, a4
+; RV32ZFINX_NOZICOND-NEXT:    call __gtdf2
+; RV32ZFINX_NOZICOND-NEXT:    bgtz a0, .LBB2_2
+; RV32ZFINX_NOZICOND-NEXT:  # %bb.1: # %entry
+; RV32ZFINX_NOZICOND-NEXT:    mv s2, s3
+; RV32ZFINX_NOZICOND-NEXT:    mv s0, s1
+; RV32ZFINX_NOZICOND-NEXT:  .LBB2_2: # %entry
+; RV32ZFINX_NOZICOND-NEXT:    mv a0, s2
+; RV32ZFINX_NOZICOND-NEXT:    mv a1, s0
+; RV32ZFINX_NOZICOND-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
+; RV32ZFINX_NOZICOND-NEXT:    lw s0, 24(sp) # 4-byte Folded Reload
+; RV32ZFINX_NOZICOND-NEXT:    lw s1, 20(sp) # 4-byte Folded Reload
+; RV32ZFINX_NOZICOND-NEXT:    lw s2, 16(sp) # 4-byte Folded Reload
+; RV32ZFINX_NOZICOND-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
+; RV32ZFINX_NOZICOND-NEXT:    addi sp, sp, 32
+; RV32ZFINX_NOZICOND-NEXT:    ret
+;
+; RV32ZDINX_ZICOND-LABEL: select_f64_fcmp:
+; RV32ZDINX_ZICOND:       # %bb.0: # %entry
+; RV32ZDINX_ZICOND-NEXT:    flt.d a0, a2, a0
+; RV32ZDINX_ZICOND-NEXT:    bnez a0, .LBB2_2
+; RV32ZDINX_ZICOND-NEXT:  # %bb.1: # %entry
+; RV32ZDINX_ZICOND-NEXT:    fmv.d a4, a6
+; RV32ZDINX_ZICOND-NEXT:  .LBB2_2: # %entry
+; RV32ZDINX_ZICOND-NEXT:    mv a0, a4
+; RV32ZDINX_ZICOND-NEXT:    mv a1, a5
+; RV32ZDINX_ZICOND-NEXT:    ret
+;
+; 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:    fmv.d a4, a6
+; RV32ZDINX_NOZICOND-NEXT:  .LBB2_2: # %entry
+; RV32ZDINX_NOZICOND-NEXT:    mv a0, a4
+; RV32ZDINX_NOZICOND-NEXT:    mv a1, a5
+; RV32ZDINX_NOZICOND-NEXT:    ret
+entry:
+  %cmp = fcmp ogt double %a, %b
+  %sel = select i1 %cmp, double %c, double %d
+  ret double %sel
+}
+
+; -----------------------------------------------------------------------------
+; half select with  i1 condition (cond ? a : b), Zfinx
+; -----------------------------------------------------------------------------
+
+define dso_local noundef half @select_half_i1(i1 %cond, half %a, half %b) nounwind {
+; RV64ZDINX_ZICOND-LABEL: select_half_i1:
+; RV64ZDINX_ZICOND:       # %bb.0: # %entry
+; RV64ZDINX_ZICOND-NEXT:    # kill: def $x12_w killed $x12_w def $x12
+; RV64ZDINX_ZICOND-NEXT:    # kill: def $x11_w killed $x11_w def $x11
+; RV64ZDINX_ZICOND-NEXT:    andi a0, a0, 1
+; RV64ZDINX_ZICOND-NEXT:    czero.nez a2, a2, a0
+; RV64ZDINX_ZICOND-NEXT:    czero.eqz a0, a1, a0
+; RV64ZDINX_ZICOND-NEXT:    or a0, a0, a2
+; RV64ZDINX_ZICOND-NEXT:    lui a1, 1048560
+; RV64ZDINX_ZICOND-NEXT:    or a0, a0, a1
+; RV64ZDINX_ZICOND-NEXT:    # kill: def $x10_w killed $x10_w killed $x10
+; RV64ZDINX_ZICOND-NEXT:    ret
+;
+; RV64ZDINX_NOZICOND-LABEL: select_half_i1:
+; RV64ZDINX_NOZICOND:       # %bb.0: # %entry
+; RV64ZDINX_NOZICOND-NEXT:    # kill: def $x12_w killed $x12_w def $x12
+; RV64ZDINX_NOZICOND-NEXT:    andi a0, a0, 1
+; RV64ZDINX_NOZICOND-NEXT:    # kill: def $x11_w killed $x11_w def $x11
+; RV64ZDINX_NOZICOND-NEXT:    bnez a0, .LBB3_2
+; RV64ZDINX_NOZICOND-NEXT:  # %bb.1: # %entry
+; RV64ZDINX_NOZICOND-NEXT:    mv a1, a2
+; RV64ZDINX_NOZICOND-NEXT:  .LBB3_2: # %entry
+; RV64ZDINX_NOZICOND-NEXT:    lui a0, 1048560
+; RV64ZDINX_NOZICOND-NEXT:    or a0, a1, a0
+; RV64ZDINX_NOZICOND-NEXT:    # kill: def $x10_w killed $x10_w killed $x10
+; RV64ZDINX_NOZICOND-NEXT:    ret
+;
+; RV64ZHINX_ZICOND-LABEL: select_half_i1:
+; RV64ZHINX_ZICOND:       # %bb.0: # %entry
+; RV64ZHINX_ZICOND-NEXT:    # kill: def $x12_h killed $x12_h def $x12
+; RV64ZHINX_ZICOND-NEXT:    # kill: def $x11_h killed $x11_h def $x11
+; RV64ZHINX_ZICOND-NEXT:    andi a0, a0, 1
+; RV64ZHINX_ZICOND-NEXT:    czero.nez a2, a2, a0
+; RV64ZHINX_ZICOND-NEXT:    czero.eqz a0, a1, a0
+; RV64ZHINX_ZICOND-NEXT:    or a0, a0, a2
+; RV64ZHINX_ZICOND-NEXT:    # kill: def $x10_h killed $x10_h killed $x10
+; RV64ZHINX_ZICOND-NEXT:    ret
+;
+; RV64FD-LABEL: select_half_i1:
+; RV64FD:       # %bb.0: # %entry
+; RV64FD-NEXT:    andi a0, a0, 1
+; RV64FD-NEXT:    bnez a0, .LBB3_2
+; RV64FD-NEXT:  # %bb.1: # %entry
+; RV64FD-NEXT:    fmv.x.w a0, fa1
+; RV64FD-NEXT:    j .LBB3_3
+; RV64FD-NEXT:  .LBB3_2:
+; RV64FD-NEXT:    fmv.x.w a0, fa0
+; RV64FD-NEXT:  .LBB3_3: # %entry
+; RV64FD-NEXT:    lui a1, 1048560
+; RV64FD-NEXT:    or a0, a0, a1
+; RV64FD-NEXT:    fmv.w.x fa0, a0
+; RV64FD-NEXT:    ret
+;
+; RV32ZFINX_ZICOND-LABEL: select_half_i1:
+; RV32ZFINX_ZICOND:       # %bb.0: # %entry
+; RV32ZFINX_ZICOND-NEXT:    # kill: def $x12_w killed $x12_w def $x12
+; RV32ZFINX_ZICOND-NEXT:    # kill: def $x11_w killed $x11_w def $x11
+; RV32ZFINX_ZICOND-NEXT:    andi a0, a0, 1
+; RV32ZFINX_ZICOND-NEXT:    czero.nez a2, a2, a0
+; RV32ZFINX_ZICOND-NEXT:    czero.eqz a0, a1, a0
+; RV32ZFINX_ZICOND-NEXT:    or a0, a0, a2
+; RV32ZFINX_ZICOND-NEXT:    lui a1, 1048560
+; RV32ZFINX_ZICOND-NEXT:    or a0, a0, a1
+; RV32ZFINX_ZICOND-NEXT:    # kill: def $x10_w killed $x10_w killed $x10
+; RV32ZFINX_ZICOND-NEXT:    ret
+;
+; RV32ZFINX_NOZICOND-LABEL: select_half_i1:
+; RV32ZFINX_NOZICOND:       # %bb.0: # %entry
+; RV32ZFINX_NOZICOND-NEXT:    # kill: def $x12_w killed $x12_w def $x12
+; RV32ZFINX_NOZICOND-NEXT:    andi a0, a0, 1
+; RV32ZFINX_NOZICOND-NEXT:    # kill: def $x11_w killed $x11_w def $x11
+; RV32ZFINX_NOZICOND-NEXT:    bnez a0, .LBB3_2
+; RV32ZFINX_NOZICOND-NEXT:  # %bb.1: # %entry
+; RV32ZFINX_NOZICOND-NEXT:    mv a1, a2
+; RV32ZFINX_NOZICOND-NEXT:  .LBB3_2: # %entry
+; RV32ZFINX_NOZICOND-NEXT:    lui a0, 1048560
+; RV32ZFINX_NOZICOND-NEXT:    or a0, a1, a0
+; RV32ZFINX_NOZICOND-NEXT:    # kill: def $x10_w killed $x10_w killed $x10
+; RV32ZFINX_NOZICOND-NEXT:    ret
+;
+; RV32ZDINX_ZICOND-LABEL: select_half_i1:
+; RV32ZDINX_ZICOND:       # %bb.0: # %entry
+; RV32ZDINX_ZICOND-NEXT:    # kill: def $x12_w killed $x12_w def $x12
+; RV32ZDINX_ZICOND-NEXT:    # kill: def $x11_w killed $x11_w def $x11
+; RV32ZDINX_ZICOND-NEXT:    andi a0, a0, 1
+; RV32ZDINX_ZICOND-NEXT:    czero.nez a2, a2, a0
+; RV32ZDINX_ZICOND-NEXT:    czero.eqz a0, a1, a0
+; RV32ZDINX_ZICOND-NEXT:    or a0, a0, a2
+; RV32ZDINX_ZICOND-NEXT:    lui a1, 1048560
+; RV32ZDINX_ZICOND-NEXT:    or a0, a0, a1
+; RV32ZDINX_ZICOND-NEXT:    # kill: def $x10_w killed $x10_w killed $x10
+; RV32ZDINX_ZICOND-NEXT:    ret
+;
+; RV32ZDINX_NOZICOND-LABEL: select_half_i1:
+; RV32ZDINX_NOZICOND:       # %bb.0: # %entry
+; RV32ZDINX_NOZICOND-NEXT:    # kill: def $x12_w killed $x12_w def $x12
+; RV32ZDINX_NOZICOND-NEXT:    andi a0, a0, 1
+; RV32ZDINX_NOZICOND-NEXT:    # kill: def $x11_w killed $x11_w def $x11
+; RV32ZDINX_NOZICOND-NEXT:    bnez a0, .LBB3_2
+; RV32ZDINX_NOZICOND-NEXT:  # %bb.1: # %entry
+; RV32ZDINX_NOZICOND-NEXT:    mv a1, a2
+; RV32ZDINX_NOZICOND-NEXT:  .LBB3_2: # %entry
+; RV32ZDINX_NOZICOND-NEXT:    lui a0, 1048560
+; RV32ZDINX_NOZICOND-NEXT:    or a0, a1, a0
+; RV32ZDINX_NOZICOND-NEXT:    # kill: def $x10_w killed $x10_w killed $x10
+; RV32ZDINX_NOZICOND-NEXT:    ret
+entry:
+  %sel = select i1 %cond, half %a, half %b
+  ret half %sel
+}
+
+; -----------------------------------------------------------------------------
+; Test select with i1 condition and zero ret val (cond ? a : 0), Zfinx
+; -----------------------------------------------------------------------------
+define dso_local noundef float @select_i1_f32_0(i1 %cond, float %t) nounwind {
+; RV64ZDINX_ZICOND-LABEL: select_i1_f32_0:
+; RV64ZDINX_ZICOND:       # %bb.0: # %entry
+; RV64ZDINX_ZICOND-NEXT:    # kill: def $x11_w killed $x11_w def $x11
+; RV64ZDINX_ZICOND-NEXT:    andi a0, a0, 1
+; RV64ZDINX_ZICOND-NEXT:    czero.eqz a0, a1, a0
+; RV64ZDINX_ZICOND-NEXT:    # kill: def $x10_w killed $x10_w killed $x10
+; RV64ZDINX_ZICOND-NEXT:    ret
+;
+; RV64ZDINX_NOZICOND-LABEL: select_i1_f32_0:
+; RV64ZDINX_NOZICOND:       # %bb.0: # %entry
+; RV64ZDINX_NOZICOND-NEXT:    andi a2, a0, 1
+; RV64ZDINX_NOZICOND-NEXT:    mv a0, a1
+; RV64ZDINX_NOZICOND-NEXT:    bnez a2, .LBB4_2
+; RV64ZDINX_NOZICOND-NEXT:  # %bb.1: # %entry
+; RV64ZDINX_NOZICOND-NEXT:    li a0, 0
+; RV64ZDINX_NOZICOND-NEXT:  .LBB4_2: # %entry
+; RV64ZDINX_NOZICOND-NEXT:    ret
+;
+; RV64ZHINX_ZICOND-LABEL: select_i1_f32_0:
+; RV64ZHINX_ZICOND:       # %bb.0: # %entry
+; RV64ZHINX_ZICOND-NEXT:    # kill: def $x11_w killed $x11_w def $x11
+; RV64ZHINX_ZICOND-NEXT:    andi a0, a0, 1
+; RV64ZHINX_ZICOND-NEXT:    czero.eqz a0, a1, a0
+; RV64ZHINX_ZICOND-NEXT:    # kill: def $x10_w killed $x10_w killed $x10
+; RV64ZHINX_ZICOND-NEXT:    ret
+;
+; RV64FD-LABEL: select_i1_f32_0:
+; RV64FD:       # %bb.0: # %entry
+; RV64FD-NEXT:    andi a0, a0, 1
+; RV64FD-NEXT:    bnez a0, .LBB4_2
+; RV64FD-NEXT:  # %bb.1: # %entry
+; RV64FD-NEXT:    fmv.w.x fa0, zero
+; RV64FD-NEXT:  .LBB4_2: # %entry
+; RV64FD-NEXT:    ret
+;
+; RV32ZFINX_ZICOND-LABEL: select_i1_f32_0:
+; RV32ZFINX_ZICOND:       # %bb.0: # %entry
+; RV32ZFINX_ZICOND-NEXT:    # kill: def $x11_w killed $x11_w def $x11
+; RV32ZFINX_ZICOND-NEXT:    andi a0, a0, 1
+; RV32ZFINX_ZICOND-NEXT:    czero.eqz a0, a1, a0
+; RV32ZFINX_ZICOND-NEXT:    # kill: def $x10_w killed $x10_w killed $x10
+; RV32ZFINX_ZICOND-NEXT:    ret
+;
+; RV32ZFINX_NOZICOND-LABEL: select_i1_f32_0:
+; RV32ZFINX_NOZICOND:       # %bb.0: # %entry
+; RV32ZFINX_NOZICOND-NEXT:    andi a2, a0, 1
+; RV32ZFINX_NOZICOND-NEXT:    mv a0, a1
+; RV32ZFINX_NOZICOND-NEXT:    bnez a2, .LBB4_2
+; RV32ZFINX_NOZICOND-NEXT:  # %bb.1: # %entry
+; RV32ZFINX_NOZICOND-NEXT:    li a0, 0
+; RV32ZFINX_NOZICOND-NEXT:  .LBB4_2: # %entry
+; RV32ZFINX_NOZICOND-NEXT:    ret
+;
+; RV32ZDINX_ZICOND-LABEL: select_i1_f32_0:
+; RV32ZDINX_ZICOND:       # %bb.0: # %entry
+; RV32ZDINX_ZICOND-NEXT:    # kill: def $x11_w killed $x11_w def $x11
+; RV32ZDINX_ZICOND-NEXT:    andi a0, a0, 1
+; RV32ZDINX_ZICOND-NEXT:    czero.eqz a0, a1, a0
+; RV32ZDINX_ZICOND-NEXT:    # kill: def $x10_w killed $x10_w killed $x10
+; RV32ZDINX_ZICOND-NEXT:    ret
+;
+; RV32ZDINX_NOZICOND-LABEL: select_i1_f32_0:
+; RV32ZDINX_NOZICOND:       # %bb.0: # %entry
+; RV32ZDINX_NOZICOND-NEXT:    andi a2, a0, 1
+; RV32ZDINX_NOZICOND-NEXT:    mv a0, a1
+; RV32ZDINX_NOZICOND-NEXT:    bnez a2, .LBB4_2
+; RV32ZDINX_NOZICOND-NEXT:  # %bb.1: # %entry
+; RV32ZDINX_NOZICOND-NEXT:    li a0, 0
+; RV32ZDINX_NOZICOND-NEXT:  .LBB4_2: # %entry
+; RV32ZDINX_NOZICOND-NEXT:    ret
+entry:
+  %sel = select i1 %cond, float %t, float 0.000000e+00
+  ret float %sel
+}
+
+; -----------------------------------------------------------------------------
+; Test select with i1 condition and zero ret val for half fp (cond ? a : 0)
+; -----------------------------------------------------------------------------
+define dso_local noundef half @select_i1_half_0(i1 %cond, half %val) nounwind {
+; RV64ZDINX_ZICOND-LABEL: select_i1_half_0:
+; RV64ZDINX_ZICOND:       # %bb.0: # %entry
+; RV64ZDINX_ZICOND-NEXT:    # kill: def $x11_w killed $x11_w def $x11
+; RV64ZDINX_ZICOND-NEXT:    andi a0, a0, 1
+; RV64ZDINX_ZICOND-NEXT:    czero.eqz a0, a1, a0
+; RV64ZDINX_ZICOND-NEXT:    lui a1, 1048560
+; RV64ZDINX_ZICOND-NEXT:    or a0, a0, a1
+; RV64ZDINX_ZICOND-NEXT:    # kill: def $x10_w killed $x10_w killed $x10
+; RV64ZDINX_ZICOND-NEXT:    ret
+;
+; RV64ZDINX_NOZICOND-LABEL: select_i1_half_0:
+; RV64ZDINX_NOZICOND:       # %bb.0: # %entry
+; RV64ZDINX_NOZICOND-NEXT:    # kill: def $x11_w killed $x11_w def $x11
+; RV64ZDINX_NOZICOND-NEXT:    slli a0, a0, 63
+; RV64ZDINX_NOZICOND-NEXT:    srai a0, a0, 63
+; RV64ZDINX_NOZICOND-NEXT:    and a0, a0, a1
+; RV64ZDINX_NOZICOND-NEXT:    lui a1, 1048560
+; RV64ZDINX_NOZICOND-NEXT:    or a0, a0, a1
+; RV64ZDINX_NOZICOND-NEXT:    # kill: def $x10_w killed $x10_w killed $x10
+; RV64ZDINX_NOZICOND-NEXT:    ret
+;
+; RV64ZHINX_ZICOND-LABEL: select_i1_half_0:
+; RV64ZHINX_ZICOND:       # %bb.0: # %entry
+; RV64ZHINX_ZICOND-NEXT:    # kill: def $x11_h killed $x11_h def $x11
+; RV64ZHINX_ZICOND-NEXT:    andi a0, a0, 1
+; RV64ZHINX_ZICOND-NEXT:    czero.eqz a0, a1, a0
+; RV64ZHINX_ZICOND-NEXT:    # kill: def $x10_h killed $x10_h killed $x10
+; RV64ZHINX_ZICOND-NEXT:    ret
+;
+; RV64FD-LABEL: select_i1_half_0:
+; RV64FD:       # %bb.0: # %entry
+; RV64FD-NEXT:    fmv.x.w a1, fa0
+; RV64FD-NEXT:    slli a0, a0, 63
+; RV64FD-NEXT:    srai a0, a0, 63
+; RV64FD-NEXT:    and a0, a0, a1
+; RV64FD-NEXT:    lui a1, 1048560
+; RV64FD-NEXT:    or a0, a0, a1
+; RV64FD-NEXT:    fmv.w.x fa0, a0
+; RV64FD-NEXT:    ret
+;
+; RV32ZFINX_ZICOND-LABEL: select_i1_half_0:
+; RV32ZFINX_ZICOND:       # %bb.0: # %entry
+; RV32ZFINX_ZICOND-NEXT:    # kill: def $x11_w killed $x11_w def $x11
+; RV32ZFINX_ZICOND-NEXT:    andi a0, a0, 1
+; RV32ZFINX_ZICOND-NEXT:    czero.eqz a0, a1, a0
+; RV32ZFINX_ZICOND-NEXT:    lui a1, 1048560
+; RV32ZFINX_ZICOND-NEXT:    or a0, a0, a1
+; RV32ZFINX_ZICOND-NEXT:    # kill: def $x10_w killed $x10_w killed $x10
+; RV32ZFINX_ZICOND-NEXT:    ret
+;
+; RV32ZFINX_NOZICOND-LABEL: select_i1_half_0:
+; RV32ZFINX_NOZICOND:       # %bb.0: # %entry
+; RV32ZFINX_NOZICOND-NEXT:    # kill: def $x11_w killed $x11_w def $x11
+; RV32ZFINX_NOZICOND-NEXT:    slli a0, a0, 31
+; RV32ZFINX_NOZICOND-NEXT:    srai a0, a0, 31
+; RV32ZFINX_NOZICOND-NEXT:    and a0, a0, a1
+; RV32ZFINX_NOZICOND-NEXT:    lui a1, 1048560
+; RV32ZFINX_NOZICOND-NEXT:    or a0, a0, a1
+; RV32ZFINX_NOZICOND-NEXT:    # kill: def $x10_w killed $x10_w killed $x10
+; RV32ZFINX_NOZICOND-NEXT:    ret
+;
+; RV32ZDINX_ZICOND-LABEL: select_i1_half_0:
+; RV32ZDINX_ZICOND:       # %bb.0: # %entry
+; RV32ZDINX_ZICOND-NEXT:    # kill: def $x11_w killed $x11_w def $x11
+; RV32ZDINX_ZICOND-NEXT:    andi a0, a0, 1
+; RV32ZDINX_ZICOND-NEXT:    czero.eqz a0, a1, a0
+; RV32ZDINX_ZICOND-NEXT:    lui a1, 1048560
+; RV32ZDINX_ZICOND-NEXT:    or a0, a0, a1
+; RV32ZDINX_ZICOND-NEXT:    # kill: def $x10_w killed $x10_w killed $x10
+; RV32ZDINX_ZICOND-NEXT:    ret
+;
+; RV32ZDINX_NOZICOND-LABEL: select_i1_half_0:
+; RV32ZDINX_NOZICOND:       # %bb.0: # %entry
+; RV32ZDINX_NOZICOND-NEXT:    # kill: def $x11_w killed $x11_w def $x11
+; RV32ZDINX_NOZICOND-NEXT:    slli a0, a0, 31
+; RV32ZDINX_NOZICOND-NEXT:    srai a0, a0, 31
+; RV32ZDINX_NOZICOND-NEXT:    and a0, a0, a1
+; RV32ZDINX_NOZICOND-NEXT:    lui a1, 1048560
+; RV32ZDINX_NOZICOND-NEXT:    or a0, a0, a1
+; RV32ZDINX_NOZICOND-NEXT:    # kill: def $x10_w killed $x10_w killed $x10
+; RV32ZDINX_NOZICOND-NEXT:    ret
+entry:
+  %sel = select i1 %cond, half %val, half 0xH0000
+  ret half %sel
+}
+
+; -----------------------------------------------------------------------------
+; Test select with i1 condition and zero value for half fp, feeding into fadd ((cond ? a : 0) + 1.0)
+; -----------------------------------------------------------------------------
+define half @select_i1_half_0_add(i1 %cond, half %val) nounwind {
+; RV64ZDINX_ZICOND-LABEL: select_i1_half_0_add:
+; RV64ZDINX_ZICOND:       # %bb.0: # %entry
+; RV64ZDINX_ZICOND-NEXT:    addi sp, sp, -16
+; RV64ZDINX_ZICOND-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
+; RV64ZDINX_ZICOND-NEXT:    # kill: def $x11_w killed $x11_w def $x11
+; RV64ZDINX_ZICOND-NEXT:    andi a0, a0, 1
+; RV64ZDINX_ZICOND-NEXT:    czero.eqz a0, a1, a0
+; RV64ZDINX_ZICOND-NEXT:    # kill: def $x10_w killed $x10_w killed $x10
+; RV64ZDINX_ZICOND-NEXT:    call __extendhfsf2
+; RV64ZDINX_ZICOND-NEXT:    lui a1, 260096
+; RV64ZDINX_ZICOND-NEXT:    fadd.s a0, a0, a1
+; RV64ZDINX_ZICOND-NEXT:    call __truncsfhf2
+; RV64ZDINX_ZICOND-NEXT:    # kill: def $x10_w killed $x10_w def $x10
+; RV64ZDINX_ZICOND-NEXT:    lui a1, 1048560
+; RV64ZDINX_ZICOND-NEXT:    or a0, a0, a1
+; RV64ZDINX_ZICOND-NEXT:    # kill: def $x10_w killed $x10_w killed $x10
+; RV64ZDINX_ZICOND-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
+; RV64ZDINX_ZICOND-NEXT:    addi sp, sp, 16
+; RV64ZDINX_ZICOND-NEXT:    ret
+;
+; RV64ZDINX_NOZICOND-LABEL: select_i1_half_0_add:
+; RV64ZDINX_NOZICOND:       # %bb.0: # %entry
+; RV64ZDINX_NOZICOND-NEXT:    addi sp, sp, -16
+; RV64ZDINX_NOZICOND-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
+; RV64ZDINX_NOZICOND-NEXT:    # kill: def $x11_w killed $x11_w def $x11
+; RV64ZDINX_NOZICOND-NEXT:    slli a0, a0, 63
+; RV64ZDINX_NOZICOND-NEXT:    srai a0, a0, 63
+; RV64ZDINX_NOZICOND-NEXT:    and a0, a0, a1
+; RV64ZDINX_NOZICOND-NEXT:    # kill: def $x10_w killed $x10_w killed $x10
+; RV64ZDINX_NOZICOND-NEXT:    call __extendhfsf2
+; RV64ZDINX_NOZICOND-NEXT:    lui a1, 260096
+; RV64ZDINX_NOZICOND-NEXT:    fadd.s a0, a0, a1
+; RV64ZDINX_NOZICOND-NEXT:    call __truncsfhf2
+; RV64ZDINX_NOZICOND-NEXT:    # kill: def $x10_w killed $x10_w def $x10
+; RV64ZDINX_NOZICOND-NEXT:    lui a1, 1048560
+; RV64ZDINX_NOZICOND-NEXT:    or a0, a0, a1
+; RV64ZDINX_NOZICOND-NEXT:    # kill: def $x10_w killed $x10_w killed $x10
+; RV64ZDINX_NOZICOND-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
+; RV64ZDINX_NOZICOND-NEXT:    addi sp, sp, 16
+; RV64ZDINX_NOZICOND-NEXT:    ret
+;
+; RV64ZHINX_ZICOND-LABEL: select_i1_half_0_add:
+; RV64ZHINX_ZICOND:       # %bb.0: # %entry
+; RV64ZHINX_ZICOND-NEXT:    # kill: def $x11_h killed $x11_h def $x11
+; RV64ZHINX_ZICOND-NEXT:    andi a0, a0, 1
+; RV64ZHINX_ZICOND-NEXT:    czero.eqz a0, a1, a0
+; RV64ZHINX_ZICOND-NEXT:    li a1, 15
+; RV64ZHINX_ZICOND-NEXT:    slli a1, a1, 10
+; RV64ZHINX_ZICOND-NEXT:    fadd.h a0, a0, a1
+; RV64ZHINX_ZICOND-NEXT:    ret
+;
+; RV64FD-LABEL: select_i1_half_0_add:
+; RV64FD:       # %bb.0: # %entry
+; RV64FD-NEXT:    addi sp, sp, -16
+; RV64FD-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
+; RV64FD-NEXT:    fmv.x.w a1, fa0
+; RV64FD-NEXT:    slli a0, a0, 63
+; RV64FD-NEXT:    srai a0, a0, 63
+; RV64FD-NEXT:    and a0, a0, a1
+; RV64FD-NEXT:    fmv.w.x fa0, a0
+; RV64FD-NEXT:    call __extendhfsf2
+; RV64FD-NEXT:    lui a0, 260096
+; RV64FD-NEXT:    fmv.w.x fa5, a0
+; RV64FD-NEXT:    fadd.s fa0, fa0, fa5
+; RV64FD-NEXT:    call __truncsfhf2
+; RV64FD-NEXT:    fmv.x.w a0, fa0
+; RV64FD-NEXT:    lui a1, 1048560
+; RV64FD-NEXT:    or a0, a0, a1
+; RV64FD-NEXT:    fmv.w.x fa0, a0
+; RV64FD-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
+; RV64FD-NEXT:    addi sp, sp, 16
+; RV64FD-NEXT:    ret
+;
+; RV32ZFINX_ZICOND-LABEL: select_i1_half_0_add:
+; RV32ZFINX_ZICOND:       # %bb.0: # %entry
+; RV32ZFINX_ZICOND-NEXT:    addi sp, sp, -16
+; RV32ZFINX_ZICOND-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
+; RV32ZFINX_ZICOND-NEXT:    # kill: def $x11_w killed $x11_w def $x11
+; RV32ZFINX_ZICOND-NEXT:    andi a0, a0, 1
+; RV32ZFINX_ZICOND-NEXT:    czero.eqz a0, a1, a0
+; RV32ZFINX_ZICOND-NEXT:    # kill: def $x10_w killed $x10_w killed $x10
+; RV32ZFINX_ZICOND-NEXT:    call __extendhfsf2
+; RV32ZFINX_ZICOND-NEXT:    lui a1, 260096
+; RV32ZFINX_ZICOND-NEXT:    fadd.s a0, a0, a1
+; RV32ZFINX_ZICOND-NEXT:    call __truncsfhf2
+; RV32ZFINX_ZICOND-NEXT:    # kill: def $x10_w killed $x10_w def $x10
+; RV32ZFINX_ZICOND-NEXT:    lui a1, 1048560
+; RV32ZFINX_ZICOND-NEXT:    or a0, a0, a1
+; RV32ZFINX_ZICOND-NEXT:    # kill: def $x10_w killed $x10_w killed $x10
+; RV32ZFINX_ZICOND-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
+; RV32ZFINX_ZICOND-NEXT:    addi sp, sp, 16
+; RV32ZFINX_ZICOND-NEXT:    ret
+;
+; RV32ZFINX_NOZICOND-LABEL: select_i1_half_0_add:
+; RV32ZFINX_NOZICOND:       # %bb.0: # %entry
+; RV32ZFINX_NOZICOND-NEXT:    addi sp, sp, -16
+; RV32ZFINX_NOZICOND-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
+; RV32ZFINX_NOZICOND-NEXT:    # kill: def $x11_w killed $x11_w def $x11
+; RV32ZFINX_NOZICOND-NEXT:    slli a0, a0, 31
+; RV32ZFINX_NOZICOND-NEXT:    srai a0, a0, 31
+; RV32ZFINX_NOZICOND-NEXT:    and a0, a0, a1
+; RV32ZFINX_NOZICOND-NEXT:    # kill: def $x10_w killed $x10_w killed $x10
+; RV32ZFINX_NOZICOND-NEXT:    call __extendhfsf2
+; RV32ZFINX_NOZICOND-NEXT:    lui a1, 260096
+; RV32ZFINX_NOZICOND-NEXT:    fadd.s a0, a0, a1
+; RV32ZFINX_NOZICOND-NEXT:    call __truncsfhf2
+; RV32ZFINX_NOZICOND-NEXT:    # kill: def $x10_w killed $x10_w def $x10
+; RV32ZFINX_NOZICOND-NEXT:    lui a1, 1048560
+; RV32ZFINX_NOZICOND-NEXT:    or a0, a0, a1
+; RV32ZFINX_NOZICOND-NEXT:    # kill: def $x10_w killed $x10_w killed $x10
+; RV32ZFINX_NOZICOND-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
+; RV32ZFINX_NOZICOND-NEXT:    addi sp, sp, 16
+; RV32ZFINX_NOZICOND-NEXT:    ret
+;
+; RV32ZDINX_ZICOND-LABEL: select_i1_half_0_add:
+; RV32ZDINX_ZICOND:       # %bb.0: # %entry
+; RV32ZDINX_ZICOND-NEXT:    addi sp, sp, -16
+; RV32ZDINX_ZICOND-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
+; RV32ZDINX_ZICOND-NEXT:    # kill: def $x11_w killed $x11_w def $x11
+; RV32ZDINX_ZICOND-NEXT:    andi a0, a0, 1
+; RV32ZDINX_ZICOND-NEXT:    czero.eqz a0, a1, a0
+; RV32ZDINX_ZICOND-NEXT:    # kill: def $x10_w killed $x10_w killed $x10
+; RV32ZDINX_ZICOND-NEXT:    call __extendhfsf2
+; RV32ZDINX_ZICOND-NEXT:    lui a1, 260096
+; RV32ZDINX_ZICOND-NEXT:    fadd.s a0, a0, a1
+; RV32ZDINX_ZICOND-NEXT:    call __truncsfhf2
+; RV32ZDINX_ZICOND-NEXT:    # kill: def $x10_w killed $x10_w def $x10
+; RV32ZDINX_ZICOND-NEXT:    lui a1, 1048560
+; RV32ZDINX_ZICOND-NEXT:    or a0, a0, a1
+; RV32ZDINX_ZICOND-NEXT:    # kill: def $x10_w killed $x10_w killed $x10
+; RV32ZDINX_ZICOND-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
+; RV32ZDINX_ZICOND-NEXT:    addi sp, sp, 16
+; RV32ZDINX_ZICOND-NEXT:    ret
+;
+; RV32ZDINX_NOZICOND-LABEL: select_i1_half_0_add:
+; RV32ZDINX_NOZICOND:       # %bb.0: # %entry
+; RV32ZDINX_NOZICOND-NEXT:    addi sp, sp, -16
+; RV32ZDINX_NOZICOND-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
+; RV32ZDINX_NOZICOND-NEXT:    # kill: def $x11_w killed $x11_w def $x11
+; RV32ZDINX_NOZICOND-NEXT:    slli a0, a0, 31
+; RV32ZDINX_NOZICOND-NEXT:    srai a0, a0, 31
+; RV32ZDINX_NOZICOND-NEXT:    and a0, a0, a1
+; RV32ZDINX_NOZICOND-NEXT:    # kill: def $x10_w killed $x10_w killed $x10
+; RV32ZDINX_NOZICOND-NEXT:    call __extendhfsf2
+; RV32ZDINX_NOZICOND-NEXT:    lui a1, 260096
+; RV32ZDINX_NOZICOND-NEXT:    fadd.s a0, a0, a1
+; RV32ZDINX_NOZICOND-NEXT:    call __truncsfhf2
+; RV32ZDINX_NOZICOND-NEXT:    # kill: def $x10_w killed $x10_w def $x10
+; RV32ZDINX_NOZICOND-NEXT:    lui a1, 1048560
+; RV32ZDINX_NOZICOND-NEXT:    or a0, a0, a1
+; RV32ZDINX_NOZICOND-NEXT:    # kill: def $x10_w killed $x10_w killed $x10
+; RV32ZDINX_NOZICOND-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
+; RV32ZDINX_NOZICOND-NEXT:    addi sp, sp, 16
+; RV32ZDINX_NOZICOND-NEXT:    ret
+entry:
+  %sel = select i1 %cond, half %val, half 0xH0000
+  %add = fadd half %sel, 1.0
+  ret half %add
+}


        


More information about the llvm-commits mailing list