mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2026-04-25 21:18:19 +00:00
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@223049 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user