aboutsummaryrefslogtreecommitdiff
path: root/lib/Transforms/Scalar/LoopUnswitch.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Transforms/Scalar/LoopUnswitch.cpp')
-rw-r--r--lib/Transforms/Scalar/LoopUnswitch.cpp33
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