Split big monster into small helpers. No functionality change.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@35379 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Anton Korobeynikov
2007-03-27 11:29:11 +00:00
parent 0b57a76bc8
commit b17b08d1f2

View File

@@ -385,6 +385,8 @@ class SelectionDAGLowering {
CaseRange Range;
};
typedef std::vector<CaseRec> CaseRecVector;
/// The comparison function for sorting Case values.
struct CaseCmp {
bool operator () (const Case& C1, const Case& C2) {
@@ -496,7 +498,23 @@ public:
void visitSwitch(SwitchInst &I);
void visitUnreachable(UnreachableInst &I) { /* noop */ }
// Helper for visitSwitch
// Helpers for visitSwitch
void handleSmallSwitchRange(CaseRec& CR,
CaseRecVector& WorkList,
Value* SV,
MachineBasicBlock* Default);
void handleJTSwitchCase(CaseRec& CR,
CaseRecVector& WorkList,
Value* SV,
MachineBasicBlock* Default);
void handleBTSplitSwitchCase(CaseRec& CR,
CaseRecVector& WorkList,
Value* SV,
MachineBasicBlock* Default);
void handleBTSmallSwitchCase(CaseRec& CR,
CaseRecVector& WorkList,
Value* SV,
MachineBasicBlock* Default);
void visitSwitchCase(SelectionDAGISel::CaseBlock &CB);
void visitJumpTable(SelectionDAGISel::JumpTable &JT);
void visitJumpTableHeader(SelectionDAGISel::JumpTable &JT,
@@ -1208,73 +1226,25 @@ void SelectionDAGLowering::visitInvoke(InvokeInst &I, bool AsTerminator) {
void SelectionDAGLowering::visitUnwind(UnwindInst &I) {
}
void SelectionDAGLowering::visitSwitch(SwitchInst &I) {
// Figure out which block is immediately after the current one.
MachineBasicBlock *NextBlock = 0;
MachineFunction::iterator BBI = CurMBB;
MachineBasicBlock *Default = FuncInfo.MBBMap[I.getDefaultDest()];
// If there is only the default destination, branch to it if it is not the
// next basic block. Otherwise, just fall through.
if (I.getNumOperands() == 2) {
// Update machine-CFG edges.
// If this is not a fall-through branch, emit the branch.
if (Default != NextBlock)
DAG.setRoot(DAG.getNode(ISD::BR, MVT::Other, getRoot(),
DAG.getBasicBlock(Default)));
CurMBB->addSuccessor(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.
std::vector<Case> Cases;
for (unsigned i = 1; i < I.getNumSuccessors(); ++i) {
MachineBasicBlock *SMBB = FuncInfo.MBBMap[I.getSuccessor(i)];
Cases.push_back(Case(I.getSuccessorValue(i), SMBB));
}
std::sort(Cases.begin(), Cases.end(), CaseCmp());
// 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.
Value *SV = I.getOperand(0);
// Get the MachineFunction which holds the current MBB. This is used during
// emission of jump tables, and when inserting any additional MBBs necessary
// to represent the switch.
/// handleSmaaSwitchCaseRange - Emit a series of specific tests (suitable for
/// small case ranges).
void SelectionDAGLowering::handleSmallSwitchRange(CaseRec& CR,
CaseRecVector& WorkList,
Value* SV,
MachineBasicBlock* Default) {
// Get the MachineFunction which holds the current MBB. This is used when
// inserting any additional MBBs necessary to represent the switch.
MachineFunction *CurMF = CurMBB->getParent();
// Push the initial CaseRec onto the worklist
std::vector<CaseRec> WorkList;
WorkList.push_back(CaseRec(CurMBB,0,0,CaseRange(Cases.begin(),Cases.end())));
while (!WorkList.empty()) {
// Grab a record representing a case range to process off the worklist
CaseRec CR = WorkList.back();
WorkList.pop_back();
Case& FrontCase = *CR.Range.first;
Case& BackCase = *(CR.Range.second-1);
const BasicBlock *LLVMBB = CR.CaseBB->getBasicBlock();
// Figure out which block is immediately after the current one.
NextBlock = 0;
BBI = CR.CaseBB;
MachineBasicBlock *NextBlock = 0;
MachineFunction::iterator BBI = CR.CaseBB;
Case& BackCase = *(CR.Range.second-1);
if (++BBI != CurMBB->getParent()->end())
NextBlock = BBI;
// Size is the number of Cases represented by this range.
unsigned Size = CR.Range.second - CR.Range.first;
// If the range has few cases (two or less) emit a series of specific
// tests.
if (Size < 3) {
// TODO: If any two of the cases has the same destination, and if one value
// is the same as the other, but has one bit unset that the other has set,
// use bit manipulation to do two compares at once. For example:
@@ -1320,22 +1290,31 @@ void SelectionDAGLowering::visitSwitch(SwitchInst &I) {
CurBlock = FallThrough;
}
}
continue;
}
/// handleJTSwitchCase - Emit jumptable for current switch case range
void SelectionDAGLowering::handleJTSwitchCase(CaseRec& CR,
CaseRecVector& WorkList,
Value* SV,
MachineBasicBlock* Default) {
// Get the MachineFunction which holds the current MBB. This is used when
// inserting any additional MBBs necessary to represent the switch.
MachineFunction *CurMF = CurMBB->getParent();
// If the switch has more than 5 blocks, and at least 31.25% dense, and the
// target supports indirect branches, then emit a jump table rather than
// lowering the switch to a binary tree of conditional branches.
// Figure out which block is immediately after the current one.
MachineBasicBlock *NextBlock = 0;
MachineFunction::iterator BBI = CR.CaseBB;
if (++BBI != CurMBB->getParent()->end())
NextBlock = BBI;
Case& FrontCase = *CR.Range.first;
Case& BackCase = *(CR.Range.second-1);
const BasicBlock *LLVMBB = CR.CaseBB->getBasicBlock();
if ((TLI.isOperationLegal(ISD::BR_JT, MVT::Other) ||
TLI.isOperationLegal(ISD::BRIND, MVT::Other)) &&
Size > 5) {
uint64_t First = cast<ConstantInt>(FrontCase.first)->getSExtValue();
uint64_t Last = cast<ConstantInt>(BackCase.first)->getSExtValue();
double Density = (double)Size / (double)((Last - First) + 1ULL);
if (Density >= 0.3125) {
// Create a new basic block to hold the code for loading the address
// of the jump table, and jumping to it. Update successor information;
// we will either branch to the default case for the switch, or the jump
@@ -1385,16 +1364,16 @@ void SelectionDAGLowering::visitSwitch(SwitchInst &I) {
visitJumpTableHeader(JT, JTH);
JTCases.push_back(SelectionDAGISel::JumpTableBlock(JTH, JT));
}
continue;
}
}
/// handleBTSmallSwitchCase - handle leaf in the binary comparison tree. Just
/// emit test.
void SelectionDAGLowering::handleBTSmallSwitchCase(CaseRec& CR,
CaseRecVector& WorkList,
Value* SV,
MachineBasicBlock* Default) {
Case& FrontCase = *CR.Range.first;
// Emit binary tree. If Size is 1, then we are processing a leaf of the
// binary search tree. Otherwise, we need to pick a pivot, and push left
// and right ranges onto the worklist.
if (Size == 1) {
// Create a CaseBlock record representing a conditional branch to
// the Case's target mbb if the value being switched on SV is equal
// to C. Otherwise, branch to default.
@@ -1411,7 +1390,32 @@ void SelectionDAGLowering::visitSwitch(SwitchInst &I) {
visitSwitchCase(CB);
else
SwitchCases.push_back(CB);
} else {
}
/// handleBTSplitSwitchCase - emit comparison and split binary search tree into
/// 2 subtrees.
void SelectionDAGLowering::handleBTSplitSwitchCase(CaseRec& CR,
CaseRecVector& WorkList,
Value* SV,
MachineBasicBlock* Default) {
// Get the MachineFunction which holds the current MBB. This is used when
// inserting any additional MBBs necessary to represent the switch.
MachineFunction *CurMF = CurMBB->getParent();
// Figure out which block is immediately after the current one.
MachineBasicBlock *NextBlock = 0;
MachineFunction::iterator BBI = CR.CaseBB;
if (++BBI != CurMBB->getParent()->end())
NextBlock = BBI;
Case& FrontCase = *CR.Range.first;
Case& BackCase = *(CR.Range.second-1);
const BasicBlock *LLVMBB = CR.CaseBB->getBasicBlock();
// Size is the number of Cases represented by this range.
unsigned Size = CR.Range.second - CR.Range.first;
uint64_t First = cast<ConstantInt>(FrontCase.first)->getSExtValue();
uint64_t Last = cast<ConstantInt>(BackCase.first)->getSExtValue();
double Density = 0;
@@ -1479,7 +1483,98 @@ void SelectionDAGLowering::visitSwitch(SwitchInst &I) {
visitSwitchCase(CB);
else
SwitchCases.push_back(CB);
}
void SelectionDAGLowering::visitSwitch(SwitchInst &I) {
// Figure out which block is immediately after the current one.
MachineBasicBlock *NextBlock = 0;
MachineFunction::iterator BBI = CurMBB;
MachineBasicBlock *Default = FuncInfo.MBBMap[I.getDefaultDest()];
// If there is only the default destination, branch to it if it is not the
// next basic block. Otherwise, just fall through.
if (I.getNumOperands() == 2) {
// Update machine-CFG edges.
// If this is not a fall-through branch, emit the branch.
if (Default != NextBlock)
DAG.setRoot(DAG.getNode(ISD::BR, MVT::Other, getRoot(),
DAG.getBasicBlock(Default)));
CurMBB->addSuccessor(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.
std::vector<Case> Cases;
for (unsigned i = 1; i < I.getNumSuccessors(); ++i) {
MachineBasicBlock *SMBB = FuncInfo.MBBMap[I.getSuccessor(i)];
Cases.push_back(Case(I.getSuccessorValue(i), SMBB));
}
std::sort(Cases.begin(), Cases.end(), CaseCmp());
// 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.
Value *SV = I.getOperand(0);
// Push the initial CaseRec onto the worklist
CaseRecVector WorkList;
WorkList.push_back(CaseRec(CurMBB,0,0,CaseRange(Cases.begin(),Cases.end())));
while (!WorkList.empty()) {
// Grab a record representing a case range to process off the worklist
CaseRec CR = WorkList.back();
WorkList.pop_back();
Case& FrontCase = *CR.Range.first;
Case& BackCase = *(CR.Range.second-1);
// Figure out which block is immediately after the current one.
NextBlock = 0;
BBI = CR.CaseBB;
if (++BBI != CurMBB->getParent()->end())
NextBlock = BBI;
// Size is the number of Cases represented by this range.
unsigned Size = CR.Range.second - CR.Range.first;
// If the range has few cases (two or less) emit a series of specific
// tests.
if (Size < 3) {
handleSmallSwitchRange(CR, WorkList, SV, Default);
continue;
}
// If the switch has more than 5 blocks, and at least 31.25% dense, and the
// target supports indirect branches, then emit a jump table rather than
// lowering the switch to a binary tree of conditional branches.
if ((TLI.isOperationLegal(ISD::BR_JT, MVT::Other) ||
TLI.isOperationLegal(ISD::BRIND, MVT::Other)) &&
Size > 5) {
uint64_t First = cast<ConstantInt>(FrontCase.first)->getSExtValue();
uint64_t Last = cast<ConstantInt>(BackCase.first)->getSExtValue();
double Density = (double)Size / (double)((Last - First) + 1ULL);
if (Density >= 0.3125) {
handleJTSwitchCase(CR, WorkList, SV, Default);
continue;
}
}
// Emit binary tree. If Size is 1, then we are processing a leaf of the
// binary search tree. Otherwise, we need to pick a pivot, and push left
// and right ranges onto the worklist.
if (Size == 1)
handleBTSmallSwitchCase(CR, WorkList, SV, Default);
else
handleBTSplitSwitchCase(CR, WorkList, SV, Default);
}
}