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();
// 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);
+ if (BLR == IntB.end()) // Should never happen!
+ return false;
VNInfo *BValNo = BLR->valno;
// Get the location that B is defined at. Two options: either this value has
// AValNo is the value number in A that defines the copy, A3 in the example.
LiveInterval::iterator ALR = IntA.FindLiveRangeContaining(CopyIdx-1);
+ if (ALR == IntA.end()) // Should never happen!
+ return false;
VNInfo *AValNo = ALR->valno;
// If AValNo is defined as a copy from IntB, we can potentially process this.
// Get the LiveRange in IntB that this value number starts with.
LiveInterval::iterator ValLR = IntB.FindLiveRangeContaining(AValNo->def-1);
+ if (ValLR == IntB.end()) // Should never happen!
+ return false;
// Make sure that the end of the live range is inside the same block as
// CopyMI.
// 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);
+ if (BLR == IntB.end()) // Should never happen!
+ return false;
VNInfo *BValNo = BLR->valno;
// Get the location that B is defined at. Two options: either this value has
// AValNo is the value number in A that defines the copy, A3 in the example.
LiveInterval::iterator ALR = IntA.FindLiveRangeContaining(CopyIdx-1);
+ if (ALR == IntA.end()) // Should never happen!
+ return false;
VNInfo *AValNo = ALR->valno;
// If other defs can reach uses of this def, then it's not safe to perform
// the optimization.
MachineInstr *UseMI = &*UI;
unsigned UseIdx = li_->getInstructionIndex(UseMI);
LiveInterval::iterator ULR = IntA.FindLiveRangeContaining(UseIdx);
+ if (ULR == IntA.end())
+ continue;
if (ULR->valno == AValNo && JoinedCopies.count(UseMI))
return false;
}
continue;
unsigned UseIdx = li_->getInstructionIndex(UseMI);
LiveInterval::iterator ULR = IntA.FindLiveRangeContaining(UseIdx);
- if (ULR->valno != AValNo)
+ if (ULR == IntA.end() || ULR->valno != AValNo)
continue;
UseMO.setReg(NewReg);
if (UseMI == CopyMI)
// remove that val# as well. However this live range is being
// extended to the end of the existing live range defined by the copy.
unsigned DefIdx = li_->getDefIndex(UseIdx);
- LiveInterval::iterator DLR = IntB.FindLiveRangeContaining(DefIdx);
+ const LiveRange *DLR = IntB.getLiveRangeContaining(DefIdx);
BHasPHIKill |= DLR->valno->hasPHIKill;
assert(DLR->valno->def == DefIdx);
BDeadValNos.push_back(DLR->valno);
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)
unsigned UseIdx = li_->getUseIndex(li_->getInstructionIndex(UseMI));
if (JoinedCopies.count(UseMI))
continue;
- LiveInterval::const_iterator UI = LI.FindLiveRangeContaining(UseIdx);
- assert(UI != LI.end());
+ const LiveRange *UI = LI.getLiveRangeContaining(UseIdx);
if (!LI.isKill(UI->valno, UseIdx+1))
UseMO.setIsKill(false);
}
/// 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()) {
- li_->removeInterval(li.reg);
if (TargetRegisterInfo::isPhysicalRegister(li.reg))
for (const unsigned* SR = tri_->getSubRegisters(li.reg); *SR; ++SR) {
if (!li_->hasInterval(*SR))
if (sli.empty())
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);
- LiveInterval::iterator LR = li.FindLiveRangeContaining(CopyIdx);
+ 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);
+ 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
continue;
unsigned UseIdx = li_->getUseIndex(li_->getInstructionIndex(UseMI));
LiveInterval::iterator ULR = li.FindLiveRangeContaining(UseIdx);
- if (ULR->valno != LR->valno)
+ if (ULR == li.end() || ULR->valno != LR->valno)
continue;
// If the use is not a use, then it's not safe to coalesce the move.
unsigned SrcReg, DstReg;
/// identity copies so they will be removed.
void SimpleRegisterCoalescing::RemoveCopiesFromValNo(LiveInterval &li,
VNInfo *VNI) {
- for (MachineRegisterInfo::use_iterator UI = mri_->use_begin(li.reg),
- UE = mri_->use_end(); UI != UE;) {
- MachineInstr *UseMI = &*UI;
- ++UI;
- if (JoinedCopies.count(UseMI))
+ MachineInstr *ImpDef = NULL;
+ MachineOperand *LastUse = NULL;
+ unsigned LastUseIdx = li_->getUseIndex(VNI->def);
+ for (MachineRegisterInfo::reg_iterator RI = mri_->reg_begin(li.reg),
+ RE = mri_->reg_end(); RI != RE;) {
+ MachineOperand *MO = &RI.getOperand();
+ MachineInstr *MI = &*RI;
+ ++RI;
+ if (MO->isDef()) {
+ if (MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF) {
+ assert(!ImpDef && "Multiple implicit_def defining same register?");
+ ImpDef = MI;
+ }
continue;
- unsigned UseIdx = li_->getUseIndex(li_->getInstructionIndex(UseMI));
- LiveInterval::iterator ULR = li.FindLiveRangeContaining(UseIdx);
- if (ULR->valno != VNI)
+ }
+ if (JoinedCopies.count(MI))
continue;
- if (UseMI->getOpcode() == TargetInstrInfo::INSERT_SUBREG)
+ unsigned UseIdx = li_->getUseIndex(li_->getInstructionIndex(MI));
+ LiveInterval::iterator ULR = li.FindLiveRangeContaining(UseIdx);
+ if (ULR == li.end() || ULR->valno != VNI)
continue;
// If the use is a copy, turn it into an identity copy.
unsigned SrcReg, DstReg;
- if (!tii_->isMoveInstr(*UseMI, SrcReg, DstReg) || SrcReg != li.reg)
- assert(0 && "Unexpected use of implicit def!");
- // Each UseMI may have multiple uses of this register. Change them all.
- for (unsigned i = 0, e = UseMI->getNumOperands(); i != e; ++i) {
- MachineOperand &MO = UseMI->getOperand(i);
- if (MO.isReg() && MO.getReg() == li.reg)
- MO.setReg(DstReg);
+ if (tii_->isMoveInstr(*MI, SrcReg, DstReg) && SrcReg == li.reg) {
+ // Each use MI may have multiple uses of this register. Change them all.
+ for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+ MachineOperand &MO = MI->getOperand(i);
+ if (MO.isReg() && MO.getReg() == li.reg)
+ MO.setReg(DstReg);
+ }
+ JoinedCopies.insert(MI);
+ } else if (UseIdx > LastUseIdx) {
+ LastUseIdx = UseIdx;
+ LastUse = MO;
}
- JoinedCopies.insert(UseMI);
+ }
+ if (LastUse)
+ LastUse->setIsKill();
+ else {
+ // Remove dead implicit_def.
+ li_->RemoveMachineInstrFromMaps(ImpDef);
+ ImpDef->eraseFromParent();
}
}
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;
+ }
}
}
}
SmallSet<const VNInfo*, 4> CopiedValNos;
for (LiveInterval::Ranges::const_iterator I = ResSrcInt->ranges.begin(),
E = ResSrcInt->ranges.end(); I != E; ++I) {
- LiveInterval::const_iterator DstLR =
- ResDstInt->FindLiveRangeContaining(I->start);
- assert(DstLR != ResDstInt->end() && "Invalid joined interval!");
+ const LiveRange *DstLR = ResDstInt->getLiveRangeContaining(I->start);
+ assert(DstLR && "Invalid joined interval!");
const VNInfo *DstValNo = DstLR->valno;
if (CopiedValNos.insert(DstValNo)) {
VNInfo *ValNo = RealInt.getNextValue(DstValNo->def, DstValNo->copy,
// by the copy is being defined by an IMPLICIT_DEF which defines a zero
// length interval. Remove the val#.
unsigned CopyIdx = li_->getDefIndex(li_->getInstructionIndex(CopyMI));
- LiveInterval::iterator LR = ResDstInt->FindLiveRangeContaining(CopyIdx);
+ const LiveRange *LR = ResDstInt->getLiveRangeContaining(CopyIdx);
VNInfo *ImpVal = LR->valno;
assert(ImpVal->def == CopyIdx);
unsigned NextDef = LR->end;
if (!li_->hasInterval(DstReg))
return false;
LiveInterval &DstInt = li_->getInterval(DstReg);
- LiveInterval::iterator DstLR = DstInt.FindLiveRangeContaining(CopyIdx);
+ const LiveRange *DstLR = DstInt.getLiveRangeContaining(CopyIdx);
DstInt.removeValNo(DstLR->valno);
CopyMI->setDesc(tii_->get(TargetInstrInfo::IMPLICIT_DEF));
for (int i = CopyMI->getNumOperands() - 1, e = 0; i > e; --i)
assert(DefMI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF);
li_->RemoveMachineInstrFromMaps(DefMI);
DefMI->eraseFromParent();
- ++numPeep;
}
}
++I;
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;
- tii_->isMoveInstr(*CopyMI, SrcReg, DstReg);
- 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);