diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 10caf4ab78a5a..7716f6c190e3c 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -8359,26 +8359,15 @@ static Instruction *foldFCmpReciprocalAndZero(FCmpInst &I, Instruction *LHSI, // Transform 'fptrunc(x) cmp C' to 'x cmp ext(C)' if possible. // Patterns include: -// fptrunc(x) < C --> x < ext(C) -// fptrunc(x) <= C --> x <= ext(C) -// fptrunc(x) > C --> x > ext(C) -// fptrunc(x) >= C --> x >= ext(C) +// fptrunc(x) < C --> x < ext(C) +// fptrunc(x) <= C --> x <= ext(C) +// fptrunc(x) > C --> x > ext(C) +// fptrunc(x) >= C --> x >= ext(C) +// fptrunc(x) ord/uno C --> x ord/uno C // where 'ext(C)' is the extension of 'C' to the type of 'x' with a small bias // due to precision loss. static Instruction *foldFCmpFpTrunc(FCmpInst &I, const Instruction &FPTrunc, const Constant &C) { - FCmpInst::Predicate Pred = I.getPredicate(); - bool RoundDown = false; - - if (Pred == FCmpInst::FCMP_OGE || Pred == FCmpInst::FCMP_UGE || - Pred == FCmpInst::FCMP_OLT || Pred == FCmpInst::FCMP_ULT) - RoundDown = true; - else if (Pred == FCmpInst::FCMP_OGT || Pred == FCmpInst::FCMP_UGT || - Pred == FCmpInst::FCMP_OLE || Pred == FCmpInst::FCMP_ULE) - RoundDown = false; - else - return nullptr; - const APFloat *CValue; if (!match(&C, m_APFloat(CValue))) return nullptr; @@ -8393,6 +8382,31 @@ static Instruction *foldFCmpFpTrunc(FCmpInst &I, const Instruction &FPTrunc, return Dest; }; + Type *DestType = FPTrunc.getOperand(0)->getType(); + const fltSemantics &DestFltSema = + DestType->getScalarType()->getFltSemantics(); + + APFloat ExtCValue = ConvertFltSema(*CValue, DestFltSema); + + FCmpInst::Predicate Pred = I.getPredicate(); + + // Fold fcmp ord/uno fptrunc X, C -> fcmp ord/uno X, C + if (Pred == FCmpInst::FCMP_ORD || Pred == FCmpInst::FCMP_UNO) { + return new FCmpInst(Pred, FPTrunc.getOperand(0), + ConstantFP::get(DestType, ExtCValue), "", &I); + } + + bool RoundDown = false; + + if (Pred == FCmpInst::FCMP_OGE || Pred == FCmpInst::FCMP_UGE || + Pred == FCmpInst::FCMP_OLT || Pred == FCmpInst::FCMP_ULT) + RoundDown = true; + else if (Pred == FCmpInst::FCMP_OGT || Pred == FCmpInst::FCMP_UGT || + Pred == FCmpInst::FCMP_OLE || Pred == FCmpInst::FCMP_ULE) + RoundDown = false; + else + return nullptr; + auto NextValue = [](const APFloat &Value, bool RoundDown) { APFloat NextValue = Value; NextValue.next(RoundDown); @@ -8400,12 +8414,6 @@ static Instruction *foldFCmpFpTrunc(FCmpInst &I, const Instruction &FPTrunc, }; APFloat NextCValue = NextValue(*CValue, RoundDown); - - Type *DestType = FPTrunc.getOperand(0)->getType(); - const fltSemantics &DestFltSema = - DestType->getScalarType()->getFltSemantics(); - - APFloat ExtCValue = ConvertFltSema(*CValue, DestFltSema); APFloat ExtNextCValue = ConvertFltSema(NextCValue, DestFltSema); // When 'NextCValue' is infinity, use an imaged 'NextCValue' that equals diff --git a/llvm/test/Transforms/InstCombine/fold-fcmp-trunc.ll b/llvm/test/Transforms/InstCombine/fold-fcmp-trunc.ll index 371f9b6807fe4..bca9be81dca16 100644 --- a/llvm/test/Transforms/InstCombine/fold-fcmp-trunc.ll +++ b/llvm/test/Transforms/InstCombine/fold-fcmp-trunc.ll @@ -104,7 +104,7 @@ define i1 @fcmp_trunc_with_reassoc(double %0) { define i1 @fcmp_trunc_with_fast(double %0) { ; CHECK-LABEL: define i1 @fcmp_trunc_with_fast( ; CHECK-SAME: double [[TMP0:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = fcmp fast oge double [[TMP0]], 0x4058FFFFF0000000 +; CHECK-NEXT: [[RESULT:%.*]] = fcmp fast oge double [[TMP0]], 0x4058FFFFF0000000 ; CHECK-NEXT: ret i1 [[RESULT]] ; %trunc = fptrunc double %0 to float @@ -327,8 +327,7 @@ define i1 @fcmp_trunc_literal_positive_inf(double %0) { define i1 @fcmp_trunc_literal_negative_inf(double %0) { ; CHECK-LABEL: define i1 @fcmp_trunc_literal_negative_inf( ; CHECK-SAME: double [[TMP0:%.*]]) { -; CHECK-NEXT: [[TRUNC:%.*]] = fptrunc double [[TMP0]] to float -; CHECK-NEXT: [[RESULT:%.*]] = fcmp uno float [[TRUNC]], 0.000000e+00 +; CHECK-NEXT: [[RESULT:%.*]] = fcmp uno double [[TMP0]], 0.000000e+00 ; CHECK-NEXT: ret i1 [[RESULT]] ; %trunc = fptrunc double %0 to float @@ -672,3 +671,46 @@ define i1 @fcmp_trunc_mn_ppc_fp128(ppc_fp128 %0) { ret i1 %result } +define i1 @fptrunc_uno_fcmp(double %arg0) { +; CHECK-LABEL: define i1 @fptrunc_uno_fcmp( +; CHECK-SAME: double [[ARG0:%.*]]) { +; CHECK-NEXT: [[V1:%.*]] = fcmp uno double [[ARG0]], 0.000000e+00 +; CHECK-NEXT: ret i1 [[V1]] +; + %v0 = fptrunc double %arg0 to float + %v1 = fcmp uno float %v0, 0.000000e+00 + ret i1 %v1 +} + +define i1 @fptrunc_uno_fcmp_commuted(double %arg0) { +; CHECK-LABEL: define i1 @fptrunc_uno_fcmp_commuted( +; CHECK-SAME: double [[ARG0:%.*]]) { +; CHECK-NEXT: [[V1:%.*]] = fcmp uno double [[ARG0]], 0.000000e+00 +; CHECK-NEXT: ret i1 [[V1]] +; + %v0 = fptrunc double %arg0 to float + %v1 = fcmp uno float 7.000000e+00, %v0 + ret i1 %v1 +} + +define i1 @fptrunc_ord_fcmp(double %arg0) { +; CHECK-LABEL: define i1 @fptrunc_ord_fcmp( +; CHECK-SAME: double [[ARG0:%.*]]) { +; CHECK-NEXT: [[V1:%.*]] = fcmp ord double [[ARG0]], 0.000000e+00 +; CHECK-NEXT: ret i1 [[V1]] +; + %v0 = fptrunc double %arg0 to float + %v1 = fcmp ord float %v0, 0.000000e+00 + ret i1 %v1 +} + +define i1 @fptrunc_ord_fcmp_commuted(double %arg0) { +; CHECK-LABEL: define i1 @fptrunc_ord_fcmp_commuted( +; CHECK-SAME: double [[ARG0:%.*]]) { +; CHECK-NEXT: [[V1:%.*]] = fcmp ord double [[ARG0]], 0.000000e+00 +; CHECK-NEXT: ret i1 [[V1]] +; + %v0 = fptrunc double %arg0 to float + %v1 = fcmp ord float 7.000000e+00, %v0 + ret i1 %v1 +} diff --git a/llvm/test/Transforms/InstCombine/known-never-nan.ll b/llvm/test/Transforms/InstCombine/known-never-nan.ll index c4ce874029647..759cabae3d72f 100644 --- a/llvm/test/Transforms/InstCombine/known-never-nan.ll +++ b/llvm/test/Transforms/InstCombine/known-never-nan.ll @@ -150,8 +150,7 @@ define i1 @fpext_maybe_nan(float %arg0) { define i1 @fptrunc_maybe_nan(double %arg0) { ; CHECK-LABEL: @fptrunc_maybe_nan( -; CHECK-NEXT: [[OP:%.*]] = fptrunc double [[ARG0:%.*]] to float -; CHECK-NEXT: [[TMP:%.*]] = fcmp ord float [[OP]], 0.000000e+00 +; CHECK-NEXT: [[TMP:%.*]] = fcmp ord double [[ARG0:%.*]], 0.000000e+00 ; CHECK-NEXT: ret i1 [[TMP]] ; %op = fptrunc double %arg0 to float