Teach RegisterCoalescer to handle symmetric sub-register copies.

It is possible to coalesce two overlapping registers to a common
super-register that it larger than both of the original registers.

The important difference is that it may be necessary to rewrite DstReg
operands as well as SrcReg operands because the sub-register index has
changed.

This behavior is still disabled by CoalescerPair.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@156869 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jakob Stoklund Olesen 2012-05-15 22:26:28 +00:00
parent 70724aaf73
commit ceacd6da8c

View File

@ -155,7 +155,7 @@ namespace {
/// physical register and the existing subregister number of the def / use /// physical register and the existing subregister number of the def / use
/// being updated is not zero, make sure to set it to the correct physical /// being updated is not zero, make sure to set it to the correct physical
/// subregister. /// subregister.
void updateRegDefsUses(const CoalescerPair &CP); void updateRegDefsUses(unsigned SrcReg, unsigned DstReg, unsigned SubIdx);
/// removeDeadDef - If a def of a live interval is now determined dead, /// removeDeadDef - If a def of a live interval is now determined dead,
/// remove the val# it defines. If the live interval becomes empty, remove /// remove the val# it defines. If the live interval becomes empty, remove
@ -270,6 +270,10 @@ bool CoalescerPair::setRegisters(const MachineInstr *MI) {
// Both registers have subreg indices. // Both registers have subreg indices.
if (SrcSub && DstSub) { if (SrcSub && DstSub) {
// Copies between different sub-registers are never coalescable.
if (Src == Dst && SrcSub != DstSub)
return false;
NewRC = TRI.getCommonSuperRegClass(SrcRC, SrcSub, DstRC, DstSub, NewRC = TRI.getCommonSuperRegClass(SrcRC, SrcSub, DstRC, DstSub,
SrcIdx, DstIdx); SrcIdx, DstIdx);
if (!NewRC) if (!NewRC)
@ -912,11 +916,10 @@ bool RegisterCoalescer::eliminateUndefCopy(MachineInstr *CopyMI,
/// physical register and the existing subregister number of the def / use /// physical register and the existing subregister number of the def / use
/// being updated is not zero, make sure to set it to the correct physical /// being updated is not zero, make sure to set it to the correct physical
/// subregister. /// subregister.
void RegisterCoalescer::updateRegDefsUses(const CoalescerPair &CP) { void RegisterCoalescer::updateRegDefsUses(unsigned SrcReg,
bool DstIsPhys = CP.isPhys(); unsigned DstReg,
unsigned SrcReg = CP.getSrcReg(); unsigned SubIdx) {
unsigned DstReg = CP.getDstReg(); bool DstIsPhys = TargetRegisterInfo::isPhysicalRegister(DstReg);
unsigned SubIdx = CP.getSrcIdx();
// Update LiveDebugVariables. // Update LiveDebugVariables.
LDV->renameRegister(SrcReg, DstReg, SubIdx); LDV->renameRegister(SrcReg, DstReg, SubIdx);
@ -1089,12 +1092,11 @@ bool RegisterCoalescer::joinCopy(MachineInstr *CopyMI, bool &Again) {
return false; // Not coalescable. return false; // Not coalescable.
} }
DEBUG(dbgs() << "\tConsidering merging " << PrintReg(CP.getSrcReg(), TRI)
<< " with " << PrintReg(CP.getDstReg(), TRI, CP.getSrcIdx())
<< "\n");
// Enforce policies. // Enforce policies.
if (CP.isPhys()) { if (CP.isPhys()) {
DEBUG(dbgs() << "\tConsidering merging " << PrintReg(CP.getSrcReg(), TRI)
<< " with " << PrintReg(CP.getDstReg(), TRI, CP.getSrcIdx())
<< '\n');
if (!shouldJoinPhys(CP)) { if (!shouldJoinPhys(CP)) {
// Before giving up coalescing, if definition of source is defined by // Before giving up coalescing, if definition of source is defined by
// trivial computation, try rematerializing it. // trivial computation, try rematerializing it.
@ -1106,12 +1108,20 @@ bool RegisterCoalescer::joinCopy(MachineInstr *CopyMI, bool &Again) {
} }
} else { } else {
DEBUG({ DEBUG({
if (CP.isCrossClass()) dbgs() << "\tConsidering merging to " << CP.getNewRC()->getName()
dbgs() << "\tCross-class to " << CP.getNewRC()->getName() << ".\n"; << " with ";
if (CP.getDstIdx() && CP.getSrcIdx())
dbgs() << PrintReg(CP.getDstReg()) << " in "
<< TRI->getSubRegIndexName(CP.getDstIdx()) << " and "
<< PrintReg(CP.getSrcReg()) << " in "
<< TRI->getSubRegIndexName(CP.getSrcIdx()) << '\n';
else
dbgs() << PrintReg(CP.getSrcReg(), TRI) << " in "
<< PrintReg(CP.getDstReg(), TRI, CP.getSrcIdx()) << '\n';
}); });
// When possible, let DstReg be the larger interval. // When possible, let DstReg be the larger interval.
if (!CP.getSrcIdx() && LIS->getInterval(CP.getSrcReg()).ranges.size() > if (!CP.isPartial() && LIS->getInterval(CP.getSrcReg()).ranges.size() >
LIS->getInterval(CP.getDstReg()).ranges.size()) LIS->getInterval(CP.getDstReg()).ranges.size())
CP.flip(); CP.flip();
} }
@ -1156,7 +1166,11 @@ bool RegisterCoalescer::joinCopy(MachineInstr *CopyMI, bool &Again) {
// Remember to delete the copy instruction. // Remember to delete the copy instruction.
markAsJoined(CopyMI); markAsJoined(CopyMI);
updateRegDefsUses(CP); // Rewrite all SrcReg operands to DstReg.
// Also update DstReg operands to include DstIdx if it is set.
if (CP.getDstIdx())
updateRegDefsUses(CP.getDstReg(), CP.getDstReg(), CP.getDstIdx());
updateRegDefsUses(CP.getSrcReg(), CP.getDstReg(), CP.getSrcIdx());
// If we have extended the live range of a physical register, make sure we // If we have extended the live range of a physical register, make sure we
// update live-in lists as well. // update live-in lists as well.