Index: llvm/trunk/lib/Transforms/Scalar/LICM.cpp =================================================================== --- llvm/trunk/lib/Transforms/Scalar/LICM.cpp +++ llvm/trunk/lib/Transforms/Scalar/LICM.cpp @@ -477,6 +477,20 @@ continue; } + // Try hoisting the instruction out to the preheader. We can only do + // this if all of the operands of the instruction are loop invariant and + // if it is safe to hoist the instruction. + // + if (CurLoop->hasLoopInvariantOperands(&I) && + canSinkOrHoistInst(I, AA, DT, CurLoop, CurAST, SafetyInfo, ORE) && + (IsMustExecute || + isSafeToExecuteUnconditionally( + I, DT, CurLoop, SafetyInfo, ORE, + CurLoop->getLoopPreheader()->getTerminator()))) { + Changed |= hoist(I, DT, CurLoop, SafetyInfo, ORE); + continue; + } + // Attempt to remove floating point division out of the loop by // converting it to a reciprocal multiplication. if (I.getOpcode() == Instruction::FDiv && @@ -500,20 +514,6 @@ continue; } - // Try hoisting the instruction out to the preheader. We can only do - // this if all of the operands of the instruction are loop invariant and - // if it is safe to hoist the instruction. - // - if (CurLoop->hasLoopInvariantOperands(&I) && - canSinkOrHoistInst(I, AA, DT, CurLoop, CurAST, SafetyInfo, ORE) && - (IsMustExecute || - isSafeToExecuteUnconditionally( - I, DT, CurLoop, SafetyInfo, ORE, - CurLoop->getLoopPreheader()->getTerminator()))) { - Changed |= hoist(I, DT, CurLoop, SafetyInfo, ORE); - continue; - } - if (IsMustExecute) IsMustExecute = isGuaranteedToTransferExecutionToSuccessor(&I); } Index: llvm/trunk/test/Transforms/LICM/hoist-fast-fdiv.ll =================================================================== --- llvm/trunk/test/Transforms/LICM/hoist-fast-fdiv.ll +++ llvm/trunk/test/Transforms/LICM/hoist-fast-fdiv.ll @@ -1,9 +1,9 @@ ; RUN: opt -licm -S < %s | FileCheck %s ; Function Attrs: noinline norecurse nounwind readnone ssp uwtable -define zeroext i1 @f(double %v) #0 { +define zeroext i1 @invariant_denom(double %v) #0 { entry: -; CHECK-LABEL: @f( +; CHECK-LABEL: @invariant_denom( ; CHECK-NEXT: entry: ; CHECK-NEXT: fdiv fast double 1.000000e+00, %v br label %loop @@ -32,3 +32,29 @@ ret i1 %v16 } +define void @invariant_fdiv(float* %out, float %arg) { +; CHECK-LABEL: @invariant_fdiv( +; CHECK-NEXT: entry: +; CHECK-NEXT: %div = fdiv fast float 4.000000e+00, %arg +; CHECK-NEXT: fmul fast float %div, 0x41F0000000000000 +entry: + br label %loop + +loop: ; preds = %loop, %entry + %ind = phi i32 [ 0, %entry ], [ %inc, %loop ] + +; CHECK-LABEL: loop: +; CHECK: getelementptr +; CHECK-NOT: fdiv +; CHECK-NOT: fmul + %div = fdiv fast float 4.000000e+00, %arg + %mul = fmul fast float %div, 0x41F0000000000000 + %gep = getelementptr inbounds float, float* %out, i32 %ind + store float %mul, float* %gep, align 4 + %inc = add nuw nsw i32 %ind, 1 + %cond = icmp eq i32 %inc, 1024 + br i1 %cond, label %exit, label %loop + +exit: ; preds = %loop + ret void +}