static cl::opt<bool>
CommuteDef("coalescer-commute-instrs",
- cl::init(false), cl::Hidden);
+ cl::init(true), cl::Hidden);
+
+ static cl::opt<int>
+ CommuteLimit("commute-limit",
+ cl::init(-1), cl::Hidden);
RegisterPass<SimpleRegisterCoalescing>
X("simple-register-coalescing", "Simple Register Coalescing");
return true;
}
+/// HasOtherReachingDefs - Return true if there are definitions of IntB
+/// other than BValNo val# that can reach uses of AValno val# of IntA.
+bool SimpleRegisterCoalescing::HasOtherReachingDefs(LiveInterval &IntA,
+ LiveInterval &IntB,
+ VNInfo *AValNo,
+ VNInfo *BValNo) {
+ for (LiveInterval::iterator AI = IntA.begin(), AE = IntA.end();
+ AI != AE; ++AI) {
+ if (AI->valno != AValNo) continue;
+ LiveInterval::Ranges::iterator BI =
+ std::upper_bound(IntB.ranges.begin(), IntB.ranges.end(), AI->start);
+ if (BI != IntB.ranges.begin())
+ --BI;
+ for (; BI != IntB.ranges.end() && AI->end >= BI->start; ++BI) {
+ if (BI->valno == BValNo)
+ continue;
+ if (BI->start <= AI->start && BI->end > AI->start)
+ return true;
+ if (BI->start > AI->start && BI->start < AI->end)
+ return true;
+ }
+ }
+ return false;
+}
+
/// RemoveCopyByCommutingDef - We found a non-trivially-coalescable copy with IntA
/// being the source and IntB being the dest, thus this defines a value number
/// in IntB. If the source value number (in IntA) is defined by a commutable
unsigned CopyIdx = li_->getDefIndex(li_->getInstructionIndex(CopyMI));
+ // FIXME: For now, only eliminate the copy by commuting its def when the
+ // source register is a virtual register. We want to guard against cases
+ // where the copy is a back edge copy and commuting the def lengthen the
+ // live interval of the source register to the entire loop.
+ if (TargetRegisterInfo::isPhysicalRegister(IntA.reg))
+ return false;
+
// BValNo is a value number in B that is defined by a copy from A. 'B3' in
// the example above.
LiveInterval::iterator BLR = IntB.FindLiveRangeContaining(CopyIdx);
// Make sure there are no other definitions of IntB that would reach the
// uses which the new definition can reach.
- for (LiveInterval::iterator AI = IntA.begin(), AE = IntA.end();
- AI != AE; ++AI) {
- if (AI->valno != AValNo) continue;
- LiveInterval::Ranges::iterator BI =
- std::upper_bound(IntB.ranges.begin(), IntB.ranges.end(), AI->start);
- if (BI != IntB.ranges.begin())
- --BI;
- for (; BI != IntB.ranges.end() && AI->end >= BI->start; ++BI) {
- if (BI->valno == BLR->valno)
- continue;
- if (BI->start <= AI->start && BI->end > AI->start)
- return false;
- if (BI->start > AI->start && BI->start < AI->end)
- return false;
- }
- }
+ if (HasOtherReachingDefs(IntA, IntB, AValNo, BValNo))
+ return false;
+
+ if (CommuteLimit >= 0 && numCommutes >= (unsigned)CommuteLimit)
+ return false;
// At this point we have decided that it is legal to do this
// transformation. Start by commuting the instruction.
MachineBasicBlock *MBB = DefMI->getParent();
MachineInstr *NewMI = tii_->commuteInstruction(DefMI);
+ if (!NewMI)
+ return false;
if (NewMI != DefMI) {
li_->ReplaceMachineInstrInMaps(DefMI, NewMI);
MBB->insert(DefMI, NewMI);
MBB->erase(DefMI);
}
- unsigned OpIdx = NewMI->findRegisterUseOperandIdx(IntA.reg);
+ unsigned OpIdx = NewMI->findRegisterUseOperandIdx(IntA.reg, false);
NewMI->getOperand(OpIdx).setIsKill();
- // Update uses of IntA of the specific Val# with IntB.
bool BHasPHIKill = BValNo->hasPHIKill;
SmallVector<VNInfo*, 4> BDeadValNos;
SmallVector<unsigned, 4> BKills;
std::map<unsigned, unsigned> BExtend;
+
+ // If ALR and BLR overlaps and end of BLR extends beyond end of ALR, e.g.
+ // A = or A, B
+ // ...
+ // B = A
+ // ...
+ // C = A<kill>
+ // ...
+ // = B
+ //
+ // then do not add kills of A to the newly created B interval.
+ bool Extended = BLR->end > ALR->end && ALR->end != ALR->start;
+ if (Extended)
+ BExtend[ALR->end] = BLR->end;
+
+ // Update uses of IntA of the specific Val# with IntB.
for (MachineRegisterInfo::use_iterator UI = mri_->use_begin(IntA.reg),
UE = mri_->use_end(); UI != UE;) {
MachineOperand &UseMO = UI.getOperand();
if (ULR->valno != AValNo)
continue;
UseMO.setReg(NewReg);
- if (UseMO.isKill())
- BKills.push_back(li_->getUseIndex(UseIdx)+1);
if (UseMI == CopyMI)
continue;
+ if (UseMO.isKill()) {
+ if (Extended)
+ UseMO.setIsKill(false);
+ else
+ BKills.push_back(li_->getUseIndex(UseIdx)+1);
+ }
unsigned SrcReg, DstReg;
if (!tii_->isMoveInstr(*UseMI, SrcReg, DstReg))
continue;
JoinedCopies.insert(UseMI);
// If this is a kill but it's going to be removed, the last use
// of the same val# is the new kill.
- if (UseMO.isKill()) {
+ if (UseMO.isKill())
BKills.pop_back();
- }
}
}
return true;
}
-/// RemoveUnnecessaryKills - Remove kill markers that are no longer accurate
-/// due to live range lengthening as the result of coalescing.
-void SimpleRegisterCoalescing::RemoveUnnecessaryKills(unsigned Reg,
- LiveInterval &LI) {
- for (MachineRegisterInfo::use_iterator UI = mri_->use_begin(Reg),
- UE = mri_->use_end(); UI != UE; ++UI) {
- MachineOperand &UseMO = UI.getOperand();
- if (UseMO.isKill()) {
- MachineInstr *UseMI = UseMO.getParent();
- unsigned UseIdx = li_->getUseIndex(li_->getInstructionIndex(UseMI));
- if (JoinedCopies.count(UseMI))
- continue;
- LiveInterval::const_iterator UI = LI.FindLiveRangeContaining(UseIdx);
- assert(UI != LI.end());
- if (!LI.isKill(UI->valno, UseIdx+1))
- UseMO.setIsKill(false);
- }
- }
-}
-
/// isBackEdgeCopy - Returns true if CopyMI is a back edge copy.
///
bool SimpleRegisterCoalescing::isBackEdgeCopy(MachineInstr *CopyMI,
O.setSubReg(0);
} else {
unsigned OldSubIdx = O.getSubReg();
- assert((!SubIdx || !OldSubIdx) && "Conflicting sub-register index!");
- if (SubIdx)
+ // Sub-register indexes goes from small to large. e.g.
+ // RAX: 0 -> AL, 1 -> AH, 2 -> AX, 3 -> EAX
+ // EAX: 0 -> AL, 1 -> AH, 2 -> AX
+ // So RAX's sub-register 2 is AX, RAX's sub-regsiter 3 is EAX, whose
+ // sub-register 2 is also AX.
+ if (SubIdx && OldSubIdx && SubIdx != OldSubIdx)
+ assert(OldSubIdx < SubIdx && "Conflicting sub-register index!");
+ else if (SubIdx)
O.setSubReg(SubIdx);
O.setReg(DstReg);
}
}
}
+/// RemoveUnnecessaryKills - Remove kill markers that are no longer accurate
+/// due to live range lengthening as the result of coalescing.
+void SimpleRegisterCoalescing::RemoveUnnecessaryKills(unsigned Reg,
+ LiveInterval &LI) {
+ for (MachineRegisterInfo::use_iterator UI = mri_->use_begin(Reg),
+ UE = mri_->use_end(); UI != UE; ++UI) {
+ MachineOperand &UseMO = UI.getOperand();
+ if (UseMO.isKill()) {
+ MachineInstr *UseMI = UseMO.getParent();
+ unsigned SReg, DReg;
+ if (!tii_->isMoveInstr(*UseMI, SReg, DReg))
+ continue;
+ unsigned UseIdx = li_->getUseIndex(li_->getInstructionIndex(UseMI));
+ if (JoinedCopies.count(UseMI))
+ continue;
+ LiveInterval::const_iterator UI = LI.FindLiveRangeContaining(UseIdx);
+ assert(UI != LI.end());
+ if (!LI.isKill(UI->valno, UseIdx+1))
+ UseMO.setIsKill(false);
+ }
+ }
+}
+
+/// ShortenDeadCopyLiveRange - Shorten a live range as it's artificially
+/// extended by a dead copy. Mark the last use (if any) of the val# as kill
+/// as ends the live range there. If there isn't another use, then this
+/// live range is dead.
+void SimpleRegisterCoalescing::ShortenDeadCopyLiveRange(LiveInterval &li,
+ MachineInstr *CopyMI) {
+ unsigned CopyIdx = li_->getInstructionIndex(CopyMI);
+ LiveInterval::iterator MLR =
+ li.FindLiveRangeContaining(li_->getDefIndex(CopyIdx));
+ unsigned RemoveStart = MLR->start;
+ unsigned RemoveEnd = MLR->end;
+ unsigned LastUseIdx;
+ MachineOperand *LastUse = lastRegisterUse(RemoveStart, CopyIdx, li.reg,
+ LastUseIdx);
+ if (LastUse) {
+ // Shorten the liveinterval to the end of last use.
+ LastUse->setIsKill();
+ RemoveStart = li_->getDefIndex(LastUseIdx);
+ }
+ li.removeRange(RemoveStart, RemoveEnd, true);
+ if (li.empty())
+ li_->removeInterval(li.reg);
+}
+
/// 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
// Check if it is necessary to propagate "isDead" property before intervals
// are joined.
- MachineOperand *mopd = CopyMI->findRegisterDefOperand(DstReg);
+ MachineOperand *mopd = CopyMI->findRegisterDefOperand(DstReg, false);
bool isDead = mopd->isDead();
bool isShorten = false;
unsigned SrcStart = 0, RemoveStart = 0;
SrcInt.FindLiveRangeContaining(li_->getUseIndex(CopyIdx));
RemoveStart = SrcStart = SrcLR->start;
RemoveEnd = SrcEnd = SrcLR->end;
- // 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 > li_->getDefIndex(CopyIdx)) {
+ // If there are other uses of SrcReg beyond the copy, there is nothing to do.
isDead = false;
} else {
unsigned LastUseIdx;
MachineOperand *LastUse =
lastRegisterUse(SrcStart, CopyIdx, SrcReg, LastUseIdx);
if (LastUse) {
- // Shorten the liveinterval to the end of last use.
+ // There are uses before the copy, just shorten the live range to the end
+ // of last use.
LastUse->setIsKill();
isDead = false;
isShorten = true;
RemoveStart = li_->getDefIndex(LastUseIdx);
- RemoveEnd = SrcEnd;
} else {
+ // This live range is truly dead. Remove it.
MachineInstr *SrcMI = li_->getInstructionFromIndex(SrcStart);
- if (SrcMI) {
- MachineOperand *mops = findDefOperand(SrcMI, SrcReg);
- if (mops)
- // A dead def should have a single cycle interval.
- ++RemoveStart;
- }
+ if (SrcMI && SrcMI->modifiesRegister(SrcReg, tri_))
+ // A dead def should have a single cycle interval.
+ ++RemoveStart;
}
}
}
} else {
MachineInstr *SrcMI = li_->getInstructionFromIndex(SrcStart);
if (SrcMI) {
- MachineOperand *mops = findDefOperand(SrcMI, SrcReg);
- if (mops)
- mops->setIsDead();
+ int DeadIdx = SrcMI->findRegisterDefOperandIdx(SrcReg, false, tri_);
+ if (DeadIdx != -1)
+ SrcMI->getOperand(DeadIdx).setIsDead();
}
}
}
return true;
}
-
// Otherwise, we are unable to join the intervals.
DOUT << "Interference!\n";
Again = true; // May be possible to coalesce later.
// we have to update any aliased register's live ranges to indicate that they
// have clobbered values for this range.
if (TargetRegisterInfo::isPhysicalRegister(DstReg)) {
- // Unset unnecessary kills.
- if (!ResDstInt->containsOneValue()) {
- for (LiveInterval::Ranges::const_iterator I = ResSrcInt->begin(),
- E = ResSrcInt->end(); I != E; ++I)
- unsetRegisterKills(I->start, I->end, DstReg);
- }
-
// If this is a extract_subreg where dst is a physical register, e.g.
// cl = EXTRACT_SUBREG reg1024, 1
// then create and update the actual physical register allocated to RHS.
}
-/// findDefOperand - Returns the MachineOperand that is a def of the specific
-/// register. It returns NULL if the def is not found.
-MachineOperand *SimpleRegisterCoalescing::findDefOperand(MachineInstr *MI,
- unsigned Reg) const {
- for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
- MachineOperand &MO = MI->getOperand(i);
- if (MO.isRegister() && MO.isDef() &&
- tri_->regsOverlap(MO.getReg(), Reg))
- return &MO;
- }
- return NULL;
-}
-
-/// unsetRegisterKills - Unset IsKill property of all uses of specific register
-/// between cycles Start and End.
-void SimpleRegisterCoalescing::unsetRegisterKills(unsigned Start, unsigned End,
- unsigned Reg) {
- int e = (End-1) / InstrSlots::NUM * InstrSlots::NUM;
- int s = Start;
- while (e >= s) {
- // Skip deleted instructions
- MachineInstr *MI = li_->getInstructionFromIndex(e);
- while ((e - InstrSlots::NUM) >= s && !MI) {
- e -= InstrSlots::NUM;
- MI = li_->getInstructionFromIndex(e);
- }
- if (e < s || MI == NULL)
- return;
-
- for (unsigned i = 0, NumOps = MI->getNumOperands(); i != NumOps; ++i) {
- MachineOperand &MO = MI->getOperand(i);
- if (MO.isRegister() && MO.isKill() && MO.getReg() &&
- tri_->regsOverlap(MO.getReg(), Reg)) {
- MO.setIsKill(false);
- }
- }
-
- e -= InstrSlots::NUM;
- }
-}
-
void SimpleRegisterCoalescing::printRegName(unsigned reg) const {
if (TargetRegisterInfo::isPhysicalRegister(reg))
cerr << tri_->getName(reg);
if (tii_->isMoveInstr(*mii, srcReg, dstReg) && srcReg == dstReg) {
// remove from def list
LiveInterval &RegInt = li_->getOrCreateInterval(srcReg);
- MachineOperand *MO = mii->findRegisterDefOperand(dstReg);
// If def of this move instruction is dead, remove its live range from
// the dstination register's live interval.
- if (MO->isDead()) {
- unsigned MoveIdx = li_->getDefIndex(li_->getInstructionIndex(mii));
- LiveInterval::iterator MLR = RegInt.FindLiveRangeContaining(MoveIdx);
- RegInt.removeRange(MLR->start, MoveIdx+1, true);
- if (RegInt.empty())
- li_->removeInterval(srcReg);
- }
+ if (mii->registerDefIsDead(dstReg))
+ ShortenDeadCopyLiveRange(RegInt, mii);
li_->RemoveMachineInstrFromMaps(mii);
mii = mbbi->erase(mii);
++numPeep;