i2miMap_.clear();
r2iMap_.clear();
r2rMap_.clear();
+ JoinedLIs.clear();
}
// are joined.
MachineOperand *mopd = CopyMI->findRegisterDefOperand(DstReg);
bool isDead = mopd->isDead();
+ bool isShorten = false;
unsigned SrcStart = 0;
unsigned SrcEnd = 0;
if (isDead) {
// The instruction which defines the src is only truly dead if there are
// no intermediate uses and there isn't a use beyond the copy.
// FIXME: find the last use, mark is kill and shorten the live range.
- if (SrcEnd > getDefIndex(CopyIdx) ||
- hasRegisterUse(repSrcReg, SrcStart, CopyIdx))
+ if (SrcEnd > getDefIndex(CopyIdx))
isDead = false;
+ else {
+ MachineOperand *MOU;
+ MachineInstr *LastUse =
+ lastRegisterUse(repSrcReg, SrcStart, CopyIdx, MOU);
+ if (LastUse) {
+ // Shorten the liveinterval to the end of last use.
+ MOU->setIsKill();
+ isDead = false;
+ isShorten = true;
+ SrcEnd = getUseIndex(getInstructionIndex(LastUse));
+ }
+ }
+ if (isDead)
+ isShorten = true;
}
// Okay, attempt to join these two intervals. On failure, this returns false.
if (JoinIntervals(DestInt, SrcInt)) {
if (isDead) {
// Result of the copy is dead. Propagate this property.
- if (SrcStart == 0 && MRegisterInfo::isPhysicalRegister(SrcReg)) {
- // Live-in to the function but dead. Remove it from MBB live-in set.
+ if (SrcStart == 0) {
+ assert(MRegisterInfo::isPhysicalRegister(repSrcReg) &&
+ "Live-in must be a physical register!");
+ // Live-in to the function but dead. Remove it from entry live-in set.
// JoinIntervals may end up swapping the two intervals.
- LiveInterval &LiveInInt = (repSrcReg == DestInt.reg) ? DestInt : SrcInt;
- LiveInInt.removeRange(SrcStart, SrcEnd);
- MachineBasicBlock *MBB = CopyMI->getParent();
- MBB->removeLiveIn(SrcReg);
+ mf_->begin()->removeLiveIn(repSrcReg);
} else {
MachineInstr *SrcMI = getInstructionFromIndex(SrcStart);
if (SrcMI) {
- // FIXME: SrcMI == NULL means the register is livein to a non-entry
- // MBB. Remove the range from its live interval?
MachineOperand *mops = SrcMI->findRegisterDefOperand(SrcReg);
if (mops)
// FIXME: mops == NULL means SrcMI defines a subregister?
}
}
}
+
+ if (isShorten) {
+ // Shorten the live interval.
+ LiveInterval &LiveInInt = (repSrcReg == DestInt.reg) ? DestInt : SrcInt;
+ LiveInInt.removeRange(SrcStart, SrcEnd);
+ }
} else {
// Coallescing failed.
DOUT << "\n\t\tJoined. Result = "; DestInt.print(DOUT, mri_);
DOUT << "\n";
- // Live range has been lengthened due to colaescing, eliminate the
- // unnecessary kills at the end of the source live ranges.
- LiveVariables::VarInfo& svi = lv_->getVarInfo(repSrcReg);
- for (unsigned i = 0, e = svi.Kills.size(); i != e; ++i) {
- MachineInstr *Kill = svi.Kills[i];
- if (Kill == CopyMI || isRemoved(Kill))
- continue;
- if (DestInt.liveAt(getInstructionIndex(Kill) + InstrSlots::NUM))
- unsetRegisterKill(Kill, repSrcReg);
- }
- if (MRegisterInfo::isVirtualRegister(repDstReg)) {
- // If both are virtual registers...
- LiveVariables::VarInfo& dvi = lv_->getVarInfo(repDstReg);
- for (unsigned i = 0, e = dvi.Kills.size(); i != e; ++i) {
- MachineInstr *Kill = dvi.Kills[i];
- if (Kill == CopyMI || isRemoved(Kill))
- continue;
- if (DestInt.liveAt(getInstructionIndex(Kill) + InstrSlots::NUM))
- unsetRegisterKill(Kill, repDstReg);
- }
- }
+ // Remember these liveintervals have been joined.
+ JoinedLIs.set(repSrcReg - MRegisterInfo::FirstVirtualRegister);
+ if (MRegisterInfo::isVirtualRegister(repDstReg))
+ JoinedLIs.set(repDstReg - MRegisterInfo::FirstVirtualRegister);
// If the intervals were swapped by Join, swap them back so that the register
// mapping (in the r2i map) is correct.
void LiveIntervals::joinIntervals() {
DOUT << "********** JOINING INTERVALS ***********\n";
+ JoinedLIs.resize(getNumIntervals());
+ JoinedLIs.reset();
+
std::vector<CopyRec> TryAgainList;
-
const LoopInfo &LI = getAnalysis<LoopInfo>();
if (LI.begin() == LI.end()) {
// If there are no loops in the function, join intervals in function order.
}
}
}
+
+ // Some live range has been lengthened due to colaescing, eliminate the
+ // unnecessary kills.
+ int RegNum = JoinedLIs.find_first();
+ while (RegNum != -1) {
+ unsigned Reg = RegNum + MRegisterInfo::FirstVirtualRegister;
+ unsigned repReg = rep(Reg);
+ LiveInterval &LI = getInterval(repReg);
+ LiveVariables::VarInfo& svi = lv_->getVarInfo(Reg);
+ for (unsigned i = 0, e = svi.Kills.size(); i != e; ++i) {
+ MachineInstr *Kill = svi.Kills[i];
+ // Suppose vr1 = op vr2, x
+ // and vr1 and vr2 are coalesced. vr2 should still be marked kill
+ // unless it is a two-address operand.
+ if (isRemoved(Kill) || hasRegisterDef(Kill, repReg))
+ continue;
+ if (LI.liveAt(getInstructionIndex(Kill) + InstrSlots::NUM))
+ unsetRegisterKill(Kill, repReg);
+ }
+ RegNum = JoinedLIs.find_next(RegNum);
+ }
DOUT << "*** Register mapping ***\n";
for (int i = 0, e = r2rMap_.size(); i != e; ++i)
return !RegClass->contains(RegB);
}
-/// hasRegisterUse - Returns true if there is any use of the specific
-/// reg between indexes Start and End.
-bool
-LiveIntervals::hasRegisterUse(unsigned Reg, unsigned Start, unsigned End) {
- for (unsigned Index = Start+InstrSlots::NUM; Index < End;
- Index += InstrSlots::NUM) {
+/// lastRegisterUse - Returns the last use of the specific register between
+/// cycles Start and End. It also returns the use operand by reference. It
+/// returns NULL if there are no uses.
+MachineInstr *
+LiveIntervals::lastRegisterUse(unsigned Reg, unsigned Start, unsigned End,
+ MachineOperand *&MOU) {
+ int e = (End-1) / InstrSlots::NUM * InstrSlots::NUM;
+ int s = Start;
+ while (e >= s) {
// Skip deleted instructions
- while (Index < End && !getInstructionFromIndex(Index))
- Index += InstrSlots::NUM;
- if (Index >= End) break;
+ MachineInstr *MI = getInstructionFromIndex(e);
+ while ((e - InstrSlots::NUM) >= s && !MI) {
+ e -= InstrSlots::NUM;
+ MI = getInstructionFromIndex(e);
+ }
+ if (e < s || MI == NULL)
+ return NULL;
- MachineInstr *MI = getInstructionFromIndex(Index);
- for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+ for (unsigned i = 0, NumOps = MI->getNumOperands(); i != NumOps; ++i) {
MachineOperand &MO = MI->getOperand(i);
if (MO.isReg() && MO.isUse() && MO.getReg() &&
- mri_->regsOverlap(rep(MO.getReg()), Reg))
- return true;
+ mri_->regsOverlap(rep(MO.getReg()), Reg)) {
+ MOU = &MO;
+ return MI;
+ }
}
+
+ e -= InstrSlots::NUM;
}
- return false;
+ return NULL;
}
/// unsetRegisterKill - Unset IsKill property of all uses of specific register
}
}
+/// hasRegisterDef - True if the instruction defines the specific register.
+///
+bool LiveIntervals::hasRegisterDef(MachineInstr *MI, unsigned Reg) {
+ for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+ MachineOperand &MO = MI->getOperand(i);
+ if (MO.isReg() && MO.isDef() &&
+ mri_->regsOverlap(rep(MO.getReg()), Reg))
+ return true;
+ }
+ return false;
+}
+
LiveInterval LiveIntervals::createInterval(unsigned reg) {
float Weight = MRegisterInfo::isPhysicalRegister(reg) ?
HUGE_VALF : 0.0F;