Fix LoopUnswitch bug. RewriteLoopBodyWithConditionConstant can delete a dead

case of a switch instruction. Back off this optimization when this would
eliminate all of the predecessors to the latch.

Sorry, I am unable to reduce a reasonably sized test case.

rdar://9486843


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@132022 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng 2011-05-24 23:12:57 +00:00
parent fef50062ea
commit 424641ef83

View File

@ -786,8 +786,13 @@ void LoopUnswitch::RemoveBlockIfDead(BasicBlock *BB,
// If this is the edge to the header block for a loop, remove the loop and // If this is the edge to the header block for a loop, remove the loop and
// promote all subloops. // promote all subloops.
if (Loop *BBLoop = LI->getLoopFor(BB)) { if (Loop *BBLoop = LI->getLoopFor(BB)) {
if (BBLoop->getLoopLatch() == BB) if (BBLoop->getLoopLatch() == BB) {
RemoveLoopFromHierarchy(BBLoop); RemoveLoopFromHierarchy(BBLoop);
if (currentLoop == BBLoop) {
currentLoop = 0;
redoLoop = false;
}
}
} }
// Remove the block from the loop info, which removes it from any loops it // Remove the block from the loop info, which removes it from any loops it
@ -859,7 +864,6 @@ void LoopUnswitch::RewriteLoopBodyWithConditionConstant(Loop *L, Value *LIC,
// FOLD boolean conditions (X|LIC), (X&LIC). Fold conditional branches, // FOLD boolean conditions (X|LIC), (X&LIC). Fold conditional branches,
// selects, switches. // selects, switches.
std::vector<User*> Users(LIC->use_begin(), LIC->use_end());
std::vector<Instruction*> Worklist; std::vector<Instruction*> Worklist;
LLVMContext &Context = Val->getContext(); LLVMContext &Context = Val->getContext();
@ -875,13 +879,14 @@ void LoopUnswitch::RewriteLoopBodyWithConditionConstant(Loop *L, Value *LIC,
Replacement = ConstantInt::get(Type::getInt1Ty(Val->getContext()), Replacement = ConstantInt::get(Type::getInt1Ty(Val->getContext()),
!cast<ConstantInt>(Val)->getZExtValue()); !cast<ConstantInt>(Val)->getZExtValue());
for (unsigned i = 0, e = Users.size(); i != e; ++i) for (Value::use_iterator UI = LIC->use_begin(), E = LIC->use_end();
if (Instruction *U = cast<Instruction>(Users[i])) { UI != E; ++UI) {
if (!L->contains(U)) Instruction *U = cast<Instruction>(*UI);
continue; if (!L->contains(U))
U->replaceUsesOfWith(LIC, Replacement); continue;
Worklist.push_back(U); U->replaceUsesOfWith(LIC, Replacement);
} Worklist.push_back(U);
}
SimplifyCode(Worklist, L); SimplifyCode(Worklist, L);
return; return;
} }
@ -889,8 +894,9 @@ void LoopUnswitch::RewriteLoopBodyWithConditionConstant(Loop *L, Value *LIC,
// Otherwise, we don't know the precise value of LIC, but we do know that it // Otherwise, we don't know the precise value of LIC, but we do know that it
// is certainly NOT "Val". As such, simplify any uses in the loop that we // is certainly NOT "Val". As such, simplify any uses in the loop that we
// can. This case occurs when we unswitch switch statements. // can. This case occurs when we unswitch switch statements.
for (unsigned i = 0, e = Users.size(); i != e; ++i) { for (Value::use_iterator UI = LIC->use_begin(), E = LIC->use_end();
Instruction *U = cast<Instruction>(Users[i]); UI != E; ++UI) {
Instruction *U = cast<Instruction>(*UI);
if (!L->contains(U)) if (!L->contains(U))
continue; continue;
@ -910,12 +916,27 @@ void LoopUnswitch::RewriteLoopBodyWithConditionConstant(Loop *L, Value *LIC,
// successor if they become single-entry, those PHI nodes may // successor if they become single-entry, those PHI nodes may
// be in the Users list. // be in the Users list.
BasicBlock *Switch = SI->getParent();
BasicBlock *SISucc = SI->getSuccessor(DeadCase);
BasicBlock *Latch = L->getLoopLatch();
// If the DeadCase successor dominates all of the predecessors of the
// loop latch, then the transformation isn't safe since it will delete
// the predecessor edges to the latch.
if (Latch) {
bool DominateAll = true;
for (pred_iterator PI = pred_begin(Latch), PE = pred_end(Latch);
DominateAll && PI != PE; ++PI)
if (!DT->dominates(SISucc, *PI))
DominateAll = false;
if (DominateAll)
continue;
}
// FIXME: This is a hack. We need to keep the successor around // FIXME: This is a hack. We need to keep the successor around
// and hooked up so as to preserve the loop structure, because // and hooked up so as to preserve the loop structure, because
// trying to update it is complicated. So instead we preserve the // trying to update it is complicated. So instead we preserve the
// loop structure and put the block on a dead code path. // loop structure and put the block on a dead code path.
BasicBlock *Switch = SI->getParent(); SplitEdge(Switch, SISucc, this);
SplitEdge(Switch, SI->getSuccessor(DeadCase), this);
// Compute the successors instead of relying on the return value // Compute the successors instead of relying on the return value
// of SplitEdge, since it may have split the switch successor // of SplitEdge, since it may have split the switch successor
// after PHI nodes. // after PHI nodes.