aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStepan Dyatkovskiy <stpworld@narod.ru>2012-04-02 17:16:45 +0000
committerStepan Dyatkovskiy <stpworld@narod.ru>2012-04-02 17:16:45 +0000
commitaad9c3f17a73b3104f4a3673a2dc511a4878e20e (patch)
tree6c13b569bf511dd07b3943a063ea0488b11e49d8
parent466958c2a04a74de99efd3d7e0d5bd81cdf1e1fe (diff)
downloadexternal_llvm-aad9c3f17a73b3104f4a3673a2dc511a4878e20e.zip
external_llvm-aad9c3f17a73b3104f4a3673a2dc511a4878e20e.tar.gz
external_llvm-aad9c3f17a73b3104f4a3673a2dc511a4878e20e.tar.bz2
Fast fix for PR12343:
http://llvm.org/bugs/show_bug.cgi?id=12343 We have not trivial way for splitting edges that are goes from indirect branch. We can do it with some tricks, but it should be additionally discussed. And it is still dangerous due to difficulty of indirect branches controlling. Fix forbids this case for unswitching. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@153879 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Transforms/Scalar/LoopUnswitch.cpp33
-rw-r--r--test/Transforms/LoopUnswitch/2012-04-02-IndirectBr.ll46
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
+}