summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2014-12-01 17:08:32 +0000
committerHans Wennborg <hans@hanshq.net>2014-12-01 17:08:32 +0000
commit1571336fb2ef5e6da5536ef7e1b76c4233e18081 (patch)
treee99c25784639760c7f6ac31ff5cc92cae6421611 /llvm/lib
parentbfe25b268e9ec1da64cb9b9eb80738f3a196a5b1 (diff)
downloadbcm5719-llvm-1571336fb2ef5e6da5536ef7e1b76c4233e18081.tar.gz
bcm5719-llvm-1571336fb2ef5e6da5536ef7e1b76c4233e18081.zip
SelectionDAG switch lowering: Replace unreachable default with most popular case.
This can significantly reduce the size of the switch, allowing for more efficient lowering. I also worked with the idea of exploiting unreachable defaults by omitting the range check for jump tables, but always ended up with a non-neglible binary size increase. It might be worth looking into some more. llvm-svn: 223049
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp59
1 files changed, 42 insertions, 17 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index fbc1502d500..ec6a1367883 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -2695,32 +2695,57 @@ void SelectionDAGBuilder::visitSwitch(const SwitchInst &SI) {
if (SwitchMBB + 1 != FuncInfo.MF->end())
NextBlock = SwitchMBB + 1;
+
+ // Create a vector of Cases, sorted so that we can efficiently create a binary
+ // search tree from them.
+ CaseVector Cases;
+ Clusterify(Cases, SI);
+
+ // Get the default destination MBB.
MachineBasicBlock *Default = FuncInfo.MBBMap[SI.getDefaultDest()];
- // If there is only the default destination, branch to it if it is not the
- // next basic block. Otherwise, just fall through.
- if (!SI.getNumCases()) {
+ if (isa<UnreachableInst>(SI.getDefaultDest()->getFirstNonPHIOrDbg())) {
+ // Replace an unreachable default destination with the most popular case
+ // destination.
+ DenseMap<const BasicBlock*, uint64_t> Popularity;
+ uint64_t MaxPop = 0;
+ const BasicBlock *MaxBB = nullptr;
+ for (auto I : SI.cases()) {
+ const BasicBlock *BB = I.getCaseSuccessor();
+ if (++Popularity[BB] > MaxPop) {
+ MaxPop = Popularity[BB];
+ MaxBB = BB;
+ }
+ }
+
+ // Set new default.
+ Default = FuncInfo.MBBMap[MaxBB];
+
+ // Remove cases that have been replaced by the default.
+ CaseItr I = Cases.begin();
+ while (I != Cases.end()) {
+ if (I->BB == Default) {
+ I = Cases.erase(I);
+ continue;
+ }
+ ++I;
+ }
+ }
+
+ // If there is only the default destination, go there directly.
+ if (Cases.empty()) {
// Update machine-CFG edges.
SwitchMBB->addSuccessor(Default);
// If this is not a fall-through branch, emit the branch.
- if (Default != NextBlock)
- DAG.setRoot(DAG.getNode(ISD::BR, getCurSDLoc(),
- MVT::Other, getControlRoot(),
- DAG.getBasicBlock(Default)));
-
+ if (Default != NextBlock) {
+ DAG.setRoot(DAG.getNode(ISD::BR, getCurSDLoc(), MVT::Other,
+ getControlRoot(), DAG.getBasicBlock(Default)));
+ }
return;
}
- // If there are any non-default case statements, create a vector of Cases
- // representing each one, and sort the vector so that we can efficiently
- // create a binary search tree from them.
- CaseVector Cases;
- Clusterify(Cases, SI);
-
- // Get the Value to be switched on and default basic blocks, which will be
- // inserted into CaseBlock records, representing basic blocks in the binary
- // search tree.
+ // Get the Value to be switched on.
const Value *SV = SI.getCondition();
// Push the initial CaseRec onto the worklist
OpenPOWER on IntegriCloud