diff --git a/lib/Transforms/Scalar/LICM.cpp b/lib/Transforms/Scalar/LICM.cpp index ebff144c2f3..99bedce6c71 100644 --- a/lib/Transforms/Scalar/LICM.cpp +++ b/lib/Transforms/Scalar/LICM.cpp @@ -108,6 +108,9 @@ namespace { BasicBlock *Preheader; // The preheader block of the current loop... Loop *CurLoop; // The current loop we are working on... AliasSetTracker *CurAST; // AliasSet information for the current loop... + bool MayThrow; // The current loop contains an instruction which + // may throw, thus preventing code motion of + // instructions with side effects. DenseMap LoopToAliasSetMap; /// cloneBasicBlockAnalysis - Simple Analysis hook. Clone alias set info. @@ -240,6 +243,15 @@ bool LICM::runOnLoop(Loop *L, LPPassManager &LPM) { CurAST->add(*BB); // Incorporate the specified basic block } + MayThrow = false; + // TODO: We've already searched for instructions which may throw in subloops. + // We may want to reuse this information. + for (Loop::block_iterator BB = L->block_begin(), BBE = L->block_end(); + (BB != BBE) && !MayThrow ; ++BB) + for (BasicBlock::iterator I = (*BB)->begin(), E = (*BB)->end(); + (I != E) && !MayThrow; ++I) + MayThrow |= I->mayThrow(); + // We want to visit all of the instructions in this loop... that are not parts // of our subloops (they have already had their invariants hoisted out of // their loop, into this loop, so there is no need to process the BODIES of @@ -418,17 +430,22 @@ bool LICM::canSinkOrHoistInst(Instruction &I) { if (!FoundMod) return true; } - // FIXME: This should use mod/ref information to see if we can hoist or sink - // the call. + // FIXME: This should use mod/ref information to see if we can hoist or + // sink the call. return false; } - // Otherwise these instructions are hoistable/sinkable - return isa(I) || isa(I) || - isa(I) || isa(I) || isa(I) || - isa(I) || isa(I) || - isa(I); + // Only these instructions are hoistable/sinkable. + bool HoistableKind = (isa(I) || isa(I) || + isa(I) || isa(I) || + isa(I) || isa(I) || + isa(I) || + isa(I)); + if (!HoistableKind) + return false; + + return isSafeToExecuteUnconditionally(I); } /// isNotUsedInLoop - Return true if the only users of this instruction are @@ -604,6 +621,12 @@ bool LICM::isSafeToExecuteUnconditionally(Instruction &Inst) { } bool LICM::isGuaranteedToExecute(Instruction &Inst) { + + // Somewhere in this loop there is an instruction which may throw and make us + // exit the loop. + if (MayThrow) + return false; + // Otherwise we have to check to make sure that the instruction dominates all // of the exit blocks. If it doesn't, then there is a path out of the loop // which does not execute this instruction, so we can't hoist it. diff --git a/test/Transforms/LICM/hoisting.ll b/test/Transforms/LICM/hoisting.ll index 6f28d53af66..98f93345e3c 100644 --- a/test/Transforms/LICM/hoisting.ll +++ b/test/Transforms/LICM/hoisting.ll @@ -29,7 +29,7 @@ Out: ; preds = %LoopTail } -declare void @foo2(i32) +declare void @foo2(i32) nounwind ;; It is ok and desirable to hoist this potentially trapping instruction. @@ -64,3 +64,29 @@ Out: ; preds = %Loop %C = sub i32 %A, %B ; [#uses=1] ret i32 %C } + +; CHECK: @test4 +; CHECK: call +; CHECK: sdiv +; CHECK: ret +define i32 @test4(i32 %x, i32 %y) nounwind uwtable ssp { +entry: + br label %for.body + +for.body: ; preds = %entry, %for.body + %i.02 = phi i32 [ 0, %entry ], [ %inc, %for.body ] + %n.01 = phi i32 [ 0, %entry ], [ %add, %for.body ] + call void @foo_may_call_exit(i32 0) + %div = sdiv i32 %x, %y + %add = add nsw i32 %n.01, %div + %inc = add nsw i32 %i.02, 1 + %cmp = icmp slt i32 %inc, 10000 + br i1 %cmp, label %for.body, label %for.end + +for.end: ; preds = %for.body + %n.0.lcssa = phi i32 [ %add, %for.body ] + ret i32 %n.0.lcssa +} + +declare void @foo_may_call_exit(i32) +