Skip to content

Commit

Permalink
Fast fix for PR12343:
Browse files Browse the repository at this point in the history
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
  • Loading branch information
kaomoneus committed Apr 2, 2012
1 parent 466958c commit aad9c3f
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 4 deletions.
33 changes: 29 additions & 4 deletions lib/Transforms/Scalar/LoopUnswitch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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);
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -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 %"
Expand All @@ -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.
Expand Down Expand Up @@ -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
Expand Down
46 changes: 46 additions & 0 deletions test/Transforms/LoopUnswitch/2012-04-02-IndirectBr.ll
Original file line number Diff line number Diff line change
@@ -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
}

0 comments on commit aad9c3f

Please sign in to comment.