diff options
author | Benjamin Kramer <benny.kra@googlemail.com> | 2011-03-31 10:12:07 +0000 |
---|---|---|
committer | Benjamin Kramer <benny.kra@googlemail.com> | 2011-03-31 10:12:07 +0000 |
commit | b194bdc03b6aa932ba4f719a8aa02db8d498f364 (patch) | |
tree | 28804355f79af5e0e726722459be2c1190c56a75 | |
parent | cd0274ca189040a2fd883b00a678184afc2cda3a (diff) | |
download | llvm-b194bdc03b6aa932ba4f719a8aa02db8d498f364.tar.gz llvm-b194bdc03b6aa932ba4f719a8aa02db8d498f364.tar.bz2 llvm-b194bdc03b6aa932ba4f719a8aa02db8d498f364.tar.xz |
InstCombine: Shrink "fcmp (fpext x), C" to "fcmp x, C" if C can be losslessly converted to the type of x.
Fixes PR9592.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@128625 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Transforms/InstCombine/InstCombineCompares.cpp | 34 | ||||
-rw-r--r-- | test/Transforms/InstCombine/fcmp.ll | 23 |
2 files changed, 57 insertions, 0 deletions
diff --git a/lib/Transforms/InstCombine/InstCombineCompares.cpp b/lib/Transforms/InstCombine/InstCombineCompares.cpp index 698b715fd8..48ce7cffb5 100644 --- a/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -2762,6 +2762,40 @@ Instruction *InstCombiner::visitFCmpInst(FCmpInst &I) { if (Constant *RHSC = dyn_cast<Constant>(Op1)) { if (Instruction *LHSI = dyn_cast<Instruction>(Op0)) switch (LHSI->getOpcode()) { + case Instruction::FPExt: { + // fcmp (fpext x), C -> fcmp x, (fptrunc C) if fptrunc is lossless + FPExtInst *LHSExt = cast<FPExtInst>(LHSI); + ConstantFP *RHSF = dyn_cast<ConstantFP>(RHSC); + if (!RHSF) + break; + + const fltSemantics *Sem; + // FIXME: This shouldn't be here. + if (LHSExt->getSrcTy()->isFloatTy()) + Sem = &APFloat::IEEEsingle; + else if (LHSExt->getSrcTy()->isDoubleTy()) + Sem = &APFloat::IEEEdouble; + else if (LHSExt->getSrcTy()->isFP128Ty()) + Sem = &APFloat::IEEEquad; + else if (LHSExt->getSrcTy()->isX86_FP80Ty()) + Sem = &APFloat::x87DoubleExtended; + else if (LHSExt->getSrcTy()->isPPC_FP128Ty()) + Sem = &APFloat::PPCDoubleDouble; + else + break; + + bool Lossy; + APFloat F = RHSF->getValueAPF(); + F.convert(*Sem, APFloat::rmNearestTiesToEven, &Lossy); + + // Avoid lossy conversions and denormals. + if (!Lossy && + F.compare(APFloat::getSmallestNormalized(*Sem)) != + APFloat::cmpLessThan) + return new FCmpInst(I.getPredicate(), LHSExt->getOperand(0), + ConstantFP::get(RHSC->getContext(), F)); + break; + } case Instruction::PHI: // Only fold fcmp into the PHI if the phi and fcmp are in the same // block. If in the same block, we're encouraging jump threading. If diff --git a/test/Transforms/InstCombine/fcmp.ll b/test/Transforms/InstCombine/fcmp.ll index bef4855a0e..49bd50717d 100644 --- a/test/Transforms/InstCombine/fcmp.ll +++ b/test/Transforms/InstCombine/fcmp.ll @@ -9,3 +9,26 @@ define i1 @test1(float %x, float %y) nounwind { ; CHECK-NEXT: fcmp ogt float %x, %y } +define i1 @test2(float %a) nounwind { + %ext = fpext float %a to double + %cmp = fcmp ogt double %ext, 1.000000e+00 + ret i1 %cmp +; CHECK: @test2 +; CHECK-NEXT: fcmp ogt float %a, 1.0 +} + +define i1 @test3(float %a) nounwind { + %ext = fpext float %a to double + %cmp = fcmp ogt double %ext, 0x3FF0000000000001 ; more precision than float. + ret i1 %cmp +; CHECK: @test3 +; CHECK-NEXT: fpext float %a to double +} + +define i1 @test4(float %a) nounwind { + %ext = fpext float %a to double + %cmp = fcmp ogt double %ext, 0x36A0000000000000 ; denormal in float. + ret i1 %cmp +; CHECK: @test4 +; CHECK-NEXT: fpext float %a to double +} |