Index: lib/CodeGen/SelectionDAG/TargetLowering.cpp =================================================================== --- lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -114,7 +114,6 @@ return LowerCallTo(CLI); } - /// SoftenSetCCOperands - Soften the operands of a comparison. This code is /// shared among BR_CC, SELECT_CC, and SETCC handlers. void TargetLowering::softenSetCCOperands(SelectionDAG &DAG, EVT VT, @@ -126,6 +125,7 @@ // Expand into one or more soft-fp libcall(s). RTLIB::Libcall LC1 = RTLIB::UNKNOWN_LIBCALL, LC2 = RTLIB::UNKNOWN_LIBCALL; + bool ShouldInvertCC = false; switch (CCCode) { case ISD::SETEQ: case ISD::SETOEQ: @@ -165,35 +165,39 @@ LC1 = (VT == MVT::f32) ? RTLIB::O_F32 : (VT == MVT::f64) ? RTLIB::O_F64 : RTLIB::O_F128; break; - default: + case ISD::SETONE: + // SETONE = SETOLT | SETOGT + LC1 = (VT == MVT::f32) ? RTLIB::OLT_F32 : + (VT == MVT::f64) ? RTLIB::OLT_F64 : RTLIB::OLT_F128; + LC2 = (VT == MVT::f32) ? RTLIB::OGT_F32 : + (VT == MVT::f64) ? RTLIB::OGT_F64 : RTLIB::OGT_F128; + break; + case ISD::SETUEQ: LC1 = (VT == MVT::f32) ? RTLIB::UO_F32 : (VT == MVT::f64) ? RTLIB::UO_F64 : RTLIB::UO_F128; + LC2 = (VT == MVT::f32) ? RTLIB::OEQ_F32 : + (VT == MVT::f64) ? RTLIB::OEQ_F64 : RTLIB::OEQ_F128; + break; + default: + // Invert CC for unordered comparisons + ShouldInvertCC = true; switch (CCCode) { - case ISD::SETONE: - // SETONE = SETOLT | SETOGT - LC1 = (VT == MVT::f32) ? RTLIB::OLT_F32 : - (VT == MVT::f64) ? RTLIB::OLT_F64 : RTLIB::OLT_F128; - // Fallthrough - case ISD::SETUGT: - LC2 = (VT == MVT::f32) ? RTLIB::OGT_F32 : - (VT == MVT::f64) ? RTLIB::OGT_F64 : RTLIB::OGT_F128; - break; - case ISD::SETUGE: - LC2 = (VT == MVT::f32) ? RTLIB::OGE_F32 : - (VT == MVT::f64) ? RTLIB::OGE_F64 : RTLIB::OGE_F128; - break; case ISD::SETULT: - LC2 = (VT == MVT::f32) ? RTLIB::OLT_F32 : - (VT == MVT::f64) ? RTLIB::OLT_F64 : RTLIB::OLT_F128; - break; + LC1 = (VT == MVT::f32) ? RTLIB::OGE_F32 : + (VT == MVT::f64) ? RTLIB::OGE_F64 : RTLIB::OGE_F128; + break; case ISD::SETULE: - LC2 = (VT == MVT::f32) ? RTLIB::OLE_F32 : - (VT == MVT::f64) ? RTLIB::OLE_F64 : RTLIB::OLE_F128; - break; - case ISD::SETUEQ: - LC2 = (VT == MVT::f32) ? RTLIB::OEQ_F32 : - (VT == MVT::f64) ? RTLIB::OEQ_F64 : RTLIB::OEQ_F128; - break; + LC1 = (VT == MVT::f32) ? RTLIB::OGT_F32 : + (VT == MVT::f64) ? RTLIB::OGT_F64 : RTLIB::OGT_F128; + break; + case ISD::SETUGT: + LC1 = (VT == MVT::f32) ? RTLIB::OLE_F32 : + (VT == MVT::f64) ? RTLIB::OLE_F64 : RTLIB::OLE_F128; + break; + case ISD::SETUGE: + LC1 = (VT == MVT::f32) ? RTLIB::OLT_F32 : + (VT == MVT::f64) ? RTLIB::OLT_F64 : RTLIB::OLT_F128; + break; default: llvm_unreachable("Do not know how to soften this setcc!"); } } @@ -202,18 +206,22 @@ EVT RetVT = getCmpLibcallReturnType(); SDValue Ops[2] = { NewLHS, NewRHS }; NewLHS = makeLibCall(DAG, LC1, RetVT, Ops, 2, false/*sign irrelevant*/, - dl).first; + dl).first; NewRHS = DAG.getConstant(0, dl, RetVT); + CCCode = getCmpLibcallCC(LC1); + if (ShouldInvertCC) + CCCode = getSetCCInverse(CCCode, true); + if (LC2 != RTLIB::UNKNOWN_LIBCALL) { SDValue Tmp = DAG.getNode(ISD::SETCC, dl, - getSetCCResultType(*DAG.getContext(), RetVT), - NewLHS, NewRHS, DAG.getCondCode(CCCode)); + getSetCCResultType(*DAG.getContext(), RetVT), + NewLHS, NewRHS, DAG.getCondCode(CCCode)); NewLHS = makeLibCall(DAG, LC2, RetVT, Ops, 2, false/*sign irrelevant*/, - dl).first; + dl).first; NewLHS = DAG.getNode(ISD::SETCC, dl, - getSetCCResultType(*DAG.getContext(), RetVT), NewLHS, - NewRHS, DAG.getCondCode(getCmpLibcallCC(LC2))); + getSetCCResultType(*DAG.getContext(), RetVT), NewLHS, + NewRHS, DAG.getCondCode(getCmpLibcallCC(LC2))); NewLHS = DAG.getNode(ISD::OR, dl, Tmp.getValueType(), Tmp, NewLHS); NewRHS = SDValue(); } Index: test/CodeGen/AArch64/arm64-fp128.ll =================================================================== --- test/CodeGen/AArch64/arm64-fp128.ll +++ test/CodeGen/AArch64/arm64-fp128.ll @@ -148,14 +148,9 @@ ; CHECK: ldr q1, [{{x[0-9]+}}, :lo12:rhs] %val = fcmp ugt fp128 %lhs, %rhs -; CHECK: bl __gttf2 +; CHECK: bl __letf2 ; CHECK: cmp w0, #0 -; CHECK: cset [[GT:w[0-9]+]], gt - -; CHECK: bl __unordtf2 -; CHECK: cmp w0, #0 -; CHECK: cset [[UNORDERED:w[0-9]+]], ne -; CHECK: orr w0, [[UNORDERED]], [[GT]] +; CHECK: cset w0, gt ret i1 %val ; CHECK: ret @@ -171,29 +166,19 @@ ; olt == !uge, which LLVM unfortunately "optimizes" this to. %cond = fcmp olt fp128 %lhs, %rhs -; CHECK: bl __getf2 -; CHECK: cmp w0, #0 -; CHECK: cset [[OGE:w[0-9]+]], ge - -; CHECK: bl __unordtf2 -; CHECK: cmp w0, #0 -; CHECK: cset [[UNORDERED:w[0-9]+]], ne - -; CHECK: orr [[UGE:w[0-9]+]], [[UNORDERED]], [[OGE]] -; CHECK: cbnz [[UGE]], [[RET29:.LBB[0-9]+_[0-9]+]] +; CHECK: bl __lttf2 +; CHECK-NEXT: cmp w0, #0 +; CHECK-NEXT: b.ge {{.LBB[0-9]+_[0-9]+}} br i1 %cond, label %iftrue, label %iffalse iftrue: ret i32 42 ; CHECK-NEXT: BB# ; CHECK-NEXT: movz w0, #0x2a -; CHECK-NEXT: b [[REALRET:.LBB[0-9]+_[0-9]+]] - +; CHECK: ret iffalse: ret i32 29 -; CHECK: [[RET29]]: -; CHECK-NEXT: movz w0, #0x1d -; CHECK-NEXT: [[REALRET]]: +; CHECK: movz w0, #0x1d ; CHECK: ret } Index: test/CodeGen/Mips/mips16fpe.ll =================================================================== --- test/CodeGen/Mips/mips16fpe.ll +++ test/CodeGen/Mips/mips16fpe.ll @@ -297,7 +297,7 @@ %and2 = and i1 %lnot, %cmp1 %and = zext i1 %and2 to i32 store i32 %and, i32* @ltsf2_result, align 4 -;16hf: lw ${{[0-9]+}}, %call16(__mips16_unordsf2)(${{[0-9]+}}) +;16hf: lw ${{[0-9]+}}, %call16(__mips16_ltsf2)(${{[0-9]+}}) ;16hf: lw ${{[0-9]+}}, %call16(__mips16_ltsf2)(${{[0-9]+}}) ret void } @@ -313,7 +313,7 @@ %and2 = and i1 %lnot, %cmp1 %and = zext i1 %and2 to i32 store i32 %and, i32* @ltdf2_result, align 4 -;16hf: lw ${{[0-9]+}}, %call16(__mips16_unorddf2)(${{[0-9]+}}) +;16hf: lw ${{[0-9]+}}, %call16(__mips16_ltdf2)(${{[0-9]+}}) ;16hf: lw ${{[0-9]+}}, %call16(__mips16_ltdf2)(${{[0-9]+}}) ret void } Index: test/CodeGen/Thumb2/float-cmp.ll =================================================================== --- test/CodeGen/Thumb2/float-cmp.ll +++ test/CodeGen/Thumb2/float-cmp.ll @@ -81,8 +81,7 @@ } define i1 @cmp_f_ugt(float %a, float %b) { ; CHECK-LABEL: cmp_f_ugt: -; NONE: bl __aeabi_fcmpgt -; NONE: bl __aeabi_fcmpun +; NONE: bl __aeabi_fcmple ; HARD: vcmpe.f32 ; HARD: movhi r0, #1 %1 = fcmp ugt float %a, %b @@ -90,8 +89,7 @@ } define i1 @cmp_f_uge(float %a, float %b) { ; CHECK-LABEL: cmp_f_uge: -; NONE: bl __aeabi_fcmpge -; NONE: bl __aeabi_fcmpun +; NONE: bl __aeabi_fcmplt ; HARD: vcmpe.f32 ; HARD: movpl r0, #1 %1 = fcmp uge float %a, %b @@ -99,8 +97,7 @@ } define i1 @cmp_f_ult(float %a, float %b) { ; CHECK-LABEL: cmp_f_ult: -; NONE: bl __aeabi_fcmplt -; NONE: bl __aeabi_fcmpun +; NONE: bl __aeabi_fcmpge ; HARD: vcmpe.f32 ; HARD: movlt r0, #1 %1 = fcmp ult float %a, %b @@ -108,8 +105,7 @@ } define i1 @cmp_f_ule(float %a, float %b) { ; CHECK-LABEL: cmp_f_ule: -; NONE: bl __aeabi_fcmple -; NONE: bl __aeabi_fcmpun +; NONE: bl __aeabi_fcmpgt ; HARD: vcmpe.f32 ; HARD: movle r0, #1 %1 = fcmp ule float %a, %b @@ -214,10 +210,8 @@ } define i1 @cmp_d_ugt(double %a, double %b) { ; CHECK-LABEL: cmp_d_ugt: -; NONE: bl __aeabi_dcmpgt -; NONE: bl __aeabi_dcmpun -; SP: bl __aeabi_dcmpgt -; SP: bl __aeabi_dcmpun +; NONE: bl __aeabi_dcmple +; SP: bl __aeabi_dcmple ; DP: vcmpe.f64 ; DP: movhi r0, #1 %1 = fcmp ugt double %a, %b @@ -226,10 +220,8 @@ define i1 @cmp_d_ult(double %a, double %b) { ; CHECK-LABEL: cmp_d_ult: -; NONE: bl __aeabi_dcmplt -; NONE: bl __aeabi_dcmpun -; SP: bl __aeabi_dcmplt -; SP: bl __aeabi_dcmpun +; NONE: bl __aeabi_dcmpge +; SP: bl __aeabi_dcmpge ; DP: vcmpe.f64 ; DP: movlt r0, #1 %1 = fcmp ult double %a, %b @@ -268,10 +260,8 @@ define i1 @cmp_d_uge(double %a, double %b) { ; CHECK-LABEL: cmp_d_uge: -; NONE: bl __aeabi_dcmpge -; NONE: bl __aeabi_dcmpun -; SP: bl __aeabi_dcmpge -; SP: bl __aeabi_dcmpun +; NONE: bl __aeabi_dcmplt +; SP: bl __aeabi_dcmplt ; DP: vcmpe.f64 ; DP: movpl r0, #1 %1 = fcmp uge double %a, %b @@ -280,10 +270,8 @@ define i1 @cmp_d_ule(double %a, double %b) { ; CHECK-LABEL: cmp_d_ule: -; NONE: bl __aeabi_dcmple -; NONE: bl __aeabi_dcmpun -; SP: bl __aeabi_dcmple -; SP: bl __aeabi_dcmpun +; NONE: bl __aeabi_dcmpgt +; SP: bl __aeabi_dcmpgt ; DP: vcmpe.f64 ; DP: movle r0, #1 %1 = fcmp ule double %a, %b Index: test/CodeGen/Thumb2/float-intrinsics-double.ll =================================================================== --- test/CodeGen/Thumb2/float-intrinsics-double.ll +++ test/CodeGen/Thumb2/float-intrinsics-double.ll @@ -109,9 +109,8 @@ define double @abs_d(double %a) { ; CHECK-LABEL: abs_d: ; NONE: bic r1, r1, #-2147483648 -; SP: bl __aeabi_dcmpgt -; SP: bl __aeabi_dcmpun ; SP: bl __aeabi_dsub +; SP: bl __aeabi_dcmple ; DP: vabs.f64 d0, d0 %1 = call double @llvm.fabs.f64(double %a) ret double %1 Index: test/CodeGen/X86/fpcmp-soft-fp.ll =================================================================== --- test/CodeGen/X86/fpcmp-soft-fp.ll +++ test/CodeGen/X86/fpcmp-soft-fp.ll @@ -0,0 +1,128 @@ +; RUN: llc < %s -march=x86 -mcpu=pentium -float-abi=soft | FileCheck %s + +define i1 @test1(double %d) #0 { +entry: + %cmp = fcmp ule double %d, 0.000000e+00 + ret i1 %cmp +} +; CHECK-LABEL: test1: +; CHECK: calll __gtdf2 +; CHECK: setle +; CHECK: retl + +define i1 @test2(double %d) #0 { +entry: + %cmp = fcmp ult double %d, 0.000000e+00 + ret i1 %cmp +} +; CHECK-LABEL: test2: +; CHECK: calll __gedf2 +; CHECK: sets +; CHECK: retl + +define i1 @test3(double %d) #0 { +entry: + %cmp = fcmp ugt double %d, 0.000000e+00 + ret i1 %cmp +} +; CHECK-LABEL: test3: +; CHECK: calll __ledf2 +; CHECK: setg +; CHECK: retl + +define i1 @test4(double %d) #0 { +entry: + %cmp = fcmp uge double %d, 0.000000e+00 + ret i1 %cmp +} +; CHECK-LABEL: test4: +; CHECK: calll __ltdf2 +; CHECK: setns +; CHECK: retl + +define i1 @test5(double %d) #0 { +entry: + %cmp = fcmp ole double %d, 0.000000e+00 + ret i1 %cmp +} +; CHECK-LABEL: test5: +; CHECK: calll __ledf2 +; CHECK: setle +; CHECK: retl + +define i1 @test6(double %d) #0 { +entry: + %cmp = fcmp olt double %d, 0.000000e+00 + ret i1 %cmp +} +; CHECK-LABEL: test6: +; CHECK: calll __ltdf2 +; CHECK: sets +; CHECK: retl + +define i1 @test7(double %d) #0 { +entry: + %cmp = fcmp ogt double %d, 0.000000e+00 + ret i1 %cmp +} +; CHECK-LABEL: test7: +; CHECK: calll __gtdf2 +; CHECK: setg +; CHECK: retl + +define i1 @test8(double %d) #0 { +entry: + %cmp = fcmp oge double %d, 0.000000e+00 + ret i1 %cmp +} +; CHECK-LABEL: test8: +; CHECK: calll __gedf2 +; CHECK: setns +; CHECK: retl + +define i1 @test9(double %d) #0 { +entry: + %cmp = fcmp oeq double %d, 0.000000e+00 + ret i1 %cmp +} +; CHECK-LABEL: test9: +; CHECK: calll __eqdf2 +; CHECK: sete +; CHECK: retl + +define i1 @test10(double %d) #0 { +entry: + %cmp = fcmp ueq double %d, 0.000000e+00 + ret i1 %cmp +} +; CHECK-LABEL: test10: +; CHECK: calll __eqdf2 +; CHECK: sete +; CHECK: calll __unorddf2 +; CHECK: setne +; CHECK: retl + +define i1 @test11(double %d) #0 { +entry: + %cmp = fcmp one double %d, 0.000000e+00 + ret i1 %cmp +} +; CHECK-LABEL: test11: +; CHECK: calll __gtdf2 +; CHECK: setg +; CHECK: calll __ltdf2 +; CHECK: sets +; CHECK: retl + +define i1 @test12(double %d) #0 { +entry: + %cmp = fcmp une double %d, 0.000000e+00 + ret i1 %cmp +} +; CHECK-LABEL: test12: +; CHECK: calll __nedf2 +; CHECK: setne +; CHECK: retl + +attributes #0 = { "use-soft-float"="true" } +