diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 2d2a998b750fe..4c34d56526ffe 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -6683,7 +6683,6 @@ Instruction *InstCombinerImpl::visitFCmpInst(FCmpInst &I) { if (match(Op1, m_FPExt(m_Value(Y))) && X->getType() == Y->getType()) return new FCmpInst(Pred, X, Y, "", &I); - // fcmp (fpext X), C -> fcmp X, (fptrunc C) if fptrunc is lossless const APFloat *C; if (match(Op1, m_APFloat(C))) { const fltSemantics &FPSem = @@ -6692,6 +6691,31 @@ Instruction *InstCombinerImpl::visitFCmpInst(FCmpInst &I) { APFloat TruncC = *C; TruncC.convert(FPSem, APFloat::rmNearestTiesToEven, &Lossy); + if (Lossy) { + // X can't possibly equal the higher-precision constant, so reduce any + // equality comparison. + // TODO: Other predicates can be handled via getFCmpCode(). + switch (Pred) { + case FCmpInst::FCMP_OEQ: + // X is ordered and equal to an impossible constant --> false + return replaceInstUsesWith(I, ConstantInt::getFalse(I.getType())); + case FCmpInst::FCMP_ONE: + // X is ordered and not equal to an impossible constant --> ordered + return new FCmpInst(FCmpInst::FCMP_ORD, X, + ConstantFP::getNullValue(X->getType())); + case FCmpInst::FCMP_UEQ: + // X is unordered or equal to an impossible constant --> unordered + return new FCmpInst(FCmpInst::FCMP_UNO, X, + ConstantFP::getNullValue(X->getType())); + case FCmpInst::FCMP_UNE: + // X is unordered or not equal to an impossible constant --> true + return replaceInstUsesWith(I, ConstantInt::getTrue(I.getType())); + default: + break; + } + } + + // fcmp (fpext X), C -> fcmp X, (fptrunc C) if fptrunc is lossless // Avoid lossy conversions and denormals. // Zero is a special case that's OK to convert. APFloat Fabs = TruncC; diff --git a/llvm/test/Transforms/InstCombine/fcmp.ll b/llvm/test/Transforms/InstCombine/fcmp.ll index b0211d52f197f..7ababebe3b0dd 100644 --- a/llvm/test/Transforms/InstCombine/fcmp.ll +++ b/llvm/test/Transforms/InstCombine/fcmp.ll @@ -674,9 +674,7 @@ define i1 @is_signbit_set_simplify_nan(double %x) { define <2 x i1> @lossy_oeq(<2 x float> %x) { ; CHECK-LABEL: @lossy_oeq( -; CHECK-NEXT: [[E:%.*]] = fpext <2 x float> [[X:%.*]] to <2 x double> -; CHECK-NEXT: [[R:%.*]] = fcmp oeq <2 x double> [[E]], -; CHECK-NEXT: ret <2 x i1> [[R]] +; CHECK-NEXT: ret <2 x i1> zeroinitializer ; %e = fpext <2 x float> %x to <2 x double> %r = fcmp oeq <2 x double> %e, @@ -687,7 +685,7 @@ define i1 @lossy_one(float %x, double* %p) { ; CHECK-LABEL: @lossy_one( ; CHECK-NEXT: [[E:%.*]] = fpext float [[X:%.*]] to double ; CHECK-NEXT: store double [[E]], double* [[P:%.*]], align 8 -; CHECK-NEXT: [[R:%.*]] = fcmp one double [[E]], 1.000000e-01 +; CHECK-NEXT: [[R:%.*]] = fcmp ord float [[X]], 0.000000e+00 ; CHECK-NEXT: ret i1 [[R]] ; %e = fpext float %x to double @@ -698,8 +696,7 @@ define i1 @lossy_one(float %x, double* %p) { define i1 @lossy_ueq(half %x) { ; CHECK-LABEL: @lossy_ueq( -; CHECK-NEXT: [[E:%.*]] = fpext half [[X:%.*]] to double -; CHECK-NEXT: [[R:%.*]] = fcmp ueq double [[E]], 6.553600e+04 +; CHECK-NEXT: [[R:%.*]] = fcmp uno half [[X:%.*]], 0xH0000 ; CHECK-NEXT: ret i1 [[R]] ; %e = fpext half %x to double @@ -709,9 +706,7 @@ define i1 @lossy_ueq(half %x) { define i1 @lossy_une(half %x) { ; CHECK-LABEL: @lossy_une( -; CHECK-NEXT: [[E:%.*]] = fpext half [[X:%.*]] to float -; CHECK-NEXT: [[R:%.*]] = fcmp une float [[E]], 2.049000e+03 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 true ; %e = fpext half %x to float %r = fcmp une float %e, 2049.0