diff options
-rw-r--r-- | lib/CodeGen/SelectionDAG/TargetLowering.cpp | 37 | ||||
-rw-r--r-- | test/CodeGen/X86/compare-inf.ll | 76 |
2 files changed, 113 insertions, 0 deletions
diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 7bd85fdb96..a2baee4231 100644 --- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -1922,6 +1922,43 @@ TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1, // materialize 0.0. if (Cond == ISD::SETO || Cond == ISD::SETUO) return DAG.getSetCC(dl, VT, N0, N0, Cond); + + // If the condition is not legal, see if we can find an equivalent one + // which is legal. + if (!isCondCodeLegal(Cond, N0.getValueType())) { + // If the comparison was an awkward floating-point == or != and one of + // the comparison operands is infinity or negative infinity, convert the + // condition to a less-awkward <= or >=. + if (CFP->getValueAPF().isInfinity()) { + if (CFP->getValueAPF().isNegative()) { + if (Cond == ISD::SETOEQ && + isCondCodeLegal(ISD::SETOLE, N0.getValueType())) + return DAG.getSetCC(dl, VT, N0, N1, ISD::SETOLE); + if (Cond == ISD::SETUEQ && + isCondCodeLegal(ISD::SETOLE, N0.getValueType())) + return DAG.getSetCC(dl, VT, N0, N1, ISD::SETULE); + if (Cond == ISD::SETUNE && + isCondCodeLegal(ISD::SETUGT, N0.getValueType())) + return DAG.getSetCC(dl, VT, N0, N1, ISD::SETUGT); + if (Cond == ISD::SETONE && + isCondCodeLegal(ISD::SETUGT, N0.getValueType())) + return DAG.getSetCC(dl, VT, N0, N1, ISD::SETOGT); + } else { + if (Cond == ISD::SETOEQ && + isCondCodeLegal(ISD::SETOGE, N0.getValueType())) + return DAG.getSetCC(dl, VT, N0, N1, ISD::SETOGE); + if (Cond == ISD::SETUEQ && + isCondCodeLegal(ISD::SETOGE, N0.getValueType())) + return DAG.getSetCC(dl, VT, N0, N1, ISD::SETUGE); + if (Cond == ISD::SETUNE && + isCondCodeLegal(ISD::SETULT, N0.getValueType())) + return DAG.getSetCC(dl, VT, N0, N1, ISD::SETULT); + if (Cond == ISD::SETONE && + isCondCodeLegal(ISD::SETULT, N0.getValueType())) + return DAG.getSetCC(dl, VT, N0, N1, ISD::SETOLT); + } + } + } } if (N0 == N1) { diff --git a/test/CodeGen/X86/compare-inf.ll b/test/CodeGen/X86/compare-inf.ll new file mode 100644 index 0000000000..2be90c9764 --- /dev/null +++ b/test/CodeGen/X86/compare-inf.ll @@ -0,0 +1,76 @@ +; RUN: llc < %s -march=x86-64 | FileCheck %s + +; Convert oeq and une to ole/oge/ule/uge when comparing with infinity +; and negative infinity, because those are more efficient on x86. + +; CHECK: oeq_inff: +; CHECK: ucomiss +; CHECK: jae +define float @oeq_inff(float %x, float %y) nounwind readonly { + %t0 = fcmp oeq float %x, 0x7FF0000000000000 + %t1 = select i1 %t0, float 1.0, float %y + ret float %t1 +} + +; CHECK: oeq_inf: +; CHECK: ucomisd +; CHECK: jae +define double @oeq_inf(double %x, double %y) nounwind readonly { + %t0 = fcmp oeq double %x, 0x7FF0000000000000 + %t1 = select i1 %t0, double 1.0, double %y + ret double %t1 +} + +; CHECK: une_inff: +; CHECK: ucomiss +; CHECK: jb +define float @une_inff(float %x, float %y) nounwind readonly { + %t0 = fcmp une float %x, 0x7FF0000000000000 + %t1 = select i1 %t0, float 1.0, float %y + ret float %t1 +} + +; CHECK: une_inf: +; CHECK: ucomisd +; CHECK: jb +define double @une_inf(double %x, double %y) nounwind readonly { + %t0 = fcmp une double %x, 0x7FF0000000000000 + %t1 = select i1 %t0, double 1.0, double %y + ret double %t1 +} + +; CHECK: oeq_neg_inff: +; CHECK: ucomiss +; CHECK: jae +define float @oeq_neg_inff(float %x, float %y) nounwind readonly { + %t0 = fcmp oeq float %x, 0xFFF0000000000000 + %t1 = select i1 %t0, float 1.0, float %y + ret float %t1 +} + +; CHECK: oeq_neg_inf: +; CHECK: ucomisd +; CHECK: jae +define double @oeq_neg_inf(double %x, double %y) nounwind readonly { + %t0 = fcmp oeq double %x, 0xFFF0000000000000 + %t1 = select i1 %t0, double 1.0, double %y + ret double %t1 +} + +; CHECK: une_neg_inff: +; CHECK: ucomiss +; CHECK: jb +define float @une_neg_inff(float %x, float %y) nounwind readonly { + %t0 = fcmp une float %x, 0xFFF0000000000000 + %t1 = select i1 %t0, float 1.0, float %y + ret float %t1 +} + +; CHECK: une_neg_inf: +; CHECK: ucomisd +; CHECK: jb +define double @une_neg_inf(double %x, double %y) nounwind readonly { + %t0 = fcmp une double %x, 0xFFF0000000000000 + %t1 = select i1 %t0, double 1.0, double %y + ret double %t1 +} |