diff --git a/lib/Transforms/Scalar/IndVarSimplify.cpp b/lib/Transforms/Scalar/IndVarSimplify.cpp index ba19fbfc963..53d3ab5f048 100644 --- a/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -722,6 +722,23 @@ void IndVarSimplify::OptimizeCanonicalIVType(Loop *L) { Incr->eraseFromParent(); } +/// Return true if it is OK to use SIToFPInst for an inducation variable +/// with given inital and exit values. +static bool useSIToFPInst(ConstantFP &InitV, ConstantFP &ExitV, + uint64_t intIV, uint64_t intEV) { + + if (InitV.getValueAPF().isNegative() || ExitV.getValueAPF().isNegative()) + return true; + + // If the iteration range can be handled by SIToFPInst then use it. + APInt Max = APInt::getSignedMaxValue(32); + if (Max.getZExtValue() > abs(intEV - intIV)) + return true; + + return false; +} + +/// convertToInt - Convert APF to an integer, if possible. static bool convertToInt(const APFloat &APF, uint64_t *intVal) { bool isExact = false; @@ -858,9 +875,9 @@ void IndVarSimplify::HandleFloatingPointIV(Loop *L, PHINode *PH, Incr->replaceAllUsesWith(UndefValue::get(Incr->getType())); DeadInsts.insert(Incr); - // Replace floating induction variable. - if (EV->getValueAPF().isNegative() - || InitValue->getValueAPF().isNegative()) { + // Replace floating induction variable. Give SIToFPInst preference over + // UIToFPInst because it is faster on platforms that are widely used. + if (useSIToFPInst(*InitValue, *EV, newInitValue, intEV)) { SIToFPInst *Conv = new SIToFPInst(NewPHI, PH->getType(), "indvar.conv", PH->getParent()->getFirstNonPHI()); PH->replaceAllUsesWith(Conv); diff --git a/test/Transforms/IndVarsSimplify/2008-11-17-Floating.ll b/test/Transforms/IndVarsSimplify/2008-11-17-Floating.ll new file mode 100644 index 00000000000..faf1da3058c --- /dev/null +++ b/test/Transforms/IndVarsSimplify/2008-11-17-Floating.ll @@ -0,0 +1,35 @@ +; RUN: llvm-as < %s | opt -indvars | llvm-dis | grep icmp | count 2 +; RUN: llvm-as < %s | opt -indvars | llvm-dis | grep sitofp | count 1 +; RUN: llvm-as < %s | opt -indvars | llvm-dis | grep uitofp | count 1 + +define void @bar() nounwind { +entry: + br label %bb + +bb: ; preds = %bb, %entry + %x.0.reg2mem.0 = phi double [ 0.000000e+00, %entry ], [ %1, %bb ] ; [#uses=2] + %0 = tail call i32 @foo(double %x.0.reg2mem.0) nounwind ; [#uses=0] + %1 = add double %x.0.reg2mem.0, 1.0e+0 ; [#uses=2] + %2 = fcmp olt double %1, 2147483646.0e+0 ; [#uses=1] + br i1 %2, label %bb, label %return + +return: ; preds = %bb + ret void +} + +define void @bar1() nounwind { +entry: + br label %bb + +bb: ; preds = %bb, %entry + %x.0.reg2mem.0 = phi double [ 0.000000e+00, %entry ], [ %1, %bb ] ; [#uses=2] + %0 = tail call i32 @foo(double %x.0.reg2mem.0) nounwind ; [#uses=0] + %1 = add double %x.0.reg2mem.0, 1.0e+0 ; [#uses=2] + %2 = fcmp olt double %1, 2147483647.0e+0 ; [#uses=1] + br i1 %2, label %bb, label %return + +return: ; preds = %bb + ret void +} + +declare i32 @foo(double)