mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-14 11:32:34 +00:00
Make LoopUnswitch able to unswitch loops with live-out values by taking advantage
of LCSSA. This results several times the number of unswitchings occurring on tests such and timberwolfmc, unix-tbl, and ldecod. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@28912 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
da08d2c39a
commit
2b67f07d2b
@ -208,31 +208,6 @@ bool LoopUnswitch::visitLoop(Loop *L) {
|
||||
return Changed;
|
||||
}
|
||||
|
||||
|
||||
/// LoopValuesUsedOutsideLoop - Return true if there are any values defined in
|
||||
/// the loop that are used by instructions outside of it.
|
||||
static bool LoopValuesUsedOutsideLoop(Loop *L) {
|
||||
// We will be doing lots of "loop contains block" queries. Loop::contains is
|
||||
// linear time, use a set to speed this up.
|
||||
std::set<BasicBlock*> LoopBlocks;
|
||||
|
||||
for (Loop::block_iterator BB = L->block_begin(), E = L->block_end();
|
||||
BB != E; ++BB)
|
||||
LoopBlocks.insert(*BB);
|
||||
|
||||
for (Loop::block_iterator BB = L->block_begin(), E = L->block_end();
|
||||
BB != E; ++BB) {
|
||||
for (BasicBlock::iterator I = (*BB)->begin(), E = (*BB)->end(); I != E; ++I)
|
||||
for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI != E;
|
||||
++UI) {
|
||||
BasicBlock *UserBB = cast<Instruction>(*UI)->getParent();
|
||||
if (!LoopBlocks.count(UserBB))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// isTrivialLoopExitBlock - Check to see if all paths from BB either:
|
||||
/// 1. Exit the loop with no side effects.
|
||||
/// 2. Branch to the latch block with no side-effects.
|
||||
@ -392,16 +367,6 @@ bool LoopUnswitch::UnswitchIfProfitable(Value *LoopCond, Constant *Val,Loop *L){
|
||||
return false;
|
||||
}
|
||||
|
||||
// If this loop has live-out values, we can't unswitch it. We need something
|
||||
// like loop-closed SSA form in order to know how to insert PHI nodes for
|
||||
// these values.
|
||||
if (LoopValuesUsedOutsideLoop(L)) {
|
||||
DEBUG(std::cerr << "NOT unswitching loop %" << L->getHeader()->getName()
|
||||
<< ", a loop value is used outside loop! Cost: "
|
||||
<< Cost << "\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// If this is a trivial condition to unswitch (which results in no code
|
||||
// duplication), do it now.
|
||||
Constant *CondVal;
|
||||
@ -456,18 +421,6 @@ BasicBlock *LoopUnswitch::SplitEdge(BasicBlock *BB, BasicBlock *Succ) {
|
||||
// If the successor only has a single pred, split the top of the successor
|
||||
// block.
|
||||
assert(SP == BB && "CFG broken");
|
||||
|
||||
// If this block has a single predecessor, remove any phi nodes. Unswitch
|
||||
// expect that, after split the edges from inside the loop to the exit
|
||||
// block, that there will be no phi nodes in the new exit block. Single
|
||||
// entry phi nodes break this assumption.
|
||||
BasicBlock::iterator I = Succ->begin();
|
||||
while (PHINode *PN = dyn_cast<PHINode>(I)) {
|
||||
PN->replaceAllUsesWith(PN->getIncomingValue(0));
|
||||
PN->eraseFromParent();
|
||||
I = Succ->begin();
|
||||
}
|
||||
|
||||
return SplitBlock(Succ, Succ->begin());
|
||||
} else {
|
||||
// Otherwise, if BB has a single successor, split it at the bottom of the
|
||||
@ -616,8 +569,8 @@ void LoopUnswitch::UnswitchNontrivialCondition(Value *LIC, Constant *Val,
|
||||
ExitBlocks.erase(std::unique(ExitBlocks.begin(), ExitBlocks.end()),
|
||||
ExitBlocks.end());
|
||||
|
||||
// Split all of the edges from inside the loop to their exit blocks. This
|
||||
// unswitching trivial: no phi nodes to update.
|
||||
// Split all of the edges from inside the loop to their exit blocks. Update
|
||||
// the appropriate Phi nodes as we do so.
|
||||
unsigned NumBlocks = L->getBlocks().size();
|
||||
|
||||
for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i) {
|
||||
@ -627,7 +580,41 @@ void LoopUnswitch::UnswitchNontrivialCondition(Value *LIC, Constant *Val,
|
||||
for (unsigned j = 0, e = Preds.size(); j != e; ++j) {
|
||||
assert(L->contains(Preds[j]) &&
|
||||
"All preds of loop exit blocks must be the same loop!");
|
||||
SplitEdge(Preds[j], ExitBlock);
|
||||
BasicBlock* MiddleBlock = SplitEdge(Preds[j], ExitBlock);
|
||||
BasicBlock* StartBlock = Preds[j];
|
||||
BasicBlock* EndBlock;
|
||||
if (MiddleBlock->getSinglePredecessor() == ExitBlock) {
|
||||
EndBlock = MiddleBlock;
|
||||
MiddleBlock = EndBlock->getSinglePredecessor();;
|
||||
} else {
|
||||
EndBlock = ExitBlock;
|
||||
}
|
||||
|
||||
std::set<PHINode*> InsertedPHIs;
|
||||
PHINode* OldLCSSA = 0;
|
||||
for (BasicBlock::iterator I = EndBlock->begin();
|
||||
(OldLCSSA = dyn_cast<PHINode>(I)); ++I) {
|
||||
Value* OldValue = OldLCSSA->getIncomingValueForBlock(MiddleBlock);
|
||||
PHINode* NewLCSSA = new PHINode(OldLCSSA->getType(),
|
||||
OldLCSSA->getName() + ".us-lcssa",
|
||||
MiddleBlock->getTerminator());
|
||||
NewLCSSA->addIncoming(OldValue, StartBlock);
|
||||
OldLCSSA->setIncomingValue(OldLCSSA->getBasicBlockIndex(MiddleBlock),
|
||||
NewLCSSA);
|
||||
InsertedPHIs.insert(NewLCSSA);
|
||||
}
|
||||
|
||||
Instruction* InsertPt = EndBlock->begin();
|
||||
while (dyn_cast<PHINode>(InsertPt)) ++InsertPt;
|
||||
for (BasicBlock::iterator I = MiddleBlock->begin();
|
||||
(OldLCSSA = dyn_cast<PHINode>(I)) && InsertedPHIs.count(OldLCSSA) == 0;
|
||||
++I) {
|
||||
PHINode *NewLCSSA = new PHINode(OldLCSSA->getType(),
|
||||
OldLCSSA->getName() + ".us-lcssa",
|
||||
InsertPt);
|
||||
OldLCSSA->replaceAllUsesWith(NewLCSSA);
|
||||
NewLCSSA->addIncoming(OldLCSSA, MiddleBlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -967,7 +954,30 @@ void LoopUnswitch::RewriteLoopBodyWithConditionConstant(Loop *L, Value *LIC,
|
||||
// Found a dead case value. Don't remove PHI nodes in the
|
||||
// successor if they become single-entry, those PHI nodes may
|
||||
// be in the Users list.
|
||||
SI->getSuccessor(i)->removePredecessor(SI->getParent(), true);
|
||||
|
||||
// FIXME: This is a hack. We need to keep the successor around
|
||||
// and hooked up so as to preserve the loop structure, because
|
||||
// trying to update it is complicated. So instead we preserve the
|
||||
// loop structure and put the block on an dead code path.
|
||||
|
||||
BasicBlock* Old = SI->getParent();
|
||||
BasicBlock* Split = SplitBlock(Old, SI);
|
||||
|
||||
Instruction* OldTerm = Old->getTerminator();
|
||||
BranchInst* Branch = new BranchInst(Split,
|
||||
SI->getSuccessor(i),
|
||||
ConstantBool::True,
|
||||
OldTerm);
|
||||
|
||||
Old->getTerminator()->eraseFromParent();
|
||||
|
||||
for (BasicBlock::iterator II = SI->getSuccessor(i)->begin(),
|
||||
IE = SI->getSuccessor(i)->end(); II != IE; ++II) {
|
||||
if (isa<PHINode>(*II)) {
|
||||
(*II).replaceUsesOfWith(Split, Old);
|
||||
}
|
||||
}
|
||||
|
||||
SI->removeCase(i);
|
||||
break;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user