From 46c83c80c5737743c955ff007fa6409804a7abf0 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Tue, 14 Dec 2010 00:37:49 +0000 Subject: [PATCH] Try reassigning all virtual register interferences, not just those with lower spill weight. Filter out fixed registers instead. Add support for reassigning an interference that was assigned to an alias. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@121737 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/RegAllocGreedy.cpp | 120 +++++++++++++++++++-------------- 1 file changed, 71 insertions(+), 49 deletions(-) diff --git a/lib/CodeGen/RegAllocGreedy.cpp b/lib/CodeGen/RegAllocGreedy.cpp index 005165eed69..402898905e4 100644 --- a/lib/CodeGen/RegAllocGreedy.cpp +++ b/lib/CodeGen/RegAllocGreedy.cpp @@ -80,10 +80,12 @@ public: static char ID; private: - bool checkUncachedInterference(LiveInterval &, unsigned); + bool checkUncachedInterference(LiveInterval&, unsigned); + LiveInterval *getSingleInterference(LiveInterval&, unsigned); bool reassignVReg(LiveInterval &InterferingVReg, unsigned OldPhysReg); bool reassignInterferences(LiveInterval &VirtReg, unsigned PhysReg); + unsigned tryReassign(LiveInterval&, AllocationOrder&); unsigned trySplit(LiveInterval&, AllocationOrder&, SmallVectorImpl&); }; @@ -163,6 +165,35 @@ bool RAGreedy::checkUncachedInterference(LiveInterval &VirtReg, return false; } +/// getSingleInterference - Return the single interfering virtual register +/// assigned to PhysReg. Return 0 if more than one virtual register is +/// interfering. +LiveInterval *RAGreedy::getSingleInterference(LiveInterval &VirtReg, + unsigned PhysReg) { + LiveInterval *Interference = 0; + + // Check direct interferences. + LiveIntervalUnion::Query &Q = query(VirtReg, PhysReg); + if (Q.checkInterference()) { + if (!Q.seenAllInterferences()) + return 0; + Q.collectInterferingVRegs(1); + Interference = Q.interferingVRegs().front(); + } + + // Check aliases. + for (const unsigned *AliasI = TRI->getAliasSet(PhysReg); *AliasI; ++AliasI) { + LiveIntervalUnion::Query &Q = query(VirtReg, *AliasI); + if (Q.checkInterference()) { + if (Interference || !Q.seenAllInterferences()) + return 0; + Q.collectInterferingVRegs(1); + Interference = Q.interferingVRegs().front(); + } + } + return Interference; +} + // Attempt to reassign this virtual register to a different physical register. // // FIXME: we are not yet caching these "second-level" interferences discovered @@ -173,23 +204,26 @@ bool RAGreedy::checkUncachedInterference(LiveInterval &VirtReg, // FIXME: This may result in a lot of alias queries. We could summarize alias // live intervals in their parent register's live union, but it's messy. bool RAGreedy::reassignVReg(LiveInterval &InterferingVReg, - unsigned OldPhysReg) { - assert(OldPhysReg == VRM->getPhys(InterferingVReg.reg) && + unsigned WantedPhysReg) { + assert(TargetRegisterInfo::isVirtualRegister(InterferingVReg.reg) && + "Can only reassign virtual registers"); + assert(TRI->regsOverlap(WantedPhysReg, VRM->getPhys(InterferingVReg.reg)) && "inconsistent phys reg assigment"); AllocationOrder Order(InterferingVReg.reg, *VRM, ReservedRegs); while (unsigned PhysReg = Order.next()) { - if (PhysReg == OldPhysReg) + // Don't reassign to a WantedPhysReg alias. + if (TRI->regsOverlap(PhysReg, WantedPhysReg)) continue; if (checkUncachedInterference(InterferingVReg, PhysReg)) continue; - DEBUG(dbgs() << "reassigning: " << InterferingVReg << " from " << - TRI->getName(OldPhysReg) << " to " << TRI->getName(PhysReg) << '\n'); - // Reassign the interfering virtual reg to this physical reg. - PhysReg2LiveUnion[OldPhysReg].extract(InterferingVReg); + unsigned OldAssign = VRM->getPhys(InterferingVReg.reg); + DEBUG(dbgs() << "reassigning: " << InterferingVReg << " from " << + TRI->getName(OldAssign) << " to " << TRI->getName(PhysReg) << '\n'); + PhysReg2LiveUnion[OldAssign].extract(InterferingVReg); VRM->clearVirt(InterferingVReg.reg); VRM->assignVirt2Phys(InterferingVReg.reg, PhysReg); PhysReg2LiveUnion[PhysReg].unify(InterferingVReg); @@ -199,30 +233,32 @@ bool RAGreedy::reassignVReg(LiveInterval &InterferingVReg, return false; } -// Collect all virtual regs currently assigned to PhysReg that interfere with -// VirtReg. -// -// Currently, for simplicity, we only attempt to reassign a single interference -// within the same register class. +/// reassignInterferences - Reassign all interferences to different physical +/// registers such that Virtreg can be assigned to PhysReg. +/// Currently this only works with a single interference. +/// @param VirtReg Currently unassigned virtual register. +/// @param PhysReg Physical register to be cleared. +/// @return True on success, false if nothing was changed. bool RAGreedy::reassignInterferences(LiveInterval &VirtReg, unsigned PhysReg) { - LiveIntervalUnion::Query &Q = query(VirtReg, PhysReg); - - // Limit the interference search to one interference. - Q.collectInterferingVRegs(1); - assert(Q.interferingVRegs().size() == 1 && - "expected at least one interference"); - - // Do not attempt reassignment unless we find only a single interference. - if (!Q.seenAllInterferences()) + LiveInterval *InterferingVReg = getSingleInterference(VirtReg, PhysReg); + if (!InterferingVReg) return false; + if (TargetRegisterInfo::isPhysicalRegister(InterferingVReg->reg)) + return false; + return reassignVReg(*InterferingVReg, PhysReg); +} - // Don't allow any interferences on aliases. - for (const unsigned *AliasI = TRI->getAliasSet(PhysReg); *AliasI; ++AliasI) { - if (query(VirtReg, *AliasI).checkInterference()) - return false; - } - - return reassignVReg(*Q.interferingVRegs()[0], PhysReg); +/// tryReassign - Try to reassign interferences to different physregs. +/// @param VirtReg Currently unassigned virtual register. +/// @param Order Physregs to try. +/// @return Physreg to assign VirtReg, or 0. +unsigned RAGreedy::tryReassign(LiveInterval &VirtReg, AllocationOrder &Order) { + NamedRegionTimer T("Reassign", TimerGroupName, TimePassesIsEnabled); + Order.rewind(); + while (unsigned PhysReg = Order.next()) + if (reassignInterferences(VirtReg, PhysReg)) + return PhysReg; + return 0; } /// trySplit - Try to split VirtReg or one of its interferences, making it @@ -255,29 +291,15 @@ unsigned RAGreedy::selectOrSplit(LiveInterval &VirtReg, // The current VirtReg must either be spillable, or one of its interferences // must have less spill weight. - if (InterferingVirtReg->weight < VirtReg.weight ) { - // For simplicity, only consider reassigning registers in the same class. - if (InterfReg == PhysReg) - ReassignCands.push_back(PhysReg); - else - PhysRegSpillCands.push_back(PhysReg); - } + if (InterferingVirtReg->weight < VirtReg.weight ) + PhysRegSpillCands.push_back(PhysReg); } - // Try to reassign interfering physical register. Priority among - // PhysRegSpillCands does not matter yet, because the reassigned virtual - // registers will still be assigned to physical registers. - { - NamedRegionTimer T("Reassign", TimerGroupName, TimePassesIsEnabled); - for (SmallVectorImpl::iterator PhysRegI = ReassignCands.begin(), - PhysRegE = ReassignCands.end(); PhysRegI != PhysRegE; ++PhysRegI) - if (reassignInterferences(VirtReg, *PhysRegI)) - // Reassignment successfull. Allocate now to this PhysReg. - return *PhysRegI; - } - PhysRegSpillCands.insert(PhysRegSpillCands.end(), ReassignCands.begin(), - ReassignCands.end()); + // Try to reassign interferences. + if (unsigned PhysReg = tryReassign(VirtReg, Order)) + return PhysReg; + // Try splitting VirtReg or interferences. unsigned PhysReg = trySplit(VirtReg, Order, SplitVRegs); if (PhysReg || !SplitVRegs.empty()) return PhysReg;