Fix CodeGen/Generic/2006-09-06-SwitchLowering.ll, a bug where SDIsel inserted

too many phi operands when lowering a switch to branches in some cases.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@30142 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2006-09-07 01:59:34 +00:00
parent 5aa0307315
commit d5e93c0795

View File

@ -922,7 +922,6 @@ void SelectionDAGLowering::visitSwitch(SwitchInst &I) {
// If the switch has more than 5 blocks, and at least 31.25% dense, and the // 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 // target supports indirect branches, then emit a jump table rather than
// lowering the switch to a binary tree of conditional branches. // lowering the switch to a binary tree of conditional branches.
// FIXME: Make this work with PIC code
if (TLI.isOperationLegal(ISD::BRIND, TLI.getPointerTy()) && if (TLI.isOperationLegal(ISD::BRIND, TLI.getPointerTy()) &&
Cases.size() > 5) { Cases.size() > 5) {
uint64_t First = cast<ConstantIntegral>(Cases.front().first)->getRawValue(); uint64_t First = cast<ConstantIntegral>(Cases.front().first)->getRawValue();
@ -3412,12 +3411,14 @@ void SelectionDAGISel::BuildSelectionDAG(SelectionDAG &DAG, BasicBlock *LLVMBB,
// Emit constants only once even if used by multiple PHI nodes. // Emit constants only once even if used by multiple PHI nodes.
std::map<Constant*, unsigned> ConstantsOut; std::map<Constant*, unsigned> ConstantsOut;
// Check successor nodes PHI nodes that expect a constant to be available from // Check successor nodes PHI nodes that expect a constant to be available from
// this block. // this block.
TerminatorInst *TI = LLVMBB->getTerminator(); TerminatorInst *TI = LLVMBB->getTerminator();
for (unsigned succ = 0, e = TI->getNumSuccessors(); succ != e; ++succ) { for (unsigned succ = 0, e = TI->getNumSuccessors(); succ != e; ++succ) {
BasicBlock *SuccBB = TI->getSuccessor(succ); BasicBlock *SuccBB = TI->getSuccessor(succ);
if (!isa<PHINode>(SuccBB->begin())) continue;
MachineBasicBlock::iterator MBBI = FuncInfo.MBBMap[SuccBB]->begin(); MachineBasicBlock::iterator MBBI = FuncInfo.MBBMap[SuccBB]->begin();
PHINode *PN; PHINode *PN;
@ -3589,31 +3590,47 @@ void SelectionDAGISel::SelectBasicBlock(BasicBlock *LLVMBB, MachineFunction &MF,
// If we generated any switch lowering information, build and codegen any // If we generated any switch lowering information, build and codegen any
// additional DAGs necessary. // additional DAGs necessary.
for(unsigned i = 0, e = SwitchCases.size(); i != e; ++i) { for (unsigned i = 0, e = SwitchCases.size(); i != e; ++i) {
SelectionDAG SDAG(TLI, MF, getAnalysisToUpdate<MachineDebugInfo>()); SelectionDAG SDAG(TLI, MF, getAnalysisToUpdate<MachineDebugInfo>());
CurDAG = &SDAG; CurDAG = &SDAG;
SelectionDAGLowering SDL(SDAG, TLI, FuncInfo); SelectionDAGLowering SDL(SDAG, TLI, FuncInfo);
// Set the current basic block to the mbb we wish to insert the code into // Set the current basic block to the mbb we wish to insert the code into
BB = SwitchCases[i].ThisBB; BB = SwitchCases[i].ThisBB;
SDL.setCurrentBasicBlock(BB); SDL.setCurrentBasicBlock(BB);
// Emit the code // Emit the code
SDL.visitSwitchCase(SwitchCases[i]); SDL.visitSwitchCase(SwitchCases[i]);
SDAG.setRoot(SDL.getRoot()); SDAG.setRoot(SDL.getRoot());
CodeGenAndEmitDAG(SDAG); CodeGenAndEmitDAG(SDAG);
// Iterate over the phi nodes, if there is a phi node in a successor of this
// block (for instance, the default block), then add a pair of operands to // Handle any PHI nodes in successors of this chunk, as if we were coming
// the phi node for this block, as if we were coming from the original // from the original BB before switch expansion. Note that PHI nodes can
// BB before switch expansion. // occur multiple times in PHINodesToUpdate. We have to be very careful to
for (unsigned pi = 0, pe = PHINodesToUpdate.size(); pi != pe; ++pi) { // handle them the right number of times.
MachineInstr *PHI = PHINodesToUpdate[pi].first; while ((BB = SwitchCases[i].LHSBB)) { // Handle LHS and RHS.
MachineBasicBlock *PHIBB = PHI->getParent(); for (MachineBasicBlock::iterator Phi = BB->begin();
assert(PHI->getOpcode() == TargetInstrInfo::PHI && Phi != BB->end() && Phi->getOpcode() == TargetInstrInfo::PHI; ++Phi){
"This is not a machine PHI node that we are updating!"); // This value for this PHI node is recorded in PHINodesToUpdate, get it.
if (PHIBB == SwitchCases[i].LHSBB || PHIBB == SwitchCases[i].RHSBB) { for (unsigned pn = 0; ; ++pn) {
PHI->addRegOperand(PHINodesToUpdate[pi].second, false); assert(pn != PHINodesToUpdate.size() && "Didn't find PHI entry!");
PHI->addMachineBasicBlockOperand(BB); if (PHINodesToUpdate[pn].first == Phi) {
Phi->addRegOperand(PHINodesToUpdate[pn].second, false);
Phi->addMachineBasicBlockOperand(SwitchCases[i].ThisBB);
break;
}
}
} }
// Don't process RHS if same block as LHS.
if (BB == SwitchCases[i].RHSBB)
SwitchCases[i].RHSBB = 0;
// If we haven't handled the RHS, do so now. Otherwise, we're done.
SwitchCases[i].LHSBB = SwitchCases[i].RHSBB;
SwitchCases[i].RHSBB = 0;
} }
assert(SwitchCases[i].LHSBB == 0 && SwitchCases[i].RHSBB == 0);
} }
} }