void SelectionDAGLowering::visitSwitchCase(CaseBlock &CB) {
SDValue Cond;
SDValue CondLHS = getValue(CB.CmpLHS);
void SelectionDAGLowering::visitSwitchCase(CaseBlock &CB) {
SDValue Cond;
SDValue CondLHS = getValue(CB.CmpLHS);
-
- // Build the setcc now.
+
+ // Build the setcc now.
if (CB.CmpMHS == NULL) {
// Fold "(X == true)" to X and "(X == false)" to !X to
// handle common cases produced by branch lowering.
if (CB.CmpMHS == NULL) {
// Fold "(X == true)" to X and "(X == false)" to !X to
// handle common cases produced by branch lowering.
} else {
assert(CB.CC == ISD::SETLE && "Can handle only LE ranges now");
} else {
assert(CB.CC == ISD::SETLE && "Can handle only LE ranges now");
- uint64_t Low = cast<ConstantInt>(CB.CmpLHS)->getSExtValue();
- uint64_t High = cast<ConstantInt>(CB.CmpRHS)->getSExtValue();
+ const APInt& Low = cast<ConstantInt>(CB.CmpLHS)->getValue();
+ const APInt& High = cast<ConstantInt>(CB.CmpRHS)->getValue();
SDValue CmpOp = getValue(CB.CmpMHS);
MVT VT = CmpOp.getValueType();
SDValue CmpOp = getValue(CB.CmpMHS);
MVT VT = CmpOp.getValueType();
DAG.getConstant(High-Low, VT), ISD::SETULE);
}
}
DAG.getConstant(High-Low, VT), ISD::SETULE);
}
}
// Update successor info
CurMBB->addSuccessor(CB.TrueBB);
CurMBB->addSuccessor(CB.FalseBB);
// Update successor info
CurMBB->addSuccessor(CB.TrueBB);
CurMBB->addSuccessor(CB.FalseBB);
// Set NextBlock to be the MBB immediately after the current one, if any.
// This is used to avoid emitting unnecessary branches to the next block.
MachineBasicBlock *NextBlock = 0;
MachineFunction::iterator BBI = CurMBB;
if (++BBI != CurMBB->getParent()->end())
NextBlock = BBI;
// Set NextBlock to be the MBB immediately after the current one, if any.
// This is used to avoid emitting unnecessary branches to the next block.
MachineBasicBlock *NextBlock = 0;
MachineFunction::iterator BBI = CurMBB;
if (++BBI != CurMBB->getParent()->end())
NextBlock = BBI;
// If the lhs block is the next block, invert the condition so that we can
// fall through to the lhs instead of the rhs block.
if (CB.TrueBB == NextBlock) {
// If the lhs block is the next block, invert the condition so that we can
// fall through to the lhs instead of the rhs block.
if (CB.TrueBB == NextBlock) {
}
SDValue BrCond = DAG.getNode(ISD::BRCOND, MVT::Other, getControlRoot(), Cond,
DAG.getBasicBlock(CB.TrueBB));
}
SDValue BrCond = DAG.getNode(ISD::BRCOND, MVT::Other, getControlRoot(), Cond,
DAG.getBasicBlock(CB.TrueBB));
// If the branch was constant folded, fix up the CFG.
if (BrCond.getOpcode() == ISD::BR) {
CurMBB->removeSuccessor(CB.FalseBB);
DAG.setRoot(BrCond);
} else {
// Otherwise, go ahead and insert the false branch.
// If the branch was constant folded, fix up the CFG.
if (BrCond.getOpcode() == ISD::BR) {
CurMBB->removeSuccessor(CB.FalseBB);
DAG.setRoot(BrCond);
} else {
// Otherwise, go ahead and insert the false branch.
- if (BrCond == getControlRoot())
+ if (BrCond == getControlRoot())
CurMBB->removeSuccessor(CB.TrueBB);
CurMBB->removeSuccessor(CB.TrueBB);
if (CB.FalseBB == NextBlock)
DAG.setRoot(BrCond);
else
if (CB.FalseBB == NextBlock)
DAG.setRoot(BrCond);
else
- DAG.setRoot(DAG.getNode(ISD::BR, MVT::Other, BrCond,
+ DAG.setRoot(DAG.getNode(ISD::BR, MVT::Other, BrCond,
DAG.getBasicBlock(CB.FalseBB)));
}
}
DAG.getBasicBlock(CB.FalseBB)));
}
}
MVT VT = SwitchOp.getValueType();
SDValue SUB = DAG.getNode(ISD::SUB, VT, SwitchOp,
DAG.getConstant(JTH.First, VT));
MVT VT = SwitchOp.getValueType();
SDValue SUB = DAG.getNode(ISD::SUB, VT, SwitchOp,
DAG.getConstant(JTH.First, VT));
// The SDNode we just created, which holds the value being switched on
// minus the the smallest case value, needs to be copied to a virtual
// register so it can be used as an index into the jump table in a
// The SDNode we just created, which holds the value being switched on
// minus the the smallest case value, needs to be copied to a virtual
// register so it can be used as an index into the jump table in a
SwitchOp = DAG.getNode(ISD::TRUNCATE, TLI.getPointerTy(), SUB);
else
SwitchOp = DAG.getNode(ISD::ZERO_EXTEND, TLI.getPointerTy(), SUB);
SwitchOp = DAG.getNode(ISD::TRUNCATE, TLI.getPointerTy(), SUB);
else
SwitchOp = DAG.getNode(ISD::ZERO_EXTEND, TLI.getPointerTy(), SUB);
unsigned JumpTableReg = FuncInfo.MakeReg(TLI.getPointerTy());
SDValue CopyTo = DAG.getCopyToReg(getControlRoot(), JumpTableReg, SwitchOp);
JT.Reg = JumpTableReg;
unsigned JumpTableReg = FuncInfo.MakeReg(TLI.getPointerTy());
SDValue CopyTo = DAG.getCopyToReg(getControlRoot(), JumpTableReg, SwitchOp);
JT.Reg = JumpTableReg;
SDValue BrRange = DAG.getNode(ISD::BRCOND, MVT::Other, CopyTo, RangeCmp,
DAG.getBasicBlock(B.Default));
SDValue BrRange = DAG.getNode(ISD::BRCOND, MVT::Other, CopyTo, RangeCmp,
DAG.getBasicBlock(B.Default));
if (MBB == NextBlock)
DAG.setRoot(BrRange);
else
if (MBB == NextBlock)
DAG.setRoot(BrRange);
else
unsigned Reg,
BitTestCase &B) {
// Emit bit tests and jumps
unsigned Reg,
BitTestCase &B) {
// Emit bit tests and jumps
- SDValue SwitchVal = DAG.getCopyFromReg(getControlRoot(), Reg,
+ SDValue SwitchVal = DAG.getCopyFromReg(getControlRoot(), Reg,
SDValue AndOp = DAG.getNode(ISD::AND, TLI.getPointerTy(), SwitchVal,
DAG.getConstant(B.Mask, TLI.getPointerTy()));
SDValue AndCmp = DAG.getSetCC(TLI.getSetCCResultType(AndOp), AndOp,
SDValue AndOp = DAG.getNode(ISD::AND, TLI.getPointerTy(), SwitchVal,
DAG.getConstant(B.Mask, TLI.getPointerTy()));
SDValue AndCmp = DAG.getSetCC(TLI.getSetCCResultType(AndOp), AndOp,
CurMBB->addSuccessor(B.TargetBB);
CurMBB->addSuccessor(NextMBB);
CurMBB->addSuccessor(B.TargetBB);
CurMBB->addSuccessor(NextMBB);
SDValue BrAnd = DAG.getNode(ISD::BRCOND, MVT::Other, getControlRoot(),
AndCmp, DAG.getBasicBlock(B.TargetBB));
SDValue BrAnd = DAG.getNode(ISD::BRCOND, MVT::Other, getControlRoot(),
AndCmp, DAG.getBasicBlock(B.TargetBB));
Value* SV,
MachineBasicBlock* Default) {
Case& BackCase = *(CR.Range.second-1);
Value* SV,
MachineBasicBlock* Default) {
Case& BackCase = *(CR.Range.second-1);
// Size is the number of Cases represented by this range.
// Size is the number of Cases represented by this range.
- unsigned Size = CR.Range.second - CR.Range.first;
+ size_t Size = CR.Range.second - CR.Range.first;
// Get the MachineFunction which holds the current MBB. This is used when
// inserting any additional MBBs necessary to represent the switch.
// 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();
+ MachineFunction *CurMF = CurMBB->getParent();
// Figure out which block is immediately after the current one.
MachineBasicBlock *NextBlock = 0;
// Figure out which block is immediately after the current one.
MachineBasicBlock *NextBlock = 0;
// 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:
// "if (X == 6 || X == 4)" -> "if ((X|2) == 6)"
// 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:
// "if (X == 6 || X == 4)" -> "if ((X|2) == 6)"
// Rearrange the case blocks so that the last one falls through if possible.
if (NextBlock && Default != NextBlock && BackCase.BB != NextBlock) {
// The last case block won't fall through into 'NextBlock' if we emit the
// Rearrange the case blocks so that the last one falls through if possible.
if (NextBlock && Default != NextBlock && BackCase.BB != NextBlock) {
// The last case block won't fall through into 'NextBlock' if we emit the
// 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.
// 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.
LHS = I->Low; MHS = SV; RHS = I->High;
}
CaseBlock CB(CC, LHS, RHS, MHS, I->BB, FallThrough, CurBlock);
LHS = I->Low; MHS = SV; RHS = I->High;
}
CaseBlock CB(CC, LHS, RHS, MHS, I->BB, FallThrough, CurBlock);
// If emitting the first comparison, just call visitSwitchCase to emit the
// code into the current block. Otherwise, push the CaseBlock onto the
// vector to be later processed by SDISel, and insert the node's MBB
// If emitting the first comparison, just call visitSwitchCase to emit the
// code into the current block. Otherwise, push the CaseBlock onto the
// vector to be later processed by SDISel, and insert the node's MBB
visitSwitchCase(CB);
else
SwitchCases.push_back(CB);
visitSwitchCase(CB);
else
SwitchCases.push_back(CB);
CurBlock = FallThrough;
}
CurBlock = FallThrough;
}
(TLI.isOperationLegal(ISD::BR_JT, MVT::Other) ||
TLI.isOperationLegal(ISD::BRIND, MVT::Other));
}
(TLI.isOperationLegal(ISD::BR_JT, MVT::Other) ||
TLI.isOperationLegal(ISD::BRIND, MVT::Other));
}
/// handleJTSwitchCase - Emit jumptable for current switch case range
bool SelectionDAGLowering::handleJTSwitchCase(CaseRec& CR,
CaseRecVector& WorkList,
/// handleJTSwitchCase - Emit jumptable for current switch case range
bool SelectionDAGLowering::handleJTSwitchCase(CaseRec& CR,
CaseRecVector& WorkList,
Case& FrontCase = *CR.Range.first;
Case& BackCase = *(CR.Range.second-1);
Case& FrontCase = *CR.Range.first;
Case& BackCase = *(CR.Range.second-1);
- int64_t First = cast<ConstantInt>(FrontCase.Low)->getSExtValue();
- int64_t Last = cast<ConstantInt>(BackCase.High)->getSExtValue();
+ const APInt& First = cast<ConstantInt>(FrontCase.Low)->getValue();
+ const APInt& Last = cast<ConstantInt>(BackCase.High)->getValue();
for (CaseItr I = CR.Range.first, E = CR.Range.second;
I!=E; ++I)
TSize += I->size();
if (!areJTsAllowed(TLI) || TSize <= 3)
return false;
for (CaseItr I = CR.Range.first, E = CR.Range.second;
I!=E; ++I)
TSize += I->size();
if (!areJTsAllowed(TLI) || TSize <= 3)
return false;
-
- double Density = (double)TSize / (double)((Last - First) + 1ULL);
+
+ APInt Range = Last - First + 1ULL;
+ double Density = (double)TSize / Range.roundToDouble();
if (Density < 0.4)
return false;
if (Density < 0.4)
return false;
- DOUT << "Lowering jump table\n"
+ /*DOUT << "Lowering jump table\n"
<< "First entry: " << First << ". Last entry: " << Last << "\n"
<< "First entry: " << First << ". Last entry: " << Last << "\n"
- << "Size: " << TSize << ". Density: " << Density << "\n\n";
+ << "Size: " << TSize << ". Density: " << Density << "\n\n";*/
// Get the MachineFunction which holds the current MBB. This is used when
// inserting any additional MBBs necessary to represent the switch.
// Get the MachineFunction which holds the current MBB. This is used when
// inserting any additional MBBs necessary to represent the switch.
CurMF->insert(BBI, JumpTableBB);
CR.CaseBB->addSuccessor(Default);
CR.CaseBB->addSuccessor(JumpTableBB);
CurMF->insert(BBI, JumpTableBB);
CR.CaseBB->addSuccessor(Default);
CR.CaseBB->addSuccessor(JumpTableBB);
// Build a vector of destination BBs, corresponding to each target
// of the jump table. If the value of the jump table slot corresponds to
// a case statement, push the case's BB onto the vector, otherwise, push
// the default BB.
std::vector<MachineBasicBlock*> DestBBs;
// Build a vector of destination BBs, corresponding to each target
// of the jump table. If the value of the jump table slot corresponds to
// a case statement, push the case's BB onto the vector, otherwise, push
// the default BB.
std::vector<MachineBasicBlock*> DestBBs;
for (CaseItr I = CR.Range.first, E = CR.Range.second; I != E; ++TEI) {
for (CaseItr I = CR.Range.first, E = CR.Range.second; I != E; ++TEI) {
- int64_t Low = cast<ConstantInt>(I->Low)->getSExtValue();
- int64_t High = cast<ConstantInt>(I->High)->getSExtValue();
-
- if ((Low <= TEI) && (TEI <= High)) {
+ const APInt& Low = cast<ConstantInt>(I->Low)->getValue();
+ const APInt& High = cast<ConstantInt>(I->High)->getValue();
+
+ if (Low.sle(TEI) && TEI.sle(High)) {
DestBBs.push_back(I->BB);
if (TEI==High)
++I;
DestBBs.push_back(I->BB);
if (TEI==High)
++I;
DestBBs.push_back(Default);
}
}
DestBBs.push_back(Default);
}
}
// Update successor info. Add one edge to each unique successor.
// Update successor info. Add one edge to each unique successor.
- BitVector SuccsHandled(CR.CaseBB->getParent()->getNumBlockIDs());
- for (std::vector<MachineBasicBlock*>::iterator I = DestBBs.begin(),
+ BitVector SuccsHandled(CR.CaseBB->getParent()->getNumBlockIDs());
+ for (std::vector<MachineBasicBlock*>::iterator I = DestBBs.begin(),
E = DestBBs.end(); I != E; ++I) {
if (!SuccsHandled[(*I)->getNumber()]) {
SuccsHandled[(*I)->getNumber()] = true;
JumpTableBB->addSuccessor(*I);
}
}
E = DestBBs.end(); I != E; ++I) {
if (!SuccsHandled[(*I)->getNumber()]) {
SuccsHandled[(*I)->getNumber()] = true;
JumpTableBB->addSuccessor(*I);
}
}
// Create a jump table index for this jump table, or return an existing
// one.
unsigned JTI = CurMF->getJumpTableInfo()->getJumpTableIndex(DestBBs);
// Create a jump table index for this jump table, or return an existing
// one.
unsigned JTI = CurMF->getJumpTableInfo()->getJumpTableIndex(DestBBs);
// Set the jump table information so that we can codegen it as a second
// MachineBasicBlock
JumpTable JT(-1U, JTI, JumpTableBB, Default);
JumpTableHeader JTH(First, Last, SV, CR.CaseBB, (CR.CaseBB == CurMBB));
if (CR.CaseBB == CurMBB)
visitJumpTableHeader(JT, JTH);
// Set the jump table information so that we can codegen it as a second
// MachineBasicBlock
JumpTable JT(-1U, JTI, JumpTableBB, Default);
JumpTableHeader JTH(First, Last, SV, CR.CaseBB, (CR.CaseBB == CurMBB));
if (CR.CaseBB == CurMBB)
visitJumpTableHeader(JT, JTH);
JTCases.push_back(JumpTableBlock(JTH, JT));
return true;
JTCases.push_back(JumpTableBlock(JTH, JT));
return true;
MachineBasicBlock* Default) {
// Get the MachineFunction which holds the current MBB. This is used when
// inserting any additional MBBs necessary to represent the switch.
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();
+ MachineFunction *CurMF = CurMBB->getParent();
// Figure out which block is immediately after the current one.
MachineBasicBlock *NextBlock = 0;
// Figure out which block is immediately after the current one.
MachineBasicBlock *NextBlock = 0;
// Size is the number of Cases represented by this range.
unsigned Size = CR.Range.second - CR.Range.first;
// Size is the number of Cases represented by this range.
unsigned Size = CR.Range.second - CR.Range.first;
- int64_t First = cast<ConstantInt>(FrontCase.Low)->getSExtValue();
- int64_t Last = cast<ConstantInt>(BackCase.High)->getSExtValue();
+ const APInt& First = cast<ConstantInt>(FrontCase.Low)->getValue();
+ const APInt& Last = cast<ConstantInt>(BackCase.High)->getValue();
double FMetric = 0;
CaseItr Pivot = CR.Range.first + Size/2;
// Select optimal pivot, maximizing sum density of LHS and RHS. This will
// (heuristically) allow us to emit JumpTable's later.
double FMetric = 0;
CaseItr Pivot = CR.Range.first + Size/2;
// Select optimal pivot, maximizing sum density of LHS and RHS. This will
// (heuristically) allow us to emit JumpTable's later.
for (CaseItr I = CR.Range.first, E = CR.Range.second;
I!=E; ++I)
TSize += I->size();
for (CaseItr I = CR.Range.first, E = CR.Range.second;
I!=E; ++I)
TSize += I->size();
- uint64_t LSize = FrontCase.size();
- uint64_t RSize = TSize-LSize;
- DOUT << "Selecting best pivot: \n"
+ size_t LSize = FrontCase.size();
+ size_t RSize = TSize-LSize;
+ /*DOUT << "Selecting best pivot: \n"
<< "First: " << First << ", Last: " << Last <<"\n"
<< "First: " << First << ", Last: " << Last <<"\n"
- << "LSize: " << LSize << ", RSize: " << RSize << "\n";
+ << "LSize: " << LSize << ", RSize: " << RSize << "\n";*/
for (CaseItr I = CR.Range.first, J=I+1, E = CR.Range.second;
J!=E; ++I, ++J) {
for (CaseItr I = CR.Range.first, J=I+1, E = CR.Range.second;
J!=E; ++I, ++J) {
- int64_t LEnd = cast<ConstantInt>(I->High)->getSExtValue();
- int64_t RBegin = cast<ConstantInt>(J->Low)->getSExtValue();
- assert((RBegin-LEnd>=1) && "Invalid case distance");
- double LDensity = (double)LSize / (double)((LEnd - First) + 1ULL);
- double RDensity = (double)RSize / (double)((Last - RBegin) + 1ULL);
- double Metric = Log2_64(RBegin-LEnd)*(LDensity+RDensity);
+ const APInt& LEnd = cast<ConstantInt>(I->High)->getValue();
+ const APInt& RBegin = cast<ConstantInt>(J->Low)->getValue();
+ assert((RBegin - LEnd - 1).isNonNegative() && "Invalid case distance");
+ double LDensity = (double)LSize / (LEnd - First + 1ULL).roundToDouble();
+ double RDensity = (double)RSize / (Last - RBegin + 1ULL).roundToDouble();
+ double Metric = (RBegin-LEnd).logBase2()*(LDensity+RDensity);
// Should always split in some non-trivial place
// Should always split in some non-trivial place
<< "LEnd: " << LEnd << ", RBegin: " << RBegin << "\n"
<< "LDensity: " << LDensity << ", RDensity: " << RDensity << "\n"
<< "LEnd: " << LEnd << ", RBegin: " << RBegin << "\n"
<< "LDensity: " << LDensity << ", RDensity: " << RDensity << "\n"
- << "Metric: " << Metric << "\n";
+ << "Metric: " << Metric << "\n";*/
if (FMetric < Metric) {
Pivot = J;
FMetric = Metric;
if (FMetric < Metric) {
Pivot = J;
FMetric = Metric;
} else {
Pivot = CR.Range.first + Size/2;
}
} else {
Pivot = CR.Range.first + Size/2;
}
CaseRange LHSR(CR.Range.first, Pivot);
CaseRange RHSR(Pivot, CR.Range.second);
Constant *C = Pivot->Low;
MachineBasicBlock *FalseBB = 0, *TrueBB = 0;
CaseRange LHSR(CR.Range.first, Pivot);
CaseRange RHSR(Pivot, CR.Range.second);
Constant *C = Pivot->Low;
MachineBasicBlock *FalseBB = 0, *TrueBB = 0;
// We know that we branch to the LHS if the Value being switched on is
// less than the Pivot value, C. We use this to optimize our binary
// tree a bit, by recognizing that if SV is greater than or equal to the
// We know that we branch to the LHS if the Value being switched on is
// less than the Pivot value, C. We use this to optimize our binary
// tree a bit, by recognizing that if SV is greater than or equal to the
// rather than creating a leaf node for it.
if ((LHSR.second - LHSR.first) == 1 &&
LHSR.first->High == CR.GE &&
// rather than creating a leaf node for it.
if ((LHSR.second - LHSR.first) == 1 &&
LHSR.first->High == CR.GE &&
- cast<ConstantInt>(C)->getSExtValue() ==
- (cast<ConstantInt>(CR.GE)->getSExtValue() + 1LL)) {
+ cast<ConstantInt>(C)->getValue() ==
+ (cast<ConstantInt>(CR.GE)->getValue() + 1LL)) {
TrueBB = LHSR.first->BB;
} else {
TrueBB = CurMF->CreateMachineBasicBlock(LLVMBB);
CurMF->insert(BBI, TrueBB);
WorkList.push_back(CaseRec(TrueBB, C, CR.GE, LHSR));
}
TrueBB = LHSR.first->BB;
} else {
TrueBB = CurMF->CreateMachineBasicBlock(LLVMBB);
CurMF->insert(BBI, TrueBB);
WorkList.push_back(CaseRec(TrueBB, C, CR.GE, LHSR));
}
// Similar to the optimization above, if the Value being switched on is
// known to be less than the Constant CR.LT, and the current Case Value
// is CR.LT - 1, then we can branch directly to the target block for
// the current Case Value, rather than emitting a RHS leaf node for it.
if ((RHSR.second - RHSR.first) == 1 && CR.LT &&
// Similar to the optimization above, if the Value being switched on is
// known to be less than the Constant CR.LT, and the current Case Value
// is CR.LT - 1, then we can branch directly to the target block for
// the current Case Value, rather than emitting a RHS leaf node for it.
if ((RHSR.second - RHSR.first) == 1 && CR.LT &&
- cast<ConstantInt>(RHSR.first->Low)->getSExtValue() ==
- (cast<ConstantInt>(CR.LT)->getSExtValue() - 1LL)) {
+ cast<ConstantInt>(RHSR.first->Low)->getValue() ==
+ (cast<ConstantInt>(CR.LT)->getValue() - 1LL)) {
FalseBB = RHSR.first->BB;
} else {
FalseBB = CurMF->CreateMachineBasicBlock(LLVMBB);
FalseBB = RHSR.first->BB;
} else {
FalseBB = CurMF->CreateMachineBasicBlock(LLVMBB);
// Get the MachineFunction which holds the current MBB. This is used when
// inserting any additional MBBs necessary to represent the switch.
// 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();
+ MachineFunction *CurMF = CurMBB->getParent();
for (CaseItr I = CR.Range.first, E = CR.Range.second;
I!=E; ++I) {
// Single case counts one, case range - two.
for (CaseItr I = CR.Range.first, E = CR.Range.second;
I!=E; ++I) {
// Single case counts one, case range - two.
- if (I->Low == I->High)
- numCmps +=1;
- else
- numCmps +=2;
+ numCmps += (I->Low == I->High ? 1 : 2);
// Count unique destinations
SmallSet<MachineBasicBlock*, 4> Dests;
for (CaseItr I = CR.Range.first, E = CR.Range.second; I!=E; ++I) {
// Count unique destinations
SmallSet<MachineBasicBlock*, 4> Dests;
for (CaseItr I = CR.Range.first, E = CR.Range.second; I!=E; ++I) {
}
DOUT << "Total number of unique destinations: " << Dests.size() << "\n"
<< "Total number of comparisons: " << numCmps << "\n";
}
DOUT << "Total number of unique destinations: " << Dests.size() << "\n"
<< "Total number of comparisons: " << numCmps << "\n";
// Compute span of values.
// Compute span of values.
- Constant* minValue = FrontCase.Low;
- Constant* maxValue = BackCase.High;
- uint64_t range = cast<ConstantInt>(maxValue)->getSExtValue() -
- cast<ConstantInt>(minValue)->getSExtValue();
- DOUT << "Compare range: " << range << "\n"
- << "Low bound: " << cast<ConstantInt>(minValue)->getSExtValue() << "\n"
- << "High bound: " << cast<ConstantInt>(maxValue)->getSExtValue() << "\n";
-
- if (range>=IntPtrBits ||
+ const APInt& minValue = cast<ConstantInt>(FrontCase.Low)->getValue();
+ const APInt& maxValue = cast<ConstantInt>(BackCase.High)->getValue();
+ APInt cmpRange = maxValue - minValue;
+ /*DOUT << "Compare range: " << Range << "\n"
+ << "Low bound: " << cast<ConstantInt>(minValue)->getValue() << "\n"
+ << "High bound: " << cast<ConstantInt>(maxValue)->getValue() << "\n";*/
+
+ if (cmpRange.uge(APInt(cmpRange.getBitWidth(), IntPtrBits)) ||
(!(Dests.size() == 1 && numCmps >= 3) &&
!(Dests.size() == 2 && numCmps >= 5) &&
!(Dests.size() >= 3 && numCmps >= 6)))
return false;
(!(Dests.size() == 1 && numCmps >= 3) &&
!(Dests.size() == 2 && numCmps >= 5) &&
!(Dests.size() >= 3 && numCmps >= 6)))
return false;
DOUT << "Emitting bit tests\n";
DOUT << "Emitting bit tests\n";
- int64_t lowBound = 0;
-
+ APInt lowBound = APInt::getNullValue(cmpRange.getBitWidth());
+
// Optimize the case where all the case values fit in a
// word without having to subtract minValue. In this case,
// we can optimize away the subtraction.
// Optimize the case where all the case values fit in a
// word without having to subtract minValue. In this case,
// we can optimize away the subtraction.
- if (cast<ConstantInt>(minValue)->getSExtValue() >= 0 &&
- cast<ConstantInt>(maxValue)->getSExtValue() < IntPtrBits) {
- range = cast<ConstantInt>(maxValue)->getSExtValue();
+ if (minValue.isNonNegative() &&
+ maxValue.slt(APInt(maxValue.getBitWidth(), IntPtrBits))) {
+ cmpRange = maxValue;
- lowBound = cast<ConstantInt>(minValue)->getSExtValue();
CaseBitsVector CasesBits;
unsigned i, count = 0;
CaseBitsVector CasesBits;
unsigned i, count = 0;
for (i = 0; i < count; ++i)
if (Dest == CasesBits[i].BB)
break;
for (i = 0; i < count; ++i)
if (Dest == CasesBits[i].BB)
break;
if (i == count) {
assert((count < 3) && "Too much destinations to test!");
CasesBits.push_back(CaseBits(0, Dest, 0));
count++;
}
if (i == count) {
assert((count < 3) && "Too much destinations to test!");
CasesBits.push_back(CaseBits(0, Dest, 0));
count++;
}
-
- uint64_t lo = cast<ConstantInt>(I->Low)->getSExtValue() - lowBound;
- uint64_t hi = cast<ConstantInt>(I->High)->getSExtValue() - lowBound;
-
+
+ const APInt& lowValue = cast<ConstantInt>(I->Low)->getValue();
+ const APInt& highValue = cast<ConstantInt>(I->High)->getValue();
+
+ uint64_t lo = (lowValue - lowBound).getZExtValue();
+ uint64_t hi = (highValue - lowBound).getZExtValue();
+
for (uint64_t j = lo; j <= hi; j++) {
CasesBits[i].Mask |= 1ULL << j;
CasesBits[i].Bits++;
}
for (uint64_t j = lo; j <= hi; j++) {
CasesBits[i].Mask |= 1ULL << j;
CasesBits[i].Bits++;
}
}
std::sort(CasesBits.begin(), CasesBits.end(), CaseBitsCmp());
}
std::sort(CasesBits.begin(), CasesBits.end(), CaseBitsCmp());
BitTestInfo BTC;
// Figure out which block is immediately after the current one.
BitTestInfo BTC;
// Figure out which block is immediately after the current one.
CaseBB,
CasesBits[i].BB));
}
CaseBB,
CasesBits[i].BB));
}
-
- BitTestBlock BTB(lowBound, range, SV,
+
+ BitTestBlock BTB(lowBound, cmpRange, SV,
-1U, (CR.CaseBB == CurMBB),
CR.CaseBB, Default, BTC);
if (CR.CaseBB == CurMBB)
visitBitTestHeader(BTB);
-1U, (CR.CaseBB == CurMBB),
CR.CaseBB, Default, BTC);
if (CR.CaseBB == CurMBB)
visitBitTestHeader(BTB);
BitTestCases.push_back(BTB);
return true;
BitTestCases.push_back(BTB);
return true;
/// Clusterify - Transform simple list of Cases into list of CaseRange's
/// Clusterify - Transform simple list of Cases into list of CaseRange's
-unsigned SelectionDAGLowering::Clusterify(CaseVector& Cases,
+size_t SelectionDAGLowering::Clusterify(CaseVector& Cases,
// Start with "simple" cases
// Start with "simple" cases
- for (unsigned i = 1; i < SI.getNumSuccessors(); ++i) {
+ for (size_t i = 1; i < SI.getNumSuccessors(); ++i) {
MachineBasicBlock *SMBB = FuncInfo.MBBMap[SI.getSuccessor(i)];
Cases.push_back(Case(SI.getSuccessorValue(i),
SI.getSuccessorValue(i),
MachineBasicBlock *SMBB = FuncInfo.MBBMap[SI.getSuccessor(i)];
Cases.push_back(Case(SI.getSuccessorValue(i),
SI.getSuccessorValue(i),
std::sort(Cases.begin(), Cases.end(), CaseCmp());
// Merge case into clusters
std::sort(Cases.begin(), Cases.end(), CaseCmp());
// Merge case into clusters
// Must recompute end() each iteration because it may be
// invalidated by erase if we hold on to it
// Must recompute end() each iteration because it may be
// invalidated by erase if we hold on to it
- for (CaseItr I=Cases.begin(), J=++(Cases.begin()); J!=Cases.end(); ) {
- int64_t nextValue = cast<ConstantInt>(J->Low)->getSExtValue();
- int64_t currentValue = cast<ConstantInt>(I->High)->getSExtValue();
+ for (CaseItr I = Cases.begin(), J = ++(Cases.begin()); J != Cases.end(); ) {
+ const APInt& nextValue = cast<ConstantInt>(J->Low)->getValue();
+ const APInt& currentValue = cast<ConstantInt>(I->High)->getValue();
MachineBasicBlock* nextBB = J->BB;
MachineBasicBlock* currentBB = I->BB;
// If the two neighboring cases go to the same destination, merge them
// into a single case.
MachineBasicBlock* nextBB = J->BB;
MachineBasicBlock* currentBB = I->BB;
// If the two neighboring cases go to the same destination, merge them
// into a single case.
- if ((nextValue-currentValue==1) && (currentBB == nextBB)) {
+ if ((nextValue - currentValue == 1) && (currentBB == nextBB)) {
I->High = J->High;
J = Cases.erase(J);
} else {
I->High = J->High;
J = Cases.erase(J);
} else {
-void SelectionDAGLowering::visitSwitch(SwitchInst &SI) {
+void SelectionDAGLowering::visitSwitch(SwitchInst &SI) {
// Figure out which block is immediately after the current one.
MachineBasicBlock *NextBlock = 0;
MachineFunction::iterator BBI = CurMBB;
// Figure out which block is immediately after the current one.
MachineBasicBlock *NextBlock = 0;
MachineFunction::iterator BBI = CurMBB;
if (Default != NextBlock)
DAG.setRoot(DAG.getNode(ISD::BR, MVT::Other, getControlRoot(),
DAG.getBasicBlock(Default)));
if (Default != NextBlock)
DAG.setRoot(DAG.getNode(ISD::BR, MVT::Other, getControlRoot(),
DAG.getBasicBlock(Default)));
// 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;
// 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;
- unsigned numCmps = Clusterify(Cases, SI);
+ size_t numCmps = Clusterify(Cases, SI);
DOUT << "Clusterify finished. Total clusters: " << Cases.size()
<< ". Total compares: " << numCmps << "\n";
DOUT << "Clusterify finished. Total clusters: " << Cases.size()
<< ". Total compares: " << numCmps << "\n";
if (handleBitTestsSwitchCase(CR, WorkList, SV, Default))
continue;
if (handleBitTestsSwitchCase(CR, WorkList, SV, Default))
continue;
// If the range has few cases (two or less) emit a series of specific
// tests.
if (handleSmallSwitchRange(CR, WorkList, SV, Default))
continue;
// If the range has few cases (two or less) emit a series of specific
// tests.
if (handleSmallSwitchRange(CR, WorkList, SV, Default))
continue;
// If the switch has more than 5 blocks, and at least 40% 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 (handleJTSwitchCase(CR, WorkList, SV, Default))
continue;
// If the switch has more than 5 blocks, and at least 40% 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 (handleJTSwitchCase(CR, WorkList, SV, Default))
continue;
// Emit binary tree. We need to pick a pivot, and push left and right ranges
// onto the worklist. Leafs are handled via handleSmallSwitchRange() call.
handleBTSplitSwitchCase(CR, WorkList, SV, Default);
// Emit binary tree. We need to pick a pivot, and push left and right ranges
// onto the worklist. Leafs are handled via handleSmallSwitchRange() call.
handleBTSplitSwitchCase(CR, WorkList, SV, Default);
- unsigned Clusterify(CaseVector& Cases, const SwitchInst &SI);
-
+ size_t Clusterify(CaseVector& Cases, const SwitchInst &SI);
+
/// CaseBlock - This structure is used to communicate between SDLowering and
/// SDISel for the code generation of additional basic blocks needed by multi-
/// case switch statements.
/// CaseBlock - This structure is used to communicate between SDLowering and
/// SDISel for the code generation of additional basic blocks needed by multi-
/// case switch statements.
MachineBasicBlock *Default;
};
struct JumpTableHeader {
MachineBasicBlock *Default;
};
struct JumpTableHeader {
- JumpTableHeader(uint64_t F, uint64_t L, Value* SV, MachineBasicBlock* H,
+ JumpTableHeader(APInt F, APInt L, Value* SV, MachineBasicBlock* H,
bool E = false):
First(F), Last(L), SValue(SV), HeaderBB(H), Emitted(E) {}
bool E = false):
First(F), Last(L), SValue(SV), HeaderBB(H), Emitted(E) {}
- uint64_t First;
- uint64_t Last;
+ APInt First;
+ APInt Last;
Value *SValue;
MachineBasicBlock *HeaderBB;
bool Emitted;
Value *SValue;
MachineBasicBlock *HeaderBB;
bool Emitted;
typedef SmallVector<BitTestCase, 3> BitTestInfo;
struct BitTestBlock {
typedef SmallVector<BitTestCase, 3> BitTestInfo;
struct BitTestBlock {
- BitTestBlock(uint64_t F, uint64_t R, Value* SV,
+ BitTestBlock(APInt F, APInt R, Value* SV,
unsigned Rg, bool E,
MachineBasicBlock* P, MachineBasicBlock* D,
const BitTestInfo& C):
First(F), Range(R), SValue(SV), Reg(Rg), Emitted(E),
Parent(P), Default(D), Cases(C) { }
unsigned Rg, bool E,
MachineBasicBlock* P, MachineBasicBlock* D,
const BitTestInfo& C):
First(F), Range(R), SValue(SV), Reg(Rg), Emitted(E),
Parent(P), Default(D), Cases(C) { }
- uint64_t First;
- uint64_t Range;
+ APInt First;
+ APInt Range;
Value *SValue;
unsigned Reg;
bool Emitted;
Value *SValue;
unsigned Reg;
bool Emitted;