From: Chris Lattner Date: Thu, 7 Sep 2006 01:59:34 +0000 (+0000) Subject: Fix CodeGen/Generic/2006-09-06-SwitchLowering.ll, a bug where SDIsel inserted X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=d5e93c07957844e3086fb12d686b93dbbd2524c2 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 --- diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index b1f70cdf222..f1cdcdfa979 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -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 // target supports indirect branches, then emit a jump table rather than // lowering the switch to a binary tree of conditional branches. - // FIXME: Make this work with PIC code if (TLI.isOperationLegal(ISD::BRIND, TLI.getPointerTy()) && Cases.size() > 5) { uint64_t First = cast(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. std::map ConstantsOut; - + // Check successor nodes PHI nodes that expect a constant to be available from // this block. TerminatorInst *TI = LLVMBB->getTerminator(); for (unsigned succ = 0, e = TI->getNumSuccessors(); succ != e; ++succ) { BasicBlock *SuccBB = TI->getSuccessor(succ); + if (!isa(SuccBB->begin())) continue; + MachineBasicBlock::iterator MBBI = FuncInfo.MBBMap[SuccBB]->begin(); PHINode *PN; @@ -3589,31 +3590,47 @@ void SelectionDAGISel::SelectBasicBlock(BasicBlock *LLVMBB, MachineFunction &MF, // If we generated any switch lowering information, build and codegen any // 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()); CurDAG = &SDAG; SelectionDAGLowering SDL(SDAG, TLI, FuncInfo); + // Set the current basic block to the mbb we wish to insert the code into BB = SwitchCases[i].ThisBB; SDL.setCurrentBasicBlock(BB); + // Emit the code SDL.visitSwitchCase(SwitchCases[i]); SDAG.setRoot(SDL.getRoot()); 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 - // the phi node for this block, as if we were coming from the original - // BB before switch expansion. - for (unsigned pi = 0, pe = PHINodesToUpdate.size(); pi != pe; ++pi) { - MachineInstr *PHI = PHINodesToUpdate[pi].first; - MachineBasicBlock *PHIBB = PHI->getParent(); - assert(PHI->getOpcode() == TargetInstrInfo::PHI && - "This is not a machine PHI node that we are updating!"); - if (PHIBB == SwitchCases[i].LHSBB || PHIBB == SwitchCases[i].RHSBB) { - PHI->addRegOperand(PHINodesToUpdate[pi].second, false); - PHI->addMachineBasicBlockOperand(BB); + + // Handle any PHI nodes in successors of this chunk, as if we were coming + // from the original BB before switch expansion. Note that PHI nodes can + // occur multiple times in PHINodesToUpdate. We have to be very careful to + // handle them the right number of times. + while ((BB = SwitchCases[i].LHSBB)) { // Handle LHS and RHS. + for (MachineBasicBlock::iterator Phi = BB->begin(); + Phi != BB->end() && Phi->getOpcode() == TargetInstrInfo::PHI; ++Phi){ + // This value for this PHI node is recorded in PHINodesToUpdate, get it. + for (unsigned pn = 0; ; ++pn) { + assert(pn != PHINodesToUpdate.size() && "Didn't find PHI entry!"); + 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); } }