diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -5495,6 +5495,13 @@ if (SDValue V = combineSelectToBinOp(Op.getNode(), DAG, Subtarget)) return V; + // (select cc, 1.0, 0.0) -> (sint_to_fp (zext cc)) + const ConstantFPSDNode *FPTV = dyn_cast(TrueV); + const ConstantFPSDNode *FPFV = dyn_cast(FalseV); + if (FPTV && FPFV && FPTV->isExactlyValue(1.0) && FPFV->isExactlyValue(0.0)) { + return DAG.getNode(ISD::SINT_TO_FP, DL, VT, CondV); + } + // If the condition is not an integer SETCC which operates on XLenVT, we need // to emit a RISCVISD::SELECT_CC comparing the condition to zero. i.e.: // (select condv, truev, falsev) @@ -5562,6 +5569,15 @@ TargetCC = DAG.getCondCode(ISD::getSetCCInverse(CCVal, LHS.getValueType())); } + // (select_cc 0, x, setlt, 0.0, 1.0) + // -> (sint_to_fp (zext (setcc x, 1, setlt))) + if (FPTV && FPFV && isNullConstant(LHS) && CCVal == ISD::CondCode::SETLT && + FPTV->isExactlyValue(0.0) && FPFV->isExactlyValue(1.0)) { + SDValue SETCC = DAG.getSetCC( + DL, XLenVT, RHS, DAG.getConstant(1, DL, XLenVT), ISD::CondCode::SETLT); + return DAG.getNode(ISD::SINT_TO_FP, DL, VT, SETCC); + } + SDValue Ops[] = {LHS, RHS, TargetCC, TrueV, FalseV}; return DAG.getNode(RISCVISD::SELECT_CC, DL, VT, Ops); } diff --git a/llvm/test/CodeGen/RISCV/double-select-icmp.ll b/llvm/test/CodeGen/RISCV/double-select-icmp.ll --- a/llvm/test/CodeGen/RISCV/double-select-icmp.ll +++ b/llvm/test/CodeGen/RISCV/double-select-icmp.ll @@ -448,3 +448,69 @@ %2 = select i1 %1, double %c, double %d ret double %2 } + +define double @select_icmp_slt_one(i32 signext %a) { +; CHECK-LABEL: select_icmp_slt_one: +; CHECK: # %bb.0: +; CHECK-NEXT: slti a0, a0, 1 +; CHECK-NEXT: fcvt.d.w fa0, a0 +; CHECK-NEXT: ret +; +; RV32ZDINX-LABEL: select_icmp_slt_one: +; RV32ZDINX: # %bb.0: +; RV32ZDINX-NEXT: addi sp, sp, -16 +; RV32ZDINX-NEXT: .cfi_def_cfa_offset 16 +; RV32ZDINX-NEXT: slti a0, a0, 1 +; RV32ZDINX-NEXT: fcvt.d.w a0, a0 +; RV32ZDINX-NEXT: sw a0, 8(sp) +; RV32ZDINX-NEXT: sw a1, 12(sp) +; RV32ZDINX-NEXT: lw a0, 8(sp) +; RV32ZDINX-NEXT: lw a1, 12(sp) +; RV32ZDINX-NEXT: addi sp, sp, 16 +; RV32ZDINX-NEXT: ret +; +; RV64ZDINX-LABEL: select_icmp_slt_one: +; RV64ZDINX: # %bb.0: +; RV64ZDINX-NEXT: slti a0, a0, 1 +; RV64ZDINX-NEXT: fcvt.d.w a0, a0 +; RV64ZDINX-NEXT: ret + %1 = icmp slt i32 %a, 1 + %2 = select i1 %1, double 1.000000e+00, double 0.000000e+00 + ret double %2 +} + +define double @select_icmp_sgt_zero(i32 signext %a) { +; CHECK-LABEL: select_icmp_sgt_zero: +; CHECK: # %bb.0: +; CHECK-NEXT: slti a0, a0, 1 +; CHECK-NEXT: fcvt.d.w fa0, a0 +; CHECK-NEXT: ret +; +; RV32ZDINX-LABEL: select_icmp_sgt_zero: +; RV32ZDINX: # %bb.0: +; RV32ZDINX-NEXT: addi sp, sp, -16 +; RV32ZDINX-NEXT: .cfi_def_cfa_offset 16 +; RV32ZDINX-NEXT: slti a0, a0, 1 +; RV32ZDINX-NEXT: fcvt.d.w a0, a0 +; RV32ZDINX-NEXT: sw a0, 8(sp) +; RV32ZDINX-NEXT: sw a1, 12(sp) +; RV32ZDINX-NEXT: lw a0, 8(sp) +; RV32ZDINX-NEXT: lw a1, 12(sp) +; RV32ZDINX-NEXT: addi sp, sp, 16 +; RV32ZDINX-NEXT: ret +; +; RV64ZDINX-LABEL: select_icmp_sgt_zero: +; RV64ZDINX: # %bb.0: +; RV64ZDINX-NEXT: slti a0, a0, 1 +; RV64ZDINX-NEXT: fcvt.d.w a0, a0 +; RV64ZDINX-NEXT: ret +; CHECKZFINX-LABEL: select_icmp_sgt_zero: +; CHECKZFINX: # %bb.0: +; CHECKZFINX-NEXT: slti a0, a0, 1 +; CHECKZFINX-NEXT: fcvt.s.w a0, a0 +; CHECKZFINX-NEXT: ret + %1 = icmp sgt i32 %a, 0 + %2 = select i1 %1, double 0.000000e+00, double 1.000000e+00 + ret double %2 +} + diff --git a/llvm/test/CodeGen/RISCV/float-select-icmp.ll b/llvm/test/CodeGen/RISCV/float-select-icmp.ll --- a/llvm/test/CodeGen/RISCV/float-select-icmp.ll +++ b/llvm/test/CodeGen/RISCV/float-select-icmp.ll @@ -227,3 +227,37 @@ %2 = select i1 %1, float %c, float %d ret float %2 } + +define float @select_icmp_slt_one(i32 signext %a) { +; CHECK-LABEL: select_icmp_slt_one: +; CHECK: # %bb.0: +; CHECK-NEXT: slti a0, a0, 1 +; CHECK-NEXT: fcvt.s.w fa0, a0 +; CHECK-NEXT: ret +; +; CHECKZFINX-LABEL: select_icmp_slt_one: +; CHECKZFINX: # %bb.0: +; CHECKZFINX-NEXT: slti a0, a0, 1 +; CHECKZFINX-NEXT: fcvt.s.w a0, a0 +; CHECKZFINX-NEXT: ret + %1 = icmp slt i32 %a, 1 + %2 = select i1 %1, float 1.000000e+00, float 0.000000e+00 + ret float %2 +} + +define float @select_icmp_sgt_zero(i32 signext %a) { +; CHECK-LABEL: select_icmp_sgt_zero: +; CHECK: # %bb.0: +; CHECK-NEXT: slti a0, a0, 1 +; CHECK-NEXT: fcvt.s.w fa0, a0 +; CHECK-NEXT: ret +; +; CHECKZFINX-LABEL: select_icmp_sgt_zero: +; CHECKZFINX: # %bb.0: +; CHECKZFINX-NEXT: slti a0, a0, 1 +; CHECKZFINX-NEXT: fcvt.s.w a0, a0 +; CHECKZFINX-NEXT: ret + %1 = icmp sgt i32 %a, 0 + %2 = select i1 %1, float 0.000000e+00, float 1.000000e+00 + ret float %2 +} diff --git a/llvm/test/CodeGen/RISCV/half-select-icmp.ll b/llvm/test/CodeGen/RISCV/half-select-icmp.ll --- a/llvm/test/CodeGen/RISCV/half-select-icmp.ll +++ b/llvm/test/CodeGen/RISCV/half-select-icmp.ll @@ -475,3 +475,71 @@ %2 = select i1 %1, half %c, half %d ret half %2 } + +define half @select_icmp_slt_one(i32 signext %a) { +; CHECK-LABEL: select_icmp_slt_one: +; CHECK: # %bb.0: +; CHECK-NEXT: slti a0, a0, 1 +; CHECK-NEXT: fcvt.h.w fa0, a0 +; CHECK-NEXT: ret +; +; CHECKIZHINX-LABEL: select_icmp_slt_one: +; CHECKIZHINX: # %bb.0: +; CHECKIZHINX-NEXT: slti a0, a0, 1 +; CHECKIZHINX-NEXT: fcvt.h.w a0, a0 +; CHECKIZHINX-NEXT: ret +; +; CHECKIZFHMIN-LABEL: select_icmp_slt_one: +; CHECKIZFHMIN: # %bb.0: +; CHECKIZFHMIN-NEXT: slti a0, a0, 1 +; CHECKIZFHMIN-NEXT: fcvt.s.w fa5, a0 +; CHECKIZFHMIN-NEXT: fcvt.h.s fa0, fa5 +; CHECKIZFHMIN-NEXT: ret +; +; CHECKIZHINXMIN-LABEL: select_icmp_slt_one: +; CHECKIZHINXMIN: # %bb.0: +; CHECKIZHINXMIN-NEXT: slti a0, a0, 1 +; CHECKIZHINXMIN-NEXT: fcvt.s.w a0, a0 +; CHECKIZHINXMIN-NEXT: fcvt.h.s a0, a0 +; CHECKIZHINXMIN-NEXT: ret + %1 = icmp slt i32 %a, 1 + %2 = select i1 %1, half 1.000000e+00, half 0.000000e+00 + ret half %2 +} + +define half @select_icmp_sgt_zero(i32 signext %a) { +; CHECK-LABEL: select_icmp_sgt_zero: +; CHECK: # %bb.0: +; CHECK-NEXT: slti a0, a0, 1 +; CHECK-NEXT: fcvt.h.w fa0, a0 +; CHECK-NEXT: ret +; +; CHECKIZHINX-LABEL: select_icmp_sgt_zero: +; CHECKIZHINX: # %bb.0: +; CHECKIZHINX-NEXT: slti a0, a0, 1 +; CHECKIZHINX-NEXT: fcvt.h.w a0, a0 +; CHECKIZHINX-NEXT: ret +; +; CHECKIZFHMIN-LABEL: select_icmp_sgt_zero: +; CHECKIZFHMIN: # %bb.0: +; CHECKIZFHMIN-NEXT: slti a0, a0, 1 +; CHECKIZFHMIN-NEXT: fcvt.s.w fa5, a0 +; CHECKIZFHMIN-NEXT: fcvt.h.s fa0, fa5 +; CHECKIZFHMIN-NEXT: ret +; +; CHECKIZHINXMIN-LABEL: select_icmp_sgt_zero: +; CHECKIZHINXMIN: # %bb.0: +; CHECKIZHINXMIN-NEXT: slti a0, a0, 1 +; CHECKIZHINXMIN-NEXT: fcvt.s.w a0, a0 +; CHECKIZHINXMIN-NEXT: fcvt.h.s a0, a0 +; CHECKIZHINXMIN-NEXT: ret +; CHECKZFINX-LABEL: select_icmp_sgt_zero: +; CHECKZFINX: # %bb.0: +; CHECKZFINX-NEXT: slti a0, a0, 1 +; CHECKZFINX-NEXT: fcvt.s.w a0, a0 +; CHECKZFINX-NEXT: ret + %1 = icmp sgt i32 %a, 0 + %2 = select i1 %1, half 0.000000e+00, half 1.000000e+00 + ret half %2 +} +