From bfd3e527015f55d144adf44af94028db61dd6269 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 1 Nov 2004 06:53:58 +0000 Subject: [PATCH] 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 --- lib/Transforms/Utils/SimplifyCFG.cpp | 51 +++++++++++++--------------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp index 38d66cbcb2e..55939ae53d9 100644 --- a/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/lib/Transforms/Utils/SimplifyCFG.cpp @@ -608,31 +608,29 @@ bool llvm::SimplifyCFG(BasicBlock *BB) { // to the successor. succ_iterator SI(succ_begin(BB)); if (SI != succ_end(BB) && ++SI == succ_end(BB)) { // One succ? - BasicBlock::iterator BBI = BB->begin(); // Skip over phi nodes... while (isa(*BBI)) ++BBI; - if (BBI->isTerminator()) { // Terminator is the only non-phi instruction! - BasicBlock *Succ = *succ_begin(BB); // There is exactly one successor - - if (Succ != BB) { // Arg, don't hurt infinite loops! - // If our successor has PHI nodes, then we need to update them to - // include entries for BB's predecessors, not for BB itself. - // Be careful though, if this transformation fails (returns true) then - // we cannot do this transformation! - // - if (!PropagatePredecessorsForPHIs(BB, Succ)) { - DEBUG(std::cerr << "Killing Trivial BB: \n" << *BB); - std::string OldName = BB->getName(); - + 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 our successor has PHI nodes, then we need to update them to include + // entries for BB's predecessors, not for BB itself. Be careful though, + // if this transformation fails (returns true) then we cannot do this + // transformation! + // + if (!PropagatePredecessorsForPHIs(BB, Succ)) { + DEBUG(std::cerr << "Killing Trivial BB: \n" << *BB); + + if (isa(&BB->front())) { std::vector OldSuccPreds(pred_begin(Succ), pred_end(Succ)); - + // Move all PHI nodes in BB to Succ if they are alive, otherwise // delete them. while (PHINode *PN = dyn_cast(&BB->front())) if (PN->use_empty()) - BB->getInstList().erase(BB->begin()); // Nuke instruction... + BB->getInstList().erase(BB->begin()); // Nuke instruction. else { // The instruction is alive, so this means that Succ must have // *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. BB->getInstList().remove(BB->begin()); Succ->getInstList().push_front(PN); - + // We need to add new entries for the PHI node to account for // predecessors of Succ that the PHI node does not take into // account. At this point, since we know that BB dominated succ, @@ -651,17 +649,16 @@ bool llvm::SimplifyCFG(BasicBlock *BB) { if (OldSuccPreds[i] != BB) 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... - BB->replaceAllUsesWith(Succ); - - // Delete the old basic block... - M->getBasicBlockList().erase(BB); - - if (!OldName.empty() && !Succ->hasName()) // Transfer name if we can - Succ->setName(OldName); - return true; - } + if (!OldName.empty() && !Succ->hasName()) // Transfer name if we can + Succ->setName(OldName); + return true; } } }