InstCombine: Shrink "fcmp (fpext x), C" to "fcmp x, C" if C can be losslessly convert...
authorBenjamin Kramer <benny.kra@googlemail.com>
Thu, 31 Mar 2011 10:12:07 +0000 (10:12 +0000)
committerBenjamin Kramer <benny.kra@googlemail.com>
Thu, 31 Mar 2011 10:12:07 +0000 (10:12 +0000)
Fixes PR9592.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@128625 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/InstCombine/InstCombineCompares.cpp
test/Transforms/InstCombine/fcmp.ll

index 698b715fd8b98cd4f28280149421d1b4c5744c8c..48ce7cffb5823130935b99143b4ba84f4ac0cdcc 100644 (file)
@@ -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
index bef4855a0ed99e099235466f7b05be1b7a895ece..49bd50717dcf2e13657e81938a1610228523ceec 100644 (file)
@@ -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
+}