diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index be53f51afe79f..c11540f19e70e 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 +}