/// processBlock - Determine how to break up PHIs in the current block. Each /// PHI is broken up by some combination of renaming its operands and inserting /// copies. This method is responsible for determining which operands receive /// which treatment. void StrongPHIElimination::processBlock(MachineBasicBlock* MBB) { LiveIntervals& LI = getAnalysis<LiveIntervals>(); MachineRegisterInfo& MRI = MBB->getParent()->getRegInfo(); // Holds names that have been added to a set in any PHI within this block // before the current one. std::set<unsigned> ProcessedNames; // Iterate over all the PHI nodes in this block MachineBasicBlock::iterator P = MBB->begin(); while (P != MBB->end() && P->isPHI()) { unsigned DestReg = P->getOperand(0).getReg(); // Don't both doing PHI elimination for dead PHI's. if (P->registerDefIsDead(DestReg)) { ++P; continue; } LiveInterval& PI = LI.getOrCreateInterval(DestReg); SlotIndex pIdx = LI.getInstructionIndex(P).getDefIndex(); VNInfo* PVN = PI.getLiveRangeContaining(pIdx)->valno; PhiValueNumber.insert(std::make_pair(DestReg, PVN->id)); // PHIUnion is the set of incoming registers to the PHI node that // are going to be renames rather than having copies inserted. This set // is refinded over the course of this function. UnionedBlocks is the set // of corresponding MBBs. std::map<unsigned, MachineBasicBlock*> PHIUnion; SmallPtrSet<MachineBasicBlock*, 8> UnionedBlocks; // Iterate over the operands of the PHI node for (int i = P->getNumOperands() - 1; i >= 2; i-=2) { unsigned SrcReg = P->getOperand(i-1).getReg(); // Don't need to try to coalesce a register with itself. if (SrcReg == DestReg) { ProcessedNames.insert(SrcReg); continue; } // We don't need to insert copies for implicit_defs. MachineInstr* DefMI = MRI.getVRegDef(SrcReg); if (DefMI->isImplicitDef()) ProcessedNames.insert(SrcReg); // Check for trivial interferences via liveness information, allowing us // to avoid extra work later. Any registers that interfere cannot both // be in the renaming set, so choose one and add copies for it instead. // The conditions are: // 1) if the operand is live into the PHI node's block OR // 2) if the PHI node is live out of the operand's defining block OR // 3) if the operand is itself a PHI node and the original PHI is // live into the operand's defining block OR // 4) if the operand is already being renamed for another PHI node // in this block OR // 5) if any two operands are defined in the same block, insert copies // for one of them if (isLiveIn(SrcReg, P->getParent(), LI) || isLiveOut(P->getOperand(0).getReg(), MRI.getVRegDef(SrcReg)->getParent(), LI) || ( MRI.getVRegDef(SrcReg)->isPHI() && isLiveIn(P->getOperand(0).getReg(), MRI.getVRegDef(SrcReg)->getParent(), LI) ) || ProcessedNames.count(SrcReg) || UnionedBlocks.count(MRI.getVRegDef(SrcReg)->getParent())) { // Add a copy for the selected register MachineBasicBlock* From = P->getOperand(i).getMBB(); Waiting[From].insert(std::make_pair(SrcReg, DestReg)); UsedByAnother.insert(SrcReg); } else { // Otherwise, add it to the renaming set PHIUnion.insert(std::make_pair(SrcReg,P->getOperand(i).getMBB())); UnionedBlocks.insert(MRI.getVRegDef(SrcReg)->getParent()); } } // Compute the dominator forest for the renaming set. This is a forest // where the nodes are the registers and the edges represent dominance // relations between the defining blocks of the registers std::vector<StrongPHIElimination::DomForestNode*> DF = computeDomForest(PHIUnion, MRI); // Walk DomForest to resolve interferences at an inter-block level. This // will remove registers from the renaming set (and insert copies for them) // if interferences are found. std::vector<std::pair<unsigned, unsigned> > localInterferences; processPHIUnion(P, PHIUnion, DF, localInterferences); // If one of the inputs is defined in the same block as the current PHI // then we need to check for a local interference between that input and // the PHI. for (std::map<unsigned, MachineBasicBlock*>::iterator I = PHIUnion.begin(), E = PHIUnion.end(); I != E; ++I) if (MRI.getVRegDef(I->first)->getParent() == P->getParent()) localInterferences.push_back(std::make_pair(I->first, P->getOperand(0).getReg())); // The dominator forest walk may have returned some register pairs whose // interference cannot be determined from dominator analysis. We now // examine these pairs for local interferences. for (std::vector<std::pair<unsigned, unsigned> >::iterator I = localInterferences.begin(), E = localInterferences.end(); I != E; ++I) { std::pair<unsigned, unsigned> p = *I; MachineDominatorTree& MDT = getAnalysis<MachineDominatorTree>(); // Determine the block we need to scan and the relationship between // the two registers MachineBasicBlock* scan = 0; unsigned mode = 0; if (MRI.getVRegDef(p.first)->getParent() == MRI.getVRegDef(p.second)->getParent()) { scan = MRI.getVRegDef(p.first)->getParent(); mode = 0; // Same block } else if (MDT.dominates(MRI.getVRegDef(p.first)->getParent(), MRI.getVRegDef(p.second)->getParent())) { scan = MRI.getVRegDef(p.second)->getParent(); mode = 1; // First dominates second } else { scan = MRI.getVRegDef(p.first)->getParent(); mode = 2; // Second dominates first } // If there's an interference, we need to insert copies if (interferes(p.first, p.second, scan, LI, mode)) { // Insert copies for First for (int i = P->getNumOperands() - 1; i >= 2; i-=2) { if (P->getOperand(i-1).getReg() == p.first) { unsigned SrcReg = p.first; MachineBasicBlock* From = P->getOperand(i).getMBB(); Waiting[From].insert(std::make_pair(SrcReg, P->getOperand(0).getReg())); UsedByAnother.insert(SrcReg); PHIUnion.erase(SrcReg); } } } } // Add the renaming set for this PHI node to our overall renaming information for (std::map<unsigned, MachineBasicBlock*>::iterator QI = PHIUnion.begin(), QE = PHIUnion.end(); QI != QE; ++QI) { DEBUG(dbgs() << "Adding Renaming: " << QI->first << " -> " << P->getOperand(0).getReg() << "\n"); } RenameSets.insert(std::make_pair(P->getOperand(0).getReg(), PHIUnion)); // Remember which registers are already renamed, so that we don't try to // rename them for another PHI node in this block for (std::map<unsigned, MachineBasicBlock*>::iterator I = PHIUnion.begin(), E = PHIUnion.end(); I != E; ++I) ProcessedNames.insert(I->first); ++P; } }