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 @@ -5512,6 +5512,20 @@ if (SDValue V = combineSelectToBinOp(Op.getNode(), DAG, Subtarget)) return V; + // (select cc, 1.0, 0.0) -> (sint_to_fp (zext cc)) + // (select cc, 0.0, 1.0) -> (sint_to_fp (zext (xor cc, 1))) + const ConstantFPSDNode *FPTV = dyn_cast(TrueV); + const ConstantFPSDNode *FPFV = dyn_cast(FalseV); + if (FPTV && FPFV) { + if (FPTV->isExactlyValue(1.0) && FPFV->isExactlyValue(0.0)) + return DAG.getNode(ISD::SINT_TO_FP, DL, VT, CondV); + else if (FPTV->isExactlyValue(0.0) && FPFV->isExactlyValue(1.0)) { + SDValue XOR = DAG.getNode(ISD::XOR, DL, XLenVT, CondV, + DAG.getConstant(1, DL, XLenVT)); + return DAG.getNode(ISD::SINT_TO_FP, DL, VT, XOR); + } + } + // 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) 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,72 @@ %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: sgtz a0, a0 +; CHECK-NEXT: xori 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: sgtz a0, a0 +; RV32ZDINX-NEXT: xori 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: sgtz a0, a0 +; RV64ZDINX-NEXT: xori 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,39 @@ %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: sgtz a0, a0 +; CHECK-NEXT: xori a0, a0, 1 +; CHECK-NEXT: fcvt.s.w fa0, a0 +; CHECK-NEXT: ret +; +; CHECKZFINX-LABEL: select_icmp_sgt_zero: +; CHECKZFINX: # %bb.0: +; CHECKZFINX-NEXT: sgtz a0, a0 +; CHECKZFINX-NEXT: xori 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,75 @@ %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: sgtz a0, a0 +; CHECK-NEXT: xori a0, a0, 1 +; CHECK-NEXT: fcvt.h.w fa0, a0 +; CHECK-NEXT: ret +; +; CHECKIZHINX-LABEL: select_icmp_sgt_zero: +; CHECKIZHINX: # %bb.0: +; CHECKIZHINX-NEXT: sgtz a0, a0 +; CHECKIZHINX-NEXT: xori a0, a0, 1 +; CHECKIZHINX-NEXT: fcvt.h.w a0, a0 +; CHECKIZHINX-NEXT: ret +; +; CHECKIZFHMIN-LABEL: select_icmp_sgt_zero: +; CHECKIZFHMIN: # %bb.0: +; CHECKIZFHMIN-NEXT: sgtz a0, a0 +; CHECKIZFHMIN-NEXT: xori 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: sgtz a0, a0 +; CHECKIZHINXMIN-NEXT: xori 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 +} +