aboutsummaryrefslogtreecommitdiffstats
path: root/lib/CodeGen
diff options
context:
space:
mode:
authorEvan Cheng <evan.cheng@apple.com>2008-06-19 01:39:21 +0000
committerEvan Cheng <evan.cheng@apple.com>2008-06-19 01:39:21 +0000
commite00f5de361bcc69d05e07303460e6849668b7169 (patch)
tree89ecba71ec1a6129624fe4fb56b66f01d82f852d /lib/CodeGen
parent1b38ec83f07d5801035567160008cd7cb99a5c1a (diff)
downloadexternal_llvm-e00f5de361bcc69d05e07303460e6849668b7169.zip
external_llvm-e00f5de361bcc69d05e07303460e6849668b7169.tar.gz
external_llvm-e00f5de361bcc69d05e07303460e6849668b7169.tar.bz2
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
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/SimpleRegisterCoalescing.cpp107
-rw-r--r--lib/CodeGen/SimpleRegisterCoalescing.h16
2 files changed, 98 insertions, 25 deletions
diff --git a/lib/CodeGen/SimpleRegisterCoalescing.cpp b/lib/CodeGen/SimpleRegisterCoalescing.cpp
index f9a2652..24e7fde 100644
--- a/lib/CodeGen/SimpleRegisterCoalescing.cpp
+++ b/lib/CodeGen/SimpleRegisterCoalescing.cpp
@@ -35,6 +35,7 @@
using namespace llvm;
STATISTIC(numJoins , "Number of interval joins performed");
+STATISTIC(numSubJoins , "Number of subclass joins performed");
STATISTIC(numCommutes , "Number of instruction commuting performed");
STATISTIC(numExtends , "Number of copies extended");
STATISTIC(numPeep , "Number of identity moves eliminated after coalescing");
@@ -48,8 +49,13 @@ EnableJoining("join-liveintervals",
static cl::opt<bool>
NewHeuristic("new-coalescer-heuristic",
- cl::desc("Use new coalescer heuristic"),
- cl::init(false));
+ cl::desc("Use new coalescer heuristic"),
+ 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>
X("simple-register-coalescing", "Simple Register Coalescing");
@@ -818,6 +824,41 @@ static unsigned getMatchingSuperReg(unsigned Reg, unsigned SubIdx,
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,
/// 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
@@ -878,6 +919,9 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
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 RealSrcReg = 0;
if (isExtSubReg || isInsSubReg) {
@@ -952,7 +996,8 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
unsigned OldSubIdx = isExtSubReg ? CopyMI->getOperand(0).getSubReg()
: CopyMI->getOperand(2).getSubReg();
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
// coalesced to a larger register so the subreg indices cancel out.
// 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
// with another? If it's the resulting destination register, then
// 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
// the register class of the super-register.
- // If they are not of the same register class, we cannot join them.
- DOUT << "\tSrc/Dest are different register classes.\n";
- // Allow the coalescer to try again in case either side gets coalesced to
- // a physical register that's compatible with the other side. e.g.
- // r1024 = MOV32to32_ r1025
- // but later r1024 is assigned EAX then r1025 may be coalesced with EAX.
- Again = true; // May be possible to coalesce later.
- return false;
+ if (!SubRC || !isProfitableToCoalesceToSubRC(SrcReg, DstReg, CopyMBB)) {
+ // If they are not of the same register class, we cannot join them.
+ DOUT << "\tSrc/Dest are different register classes.\n";
+ // Allow the coalescer to try again in case either side gets coalesced to
+ // a physical register that's compatible with the other side. e.g.
+ // r1024 = MOV32to32_ r1025
+ // but later r1024 is assigned EAX then r1025 may be coalesced with EAX.
+ Again = true; // May be possible to coalesce later.
+ return false;
+ }
}
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) {
// Add all copies that define val# in the source interval into the queue.
for (LiveInterval::const_vni_iterator i = ResSrcInt->vni_begin(),
@@ -1144,7 +1198,7 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
if (CopyMI &&
JoinedCopies.count(CopyMI) == 0 &&
tii_->isMoveInstr(*CopyMI, NewSrcReg, NewDstReg)) {
- unsigned LoopDepth = loopInfo->getLoopDepth(CopyMI->getParent());
+ unsigned LoopDepth = loopInfo->getLoopDepth(CopyMBB);
JoinQueue->push(CopyRec(CopyMI, LoopDepth,
isBackEdgeCopy(CopyMI, DstReg)));
}
@@ -1875,9 +1929,13 @@ void SimpleRegisterCoalescing::joinIntervals() {
}
/// Return true if the two specified registers belong to different register
-/// classes. The registers may be either phys or virt regs.
-bool SimpleRegisterCoalescing::differingRegisterClasses(unsigned RegA,
- unsigned RegB) const {
+/// classes. The registers may be either phys or virt regs. In the
+/// 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
+SimpleRegisterCoalescing::differingRegisterClasses(unsigned RegA, unsigned RegB,
+ const TargetRegisterClass *&SubRC) const {
// Get the register classes for the first reg.
if (TargetRegisterInfo::isPhysicalRegister(RegA)) {
@@ -1887,11 +1945,15 @@ bool SimpleRegisterCoalescing::differingRegisterClasses(unsigned RegA,
}
// Compare against the regclass for the second reg.
- const TargetRegisterClass *RegClass = mri_->getRegClass(RegA);
- if (TargetRegisterInfo::isVirtualRegister(RegB))
- return RegClass != mri_->getRegClass(RegB);
- else
- return !RegClass->contains(RegB);
+ const TargetRegisterClass *RegClassA = mri_->getRegClass(RegA);
+ if (TargetRegisterInfo::isVirtualRegister(RegB)) {
+ const TargetRegisterClass *RegClassB = mri_->getRegClass(RegB);
+ if (RegClassA == RegClassB)
+ return false;
+ SubRC = (RegClassA->hasSubClass(RegClassB)) ? RegClassB : NULL;
+ return true;
+ }
+ return !RegClassA->contains(RegB);
}
/// lastRegisterUse - Returns the last use of the specific register between
@@ -2083,6 +2145,7 @@ bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) {
mii = mbbi->erase(mii);
++numPeep;
} else if (!isMove || !TurnCopyIntoImpDef(mii, mbb, DstReg, SrcReg)) {
+ bool isMem = mii->getDesc().mayLoad() || mii->getDesc().mayStore();
SmallSet<unsigned, 4> UniqueUses;
for (unsigned i = 0, e = mii->getNumOperands(); i != e; ++i) {
const MachineOperand &mop = mii->getOperand(i);
@@ -2095,7 +2158,7 @@ bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) {
continue;
LiveInterval &RegInt = li_->getInterval(reg);
RegInt.weight +=
- li_->getSpillWeight(mop.isDef(), mop.isUse(), loopDepth);
+ li_->getSpillWeight(mop.isDef(), mop.isUse(), isMem, loopDepth);
UniqueUses.insert(reg);
}
}
diff --git a/lib/CodeGen/SimpleRegisterCoalescing.h b/lib/CodeGen/SimpleRegisterCoalescing.h
index a2041ff..3a65a9f 100644
--- a/lib/CodeGen/SimpleRegisterCoalescing.h
+++ b/lib/CodeGen/SimpleRegisterCoalescing.h
@@ -165,9 +165,13 @@ namespace llvm {
/// joins them and returns true.
bool SimpleJoin(LiveInterval &LHS, LiveInterval &RHS);
- /// Return true if the two specified registers belong to different
- /// register classes. The registers may be either phys or virt regs.
- bool differingRegisterClasses(unsigned RegA, unsigned RegB) const;
+ /// Return true if the two specified registers belong to different register
+ /// classes. The registers may be either phys or virt regs. In the
+ /// 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
@@ -205,6 +209,12 @@ namespace llvm {
/// identity copies so they will be removed.
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
/// the specified live interval is defined by a copy from the specified
/// register.