//===- StrongPHIElimination.cpp - Eliminate PHI nodes by inserting copies -===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This pass eliminates PHI instructions by aggressively coalescing the copies // that would be inserted by a naive algorithm and only inserting the copies // that are necessary. The coalescing technique initially assumes that all // registers appearing in a PHI instruction do not interfere. It then eliminates // proven interferences, using dominators to only perform a linear number of // interference tests instead of the quadratic number of interference tests // that this would naively require. This is a technique derived from: // // Budimlic, et al. Fast copy coalescing and live-range identification. // In Proceedings of the ACM SIGPLAN 2002 Conference on Programming Language // Design and Implementation (Berlin, Germany, June 17 - 19, 2002). // PLDI '02. ACM, New York, NY, 25-32. // // The original implementation constructs a data structure they call a dominance // forest for this purpose. The dominance forest was shown to be unnecessary, // as it is possible to emulate the creation and traversal of a dominance forest // by directly using the dominator tree, rather than actually constructing the // dominance forest. This technique is explained in: // // Boissinot, et al. Revisiting Out-of-SSA Translation for Correctness, Code // Quality and Efficiency, // In Proceedings of the 7th annual IEEE/ACM International Symposium on Code // Generation and Optimization (Seattle, Washington, March 22 - 25, 2009). // CGO '09. IEEE, Washington, DC, 114-125. // // Careful implementation allows for all of the dominator forest interference // checks to be performed at once in a single depth-first traversal of the // dominator tree, which is what is implemented here. // //===----------------------------------------------------------------------===// #define DEBUG_TYPE "strongphielim" #include "PHIEliminationUtils.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/LiveIntervalAnalysis.h" #include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/Debug.h" using namespace llvm; namespace { class StrongPHIElimination : public MachineFunctionPass { public: static char ID; // Pass identification, replacement for typeid StrongPHIElimination() : MachineFunctionPass(ID) { initializeStrongPHIEliminationPass(*PassRegistry::getPassRegistry()); } virtual void getAnalysisUsage(AnalysisUsage&) const; bool runOnMachineFunction(MachineFunction&); private: /// This struct represents a single node in the union-find data structure /// representing the variable congruence classes. There is one difference /// from a normal union-find data structure. We steal two bits from the parent /// pointer . One of these bits is used to represent whether the register /// itself has been isolated, and the other is used to represent whether the /// PHI with that register as its destination has been isolated. /// /// Note that this leads to the strange situation where the leader of a /// congruence class may no longer logically be a member, due to being /// isolated. struct Node { enum Flags { kRegisterIsolatedFlag = 1, kPHIIsolatedFlag = 2 }; Node(unsigned v) : value(v), rank(0) { parent.setPointer(this); } Node *getLeader(); PointerIntPair<Node*, 2> parent; unsigned value; unsigned rank; }; /// Add a register in a new congruence class containing only itself. void addReg(unsigned); /// Join the congruence classes of two registers. This function is biased /// towards the left argument, i.e. after /// /// addReg(r2); /// unionRegs(r1, r2); /// /// the leader of the unioned congruence class is the same as the leader of /// r1's congruence class prior to the union. This is actually relied upon /// in the copy insertion code. void unionRegs(unsigned, unsigned); /// Get the color of a register. The color is 0 if the register has been /// isolated. unsigned getRegColor(unsigned); // Isolate a register. void isolateReg(unsigned); /// Get the color of a PHI. The color of a PHI is 0 if the PHI has been /// isolated. Otherwise, it is the original color of its destination and /// all of its operands (before they were isolated, if they were). unsigned getPHIColor(MachineInstr*); /// Isolate a PHI. void isolatePHI(MachineInstr*); /// Traverses a basic block, splitting any interferences found between /// registers in the same congruence class. It takes two DenseMaps as /// arguments that it also updates: CurrentDominatingParent, which maps /// a color to the register in that congruence class whose definition was /// most recently seen, and ImmediateDominatingParent, which maps a register /// to the register in the same congruence class that most immediately /// dominates it. /// /// This function assumes that it is being called in a depth-first traversal /// of the dominator tree. void SplitInterferencesForBasicBlock( MachineBasicBlock&, DenseMap<unsigned, unsigned> &CurrentDominatingParent, DenseMap<unsigned, unsigned> &ImmediateDominatingParent); // Lowers a PHI instruction, inserting copies of the source and destination // registers as necessary. void InsertCopiesForPHI(MachineInstr*, MachineBasicBlock*); // Merges the live interval of Reg into NewReg and renames Reg to NewReg // everywhere that Reg appears. Requires Reg and NewReg to have non- // overlapping lifetimes. void MergeLIsAndRename(unsigned Reg, unsigned NewReg); MachineRegisterInfo *MRI; const TargetInstrInfo *TII; MachineDominatorTree *DT; LiveIntervals *LI; BumpPtrAllocator Allocator; DenseMap<unsigned, Node*> RegNodeMap; // Maps a basic block to a list of its defs of registers that appear as PHI // sources. DenseMap<MachineBasicBlock*, std::vector<MachineInstr*> > PHISrcDefs; // Maps a color to a pair of a MachineInstr* and a virtual register, which // is the operand of that PHI corresponding to the current basic block. DenseMap<unsigned, std::pair<MachineInstr*, unsigned> > CurrentPHIForColor; // FIXME: Can these two data structures be combined? Would a std::multimap // be any better? // Stores pairs of predecessor basic blocks and the source registers of // inserted copy instructions. typedef DenseSet<std::pair<MachineBasicBlock*, unsigned> > SrcCopySet; SrcCopySet InsertedSrcCopySet; // Maps pairs of predecessor basic blocks and colors to their defining copy // instructions. typedef DenseMap<std::pair<MachineBasicBlock*, unsigned>, MachineInstr*> SrcCopyMap; SrcCopyMap InsertedSrcCopyMap; // Maps inserted destination copy registers to their defining copy // instructions. typedef DenseMap<unsigned, MachineInstr*> DestCopyMap; DestCopyMap InsertedDestCopies; }; struct MIIndexCompare { MIIndexCompare(LiveIntervals *LiveIntervals) : LI(LiveIntervals) { } bool operator()(const MachineInstr *LHS, const MachineInstr *RHS) const { return LI->getInstructionIndex(LHS) < LI->getInstructionIndex(RHS); } LiveIntervals *LI; }; } // namespace STATISTIC(NumPHIsLowered, "Number of PHIs lowered"); STATISTIC(NumDestCopiesInserted, "Number of destination copies inserted"); STATISTIC(NumSrcCopiesInserted, "Number of source copies inserted"); char StrongPHIElimination::ID = 0; INITIALIZE_PASS_BEGIN(StrongPHIElimination, "strong-phi-node-elimination", "Eliminate PHI nodes for register allocation, intelligently", false, false) INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree) INITIALIZE_PASS_DEPENDENCY(SlotIndexes) INITIALIZE_PASS_DEPENDENCY(LiveIntervals) INITIALIZE_PASS_END(StrongPHIElimination, "strong-phi-node-elimination", "Eliminate PHI nodes for register allocation, intelligently", false, false) char &llvm::StrongPHIEliminationID = StrongPHIElimination::ID; void StrongPHIElimination::getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesCFG(); AU.addRequired<MachineDominatorTree>(); AU.addRequired<SlotIndexes>(); AU.addPreserved<SlotIndexes>(); AU.addRequired<LiveIntervals>(); AU.addPreserved<LiveIntervals>(); MachineFunctionPass::getAnalysisUsage(AU); } static MachineOperand *findLastUse(MachineBasicBlock *MBB, unsigned Reg) { // FIXME: This only needs to check from the first terminator, as only the // first terminator can use a virtual register. for (MachineBasicBlock::reverse_iterator RI = MBB->rbegin(); ; ++RI) { assert (RI != MBB->rend()); MachineInstr *MI = &*RI; for (MachineInstr::mop_iterator OI = MI->operands_begin(), OE = MI->operands_end(); OI != OE; ++OI) { MachineOperand &MO = *OI; if (MO.isReg() && MO.isUse() && MO.getReg() == Reg) return &MO; } } return NULL; } bool StrongPHIElimination::runOnMachineFunction(MachineFunction &MF) { MRI = &MF.getRegInfo(); TII = MF.getTarget().getInstrInfo(); DT = &getAnalysis<MachineDominatorTree>(); LI = &getAnalysis<LiveIntervals>(); for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) { for (MachineBasicBlock::iterator BBI = I->begin(), BBE = I->end(); BBI != BBE && BBI->isPHI(); ++BBI) { unsigned DestReg = BBI->getOperand(0).getReg(); addReg(DestReg); PHISrcDefs[I].push_back(BBI); for (unsigned i = 1; i < BBI->getNumOperands(); i += 2) { MachineOperand &SrcMO = BBI->getOperand(i); unsigned SrcReg = SrcMO.getReg(); addReg(SrcReg); unionRegs(DestReg, SrcReg); MachineInstr *DefMI = MRI->getVRegDef(SrcReg); if (DefMI) PHISrcDefs[DefMI->getParent()].push_back(DefMI); } } } // Perform a depth-first traversal of the dominator tree, splitting // interferences amongst PHI-congruence classes. DenseMap<unsigned, unsigned> CurrentDominatingParent; DenseMap<unsigned, unsigned> ImmediateDominatingParent; for (df_iterator<MachineDomTreeNode*> DI = df_begin(DT->getRootNode()), DE = df_end(DT->getRootNode()); DI != DE; ++DI) { SplitInterferencesForBasicBlock(*DI->getBlock(), CurrentDominatingParent, ImmediateDominatingParent); } // Insert copies for all PHI source and destination registers. for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) { for (MachineBasicBlock::iterator BBI = I->begin(), BBE = I->end(); BBI != BBE && BBI->isPHI(); ++BBI) { InsertCopiesForPHI(BBI, I); } } // FIXME: Preserve the equivalence classes during copy insertion and use // the preversed equivalence classes instead of recomputing them. RegNodeMap.clear(); for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) { for (MachineBasicBlock::iterator BBI = I->begin(), BBE = I->end(); BBI != BBE && BBI->isPHI(); ++BBI) { unsigned DestReg = BBI->getOperand(0).getReg(); addReg(DestReg); for (unsigned i = 1; i < BBI->getNumOperands(); i += 2) { unsigned SrcReg = BBI->getOperand(i).getReg(); addReg(SrcReg); unionRegs(DestReg, SrcReg); } } } DenseMap<unsigned, unsigned> RegRenamingMap; bool Changed = false; for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) { MachineBasicBlock::iterator BBI = I->begin(), BBE = I->end(); while (BBI != BBE && BBI->isPHI()) { MachineInstr *PHI = BBI; assert(PHI->getNumOperands() > 0); unsigned SrcReg = PHI->getOperand(1).getReg(); unsigned SrcColor = getRegColor(SrcReg); unsigned NewReg = RegRenamingMap[SrcColor]; if (!NewReg) { NewReg = SrcReg; RegRenamingMap[SrcColor] = SrcReg; } MergeLIsAndRename(SrcReg, NewReg); unsigned DestReg = PHI->getOperand(0).getReg(); if (!InsertedDestCopies.count(DestReg)) MergeLIsAndRename(DestReg, NewReg); for (unsigned i = 3; i < PHI->getNumOperands(); i += 2) { unsigned SrcReg = PHI->getOperand(i).getReg(); MergeLIsAndRename(SrcReg, NewReg); } ++BBI; LI->RemoveMachineInstrFromMaps(PHI); PHI->eraseFromParent(); Changed = true; } } // Due to the insertion of copies to split live ranges, the live intervals are // guaranteed to not overlap, except in one case: an original PHI source and a // PHI destination copy. In this case, they have the same value and thus don't // truly intersect, so we merge them into the value live at that point. // FIXME: Is there some better way we can handle this? for (DestCopyMap::iterator I = InsertedDestCopies.begin(), E = InsertedDestCopies.end(); I != E; ++I) { unsigned DestReg = I->first; unsigned DestColor = getRegColor(DestReg); unsigned NewReg = RegRenamingMap[DestColor]; LiveInterval &DestLI = LI->getInterval(DestReg); LiveInterval &NewLI = LI->getInterval(NewReg); assert(DestLI.ranges.size() == 1 && "PHI destination copy's live interval should be a single live " "range from the beginning of the BB to the copy instruction."); LiveRange *DestLR = DestLI.begin(); VNInfo *NewVNI = NewLI.getVNInfoAt(DestLR->start); if (!NewVNI) { NewVNI = NewLI.createValueCopy(DestLR->valno, LI->getVNInfoAllocator()); MachineInstr *CopyInstr = I->second; CopyInstr->getOperand(1).setIsKill(true); } LiveRange NewLR(DestLR->start, DestLR->end, NewVNI); NewLI.addRange(NewLR); LI->removeInterval(DestReg); MRI->replaceRegWith(DestReg, NewReg); } // Adjust the live intervals of all PHI source registers to handle the case // where the PHIs in successor blocks were the only later uses of the source // register. for (SrcCopySet::iterator I = InsertedSrcCopySet.begin(), E = InsertedSrcCopySet.end(); I != E; ++I) { MachineBasicBlock *MBB = I->first; unsigned SrcReg = I->second; if (unsigned RenamedRegister = RegRenamingMap[getRegColor(SrcReg)]) SrcReg = RenamedRegister; LiveInterval &SrcLI = LI->getInterval(SrcReg); bool isLiveOut = false; for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), SE = MBB->succ_end(); SI != SE; ++SI) { if (SrcLI.liveAt(LI->getMBBStartIdx(*SI))) { isLiveOut = true; break; } } if (isLiveOut) continue; MachineOperand *LastUse = findLastUse(MBB, SrcReg); assert(LastUse); SlotIndex LastUseIndex = LI->getInstructionIndex(LastUse->getParent()); SrcLI.removeRange(LastUseIndex.getDefIndex(), LI->getMBBEndIdx(MBB)); LastUse->setIsKill(true); } LI->renumber(); Allocator.Reset(); RegNodeMap.clear(); PHISrcDefs.clear(); InsertedSrcCopySet.clear(); InsertedSrcCopyMap.clear(); InsertedDestCopies.clear(); return Changed; } void StrongPHIElimination::addReg(unsigned Reg) { if (RegNodeMap.count(Reg)) return; RegNodeMap[Reg] = new (Allocator) Node(Reg); } StrongPHIElimination::Node* StrongPHIElimination::Node::getLeader() { Node *N = this; Node *Parent = parent.getPointer(); Node *Grandparent = Parent->parent.getPointer(); while (Parent != Grandparent) { N->parent.setPointer(Grandparent); N = Grandparent; Parent = Parent->parent.getPointer(); Grandparent = Parent->parent.getPointer(); } return Parent; } unsigned StrongPHIElimination::getRegColor(unsigned Reg) { DenseMap<unsigned, Node*>::iterator RI = RegNodeMap.find(Reg); if (RI == RegNodeMap.end()) return 0; Node *Node = RI->second; if (Node->parent.getInt() & Node::kRegisterIsolatedFlag) return 0; return Node->getLeader()->value; } void StrongPHIElimination::unionRegs(unsigned Reg1, unsigned Reg2) { Node *Node1 = RegNodeMap[Reg1]->getLeader(); Node *Node2 = RegNodeMap[Reg2]->getLeader(); if (Node1->rank > Node2->rank) { Node2->parent.setPointer(Node1->getLeader()); } else if (Node1->rank < Node2->rank) { Node1->parent.setPointer(Node2->getLeader()); } else if (Node1 != Node2) { Node2->parent.setPointer(Node1->getLeader()); Node1->rank++; } } void StrongPHIElimination::isolateReg(unsigned Reg) { Node *Node = RegNodeMap[Reg]; Node->parent.setInt(Node->parent.getInt() | Node::kRegisterIsolatedFlag); } unsigned StrongPHIElimination::getPHIColor(MachineInstr *PHI) { assert(PHI->isPHI()); unsigned DestReg = PHI->getOperand(0).getReg(); Node *DestNode = RegNodeMap[DestReg]; if (DestNode->parent.getInt() & Node::kPHIIsolatedFlag) return 0; for (unsigned i = 1; i < PHI->getNumOperands(); i += 2) { unsigned SrcColor = getRegColor(PHI->getOperand(i).getReg()); if (SrcColor) return SrcColor; } return 0; } void StrongPHIElimination::isolatePHI(MachineInstr *PHI) { assert(PHI->isPHI()); Node *Node = RegNodeMap[PHI->getOperand(0).getReg()]; Node->parent.setInt(Node->parent.getInt() | Node::kPHIIsolatedFlag); } /// SplitInterferencesForBasicBlock - traverses a basic block, splitting any /// interferences found between registers in the same congruence class. It /// takes two DenseMaps as arguments that it also updates: /// /// 1) CurrentDominatingParent, which maps a color to the register in that /// congruence class whose definition was most recently seen. /// /// 2) ImmediateDominatingParent, which maps a register to the register in the /// same congruence class that most immediately dominates it. /// /// This function assumes that it is being called in a depth-first traversal /// of the dominator tree. /// /// The algorithm used here is a generalization of the dominance-based SSA test /// for two variables. If there are variables a_1, ..., a_n such that /// /// def(a_1) dom ... dom def(a_n), /// /// then we can test for an interference between any two a_i by only using O(n) /// interference tests between pairs of variables. If i < j and a_i and a_j /// interfere, then a_i is alive at def(a_j), so it is also alive at def(a_i+1). /// Thus, in order to test for an interference involving a_i, we need only check /// for a potential interference with a_i+1. /// /// This method can be generalized to arbitrary sets of variables by performing /// a depth-first traversal of the dominator tree. As we traverse down a branch /// of the dominator tree, we keep track of the current dominating variable and /// only perform an interference test with that variable. However, when we go to /// another branch of the dominator tree, the definition of the current dominating /// variable may no longer dominate the current block. In order to correct this, /// we need to use a stack of past choices of the current dominating variable /// and pop from this stack until we find a variable whose definition actually /// dominates the current block. /// /// There will be one push on this stack for each variable that has become the /// current dominating variable, so instead of using an explicit stack we can /// simply associate the previous choice for a current dominating variable with /// the new choice. This works better in our implementation, where we test for /// interference in multiple distinct sets at once. void StrongPHIElimination::SplitInterferencesForBasicBlock( MachineBasicBlock &MBB, DenseMap<unsigned, unsigned> &CurrentDominatingParent, DenseMap<unsigned, unsigned> &ImmediateDominatingParent) { // Sort defs by their order in the original basic block, as the code below // assumes that it is processing definitions in dominance order. std::vector<MachineInstr*> &DefInstrs = PHISrcDefs[&MBB]; std::sort(DefInstrs.begin(), DefInstrs.end(), MIIndexCompare(LI)); for (std::vector<MachineInstr*>::const_iterator BBI = DefInstrs.begin(), BBE = DefInstrs.end(); BBI != BBE; ++BBI) { for (MachineInstr::const_mop_iterator I = (*BBI)->operands_begin(), E = (*BBI)->operands_end(); I != E; ++I) { const MachineOperand &MO = *I; // FIXME: This would be faster if it were possible to bail out of checking // an instruction's operands after the explicit defs, but this is incorrect // for variadic instructions, which may appear before register allocation // in the future. if (!MO.isReg() || !MO.isDef()) continue; unsigned DestReg = MO.getReg(); if (!DestReg || !TargetRegisterInfo::isVirtualRegister(DestReg)) continue; // If the virtual register being defined is not used in any PHI or has // already been isolated, then there are no more interferences to check. unsigned DestColor = getRegColor(DestReg); if (!DestColor) continue; // The input to this pass sometimes is not in SSA form in every basic // block, as some virtual registers have redefinitions. We could eliminate // this by fixing the passes that generate the non-SSA code, or we could // handle it here by tracking defining machine instructions rather than // virtual registers. For now, we just handle the situation conservatively // in a way that will possibly lead to false interferences. unsigned &CurrentParent = CurrentDominatingParent[DestColor]; unsigned NewParent = CurrentParent; if (NewParent == DestReg) continue; // Pop registers from the stack represented by ImmediateDominatingParent // until we find a parent that dominates the current instruction. while (NewParent && (!DT->dominates(MRI->getVRegDef(NewParent), *BBI) || !getRegColor(NewParent))) NewParent = ImmediateDominatingParent[NewParent]; // If NewParent is nonzero, then its definition dominates the current // instruction, so it is only necessary to check for the liveness of // NewParent in order to check for an interference. if (NewParent && LI->getInterval(NewParent).liveAt(LI->getInstructionIndex(*BBI))) { // If there is an interference, always isolate the new register. This // could be improved by using a heuristic that decides which of the two // registers to isolate. isolateReg(DestReg); CurrentParent = NewParent; } else { // If there is no interference, update ImmediateDominatingParent and set // the CurrentDominatingParent for this color to the current register. ImmediateDominatingParent[DestReg] = NewParent; CurrentParent = DestReg; } } } // We now walk the PHIs in successor blocks and check for interferences. This // is necessary because the use of a PHI's operands are logically contained in // the predecessor block. The def of a PHI's destination register is processed // along with the other defs in a basic block. CurrentPHIForColor.clear(); for (MachineBasicBlock::succ_iterator SI = MBB.succ_begin(), SE = MBB.succ_end(); SI != SE; ++SI) { for (MachineBasicBlock::iterator BBI = (*SI)->begin(), BBE = (*SI)->end(); BBI != BBE && BBI->isPHI(); ++BBI) { MachineInstr *PHI = BBI; // If a PHI is already isolated, either by being isolated directly or // having all of its operands isolated, ignore it. unsigned Color = getPHIColor(PHI); if (!Color) continue; // Find the index of the PHI operand that corresponds to this basic block. unsigned PredIndex; for (PredIndex = 1; PredIndex < PHI->getNumOperands(); PredIndex += 2) { if (PHI->getOperand(PredIndex + 1).getMBB() == &MBB) break; } assert(PredIndex < PHI->getNumOperands()); unsigned PredOperandReg = PHI->getOperand(PredIndex).getReg(); // Pop registers from the stack represented by ImmediateDominatingParent // until we find a parent that dominates the current instruction. unsigned &CurrentParent = CurrentDominatingParent[Color]; unsigned NewParent = CurrentParent; while (NewParent && (!DT->dominates(MRI->getVRegDef(NewParent)->getParent(), &MBB) || !getRegColor(NewParent))) NewParent = ImmediateDominatingParent[NewParent]; CurrentParent = NewParent; // If there is an interference with a register, always isolate the // register rather than the PHI. It is also possible to isolate the // PHI, but that introduces copies for all of the registers involved // in that PHI. if (NewParent && LI->isLiveOutOfMBB(LI->getInterval(NewParent), &MBB) && NewParent != PredOperandReg) isolateReg(NewParent); std::pair<MachineInstr*, unsigned> &CurrentPHI = CurrentPHIForColor[Color]; // If two PHIs have the same operand from every shared predecessor, then // they don't actually interfere. Otherwise, isolate the current PHI. This // could possibly be improved, e.g. we could isolate the PHI with the // fewest operands. if (CurrentPHI.first && CurrentPHI.second != PredOperandReg) isolatePHI(PHI); else CurrentPHI = std::make_pair(PHI, PredOperandReg); } } } void StrongPHIElimination::InsertCopiesForPHI(MachineInstr *PHI, MachineBasicBlock *MBB) { assert(PHI->isPHI()); ++NumPHIsLowered; unsigned PHIColor = getPHIColor(PHI); for (unsigned i = 1; i < PHI->getNumOperands(); i += 2) { MachineOperand &SrcMO = PHI->getOperand(i); // If a source is defined by an implicit def, there is no need to insert a // copy in the predecessor. if (SrcMO.isUndef()) continue; unsigned SrcReg = SrcMO.getReg(); assert(TargetRegisterInfo::isVirtualRegister(SrcReg) && "Machine PHI Operands must all be virtual registers!"); MachineBasicBlock *PredBB = PHI->getOperand(i + 1).getMBB(); unsigned SrcColor = getRegColor(SrcReg); // If neither the PHI nor the operand were isolated, then we only need to // set the phi-kill flag on the VNInfo at this PHI. if (PHIColor && SrcColor == PHIColor) { LiveInterval &SrcInterval = LI->getInterval(SrcReg); SlotIndex PredIndex = LI->getMBBEndIdx(PredBB); VNInfo *SrcVNI = SrcInterval.getVNInfoBefore(PredIndex); assert(SrcVNI); SrcVNI->setHasPHIKill(true); continue; } unsigned CopyReg = 0; if (PHIColor) { SrcCopyMap::const_iterator I = InsertedSrcCopyMap.find(std::make_pair(PredBB, PHIColor)); CopyReg = I != InsertedSrcCopyMap.end() ? I->second->getOperand(0).getReg() : 0; } if (!CopyReg) { const TargetRegisterClass *RC = MRI->getRegClass(SrcReg); CopyReg = MRI->createVirtualRegister(RC); MachineBasicBlock::iterator CopyInsertPoint = findPHICopyInsertPoint(PredBB, MBB, SrcReg); unsigned SrcSubReg = SrcMO.getSubReg(); MachineInstr *CopyInstr = BuildMI(*PredBB, CopyInsertPoint, PHI->getDebugLoc(), TII->get(TargetOpcode::COPY), CopyReg).addReg(SrcReg, 0, SrcSubReg); LI->InsertMachineInstrInMaps(CopyInstr); ++NumSrcCopiesInserted; // addLiveRangeToEndOfBlock() also adds the phikill flag to the VNInfo for // the newly added range. LI->addLiveRangeToEndOfBlock(CopyReg, CopyInstr); InsertedSrcCopySet.insert(std::make_pair(PredBB, SrcReg)); addReg(CopyReg); if (PHIColor) { unionRegs(PHIColor, CopyReg); assert(getRegColor(CopyReg) != CopyReg); } else { PHIColor = CopyReg; assert(getRegColor(CopyReg) == CopyReg); } if (!InsertedSrcCopyMap.count(std::make_pair(PredBB, PHIColor))) InsertedSrcCopyMap[std::make_pair(PredBB, PHIColor)] = CopyInstr; } SrcMO.setReg(CopyReg); // If SrcReg is not live beyond the PHI, trim its interval so that it is no // longer live-in to MBB. Note that SrcReg may appear in other PHIs that are // processed later, but this is still correct to do at this point because we // never rely on LiveIntervals being correct while inserting copies. // FIXME: Should this just count uses at PHIs like the normal PHIElimination // pass does? LiveInterval &SrcLI = LI->getInterval(SrcReg); SlotIndex MBBStartIndex = LI->getMBBStartIdx(MBB); SlotIndex PHIIndex = LI->getInstructionIndex(PHI); SlotIndex NextInstrIndex = PHIIndex.getNextIndex(); if (SrcLI.liveAt(MBBStartIndex) && SrcLI.expiredAt(NextInstrIndex)) SrcLI.removeRange(MBBStartIndex, PHIIndex, true); } unsigned DestReg = PHI->getOperand(0).getReg(); unsigned DestColor = getRegColor(DestReg); if (PHIColor && DestColor == PHIColor) { LiveInterval &DestLI = LI->getInterval(DestReg); // Set the phi-def flag for the VN at this PHI. SlotIndex PHIIndex = LI->getInstructionIndex(PHI); VNInfo *DestVNI = DestLI.getVNInfoAt(PHIIndex.getDefIndex()); assert(DestVNI); DestVNI->setIsPHIDef(true); // Prior to PHI elimination, the live ranges of PHIs begin at their defining // instruction. After PHI elimination, PHI instructions are replaced by VNs // with the phi-def flag set, and the live ranges of these VNs start at the // beginning of the basic block. SlotIndex MBBStartIndex = LI->getMBBStartIdx(MBB); DestVNI->def = MBBStartIndex; DestLI.addRange(LiveRange(MBBStartIndex, PHIIndex.getDefIndex(), DestVNI)); return; } const TargetRegisterClass *RC = MRI->getRegClass(DestReg); unsigned CopyReg = MRI->createVirtualRegister(RC); MachineInstr *CopyInstr = BuildMI(*MBB, MBB->SkipPHIsAndLabels(MBB->begin()), PHI->getDebugLoc(), TII->get(TargetOpcode::COPY), DestReg).addReg(CopyReg); LI->InsertMachineInstrInMaps(CopyInstr); PHI->getOperand(0).setReg(CopyReg); ++NumDestCopiesInserted; // Add the region from the beginning of MBB to the copy instruction to // CopyReg's live interval, and give the VNInfo the phidef flag. LiveInterval &CopyLI = LI->getOrCreateInterval(CopyReg); SlotIndex MBBStartIndex = LI->getMBBStartIdx(MBB); SlotIndex DestCopyIndex = LI->getInstructionIndex(CopyInstr); VNInfo *CopyVNI = CopyLI.getNextValue(MBBStartIndex, CopyInstr, LI->getVNInfoAllocator()); CopyVNI->setIsPHIDef(true); CopyLI.addRange(LiveRange(MBBStartIndex, DestCopyIndex.getDefIndex(), CopyVNI)); // Adjust DestReg's live interval to adjust for its new definition at // CopyInstr. LiveInterval &DestLI = LI->getOrCreateInterval(DestReg); SlotIndex PHIIndex = LI->getInstructionIndex(PHI); DestLI.removeRange(PHIIndex.getDefIndex(), DestCopyIndex.getDefIndex()); VNInfo *DestVNI = DestLI.getVNInfoAt(DestCopyIndex.getDefIndex()); assert(DestVNI); DestVNI->def = DestCopyIndex.getDefIndex(); InsertedDestCopies[CopyReg] = CopyInstr; } void StrongPHIElimination::MergeLIsAndRename(unsigned Reg, unsigned NewReg) { if (Reg == NewReg) return; LiveInterval &OldLI = LI->getInterval(Reg); LiveInterval &NewLI = LI->getInterval(NewReg); // Merge the live ranges of the two registers. DenseMap<VNInfo*, VNInfo*> VNMap; for (LiveInterval::iterator LRI = OldLI.begin(), LRE = OldLI.end(); LRI != LRE; ++LRI) { LiveRange OldLR = *LRI; VNInfo *OldVN = OldLR.valno; VNInfo *&NewVN = VNMap[OldVN]; if (!NewVN) { NewVN = NewLI.createValueCopy(OldVN, LI->getVNInfoAllocator()); VNMap[OldVN] = NewVN; } LiveRange LR(OldLR.start, OldLR.end, NewVN); NewLI.addRange(LR); } // Remove the LiveInterval for the register being renamed and replace all // of its defs and uses with the new register. LI->removeInterval(Reg); MRI->replaceRegWith(Reg, NewReg); }