diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 7f1ced9505b9b..3bffeb90002df 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -26,6 +26,7 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/PatternMatch.h" @@ -8290,15 +8291,32 @@ 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 0 // 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(); + Type *DestType = FPTrunc.getOperand(0)->getType(); + + const APFloat *CValue; + // TODO: support vec + if (!match(&C, m_APFloat(CValue))) + return nullptr; + + // Handle ord/uno + if (Pred == FCmpInst::FCMP_ORD || Pred == FCmpInst::FCMP_UNO) { + assert(!CValue->isNaN() && + "X ord/uno NaN should be folded away by simplifyFCmpInst()"); + return new FCmpInst(Pred, FPTrunc.getOperand(0), + ConstantFP::getZero(DestType), "", &I); + } + + // Handle <, >, <=, >= bool RoundDown = false; if (Pred == FCmpInst::FCMP_OGE || Pred == FCmpInst::FCMP_UGE || @@ -8310,10 +8328,6 @@ static Instruction *foldFCmpFpTrunc(FCmpInst &I, const Instruction &FPTrunc, else return nullptr; - const APFloat *CValue; - if (!match(&C, m_APFloat(CValue))) - return nullptr; - if (CValue->isNaN() || CValue->isInfinity()) return nullptr; @@ -8332,7 +8346,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(); @@ -8904,6 +8917,12 @@ Instruction *InstCombinerImpl::visitFCmpInst(FCmpInst &I) { if (match(Op1, m_FAdd(m_Value(Y), m_AnyZeroFP()))) return new FCmpInst(Pred, Op0, Y, "", &I); + // fcmp ord/uno (fptrunc X), (fptrunc Y) -> fcmp ord/uno X, Y + if ((Pred == FCmpInst::FCMP_ORD || Pred == FCmpInst::FCMP_UNO) && + match(Op0, m_FPTrunc(m_Value(X))) && match(Op1, m_FPTrunc(m_Value(Y))) && + X->getType() == Y->getType()) + return new FCmpInst(Pred, X, Y, "", &I); + if (match(Op0, m_FPExt(m_Value(X)))) { // fcmp (fpext X), (fpext Y) -> fcmp X, Y if (match(Op1, m_FPExt(m_Value(Y))) && X->getType() == Y->getType()) diff --git a/llvm/test/Transforms/InstCombine/fold-fcmp-trunc.ll b/llvm/test/Transforms/InstCombine/fold-fcmp-trunc.ll index 371f9b6807fe4..d42ba952ace99 100644 --- a/llvm/test/Transforms/InstCombine/fold-fcmp-trunc.ll +++ b/llvm/test/Transforms/InstCombine/fold-fcmp-trunc.ll @@ -57,6 +57,52 @@ define i1 @fcmp_trunc_zero(double %0) { ret i1 %result } +define i1 @fcmp_trunc_uno(double %0) { +; CHECK-LABEL: define i1 @fcmp_trunc_uno( +; CHECK-SAME: double [[TMP0:%.*]]) { +; CHECK-NEXT: [[RESULT:%.*]] = fcmp uno double [[TMP0]], 0.000000e+00 +; CHECK-NEXT: ret i1 [[RESULT]] +; + %trunc = fptrunc double %0 to float + %result = fcmp uno float %trunc, 0.000000e+00 + ret i1 %result +} + +define i1 @fcmp_trunc_ord_inf(double %0) { +; CHECK-LABEL: define i1 @fcmp_trunc_ord_inf( +; CHECK-SAME: double [[TMP0:%.*]]) { +; CHECK-NEXT: [[RESULT:%.*]] = fcmp ord double [[TMP0]], 0.000000e+00 +; CHECK-NEXT: ret i1 [[RESULT]] +; + %trunc = fptrunc double %0 to float + %result = fcmp ord float %trunc, 0x7FF0000000000000 + ret i1 %result +} + +define i1 @fcmp_trunc_pair_uno(double %x, double %y) { +; CHECK-LABEL: define i1 @fcmp_trunc_pair_uno( +; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) { +; CHECK-NEXT: [[RESULT:%.*]] = fcmp uno double [[X]], [[Y]] +; CHECK-NEXT: ret i1 [[RESULT]] +; + %tx = fptrunc double %x to float + %ty = fptrunc double %y to float + %result = fcmp uno float %tx, %ty + ret i1 %result +} + +define i1 @fcmp_trunc_pair_ord(double %x, double %y) { +; CHECK-LABEL: define i1 @fcmp_trunc_pair_ord( +; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) { +; CHECK-NEXT: [[RESULT:%.*]] = fcmp ord double [[X]], [[Y]] +; CHECK-NEXT: ret i1 [[RESULT]] +; + %tx = fptrunc double %x to float + %ty = fptrunc double %y to float + %result = fcmp ord float %tx, %ty + ret i1 %result +} + define i1 @fcmp_trunc_with_nnan(double %0) { ; CHECK-LABEL: define i1 @fcmp_trunc_with_nnan( ; CHECK-SAME: double [[TMP0:%.*]]) { @@ -104,7 +150,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 +373,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 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