SimplifyCFG: don't remove unreachable default switch destinations

An unreachable default destination can be exploited by other optimizations, and
SDag lowering is now prepared to handle them efficiently.

For example, branches to the unreachable destination will be optimized away,
such as in the case of range checks for switch lookup tables.

On 64-bit Linux, this reduces the size of a clang bootstrap by 80 kB (and
Chromium by 30 kB).

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@223050 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Hans Wennborg
2014-12-01 17:08:35 +00:00
parent e6f4d335d7
commit b2fd944378
3 changed files with 7 additions and 82 deletions

View File

@@ -3120,55 +3120,6 @@ bool SimplifyCFGOpt::SimplifyUnreachable(UnreachableInst *UI) {
--i; --e;
Changed = true;
}
// If the default value is unreachable, figure out the most popular
// destination and make it the default.
if (SI->getDefaultDest() == BB) {
std::map<BasicBlock*, std::pair<unsigned, unsigned> > Popularity;
for (SwitchInst::CaseIt i = SI->case_begin(), e = SI->case_end();
i != e; ++i) {
std::pair<unsigned, unsigned> &entry =
Popularity[i.getCaseSuccessor()];
if (entry.first == 0) {
entry.first = 1;
entry.second = i.getCaseIndex();
} else {
entry.first++;
}
}
// Find the most popular block.
unsigned MaxPop = 0;
unsigned MaxIndex = 0;
BasicBlock *MaxBlock = nullptr;
for (std::map<BasicBlock*, std::pair<unsigned, unsigned> >::iterator
I = Popularity.begin(), E = Popularity.end(); I != E; ++I) {
if (I->second.first > MaxPop ||
(I->second.first == MaxPop && MaxIndex > I->second.second)) {
MaxPop = I->second.first;
MaxIndex = I->second.second;
MaxBlock = I->first;
}
}
if (MaxBlock) {
// Make this the new default, allowing us to delete any explicit
// edges to it.
SI->setDefaultDest(MaxBlock);
Changed = true;
// If MaxBlock has phinodes in it, remove MaxPop-1 entries from
// it.
if (isa<PHINode>(MaxBlock->begin()))
for (unsigned i = 0; i != MaxPop-1; ++i)
MaxBlock->removePredecessor(SI->getParent());
for (SwitchInst::CaseIt i = SI->case_begin(), e = SI->case_end();
i != e; ++i)
if (i.getCaseSuccessor() == 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