mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-25 13:24:46 +00:00
Do not compute the predecessor list for a block unless we need it.
This speeds up simplifycfg on this program, from 44.87s to 0.29s (with a profiled build): #define CL0(a) case a: goto c; #define CL1(a) CL0(a##0) CL0(a##1) CL0(a##2) CL0(a##3) CL0(a##4) CL0(a##5) \ CL0(a##6) CL0(a##7) CL0(a##8) CL0(a##9) #define CL2(a) CL1(a##0) CL1(a##1) CL1(a##2) CL1(a##3) CL1(a##4) CL1(a##5) \ CL1(a##6) CL1(a##7) CL1(a##8) CL1(a##9) #define CL3(a) CL2(a##0) CL2(a##1) CL2(a##2) CL2(a##3) CL2(a##4) CL2(a##5) \ CL2(a##6) CL2(a##7) CL2(a##8) CL2(a##9) #define CL4(a) CL3(a##0) CL3(a##1) CL3(a##2) CL3(a##3) CL3(a##4) CL3(a##5) \ CL3(a##6) CL3(a##7) CL3(a##8) CL3(a##9) void f(); void a() { int b; c: switch (b) { CL4(1) } } This testcase is contrived to expose N^2 behavior, but this patch should speedup simplifycfg on any programs that use large switch statements. This testcase comes from GCC PR17895. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@17389 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -608,31 +608,29 @@ bool llvm::SimplifyCFG(BasicBlock *BB) {
|
|||||||
// to the successor.
|
// to the successor.
|
||||||
succ_iterator SI(succ_begin(BB));
|
succ_iterator SI(succ_begin(BB));
|
||||||
if (SI != succ_end(BB) && ++SI == succ_end(BB)) { // One succ?
|
if (SI != succ_end(BB) && ++SI == succ_end(BB)) { // One succ?
|
||||||
|
|
||||||
BasicBlock::iterator BBI = BB->begin(); // Skip over phi nodes...
|
BasicBlock::iterator BBI = BB->begin(); // Skip over phi nodes...
|
||||||
while (isa<PHINode>(*BBI)) ++BBI;
|
while (isa<PHINode>(*BBI)) ++BBI;
|
||||||
|
|
||||||
if (BBI->isTerminator()) { // Terminator is the only non-phi instruction!
|
BasicBlock *Succ = *succ_begin(BB); // There is exactly one successor.
|
||||||
BasicBlock *Succ = *succ_begin(BB); // There is exactly one successor
|
if (BBI->isTerminator() && // Terminator is the only non-phi instruction!
|
||||||
|
Succ != BB) { // Don't hurt infinite loops!
|
||||||
if (Succ != BB) { // Arg, don't hurt infinite loops!
|
// If our successor has PHI nodes, then we need to update them to include
|
||||||
// If our successor has PHI nodes, then we need to update them to
|
// entries for BB's predecessors, not for BB itself. Be careful though,
|
||||||
// include entries for BB's predecessors, not for BB itself.
|
// if this transformation fails (returns true) then we cannot do this
|
||||||
// Be careful though, if this transformation fails (returns true) then
|
// transformation!
|
||||||
// we cannot do this transformation!
|
//
|
||||||
//
|
if (!PropagatePredecessorsForPHIs(BB, Succ)) {
|
||||||
if (!PropagatePredecessorsForPHIs(BB, Succ)) {
|
DEBUG(std::cerr << "Killing Trivial BB: \n" << *BB);
|
||||||
DEBUG(std::cerr << "Killing Trivial BB: \n" << *BB);
|
|
||||||
std::string OldName = BB->getName();
|
if (isa<PHINode>(&BB->front())) {
|
||||||
|
|
||||||
std::vector<BasicBlock*>
|
std::vector<BasicBlock*>
|
||||||
OldSuccPreds(pred_begin(Succ), pred_end(Succ));
|
OldSuccPreds(pred_begin(Succ), pred_end(Succ));
|
||||||
|
|
||||||
// Move all PHI nodes in BB to Succ if they are alive, otherwise
|
// Move all PHI nodes in BB to Succ if they are alive, otherwise
|
||||||
// delete them.
|
// delete them.
|
||||||
while (PHINode *PN = dyn_cast<PHINode>(&BB->front()))
|
while (PHINode *PN = dyn_cast<PHINode>(&BB->front()))
|
||||||
if (PN->use_empty())
|
if (PN->use_empty())
|
||||||
BB->getInstList().erase(BB->begin()); // Nuke instruction...
|
BB->getInstList().erase(BB->begin()); // Nuke instruction.
|
||||||
else {
|
else {
|
||||||
// The instruction is alive, so this means that Succ must have
|
// The instruction is alive, so this means that Succ must have
|
||||||
// *ONLY* had BB as a predecessor, and the PHI node is still valid
|
// *ONLY* had BB as a predecessor, and the PHI node is still valid
|
||||||
@@ -640,7 +638,7 @@ bool llvm::SimplifyCFG(BasicBlock *BB) {
|
|||||||
// strictly dominated Succ.
|
// strictly dominated Succ.
|
||||||
BB->getInstList().remove(BB->begin());
|
BB->getInstList().remove(BB->begin());
|
||||||
Succ->getInstList().push_front(PN);
|
Succ->getInstList().push_front(PN);
|
||||||
|
|
||||||
// We need to add new entries for the PHI node to account for
|
// We need to add new entries for the PHI node to account for
|
||||||
// predecessors of Succ that the PHI node does not take into
|
// predecessors of Succ that the PHI node does not take into
|
||||||
// account. At this point, since we know that BB dominated succ,
|
// account. At this point, since we know that BB dominated succ,
|
||||||
@@ -651,17 +649,16 @@ bool llvm::SimplifyCFG(BasicBlock *BB) {
|
|||||||
if (OldSuccPreds[i] != BB)
|
if (OldSuccPreds[i] != BB)
|
||||||
PN->addIncoming(PN, OldSuccPreds[i]);
|
PN->addIncoming(PN, OldSuccPreds[i]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Everything that jumped to BB now goes to Succ.
|
||||||
|
std::string OldName = BB->getName();
|
||||||
|
BB->replaceAllUsesWith(Succ);
|
||||||
|
BB->eraseFromParent(); // Delete the old basic block.
|
||||||
|
|
||||||
// Everything that jumped to BB now goes to Succ...
|
if (!OldName.empty() && !Succ->hasName()) // Transfer name if we can
|
||||||
BB->replaceAllUsesWith(Succ);
|
Succ->setName(OldName);
|
||||||
|
return true;
|
||||||
// Delete the old basic block...
|
|
||||||
M->getBasicBlockList().erase(BB);
|
|
||||||
|
|
||||||
if (!OldName.empty() && !Succ->hasName()) // Transfer name if we can
|
|
||||||
Succ->setName(OldName);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user