#include "VirtRegMap.h"
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/Value.h"
-#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
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");
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");
AU.addPreservedID(MachineDominatorsID);
AU.addPreservedID(PHIEliminationID);
AU.addPreservedID(TwoAddressInstructionPassID);
- AU.addRequired<LiveVariables>();
AU.addRequired<LiveIntervals>();
AU.addRequired<MachineLoopInfo>();
MachineFunctionPass::getAnalysisUsage(AU);
// simply extend BLR if CopyMI doesn't end the range.
DOUT << "\nExtending: "; IntB.print(DOUT, tri_);
- IntB.removeValNo(BValNo);
+ // Remove val#'s defined by copies that will be coalesced away.
for (unsigned i = 0, e = BDeadValNos.size(); i != e; ++i)
IntB.removeValNo(BDeadValNos[i]);
- VNInfo *ValNo = IntB.getNextValue(AValNo->def, 0, li_->getVNInfoAllocator());
+
+ // Extend BValNo by merging in IntA live ranges of AValNo. Val# definition
+ // is updated. Kills are also updated.
+ VNInfo *ValNo = BValNo;
+ ValNo->def = AValNo->def;
+ ValNo->copy = NULL;
+ for (unsigned j = 0, ee = ValNo->kills.size(); j != ee; ++j) {
+ unsigned Kill = ValNo->kills[j];
+ if (Kill != BLR->end)
+ BKills.push_back(Kill);
+ }
+ ValNo->kills.clear();
for (LiveInterval::iterator AI = IntA.begin(), AE = IntA.end();
AI != AE; ++AI) {
if (AI->valno != AValNo) continue;
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
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) {
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
// if this will cause a high use density interval to target a smaller
// set of registers.
if (SmallRegSize > Threshold || LargeRegSize > Threshold) {
- LiveVariables::VarInfo &svi = lv_->getVarInfo(LargeReg);
- LiveVariables::VarInfo &dvi = lv_->getVarInfo(SmallReg);
- if ((float)dvi.NumUses / SmallRegSize <
- (float)svi.NumUses / LargeRegSize) {
+ if ((float)std::distance(mri_->use_begin(SmallReg),
+ mri_->use_end()) / SmallRegSize <
+ (float)std::distance(mri_->use_begin(LargeReg),
+ mri_->use_end()) / LargeRegSize) {
Again = true; // May be possible to coalesce later.
return false;
}
}
}
}
- } 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
// 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);
// do not join them, instead mark the physical register as its allocation
// preference.
unsigned Length = JoinVInt.getSize() / InstrSlots::NUM;
- LiveVariables::VarInfo &vi = lv_->getVarInfo(JoinVReg);
if (Length > Threshold &&
- (((float)vi.NumUses / Length) < (1.0 / Threshold))) {
+ (((float)std::distance(mri_->use_begin(JoinVReg),
+ mri_->use_end()) / Length) < (1.0 / Threshold))) {
JoinVInt.preference = JoinPReg;
++numAborts;
DOUT << "\tMay tie down a physical register, abort!\n";
for (const unsigned *AS = tri_->getSubRegisters(DstReg); *AS; ++AS)
li_->getOrCreateInterval(*AS).MergeInClobberRanges(*ResSrcInt,
li_->getVNInfoAllocator());
- } else {
- // Merge use info if the destination is a virtual register.
- LiveVariables::VarInfo& dVI = lv_->getVarInfo(DstReg);
- LiveVariables::VarInfo& sVI = lv_->getVarInfo(SrcReg);
- dVI.NumUses += sVI.NumUses;
}
// If this is a EXTRACT_SUBREG, make sure the result of coalescing is the
}
}
+ // 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(),
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)));
}
}
/// 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)) {
}
// 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
tri_ = tm_->getRegisterInfo();
tii_ = tm_->getInstrInfo();
li_ = &getAnalysis<LiveIntervals>();
- lv_ = &getAnalysis<LiveVariables>();
loopInfo = &getAnalysis<MachineLoopInfo>();
DOUT << "********** SIMPLE REGISTER COALESCING **********\n"
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);
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);
}
}