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
This commit is contained in:
Jakob Stoklund Olesen 2010-12-14 00:37:49 +00:00
parent b64d92e29f
commit 46c83c80c5

View File

@ -80,10 +80,12 @@ public:
static char ID; static char ID;
private: private:
bool checkUncachedInterference(LiveInterval &, unsigned); bool checkUncachedInterference(LiveInterval&, unsigned);
LiveInterval *getSingleInterference(LiveInterval&, unsigned);
bool reassignVReg(LiveInterval &InterferingVReg, unsigned OldPhysReg); bool reassignVReg(LiveInterval &InterferingVReg, unsigned OldPhysReg);
bool reassignInterferences(LiveInterval &VirtReg, unsigned PhysReg); bool reassignInterferences(LiveInterval &VirtReg, unsigned PhysReg);
unsigned tryReassign(LiveInterval&, AllocationOrder&);
unsigned trySplit(LiveInterval&, AllocationOrder&, unsigned trySplit(LiveInterval&, AllocationOrder&,
SmallVectorImpl<LiveInterval*>&); SmallVectorImpl<LiveInterval*>&);
}; };
@ -163,6 +165,35 @@ bool RAGreedy::checkUncachedInterference(LiveInterval &VirtReg,
return false; 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. // Attempt to reassign this virtual register to a different physical register.
// //
// FIXME: we are not yet caching these "second-level" interferences discovered // 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 // 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. // live intervals in their parent register's live union, but it's messy.
bool RAGreedy::reassignVReg(LiveInterval &InterferingVReg, bool RAGreedy::reassignVReg(LiveInterval &InterferingVReg,
unsigned OldPhysReg) { unsigned WantedPhysReg) {
assert(OldPhysReg == VRM->getPhys(InterferingVReg.reg) && assert(TargetRegisterInfo::isVirtualRegister(InterferingVReg.reg) &&
"Can only reassign virtual registers");
assert(TRI->regsOverlap(WantedPhysReg, VRM->getPhys(InterferingVReg.reg)) &&
"inconsistent phys reg assigment"); "inconsistent phys reg assigment");
AllocationOrder Order(InterferingVReg.reg, *VRM, ReservedRegs); AllocationOrder Order(InterferingVReg.reg, *VRM, ReservedRegs);
while (unsigned PhysReg = Order.next()) { while (unsigned PhysReg = Order.next()) {
if (PhysReg == OldPhysReg) // Don't reassign to a WantedPhysReg alias.
if (TRI->regsOverlap(PhysReg, WantedPhysReg))
continue; continue;
if (checkUncachedInterference(InterferingVReg, PhysReg)) if (checkUncachedInterference(InterferingVReg, PhysReg))
continue; continue;
DEBUG(dbgs() << "reassigning: " << InterferingVReg << " from " <<
TRI->getName(OldPhysReg) << " to " << TRI->getName(PhysReg) << '\n');
// Reassign the interfering virtual reg to this physical reg. // 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->clearVirt(InterferingVReg.reg);
VRM->assignVirt2Phys(InterferingVReg.reg, PhysReg); VRM->assignVirt2Phys(InterferingVReg.reg, PhysReg);
PhysReg2LiveUnion[PhysReg].unify(InterferingVReg); PhysReg2LiveUnion[PhysReg].unify(InterferingVReg);
@ -199,30 +233,32 @@ bool RAGreedy::reassignVReg(LiveInterval &InterferingVReg,
return false; return false;
} }
// Collect all virtual regs currently assigned to PhysReg that interfere with /// reassignInterferences - Reassign all interferences to different physical
// VirtReg. /// registers such that Virtreg can be assigned to PhysReg.
// /// Currently this only works with a single interference.
// Currently, for simplicity, we only attempt to reassign a single interference /// @param VirtReg Currently unassigned virtual register.
// within the same register class. /// @param PhysReg Physical register to be cleared.
/// @return True on success, false if nothing was changed.
bool RAGreedy::reassignInterferences(LiveInterval &VirtReg, unsigned PhysReg) { bool RAGreedy::reassignInterferences(LiveInterval &VirtReg, unsigned PhysReg) {
LiveIntervalUnion::Query &Q = query(VirtReg, PhysReg); LiveInterval *InterferingVReg = getSingleInterference(VirtReg, PhysReg);
if (!InterferingVReg)
// 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())
return false; return false;
if (TargetRegisterInfo::isPhysicalRegister(InterferingVReg->reg))
return false;
return reassignVReg(*InterferingVReg, PhysReg);
}
// Don't allow any interferences on aliases. /// tryReassign - Try to reassign interferences to different physregs.
for (const unsigned *AliasI = TRI->getAliasSet(PhysReg); *AliasI; ++AliasI) { /// @param VirtReg Currently unassigned virtual register.
if (query(VirtReg, *AliasI).checkInterference()) /// @param Order Physregs to try.
return false; /// @return Physreg to assign VirtReg, or 0.
} unsigned RAGreedy::tryReassign(LiveInterval &VirtReg, AllocationOrder &Order) {
NamedRegionTimer T("Reassign", TimerGroupName, TimePassesIsEnabled);
return reassignVReg(*Q.interferingVRegs()[0], PhysReg); 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 /// 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 // The current VirtReg must either be spillable, or one of its interferences
// must have less spill weight. // must have less spill weight.
if (InterferingVirtReg->weight < VirtReg.weight ) { if (InterferingVirtReg->weight < VirtReg.weight )
// For simplicity, only consider reassigning registers in the same class. PhysRegSpillCands.push_back(PhysReg);
if (InterfReg == PhysReg)
ReassignCands.push_back(PhysReg);
else
PhysRegSpillCands.push_back(PhysReg);
}
} }
// Try to reassign interfering physical register. Priority among // Try to reassign interferences.
// PhysRegSpillCands does not matter yet, because the reassigned virtual if (unsigned PhysReg = tryReassign(VirtReg, Order))
// registers will still be assigned to physical registers. return PhysReg;
{
NamedRegionTimer T("Reassign", TimerGroupName, TimePassesIsEnabled);
for (SmallVectorImpl<unsigned>::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 splitting VirtReg or interferences.
unsigned PhysReg = trySplit(VirtReg, Order, SplitVRegs); unsigned PhysReg = trySplit(VirtReg, Order, SplitVRegs);
if (PhysReg || !SplitVRegs.empty()) if (PhysReg || !SplitVRegs.empty())
return PhysReg; return PhysReg;