diff options
author | Hans Wennborg <hans@hanshq.net> | 2014-12-01 17:08:32 +0000 |
---|---|---|
committer | Hans Wennborg <hans@hanshq.net> | 2014-12-01 17:08:32 +0000 |
commit | 1571336fb2ef5e6da5536ef7e1b76c4233e18081 (patch) | |
tree | e99c25784639760c7f6ac31ff5cc92cae6421611 /llvm/lib | |
parent | bfe25b268e9ec1da64cb9b9eb80738f3a196a5b1 (diff) | |
download | bcm5719-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.cpp | 59 |
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 |