diff options
Diffstat (limited to 'lib/Transforms/Scalar/LoopUnswitch.cpp')
-rw-r--r-- | lib/Transforms/Scalar/LoopUnswitch.cpp | 33 |
1 files changed, 29 insertions, 4 deletions
diff --git a/lib/Transforms/Scalar/LoopUnswitch.cpp b/lib/Transforms/Scalar/LoopUnswitch.cpp index 053eb0c4f7..842802e217 100644 --- a/lib/Transforms/Scalar/LoopUnswitch.cpp +++ b/lib/Transforms/Scalar/LoopUnswitch.cpp @@ -191,6 +191,10 @@ namespace { loopHeader = currentLoop->getHeader(); loopPreheader = currentLoop->getLoopPreheader(); } + + /// HasIndirectBrsInPreds - Returns true if there are predecessors, that are + /// terminated with indirect branch instruction. + bool HasIndirectBrsInPreds(const SmallVectorImpl<BasicBlock *> &ExitBlocks); /// Split all of the edges from inside the loop to their exit blocks. /// Update the appropriate Phi nodes as we do so. @@ -199,7 +203,7 @@ namespace { bool UnswitchIfProfitable(Value *LoopCond, Constant *Val); void UnswitchTrivialCondition(Loop *L, Value *Cond, Constant *Val, BasicBlock *ExitBlock); - void UnswitchNontrivialCondition(Value *LIC, Constant *OnVal, Loop *L); + bool UnswitchNontrivialCondition(Value *LIC, Constant *OnVal, Loop *L); void RewriteLoopBodyWithConditionConstant(Loop *L, Value *LIC, Constant *Val, bool isEqual); @@ -634,8 +638,7 @@ bool LoopUnswitch::UnswitchIfProfitable(Value *LoopCond, Constant *Val) { if (OptimizeForSize || F->hasFnAttr(Attribute::OptimizeForSize)) return false; - UnswitchNontrivialCondition(LoopCond, Val, currentLoop); - return true; + return UnswitchNontrivialCondition(LoopCond, Val, currentLoop); } /// CloneLoop - Recursively clone the specified loop and all of its children, @@ -730,6 +733,24 @@ void LoopUnswitch::UnswitchTrivialCondition(Loop *L, Value *Cond, ++NumTrivial; } +/// HasIndirectBrsInPreds - Returns true if there are predecessors, that are +/// terminated with indirect branch instruction. +bool LoopUnswitch::HasIndirectBrsInPreds( + const SmallVectorImpl<BasicBlock *> &ExitBlocks){ + + for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i) { + const BasicBlock *ExitBlock = ExitBlocks[i]; + for (const_pred_iterator p = pred_begin(ExitBlock), e = pred_end(ExitBlock); + p != e; ++p) { + // Cannot split an edge from an IndirectBrInst + if (isa<IndirectBrInst>((*p)->getTerminator())) + return true; + + } + } + return false; +} + /// SplitExitEdges - Split all of the edges from inside the loop to their exit /// blocks. Update the appropriate Phi nodes as we do so. void LoopUnswitch::SplitExitEdges(Loop *L, @@ -755,7 +776,7 @@ void LoopUnswitch::SplitExitEdges(Loop *L, /// UnswitchNontrivialCondition - We determined that the loop is profitable /// to unswitch when LIC equal Val. Split it into loop versions and test the /// condition outside of either loop. Return the loops created as Out1/Out2. -void LoopUnswitch::UnswitchNontrivialCondition(Value *LIC, Constant *Val, +bool LoopUnswitch::UnswitchNontrivialCondition(Value *LIC, Constant *Val, Loop *L) { Function *F = loopHeader->getParent(); DEBUG(dbgs() << "loop-unswitch: Unswitching loop %" @@ -779,6 +800,8 @@ void LoopUnswitch::UnswitchNontrivialCondition(Value *LIC, Constant *Val, SmallVector<BasicBlock*, 8> ExitBlocks; L->getUniqueExitBlocks(ExitBlocks); + if (HasIndirectBrsInPreds(ExitBlocks)) + return false; // Split all of the edges from inside the loop to their exit blocks. Update // the appropriate Phi nodes as we do so. @@ -893,6 +916,8 @@ void LoopUnswitch::UnswitchNontrivialCondition(Value *LIC, Constant *Val, if (!LoopProcessWorklist.empty() && LoopProcessWorklist.back() == NewLoop && LICHandle && !isa<Constant>(LICHandle)) RewriteLoopBodyWithConditionConstant(NewLoop, LICHandle, Val, true); + + return true; } /// RemoveFromWorklist - Remove all instances of I from the worklist vector |