mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-07 12:28:24 +00:00
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:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user