diff options
author | Chris Lattner <sabre@nondot.org> | 2004-10-18 04:07:22 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2004-10-18 04:07:22 +0000 |
commit | 698f96f7c81e45292ae4f5d76b8e06c88a88a71f (patch) | |
tree | 802992dd029b46df29a9e60cb875678418f782e1 | |
parent | d7e30973cdf378d50b862431fc96128b1df81416 (diff) | |
download | external_llvm-698f96f7c81e45292ae4f5d76b8e06c88a88a71f.zip external_llvm-698f96f7c81e45292ae4f5d76b8e06c88a88a71f.tar.gz external_llvm-698f96f7c81e45292ae4f5d76b8e06c88a88a71f.tar.bz2 |
Simplify code by deleting instructions that preceed unreachable instructions.
Simplify code by simplifying terminators that branch to blocks that start
with an unreachable instruction.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@17116 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Transforms/Utils/SimplifyCFG.cpp | 102 |
1 files changed, 101 insertions, 1 deletions
diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp index 9a6be49..2d2f516 100644 --- a/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/lib/Transforms/Utils/SimplifyCFG.cpp @@ -21,7 +21,7 @@ #include <algorithm> #include <functional> #include <set> - +#include <map> using namespace llvm; // PropagatePredecessorsForPHIs - This gets "Succ" ready to have the @@ -916,6 +916,106 @@ bool llvm::SimplifyCFG(BasicBlock *BB) { return SimplifyCFG(BB) | true; } } + } else if (isa<UnreachableInst>(BB->getTerminator())) { + // If there are any instructions immediately before the unreachable that can + // be removed, do so. + Instruction *Unreachable = BB->getTerminator(); + while (Unreachable != BB->begin()) { + BasicBlock::iterator BBI = Unreachable; + --BBI; + if (isa<CallInst>(BBI)) break; + // Delete this instruction + BB->getInstList().erase(BBI); + Changed = true; + } + + // If the unreachable instruction is the first in the block, take a gander + // at all of the predecessors of this instruction, and simplify them. + if (&BB->front() == Unreachable) { + std::vector<BasicBlock*> Preds(pred_begin(BB), pred_end(BB)); + for (unsigned i = 0, e = Preds.size(); i != e; ++i) { + TerminatorInst *TI = Preds[i]->getTerminator(); + + if (BranchInst *BI = dyn_cast<BranchInst>(TI)) { + if (BI->isUnconditional()) { + if (BI->getSuccessor(0) == BB) { + new UnreachableInst(TI); + TI->eraseFromParent(); + Changed = true; + } + } else { + if (BI->getSuccessor(0) == BB) { + new BranchInst(BI->getSuccessor(1), BI); + BI->eraseFromParent(); + } else if (BI->getSuccessor(1) == BB) { + new BranchInst(BI->getSuccessor(0), BI); + BI->eraseFromParent(); + Changed = true; + } + } + } else if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) { + for (unsigned i = 1, e = SI->getNumCases(); i != e; ++i) + if (SI->getSuccessor(i) == BB) { + SI->removeCase(i); + --i; --e; + Changed = true; + } + // If the default value is unreachable, figure out the most popular + // destination and make it the default. + if (SI->getSuccessor(0) == BB) { + std::map<BasicBlock*, unsigned> Popularity; + for (unsigned i = 1, e = SI->getNumCases(); i != e; ++i) + Popularity[SI->getSuccessor(i)]++; + + // Find the most popular block. + unsigned MaxPop = 0; + BasicBlock *MaxBlock = 0; + for (std::map<BasicBlock*, unsigned>::iterator + I = Popularity.begin(), E = Popularity.end(); I != E; ++I) { + if (I->second > MaxPop) { + MaxPop = I->second; + MaxBlock = I->first; + } + } + if (MaxBlock) { + // Make this the new default, allowing us to delete any explicit + // edges to it. + SI->setSuccessor(0, MaxBlock); + Changed = true; + + for (unsigned i = 1, e = SI->getNumCases(); i != e; ++i) + if (SI->getSuccessor(i) == MaxBlock) { + SI->removeCase(i); + --i; --e; + } + } + } + } else if (InvokeInst *II = dyn_cast<InvokeInst>(TI)) { + if (II->getUnwindDest() == BB) { + // Convert the invoke to a call instruction. This would be a good + // place to note that the call does not throw though. + BranchInst *BI = new BranchInst(II->getNormalDest(), II); + II->removeFromParent(); // Take out of symbol table + + // Insert the call now... + std::vector<Value*> Args(II->op_begin()+3, II->op_end()); + CallInst *CI = new CallInst(II->getCalledValue(), Args, + II->getName(), BI); + // If the invoke produced a value, the Call does now instead. + II->replaceAllUsesWith(CI); + delete II; + Changed = true; + } + } + } + + // If this block is now dead, remove it. + if (pred_begin(BB) == pred_end(BB)) { + // We know there are no successors, so just nuke the block. + M->getBasicBlockList().erase(BB); + return true; + } + } } // Merge basic blocks into their predecessor if there is only one distinct |