STATISTIC(numAborts , "Number of times interval joining aborted");
char SimpleRegisterCoalescing::ID = 0;
-namespace {
- static cl::opt<bool>
- EnableJoining("join-liveintervals",
- cl::desc("Coalesce copies (default=true)"),
- cl::init(true));
+static cl::opt<bool>
+EnableJoining("join-liveintervals",
+ cl::desc("Coalesce copies (default=true)"),
+ cl::init(true));
- static cl::opt<bool>
- NewHeuristic("new-coalescer-heuristic",
- cl::desc("Use new coalescer heuristic"),
- cl::init(false));
+static cl::opt<bool>
+NewHeuristic("new-coalescer-heuristic",
+ cl::desc("Use new coalescer heuristic"),
+ cl::init(false));
- RegisterPass<SimpleRegisterCoalescing>
- X("simple-register-coalescing", "Simple Register Coalescing");
+static RegisterPass<SimpleRegisterCoalescing>
+X("simple-register-coalescing", "Simple Register Coalescing");
- // Declare that we implement the RegisterCoalescer interface
- RegisterAnalysisGroup<RegisterCoalescer, true/*The Default*/> V(X);
-}
+// Declare that we implement the RegisterCoalescer interface
+static RegisterAnalysisGroup<RegisterCoalescer, true/*The Default*/> V(X);
const PassInfo *llvm::SimpleRegisterCoalescingID = X.getPassInfo();
MachineOperand &O = I.getOperand();
MachineInstr *UseMI = &*I;
++I;
+ unsigned OldSubIdx = O.getSubReg();
if (DstIsPhys) {
- unsigned UseSubIdx = O.getSubReg();
unsigned UseDstReg = DstReg;
- if (UseSubIdx)
- UseDstReg = tri_->getSubReg(DstReg, UseSubIdx);
+ if (OldSubIdx)
+ UseDstReg = tri_->getSubReg(DstReg, OldSubIdx);
O.setReg(UseDstReg);
O.setSubReg(0);
} else {
- unsigned OldSubIdx = O.getSubReg();
// 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
+ // RAX: 1 -> AL, 2 -> AX, 3 -> EAX
+ // EAX: 1 -> AL, 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)
/// removeIntervalIfEmpty - Check if the live interval of a physical register
/// is empty, if so remove it and also remove the empty intervals of its
-/// sub-registers.
-static void removeIntervalIfEmpty(LiveInterval &li, LiveIntervals *li_,
+/// sub-registers. Return true if live interval is removed.
+static bool removeIntervalIfEmpty(LiveInterval &li, LiveIntervals *li_,
const TargetRegisterInfo *tri_) {
if (li.empty()) {
if (TargetRegisterInfo::isPhysicalRegister(li.reg))
li_->removeInterval(*SR);
}
li_->removeInterval(li.reg);
+ return true;
}
+ return false;
}
/// ShortenDeadCopyLiveRange - Shorten a live range defined by a dead copy.
-///
-void SimpleRegisterCoalescing::ShortenDeadCopyLiveRange(LiveInterval &li,
+/// Return true if live interval is removed.
+bool SimpleRegisterCoalescing::ShortenDeadCopyLiveRange(LiveInterval &li,
MachineInstr *CopyMI) {
unsigned CopyIdx = li_->getInstructionIndex(CopyMI);
LiveInterval::iterator MLR =
li.FindLiveRangeContaining(li_->getDefIndex(CopyIdx));
if (MLR == li.end())
- return; // Already removed by ShortenDeadCopySrcLiveRange.
+ return false; // Already removed by ShortenDeadCopySrcLiveRange.
unsigned RemoveStart = MLR->start;
unsigned RemoveEnd = MLR->end;
// Remove the liverange that's defined by this.
if (RemoveEnd == li_->getDefIndex(CopyIdx)+1) {
removeRange(li, RemoveStart, RemoveEnd, li_, tri_);
- removeIntervalIfEmpty(li, li_, tri_);
+ return removeIntervalIfEmpty(li, li_, tri_);
}
+ return false;
}
/// PropagateDeadness - Propagate the dead marker to the instruction which
}
}
-/// 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
+/// isSameOrFallThroughBB - Return true if MBB == SuccMBB or MBB simply
+/// fallthoughs to SuccMBB.
+static bool isSameOrFallThroughBB(MachineBasicBlock *MBB,
+ MachineBasicBlock *SuccMBB,
+ const TargetInstrInfo *tii_) {
+ if (MBB == SuccMBB)
+ return true;
+ MachineBasicBlock *TBB = 0, *FBB = 0;
+ std::vector<MachineOperand> Cond;
+ return !tii_->AnalyzeBranch(*MBB, TBB, FBB, Cond) && !TBB && !FBB &&
+ MBB->isSuccessor(SuccMBB);
+}
+
+/// ShortenDeadCopySrcLiveRange - 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. Return true if live interval is removed.
+bool
SimpleRegisterCoalescing::ShortenDeadCopySrcLiveRange(LiveInterval &li,
MachineInstr *CopyMI) {
unsigned CopyIdx = li_->getInstructionIndex(CopyMI);
// first instruction index starts at > 0 value.
assert(TargetRegisterInfo::isPhysicalRegister(li.reg));
// Live-in to the function but dead. Remove it from entry live-in set.
- mf_->begin()->removeLiveIn(li.reg);
+ if (mf_->begin()->isLiveIn(li.reg))
+ mf_->begin()->removeLiveIn(li.reg);
const LiveRange *LR = li.getLiveRangeContaining(CopyIdx);
removeRange(li, LR->start, LR->end, li_, tri_);
- removeIntervalIfEmpty(li, li_, tri_);
- return;
+ return removeIntervalIfEmpty(li, li_, tri_);
}
LiveInterval::iterator LR = li.FindLiveRangeContaining(CopyIdx-1);
if (LR == li.end())
// Livein but defined by a phi.
- return;
+ return false;
unsigned RemoveStart = LR->start;
unsigned RemoveEnd = li_->getDefIndex(CopyIdx)+1;
if (LR->end > RemoveEnd)
// More uses past this copy? Nothing to do.
- return;
+ return false;
+ MachineBasicBlock *CopyMBB = CopyMI->getParent();
+ unsigned MBBStart = li_->getMBBStartIdx(CopyMBB);
unsigned LastUseIdx;
MachineOperand *LastUse = lastRegisterUse(LR->start, CopyIdx-1, li.reg,
LastUseIdx);
if (LastUse) {
+ MachineInstr *LastUseMI = LastUse->getParent();
+ if (!isSameOrFallThroughBB(LastUseMI->getParent(), CopyMBB, tii_)) {
+ // r1024 = op
+ // ...
+ // BB1:
+ // = r1024
+ //
+ // BB2:
+ // r1025<dead> = r1024<kill>
+ if (MBBStart < LR->end)
+ removeRange(li, MBBStart, LR->end, li_, tri_);
+ return false;
+ }
+
// There are uses before the copy, just shorten the live range to the end
// of last use.
LastUse->setIsKill();
- MachineInstr *LastUseMI = LastUse->getParent();
removeRange(li, li_->getDefIndex(LastUseIdx), LR->end, li_, tri_);
unsigned SrcReg, DstReg;
if (tii_->isMoveInstr(*LastUseMI, SrcReg, DstReg) &&
int DeadIdx = LastUseMI->findRegisterDefOperandIdx(li.reg, false, tri_);
LastUseMI->getOperand(DeadIdx).setIsDead();
}
- return;
+ return false;
}
// Is it livein?
- MachineBasicBlock *CopyMBB = CopyMI->getParent();
- unsigned MBBStart = li_->getMBBStartIdx(CopyMBB);
if (LR->start <= MBBStart && LR->end > MBBStart) {
if (LR->start == 0) {
assert(TargetRegisterInfo::isPhysicalRegister(li.reg));
PropagateDeadness(li, CopyMI, RemoveStart, li_, tri_);
removeRange(li, RemoveStart, LR->end, li_, tri_);
- removeIntervalIfEmpty(li, li_, tri_);
+ return removeIntervalIfEmpty(li, li_, tri_);
}
/// CanCoalesceWithImpDef - Returns true if the specified copy instruction
if (SrcIsPhys && isExtSubReg) {
// r1024 = EXTRACT_SUBREG EAX, 0 then r1024 is really going to be
// coalesced with AX.
- SrcReg = tri_->getSubReg(SrcReg, SubIdx);
+ unsigned DstSubIdx = CopyMI->getOperand(0).getSubReg();
+ if (DstSubIdx) {
+ // r1024<2> = EXTRACT_SUBREG EAX, 2. Then r1024 has already been
+ // coalesced to a larger register so the subreg indices cancel out.
+ if (DstSubIdx != SubIdx) {
+ DOUT << "\t Sub-register indices mismatch.\n";
+ return false; // Not coalescable.
+ }
+ } else
+ SrcReg = tri_->getSubReg(SrcReg, SubIdx);
SubIdx = 0;
} else if (DstIsPhys && isInsSubReg) {
// EAX = INSERT_SUBREG EAX, r1024, 0
- DstReg = tri_->getSubReg(DstReg, SubIdx);
+ unsigned SrcSubIdx = CopyMI->getOperand(2).getSubReg();
+ if (SrcSubIdx) {
+ // EAX = INSERT_SUBREG EAX, r1024<2>, 2 Then r1024 has already been
+ // coalesced to a larger register so the subreg indices cancel out.
+ if (SrcSubIdx != SubIdx) {
+ DOUT << "\t Sub-register indices mismatch.\n";
+ return false; // Not coalescable.
+ }
+ } else
+ DstReg = tri_->getSubReg(DstReg, SubIdx);
SubIdx = 0;
} else if ((DstIsPhys && isExtSubReg) || (SrcIsPhys && isInsSubReg)) {
// If this is a extract_subreg where dst is a physical register, e.g.
// then create and update the actual physical register allocated to RHS.
// Ditto for
// reg1024 = INSERT_SUBREG r1024, cl, 1
+ if (CopyMI->getOperand(1).getSubReg()) {
+ DOUT << "\tSrc of extract_ / insert_subreg already coalesced with reg"
+ << " of a super-class.\n";
+ return false; // Not coalescable.
+ }
const TargetRegisterClass *RC =
mri_->getRegClass(isExtSubReg ? SrcReg : DstReg);
if (isExtSubReg) {
}
SubIdx = 0;
} else {
- unsigned LargeReg = isExtSubReg ? SrcReg : DstReg;
- unsigned SmallReg = isExtSubReg ? DstReg : SrcReg;
- unsigned LargeRegSize =
- li_->getInterval(LargeReg).getSize() / InstrSlots::NUM;
- unsigned SmallRegSize =
- li_->getInterval(SmallReg).getSize() / InstrSlots::NUM;
- const TargetRegisterClass *RC = mri_->getRegClass(SmallReg);
- unsigned Threshold = allocatableRCRegs_[RC].count();
- // Be conservative. If both sides are virtual registers, do not coalesce
- // 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) {
- Again = true; // May be possible to coalesce later.
- return false;
+ unsigned OldSubIdx = isExtSubReg ? CopyMI->getOperand(0).getSubReg()
+ : CopyMI->getOperand(2).getSubReg();
+ if (OldSubIdx) {
+ if (OldSubIdx == SubIdx && !differingRegisterClasses(SrcReg, DstReg))
+ // 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
+ // class as the would be resulting register.
+ SubIdx = 0;
+ else {
+ DOUT << "\t Sub-register indices mismatch.\n";
+ return false; // Not coalescable.
+ }
+ }
+ if (SubIdx) {
+ unsigned LargeReg = isExtSubReg ? SrcReg : DstReg;
+ unsigned SmallReg = isExtSubReg ? DstReg : SrcReg;
+ unsigned LargeRegSize =
+ li_->getInterval(LargeReg).getSize() / InstrSlots::NUM;
+ unsigned SmallRegSize =
+ li_->getInterval(SmallReg).getSize() / InstrSlots::NUM;
+ const TargetRegisterClass *RC = mri_->getRegClass(SmallReg);
+ unsigned Threshold = allocatableRCRegs_[RC].count();
+ // Be conservative. If both sides are virtual registers, do not coalesce
+ // 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) {
+ Again = true; // May be possible to coalesce later.
+ return false;
+ }
}
}
}
I->second.print(DOUT, tri_);
DOUT << "\n";
}
-
- // Delete all coalesced copies.
- for (SmallPtrSet<MachineInstr*,32>::iterator I = JoinedCopies.begin(),
- E = JoinedCopies.end(); I != E; ++I) {
- MachineInstr *CopyMI = *I;
- unsigned SrcReg, DstReg;
- if (!tii_->isMoveInstr(*CopyMI, SrcReg, DstReg)) {
- assert((CopyMI->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG ||
- CopyMI->getOpcode() == TargetInstrInfo::INSERT_SUBREG) &&
- "Unrecognized copy instruction");
- DstReg = CopyMI->getOperand(0).getReg();
- }
- if (CopyMI->registerDefIsDead(DstReg)) {
- LiveInterval &li = li_->getInterval(DstReg);
- ShortenDeadCopySrcLiveRange(li, CopyMI);
- ShortenDeadCopyLiveRange(li, CopyMI);
- }
- li_->RemoveMachineInstrFromMaps(*I);
- (*I)->eraseFromParent();
- ++numPeep;
- }
}
// Perform a final pass over the instructions and compute spill weights
for (MachineBasicBlock::iterator mii = mbb->begin(), mie = mbb->end();
mii != mie; ) {
- // if the move will be an identity move delete it
- unsigned srcReg, dstReg;
- bool isMove = tii_->isMoveInstr(*mii, srcReg, dstReg);
- if (isMove && srcReg == dstReg) {
- if (li_->hasInterval(srcReg)) {
- LiveInterval &RegInt = li_->getInterval(srcReg);
+ MachineInstr *MI = mii;
+ unsigned SrcReg, DstReg;
+ if (JoinedCopies.count(MI)) {
+ // Delete all coalesced copies.
+ if (!tii_->isMoveInstr(*MI, SrcReg, DstReg)) {
+ assert((MI->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG ||
+ MI->getOpcode() == TargetInstrInfo::INSERT_SUBREG) &&
+ "Unrecognized copy instruction");
+ DstReg = MI->getOperand(0).getReg();
+ }
+ if (MI->registerDefIsDead(DstReg)) {
+ LiveInterval &li = li_->getInterval(DstReg);
+ if (!ShortenDeadCopySrcLiveRange(li, MI))
+ ShortenDeadCopyLiveRange(li, MI);
+ }
+ li_->RemoveMachineInstrFromMaps(MI);
+ mii = mbbi->erase(mii);
+ ++numPeep;
+ continue;
+ }
+
+ // If the move will be an identity move delete it
+ bool isMove = tii_->isMoveInstr(*mii, SrcReg, DstReg);
+ if (isMove && SrcReg == DstReg) {
+ if (li_->hasInterval(SrcReg)) {
+ LiveInterval &RegInt = li_->getInterval(SrcReg);
// If def of this move instruction is dead, remove its live range
// from the dstination register's live interval.
- if (mii->registerDefIsDead(dstReg)) {
- ShortenDeadCopySrcLiveRange(RegInt, mii);
- ShortenDeadCopyLiveRange(RegInt, mii);
+ if (mii->registerDefIsDead(DstReg)) {
+ if (!ShortenDeadCopySrcLiveRange(RegInt, mii))
+ ShortenDeadCopyLiveRange(RegInt, mii);
}
}
li_->RemoveMachineInstrFromMaps(mii);
mii = mbbi->erase(mii);
++numPeep;
- } else if (!isMove || !TurnCopyIntoImpDef(mii, mbb, dstReg, srcReg)) {
+ } else if (!isMove || !TurnCopyIntoImpDef(mii, mbb, DstReg, SrcReg)) {
SmallSet<unsigned, 4> UniqueUses;
for (unsigned i = 0, e = mii->getNumOperands(); i != e; ++i) {
const MachineOperand &mop = mii->getOperand(i);