diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -6775,6 +6775,19 @@ } } + if (match(Op0, m_Sqrt(m_Value(X)))) { + // fcmp sqrt(x),C -> fcmp x,C*C + const APFloat *CF; + Instruction *Sqrt = cast(Op0); + if (match(Op1, m_APFloat(CF)) && !CF->isNegative() && Sqrt->hasNoNaNs() && + (Sqrt->hasAllowReassoc() || Sqrt->hasApproxFunc())) { + Constant *C = ConstantFP::get(X->getType(), *CF); + Instruction *FCmp = new FCmpInst(Pred, X, ConstantExpr::getFMul(C, C)); + FCmp->setFastMathFlags(I.getFastMathFlags()); + return FCmp; + } + } + 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/fcmp.ll b/llvm/test/Transforms/InstCombine/fcmp.ll --- a/llvm/test/Transforms/InstCombine/fcmp.ll +++ b/llvm/test/Transforms/InstCombine/fcmp.ll @@ -3,6 +3,7 @@ declare half @llvm.fabs.f16(half) declare double @llvm.fabs.f64(double) +declare double @llvm.sqrt.f64(double) declare <2 x float> @llvm.fabs.v2f32(<2 x float>) declare double @llvm.copysign.f64(double, double) declare <2 x double> @llvm.copysign.v2f64(<2 x double>, <2 x double>) @@ -1210,3 +1211,60 @@ %cmp = fcmp ninf une float %a, %fneg ret i1 %cmp } + +; fcmp sqrt(X),C --> fcmp X,C*C - when using afn flag +define i1 @fcmp_fsqrt_test1(double %v) { +; CHECK-LABEL: @fcmp_fsqrt_test1( +; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt double [[V:%.*]], 4.000000e+00 +; CHECK-NEXT: ret i1 [[CMP]] +; + %sqrt = call nnan afn double @llvm.sqrt.f64(double %v) + %cmp = fcmp ogt double %sqrt, 2.000000e+00 + ret i1 %cmp +} + +; fcmp sqrt(X),C --> fcmp X,C*C - when using reassoc flag +define i1 @fcmp_fsqrt_test2(double %v) { +; CHECK-LABEL: @fcmp_fsqrt_test2( +; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt double [[V:%.*]], 4.000000e+00 +; CHECK-NEXT: ret i1 [[CMP]] +; + %sqrt = call nnan reassoc double @llvm.sqrt.f64(double %v) + %cmp = fcmp ogt double %sqrt, 2.000000e+00 + ret i1 %cmp +} + +; fcmp sqrt(X),C --> fcmp X,C*C - fcmp flags are preserved +define i1 @fcmp_fsqrt_test3(double %v) { +; CHECK-LABEL: @fcmp_fsqrt_test3( +; CHECK-NEXT: [[CMP:%.*]] = fcmp fast ogt double [[V:%.*]], 4.000000e+00 +; CHECK-NEXT: ret i1 [[CMP]] +; + %sqrt = call nnan reassoc double @llvm.sqrt.f64(double %v) + %cmp = fcmp fast ogt double %sqrt, 2.000000e+00 + ret i1 %cmp +} + +; ensure we preserve sqrts when compared against negative numbers. +define i1 @fcmp_fsqrt_test4(double %v) { +; CHECK-LABEL: @fcmp_fsqrt_test4( +; CHECK-NEXT: [[SQRT:%.*]] = call nnan afn double @llvm.sqrt.f64(double [[V:%.*]]) +; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt double [[SQRT]], -2.000000e+00 +; CHECK-NEXT: ret i1 [[CMP]] +; + %sqrt = call nnan afn double @llvm.sqrt.f64(double %v) + %cmp = fcmp ogt double %sqrt, -2.000000e+00 + ret i1 %cmp +} + +; ensure we maintain sqrts when preserving NaNs. +define i1 @fcmp_fsqrt_test5(double %v) { +; CHECK-LABEL: @fcmp_fsqrt_test5( +; CHECK-NEXT: [[SQRT:%.*]] = call reassoc double @llvm.sqrt.f64(double [[V:%.*]]) +; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt double [[SQRT]], 2.000000e+00 +; CHECK-NEXT: ret i1 [[CMP]] +; + %sqrt = call reassoc double @llvm.sqrt.f64(double %v) + %cmp = fcmp ogt double %sqrt, 2.000000e+00 + ret i1 %cmp +}