X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FStrongPHIElimination.cpp;h=5d7bc23694bf9100f033c606e0b892690ba79bf6;hb=a29c13086a3add78a3a79f744573fe09eaa9dc88;hp=9a9fba550b85f2534bf9dce7ca64d19f168c36d1;hpb=55c64358d1c04990cd5f50785d3e3b27447dac21;p=oota-llvm.git diff --git a/lib/CodeGen/StrongPHIElimination.cpp b/lib/CodeGen/StrongPHIElimination.cpp index 9a9fba550b8..5d7bc23694b 100644 --- a/lib/CodeGen/StrongPHIElimination.cpp +++ b/lib/CodeGen/StrongPHIElimination.cpp @@ -33,17 +33,18 @@ #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" using namespace llvm; namespace { struct VISIBILITY_HIDDEN StrongPHIElimination : public MachineFunctionPass { static char ID; // Pass identification, replacement for typeid - StrongPHIElimination() : MachineFunctionPass((intptr_t)&ID) {} + StrongPHIElimination() : MachineFunctionPass(&ID) {} // Waiting stores, for each MBB, the set of copies that need to // be inserted into that MBB DenseMap > Waiting; + std::multimap > Waiting; // Stacks holds the renaming stack for each register std::map > Stacks; @@ -139,10 +140,9 @@ namespace { std::vector& DF, std::vector >& locals); void ScheduleCopies(MachineBasicBlock* MBB, std::set& pushed); - void InsertCopies(MachineBasicBlock* MBB, + void InsertCopies(MachineDomTreeNode* MBB, SmallPtrSet& v); - void mergeLiveIntervals(unsigned primary, unsigned secondary, - MachineBasicBlock* pred); + bool mergeLiveIntervals(unsigned primary, unsigned secondary); }; } @@ -295,7 +295,7 @@ static bool isLiveIn(unsigned r, MachineBasicBlock* MBB, LiveIntervals& LI) { LiveInterval& I = LI.getOrCreateInterval(r); unsigned idx = LI.getMBBStartIdx(MBB); - return I.liveBeforeAndAt(idx); + return I.liveAt(idx); } /// isLiveOut - help method that determines, from a regno, if a register is @@ -303,10 +303,9 @@ static bool isLiveIn(unsigned r, MachineBasicBlock* MBB, static bool isLiveOut(unsigned r, MachineBasicBlock* MBB, LiveIntervals& LI) { for (MachineBasicBlock::succ_iterator PI = MBB->succ_begin(), - E = MBB->succ_end(); PI != E; ++PI) { + E = MBB->succ_end(); PI != E; ++PI) if (isLiveIn(r, *PI, LI)) return true; - } return false; } @@ -420,7 +419,7 @@ void StrongPHIElimination::processBlock(MachineBasicBlock* MBB) { MachineBasicBlock::iterator P = MBB->begin(); while (P != MBB->end() && P->getOpcode() == TargetInstrInfo::PHI) { unsigned DestReg = P->getOperand(0).getReg(); - + // Don't both doing PHI elimination for dead PHI's. if (P->registerDefIsDead(DestReg)) { ++P; @@ -442,6 +441,17 @@ void StrongPHIElimination::processBlock(MachineBasicBlock* MBB) { // 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->getOpcode() == TargetInstrInfo::IMPLICIT_DEF) + ProcessedNames.insert(SrcReg); // Check for trivial interferences via liveness information, allowing us // to avoid extra work later. Any registers that interfere cannot both @@ -541,6 +551,12 @@ void StrongPHIElimination::processBlock(MachineBasicBlock* MBB) { } // Add the renaming set for this PHI node to our overall renaming information + for (std::map::iterator QI = PHIUnion.begin(), + QE = PHIUnion.end(); QI != QE; ++QI) { + DOUT << "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 @@ -631,13 +647,13 @@ void StrongPHIElimination::processPHIUnion(MachineInstr* Inst, void StrongPHIElimination::ScheduleCopies(MachineBasicBlock* MBB, std::set& pushed) { // FIXME: This function needs to update LiveIntervals - std::map& copy_set= Waiting[MBB]; + std::multimap& copy_set= Waiting[MBB]; - std::map worklist; + std::multimap worklist; std::map map; // Setup worklist of initial copies - for (std::map::iterator I = copy_set.begin(), + for (std::multimap::iterator I = copy_set.begin(), E = copy_set.end(); I != E; ) { map.insert(std::make_pair(I->first, I->first)); map.insert(std::make_pair(I->second, I->second)); @@ -646,9 +662,9 @@ void StrongPHIElimination::ScheduleCopies(MachineBasicBlock* MBB, worklist.insert(*I); // Avoid iterator invalidation - unsigned first = I->first; + std::multimap::iterator OI = I; ++I; - copy_set.erase(first); + copy_set.erase(OI); } else { ++I; } @@ -664,8 +680,9 @@ void StrongPHIElimination::ScheduleCopies(MachineBasicBlock* MBB, // Iterate over the worklist, inserting copies while (!worklist.empty() || !copy_set.empty()) { while (!worklist.empty()) { - std::pair curr = *worklist.begin(); - worklist.erase(curr.first); + std::multimap::iterator WI = worklist.begin(); + std::pair curr = *WI; + worklist.erase(WI); const TargetRegisterClass *RC = MF->getRegInfo().getRegClass(curr.first); @@ -679,17 +696,24 @@ void StrongPHIElimination::ScheduleCopies(MachineBasicBlock* MBB, TII->copyRegToReg(*PI->getParent(), PI, t, curr.second, RC, RC); + DOUT << "Inserted copy from " << curr.second << " to " << t << "\n"; + // Push temporary on Stacks Stacks[curr.second].push_back(t); // Insert curr.second in pushed pushed.insert(curr.second); + + // Create a live interval for this temporary + InsertedPHIDests.push_back(std::make_pair(t, --PI)); } // Insert copy from map[curr.first] to curr.second TII->copyRegToReg(*MBB, MBB->getFirstTerminator(), curr.second, map[curr.first], RC, RC); map[curr.first] = curr.second; + DOUT << "Inserted copy from " << curr.first << " to " + << curr.second << "\n"; // Push this copy onto InsertedPHICopies so we can // update LiveIntervals with it. @@ -697,15 +721,16 @@ void StrongPHIElimination::ScheduleCopies(MachineBasicBlock* MBB, InsertedPHIDests.push_back(std::make_pair(curr.second, --MI)); // If curr.first is a destination in copy_set... - for (std::map::iterator I = copy_set.begin(), + for (std::multimap::iterator I = copy_set.begin(), E = copy_set.end(); I != E; ) if (curr.first == I->second) { std::pair temp = *I; + worklist.insert(temp); // Avoid iterator invalidation + std::multimap::iterator OI = I; ++I; - copy_set.erase(temp.first); - worklist.insert(temp); + copy_set.erase(OI); break; } else { @@ -714,18 +739,32 @@ void StrongPHIElimination::ScheduleCopies(MachineBasicBlock* MBB, } if (!copy_set.empty()) { - std::pair curr = *copy_set.begin(); - copy_set.erase(curr.first); - - const TargetRegisterClass *RC = MF->getRegInfo().getRegClass(curr.first); + std::multimap::iterator CI = copy_set.begin(); + std::pair curr = *CI; + worklist.insert(curr); + copy_set.erase(CI); - // Insert a copy from dest to a new temporary t at the end of b - unsigned t = MF->getRegInfo().createVirtualRegister(RC); - TII->copyRegToReg(*MBB, MBB->getFirstTerminator(), t, - curr.second, RC, RC); - map[curr.second] = t; + LiveInterval& I = LI.getInterval(curr.second); + MachineBasicBlock::iterator term = MBB->getFirstTerminator(); + unsigned endIdx = 0; + if (term != MBB->end()) + endIdx = LI.getInstructionIndex(term); + else + endIdx = LI.getMBBEndIdx(MBB); - worklist.insert(curr); + if (I.liveAt(endIdx)) { + const TargetRegisterClass *RC = + MF->getRegInfo().getRegClass(curr.first); + + // Insert a copy from dest to a new temporary t at the end of b + unsigned t = MF->getRegInfo().createVirtualRegister(RC); + TII->copyRegToReg(*MBB, MBB->getFirstTerminator(), t, + curr.second, RC, RC); + map[curr.second] = t; + + MachineBasicBlock::iterator TI = MBB->getFirstTerminator(); + InsertedPHIDests.push_back(std::make_pair(t, --TI)); + } } } @@ -740,35 +779,74 @@ void StrongPHIElimination::ScheduleCopies(MachineBasicBlock* MBB, // PHI, we don't create multiple overlapping live intervals. std::set RegHandled; for (SmallVector, 4>::iterator I = - InsertedPHIDests.begin(), E = InsertedPHIDests.end(); I != E; ++I) - if (!RegHandled.count(I->first)) - LI.addLiveRangeToEndOfBlock(I->first, I->second); + InsertedPHIDests.begin(), E = InsertedPHIDests.end(); I != E; ++I) { + if (RegHandled.insert(I->first).second) { + LiveInterval& Int = LI.getOrCreateInterval(I->first); + unsigned instrIdx = LI.getInstructionIndex(I->second); + if (Int.liveAt(LiveIntervals::getDefIndex(instrIdx))) + Int.removeRange(LiveIntervals::getDefIndex(instrIdx), + LI.getMBBEndIdx(I->second->getParent())+1, + true); + + LiveRange R = LI.addLiveRangeToEndOfBlock(I->first, I->second); + R.valno->copy = I->second; + R.valno->def = + LiveIntervals::getDefIndex(LI.getInstructionIndex(I->second)); + } + } } /// InsertCopies - insert copies into MBB and all of its successors -void StrongPHIElimination::InsertCopies(MachineBasicBlock* MBB, +void StrongPHIElimination::InsertCopies(MachineDomTreeNode* MDTN, SmallPtrSet& visited) { + MachineBasicBlock* MBB = MDTN->getBlock(); visited.insert(MBB); std::set pushed; + LiveIntervals& LI = getAnalysis(); // Rewrite register uses from Stacks for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); - I != E; ++I) + I != E; ++I) { + if (I->getOpcode() == TargetInstrInfo::PHI) + continue; + for (unsigned i = 0; i < I->getNumOperands(); ++i) - if (I->getOperand(i).isRegister() && + if (I->getOperand(i).isReg() && Stacks[I->getOperand(i).getReg()].size()) { + // Remove the live range for the old vreg. + LiveInterval& OldInt = LI.getInterval(I->getOperand(i).getReg()); + LiveInterval::iterator OldLR = OldInt.FindLiveRangeContaining( + LiveIntervals::getUseIndex(LI.getInstructionIndex(I))); + if (OldLR != OldInt.end()) + OldInt.removeRange(*OldLR, true); + + // Change the register I->getOperand(i).setReg(Stacks[I->getOperand(i).getReg()].back()); + + // Add a live range for the new vreg + LiveInterval& Int = LI.getInterval(I->getOperand(i).getReg()); + VNInfo* FirstVN = *Int.vni_begin(); + FirstVN->hasPHIKill = false; + if (I->getOperand(i).isKill()) + FirstVN->kills.push_back( + LiveIntervals::getUseIndex(LI.getInstructionIndex(I))); + + LiveRange LR (LI.getMBBStartIdx(I->getParent()), + LiveIntervals::getUseIndex(LI.getInstructionIndex(I))+1, + FirstVN); + + Int.addRange(LR); } + } // Schedule the copies for this block ScheduleCopies(MBB, pushed); - // Recur to our successors - for (GraphTraits::ChildIteratorType I = - GraphTraits::child_begin(MBB), E = - GraphTraits::child_end(MBB); I != E; ++I) - if (!visited.count(*I)) + // Recur down the dominator tree. + for (MachineDomTreeNode::iterator I = MDTN->begin(), + E = MDTN->end(); I != E; ++I) + if (!visited.count((*I)->getBlock())) InsertCopies(*I, visited); // As we exit this block, pop the names we pushed while processing it @@ -777,9 +855,8 @@ void StrongPHIElimination::InsertCopies(MachineBasicBlock* MBB, Stacks[*I].pop_back(); } -void StrongPHIElimination::mergeLiveIntervals(unsigned primary, - unsigned secondary, - MachineBasicBlock* pred) { +bool StrongPHIElimination::mergeLiveIntervals(unsigned primary, + unsigned secondary) { LiveIntervals& LI = getAnalysis(); LiveInterval& LHS = LI.getOrCreateInterval(primary); @@ -787,20 +864,41 @@ void StrongPHIElimination::mergeLiveIntervals(unsigned primary, LI.computeNumbering(); - const LiveRange* RangeMergingIn = - RHS.getLiveRangeContaining(LI.getMBBEndIdx(pred)); - VNInfo* NewVN = LHS.getNextValue(RangeMergingIn->valno->def, - RangeMergingIn->valno->copy, - LI.getVNInfoAllocator()); - NewVN->hasPHIKill = true; - LiveRange NewRange(RangeMergingIn->start, RangeMergingIn->end, NewVN); + DenseMap VNMap; + for (LiveInterval::iterator I = RHS.begin(), E = RHS.end(); I != E; ++I) { + LiveRange R = *I; + + unsigned Start = R.start; + unsigned End = R.end; + if (LHS.getLiveRangeContaining(Start)) + return false; + + if (LHS.getLiveRangeContaining(End)) + return false; + + LiveInterval::iterator RI = std::upper_bound(LHS.begin(), LHS.end(), R); + if (RI != LHS.end() && RI->start < End) + return false; + } + + for (LiveInterval::iterator I = RHS.begin(), E = RHS.end(); I != E; ++I) { + LiveRange R = *I; + VNInfo* OldVN = R.valno; + VNInfo*& NewVN = VNMap[OldVN]; + if (!NewVN) { + NewVN = LHS.getNextValue(OldVN->def, + OldVN->copy, + LI.getVNInfoAllocator()); + NewVN->kills = OldVN->kills; + } + + LiveRange LR (R.start, R.end, NewVN); + LHS.addRange(LR); + } - if (RHS.containsOneValue()) - LI.removeInterval(RHS.reg); - else - RHS.removeRange(RangeMergingIn->start, RangeMergingIn->end, true); + LI.removeInterval(RHS.reg); - LHS.addRange(NewRange); + return true; } bool StrongPHIElimination::runOnMachineFunction(MachineFunction &Fn) { @@ -815,24 +913,85 @@ bool StrongPHIElimination::runOnMachineFunction(MachineFunction &Fn) { I->begin()->getOpcode() == TargetInstrInfo::PHI) processBlock(I); + // Break interferences where two different phis want to coalesce + // in the same register. + std::set seen; + typedef std::map > + RenameSetType; + for (RenameSetType::iterator I = RenameSets.begin(), E = RenameSets.end(); + I != E; ++I) { + for (std::map::iterator + OI = I->second.begin(), OE = I->second.end(); OI != OE; ) { + if (!seen.count(OI->first)) { + seen.insert(OI->first); + ++OI; + } else { + Waiting[OI->second].insert(std::make_pair(OI->first, I->first)); + unsigned reg = OI->first; + ++OI; + I->second.erase(reg); + DOUT << "Removing Renaming: " << reg << " -> " << I->first << "\n"; + } + } + } + // Insert copies // FIXME: This process should probably preserve LiveIntervals SmallPtrSet visited; - InsertCopies(Fn.begin(), visited); + MachineDominatorTree& MDT = getAnalysis(); + InsertCopies(MDT.getRootNode(), visited); // Perform renaming - typedef std::map > - RenameSetType; for (RenameSetType::iterator I = RenameSets.begin(), E = RenameSets.end(); I != E; ++I) - for (std::map::iterator SI = - I->second.begin(), SE = I->second.end(); SI != SE; ++SI) { - mergeLiveIntervals(I->first, SI->first, SI->second); - Fn.getRegInfo().replaceRegWith(SI->first, I->first); + while (I->second.size()) { + std::map::iterator SI = I->second.begin(); + + DOUT << "Renaming: " << SI->first << " -> " << I->first << "\n"; + + if (SI->first != I->first) { + if (mergeLiveIntervals(I->first, SI->first)) { + Fn.getRegInfo().replaceRegWith(SI->first, I->first); + + if (RenameSets.count(SI->first)) { + I->second.insert(RenameSets[SI->first].begin(), + RenameSets[SI->first].end()); + RenameSets.erase(SI->first); + } + } else { + // Insert a last-minute copy if a conflict was detected. + const TargetInstrInfo *TII = Fn.getTarget().getInstrInfo(); + const TargetRegisterClass *RC = Fn.getRegInfo().getRegClass(I->first); + TII->copyRegToReg(*SI->second, SI->second->getFirstTerminator(), + I->first, SI->first, RC, RC); + + LI.computeNumbering(); + + LiveInterval& Int = LI.getOrCreateInterval(I->first); + unsigned instrIdx = + LI.getInstructionIndex(--SI->second->getFirstTerminator()); + if (Int.liveAt(LiveIntervals::getDefIndex(instrIdx))) + Int.removeRange(LiveIntervals::getDefIndex(instrIdx), + LI.getMBBEndIdx(SI->second)+1, true); + + LiveRange R = LI.addLiveRangeToEndOfBlock(I->first, + --SI->second->getFirstTerminator()); + R.valno->copy = --SI->second->getFirstTerminator(); + R.valno->def = LiveIntervals::getDefIndex(instrIdx); + + DOUT << "Renaming failed: " << SI->first << " -> " + << I->first << "\n"; + } + } + + LiveInterval& Int = LI.getOrCreateInterval(I->first); + const LiveRange* LR = + Int.getLiveRangeContaining(LI.getMBBEndIdx(SI->second)); + LR->valno->hasPHIKill = true; + + I->second.erase(SI->first); } - // FIXME: Insert last-minute copies - // Remove PHIs std::vector phis; for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) { @@ -857,10 +1016,31 @@ bool StrongPHIElimination::runOnMachineFunction(MachineFunction &Fn) { PI.removeRange(*PI.getLiveRangeContaining(idx), true); } } else { + // Trim live intervals of input registers. They are no longer live into + // this block if they died after the PHI. If they lived after it, don't + // trim them because they might have other legitimate uses. + for (unsigned i = 1; i < PInstr->getNumOperands(); i += 2) { + unsigned reg = PInstr->getOperand(i).getReg(); + + MachineBasicBlock* MBB = PInstr->getOperand(i+1).getMBB(); + LiveInterval& InputI = LI.getInterval(reg); + if (MBB != PInstr->getParent() && + InputI.liveAt(LI.getMBBStartIdx(PInstr->getParent())) && + InputI.expiredAt(LI.getInstructionIndex(PInstr) + + LiveIntervals::InstrSlots::NUM)) + InputI.removeRange(LI.getMBBStartIdx(PInstr->getParent()), + LI.getInstructionIndex(PInstr), + true); + } + // If the PHI is not dead, then the valno defined by the PHI // now has an unknown def. unsigned idx = LI.getDefIndex(LI.getInstructionIndex(PInstr)); - PI.getLiveRangeContaining(idx)->valno->def = ~0U; + const LiveRange* PLR = PI.getLiveRangeContaining(idx); + PLR->valno->def = ~0U; + LiveRange R (LI.getMBBStartIdx(PInstr->getParent()), + PLR->start, PLR->valno); + PI.addRange(R); } LI.RemoveMachineInstrFromMaps(PInstr);