Coalesce copy from one register class to a sub register class. e.g. X86::MOV16to16_.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@52480 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng 2008-06-19 01:39:21 +00:00
parent 1b38ec83f0
commit e00f5de361
2 changed files with 98 additions and 25 deletions

View File

@ -35,6 +35,7 @@
using namespace llvm; using namespace llvm;
STATISTIC(numJoins , "Number of interval joins performed"); STATISTIC(numJoins , "Number of interval joins performed");
STATISTIC(numSubJoins , "Number of subclass joins performed");
STATISTIC(numCommutes , "Number of instruction commuting performed"); STATISTIC(numCommutes , "Number of instruction commuting performed");
STATISTIC(numExtends , "Number of copies extended"); STATISTIC(numExtends , "Number of copies extended");
STATISTIC(numPeep , "Number of identity moves eliminated after coalescing"); STATISTIC(numPeep , "Number of identity moves eliminated after coalescing");
@ -48,8 +49,13 @@ EnableJoining("join-liveintervals",
static cl::opt<bool> static cl::opt<bool>
NewHeuristic("new-coalescer-heuristic", NewHeuristic("new-coalescer-heuristic",
cl::desc("Use new coalescer heuristic"), cl::desc("Use new coalescer heuristic"),
cl::init(false)); cl::init(false), cl::Hidden);
static cl::opt<bool>
CrossClassJoin("join-subclass-copies",
cl::desc("Coalesce copies to sub- register class"),
cl::init(false), cl::Hidden);
static RegisterPass<SimpleRegisterCoalescing> static RegisterPass<SimpleRegisterCoalescing>
X("simple-register-coalescing", "Simple Register Coalescing"); X("simple-register-coalescing", "Simple Register Coalescing");
@ -818,6 +824,41 @@ static unsigned getMatchingSuperReg(unsigned Reg, unsigned SubIdx,
return 0; return 0;
} }
/// isProfitableToCoalesceToSubRC - Given that register class of DstReg is
/// a subset of the register class of SrcReg, return true if it's profitable
/// to coalesce the two registers.
bool
SimpleRegisterCoalescing::isProfitableToCoalesceToSubRC(unsigned SrcReg,
unsigned DstReg,
MachineBasicBlock *MBB){
if (!CrossClassJoin)
return false;
// First let's make sure all uses are in the same MBB.
for (MachineRegisterInfo::reg_iterator RI = mri_->reg_begin(SrcReg),
RE = mri_->reg_end(); RI != RE; ++RI) {
MachineInstr &MI = *RI;
if (MI.getParent() != MBB)
return false;
}
for (MachineRegisterInfo::reg_iterator RI = mri_->reg_begin(DstReg),
RE = mri_->reg_end(); RI != RE; ++RI) {
MachineInstr &MI = *RI;
if (MI.getParent() != MBB)
return false;
}
// Then make sure the intervals are *short*.
LiveInterval &SrcInt = li_->getInterval(SrcReg);
LiveInterval &DstInt = li_->getInterval(DstReg);
unsigned SrcSize = SrcInt.getSize() / InstrSlots::NUM;
unsigned DstSize = DstInt.getSize() / InstrSlots::NUM;
const TargetRegisterClass *RC = mri_->getRegClass(DstReg);
unsigned Threshold = allocatableRCRegs_[RC].count() * 2;
return (SrcSize + DstSize) <= Threshold;
}
/// JoinCopy - Attempt to join intervals corresponding to SrcReg/DstReg, /// JoinCopy - Attempt to join intervals corresponding to SrcReg/DstReg,
/// which are the src/dst of the copy instruction CopyMI. This returns true /// which are the src/dst of the copy instruction CopyMI. This returns true
/// if the copy was successfully coalesced away. If it is not currently /// if the copy was successfully coalesced away. If it is not currently
@ -878,6 +919,9 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
return false; // Not coalescable. return false; // Not coalescable.
} }
// Should be non-null only when coalescing to a sub-register class.
const TargetRegisterClass *SubRC = NULL;
MachineBasicBlock *CopyMBB = CopyMI->getParent();
unsigned RealDstReg = 0; unsigned RealDstReg = 0;
unsigned RealSrcReg = 0; unsigned RealSrcReg = 0;
if (isExtSubReg || isInsSubReg) { if (isExtSubReg || isInsSubReg) {
@ -952,7 +996,8 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
unsigned OldSubIdx = isExtSubReg ? CopyMI->getOperand(0).getSubReg() unsigned OldSubIdx = isExtSubReg ? CopyMI->getOperand(0).getSubReg()
: CopyMI->getOperand(2).getSubReg(); : CopyMI->getOperand(2).getSubReg();
if (OldSubIdx) { if (OldSubIdx) {
if (OldSubIdx == SubIdx && !differingRegisterClasses(SrcReg, DstReg)) if (OldSubIdx == SubIdx &&
!differingRegisterClasses(SrcReg, DstReg, SubRC))
// r1024<2> = EXTRACT_SUBREG r1025, 2. Then r1024 has already been // r1024<2> = EXTRACT_SUBREG r1025, 2. Then r1024 has already been
// coalesced to a larger register so the subreg indices cancel out. // coalesced to a larger register so the subreg indices cancel out.
// Also check if the other larger register is of the same register // Also check if the other larger register is of the same register
@ -986,7 +1031,7 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
} }
} }
} }
} else if (differingRegisterClasses(SrcReg, DstReg)) { } else if (differingRegisterClasses(SrcReg, DstReg, SubRC)) {
// FIXME: What if the resul of a EXTRACT_SUBREG is then coalesced // FIXME: What if the resul of a EXTRACT_SUBREG is then coalesced
// with another? If it's the resulting destination register, then // with another? If it's the resulting destination register, then
// the subidx must be propagated to uses (but only those defined // the subidx must be propagated to uses (but only those defined
@ -994,14 +1039,16 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
// register, it should be safe because register is assumed to have // register, it should be safe because register is assumed to have
// the register class of the super-register. // the register class of the super-register.
// If they are not of the same register class, we cannot join them. if (!SubRC || !isProfitableToCoalesceToSubRC(SrcReg, DstReg, CopyMBB)) {
DOUT << "\tSrc/Dest are different register classes.\n"; // If they are not of the same register class, we cannot join them.
// Allow the coalescer to try again in case either side gets coalesced to DOUT << "\tSrc/Dest are different register classes.\n";
// a physical register that's compatible with the other side. e.g. // Allow the coalescer to try again in case either side gets coalesced to
// r1024 = MOV32to32_ r1025 // a physical register that's compatible with the other side. e.g.
// but later r1024 is assigned EAX then r1025 may be coalesced with EAX. // r1024 = MOV32to32_ r1025
Again = true; // May be possible to coalesce later. // but later r1024 is assigned EAX then r1025 may be coalesced with EAX.
return false; Again = true; // May be possible to coalesce later.
return false;
}
} }
LiveInterval &SrcInt = li_->getInterval(SrcReg); LiveInterval &SrcInt = li_->getInterval(SrcReg);
@ -1132,6 +1179,13 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
} }
} }
// Coalescing to a virtual register that is of a sub-register class of the
// other. Make sure the resulting register is set to the right register class.
if (SubRC) {
mri_->setRegClass(DstReg, SubRC);
++numSubJoins;
}
if (NewHeuristic) { if (NewHeuristic) {
// Add all copies that define val# in the source interval into the queue. // Add all copies that define val# in the source interval into the queue.
for (LiveInterval::const_vni_iterator i = ResSrcInt->vni_begin(), for (LiveInterval::const_vni_iterator i = ResSrcInt->vni_begin(),
@ -1144,7 +1198,7 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
if (CopyMI && if (CopyMI &&
JoinedCopies.count(CopyMI) == 0 && JoinedCopies.count(CopyMI) == 0 &&
tii_->isMoveInstr(*CopyMI, NewSrcReg, NewDstReg)) { tii_->isMoveInstr(*CopyMI, NewSrcReg, NewDstReg)) {
unsigned LoopDepth = loopInfo->getLoopDepth(CopyMI->getParent()); unsigned LoopDepth = loopInfo->getLoopDepth(CopyMBB);
JoinQueue->push(CopyRec(CopyMI, LoopDepth, JoinQueue->push(CopyRec(CopyMI, LoopDepth,
isBackEdgeCopy(CopyMI, DstReg))); isBackEdgeCopy(CopyMI, DstReg)));
} }
@ -1875,9 +1929,13 @@ void SimpleRegisterCoalescing::joinIntervals() {
} }
/// Return true if the two specified registers belong to different register /// Return true if the two specified registers belong to different register
/// classes. The registers may be either phys or virt regs. /// classes. The registers may be either phys or virt regs. In the
bool SimpleRegisterCoalescing::differingRegisterClasses(unsigned RegA, /// case where both registers are virtual registers, it would also returns
unsigned RegB) const { /// true by reference the RegB register class in SubRC if it is a subset of
/// RegA's register class.
bool
SimpleRegisterCoalescing::differingRegisterClasses(unsigned RegA, unsigned RegB,
const TargetRegisterClass *&SubRC) const {
// Get the register classes for the first reg. // Get the register classes for the first reg.
if (TargetRegisterInfo::isPhysicalRegister(RegA)) { if (TargetRegisterInfo::isPhysicalRegister(RegA)) {
@ -1887,11 +1945,15 @@ bool SimpleRegisterCoalescing::differingRegisterClasses(unsigned RegA,
} }
// Compare against the regclass for the second reg. // Compare against the regclass for the second reg.
const TargetRegisterClass *RegClass = mri_->getRegClass(RegA); const TargetRegisterClass *RegClassA = mri_->getRegClass(RegA);
if (TargetRegisterInfo::isVirtualRegister(RegB)) if (TargetRegisterInfo::isVirtualRegister(RegB)) {
return RegClass != mri_->getRegClass(RegB); const TargetRegisterClass *RegClassB = mri_->getRegClass(RegB);
else if (RegClassA == RegClassB)
return !RegClass->contains(RegB); return false;
SubRC = (RegClassA->hasSubClass(RegClassB)) ? RegClassB : NULL;
return true;
}
return !RegClassA->contains(RegB);
} }
/// lastRegisterUse - Returns the last use of the specific register between /// lastRegisterUse - Returns the last use of the specific register between
@ -2083,6 +2145,7 @@ bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) {
mii = mbbi->erase(mii); mii = mbbi->erase(mii);
++numPeep; ++numPeep;
} else if (!isMove || !TurnCopyIntoImpDef(mii, mbb, DstReg, SrcReg)) { } else if (!isMove || !TurnCopyIntoImpDef(mii, mbb, DstReg, SrcReg)) {
bool isMem = mii->getDesc().mayLoad() || mii->getDesc().mayStore();
SmallSet<unsigned, 4> UniqueUses; SmallSet<unsigned, 4> UniqueUses;
for (unsigned i = 0, e = mii->getNumOperands(); i != e; ++i) { for (unsigned i = 0, e = mii->getNumOperands(); i != e; ++i) {
const MachineOperand &mop = mii->getOperand(i); const MachineOperand &mop = mii->getOperand(i);
@ -2095,7 +2158,7 @@ bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) {
continue; continue;
LiveInterval &RegInt = li_->getInterval(reg); LiveInterval &RegInt = li_->getInterval(reg);
RegInt.weight += RegInt.weight +=
li_->getSpillWeight(mop.isDef(), mop.isUse(), loopDepth); li_->getSpillWeight(mop.isDef(), mop.isUse(), isMem, loopDepth);
UniqueUses.insert(reg); UniqueUses.insert(reg);
} }
} }

View File

@ -165,9 +165,13 @@ namespace llvm {
/// joins them and returns true. /// joins them and returns true.
bool SimpleJoin(LiveInterval &LHS, LiveInterval &RHS); bool SimpleJoin(LiveInterval &LHS, LiveInterval &RHS);
/// Return true if the two specified registers belong to different /// Return true if the two specified registers belong to different register
/// register classes. The registers may be either phys or virt regs. /// classes. The registers may be either phys or virt regs. In the
bool differingRegisterClasses(unsigned RegA, unsigned RegB) const; /// case where both registers are virtual registers, it would also returns
/// true by reference the RegB register class in SubRC if it is a subset of
/// RegA's register class.
bool differingRegisterClasses(unsigned RegA, unsigned RegB,
const TargetRegisterClass *&SubRC) const;
/// AdjustCopiesBackFrom - We found a non-trivially-coalescable copy. If /// AdjustCopiesBackFrom - We found a non-trivially-coalescable copy. If
@ -205,6 +209,12 @@ namespace llvm {
/// identity copies so they will be removed. /// identity copies so they will be removed.
void RemoveCopiesFromValNo(LiveInterval &li, VNInfo *VNI); void RemoveCopiesFromValNo(LiveInterval &li, VNInfo *VNI);
/// isProfitableToCoalesceToSubRC - Given that register class of DstReg is
/// a subset of the register class of SrcReg, return true if it's profitable
/// to coalesce the two registers.
bool isProfitableToCoalesceToSubRC(unsigned SrcReg, unsigned DstReg,
MachineBasicBlock *MBB);
/// RangeIsDefinedByCopyFromReg - Return true if the specified live range of /// RangeIsDefinedByCopyFromReg - Return true if the specified live range of
/// the specified live interval is defined by a copy from the specified /// the specified live interval is defined by a copy from the specified
/// register. /// register.