mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-15 04:30:12 +00:00
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:
parent
fef50062ea
commit
424641ef83
@ -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.
|
||||||
|
Loading…
Reference in New Issue
Block a user