From 46a5f1f6e4a3be3d53b4e0016b78d108a2353f4c Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Wed, 5 Mar 2003 21:36:33 +0000 Subject: [PATCH] Implement CFGSimplify/PhiBlockMerge*.ll git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@5702 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Utils/SimplifyCFG.cpp | 46 ++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp index b1a1bdee057..3b658aacb40 100644 --- a/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/lib/Transforms/Utils/SimplifyCFG.cpp @@ -39,8 +39,8 @@ static bool PropagatePredecessorsForPHIs(BasicBlock *BB, BasicBlock *Succ) { if (find(BBPreds.begin(), BBPreds.end(), *PI) != BBPreds.end()) { // Loop over all of the PHI nodes checking to see if there are // incompatible values coming in. - BasicBlock::iterator BBI = Succ->begin(); - while (PHINode *PN = dyn_cast(&*BBI++)) { + for (BasicBlock::iterator I = Succ->begin(); + PHINode *PN = dyn_cast(&*I); ++I) { // Loop up the entries in the PHI node for BB and for *PI if the values // coming in are non-equal, we cannot merge these two blocks (instead we // should insert a conditional move or something, then merge the @@ -60,10 +60,19 @@ static bool PropagatePredecessorsForPHIs(BasicBlock *BB, BasicBlock *Succ) { Value *OldVal = PN->removeIncomingValue(BB, false); assert(OldVal && "No entry in PHI for Pred BB!"); - for (std::vector::const_iterator PredI = BBPreds.begin(), - End = BBPreds.end(); PredI != End; ++PredI) { - // Add an incoming value for each of the new incoming values... - PN->addIncoming(OldVal, *PredI); + // If this incoming value is one of the PHI nodes in BB... + if (isa(OldVal) && cast(OldVal)->getParent() == BB) { + PHINode *OldValPN = cast(OldVal); + for (std::vector::const_iterator PredI = BBPreds.begin(), + End = BBPreds.end(); PredI != End; ++PredI) { + PN->addIncoming(OldValPN->getIncomingValueForBlock(*PredI), *PredI); + } + } else { + for (std::vector::const_iterator PredI = BBPreds.begin(), + End = BBPreds.end(); PredI != End; ++PredI) { + // Add an incoming value for each of the new incoming values... + PN->addIncoming(OldVal, *PredI); + } } } return false; @@ -84,7 +93,6 @@ bool SimplifyCFG(BasicBlock *BB) { assert(BB->getTerminator() && "Degenerate basic block encountered!"); assert(&BB->getParent()->front() != BB && "Can't Simplify entry block!"); - // Remove basic blocks that have no predecessors... which are unreachable. if (pred_begin(BB) == pred_end(BB) && !BB->hasConstantReferences()) { @@ -113,11 +121,16 @@ bool SimplifyCFG(BasicBlock *BB) { return true; } - // Check to see if this block has no instructions and only a single - // successor. If so, replace block references with successor. + // Check to see if this block has no non-phi instructions and only a single + // successor. If so, replace references to this basic block with references + // to the successor. succ_iterator SI(succ_begin(BB)); if (SI != succ_end(BB) && ++SI == succ_end(BB)) { // One succ? - if (BB->front().isTerminator()) { // Terminator is the only instruction! + + 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! @@ -131,6 +144,19 @@ bool SimplifyCFG(BasicBlock *BB) { BB->replaceAllUsesWith(Succ); std::string OldName = BB->getName(); + // 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... + 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 + // now. Simply move it into Succ. + BB->getInstList().remove(BB->begin()); + Succ->getInstList().push_front(PN); + } + // Delete the old basic block... M->getBasicBlockList().erase(BB);