mirror of
https://github.com/RPCSX/llvm.git
synced 2025-05-13 10:56:01 +00:00
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:
parent
5aa0307315
commit
d5e93c0795
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user