diff options
-rw-r--r-- | lib/Transforms/Scalar/LoopUnswitch.cpp | 33 | ||||
-rw-r--r-- | test/Transforms/LoopUnswitch/2012-04-02-IndirectBr.ll | 46 |
2 files changed, 75 insertions, 4 deletions
diff --git a/lib/Transforms/Scalar/LoopUnswitch.cpp b/lib/Transforms/Scalar/LoopUnswitch.cpp index 053eb0c..842802e 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 diff --git a/test/Transforms/LoopUnswitch/2012-04-02-IndirectBr.ll b/test/Transforms/LoopUnswitch/2012-04-02-IndirectBr.ll new file mode 100644 index 0000000..c677bde --- /dev/null +++ b/test/Transforms/LoopUnswitch/2012-04-02-IndirectBr.ll @@ -0,0 +1,46 @@ +; RUN: opt -loop-unswitch -disable-output -stats -info-output-file - < %s | FileCheck --check-prefix=STATS %s +; RUN: opt -S -loop-unswitch -verify-loop-info -verify-dom-info %s | FileCheck %s + +; STATS: 1 loop-unswitch - Total number of instructions analyzed + +; CHECK: %0 = icmp eq i64 undef, 0 +; CHECK-NEXT: br i1 %0, label %"5", label %"4" + +; CHECK: "5": ; preds = %entry +; CHECK-NEXT: br label %"5.split" + +; CHECK: "5.split": ; preds = %"5" +; CHECK-NEXT: br label %"16" + +; CHECK: "16": ; preds = %"22", %"5.split" +; CHECK-NEXT: indirectbr i8* undef, [label %"22", label %"33"] + +; CHECK: "22": ; preds = %"16" +; CHECK-NEXT: br i1 %0, label %"16", label %"26" + +; CHECK: "26": ; preds = %"22" +; CHECK-NEXT: unreachable + +define void @foo() { +entry: + %0 = icmp eq i64 undef, 0 + br i1 %0, label %"5", label %"4" + +"4": ; preds = %entry + unreachable + +"5": ; preds = %entry + br label %"16" + +"16": ; preds = %"22", %"5" + indirectbr i8* undef, [label %"22", label %"33"] + +"22": ; preds = %"16" + br i1 %0, label %"16", label %"26" + +"26": ; preds = %"22" + unreachable + +"33": ; preds = %"16" + unreachable +} |