Use sint_to_fp instead of select.
Reduce the number of branch instructions and
avoid generating TargetConstantPool for double.
(select cc, 1.0, 0.0) -> (sint_to_fp (zext cc))
https://alive2.llvm.org/ce/z/aoEcd9
https://godbolt.org/z/n543Y9v3e
(select cc, 0.0, 1.0) -> (sint_to_fp (zext (xor cc, 1)))
https://alive2.llvm.org/ce/z/zngvSB
Reviewed By: craig.topper
Differential Revision: https://reviews.llvm.org/D151719
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<ConstantFPSDNode>(TrueV);
+ const ConstantFPSDNode *FPFV = dyn_cast<ConstantFPSDNode>(FalseV);
+ if (FPTV && FPFV) {
+ if (FPTV->isExactlyValue(1.0) && FPFV->isExactlyValue(0.0))
+ return DAG.getNode(ISD::SINT_TO_FP, DL, VT, CondV);
+ 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)
%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
+ %1 = icmp sgt i32 %a, 0
+ %2 = select i1 %1, double 0.000000e+00, double 1.000000e+00
+ ret double %2
+}
+
%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
+}
%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
+ %1 = icmp sgt i32 %a, 0
+ %2 = select i1 %1, half 0.000000e+00, half 1.000000e+00
+ ret half %2
+}
+