mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-09-25 17:20:48 +00:00
Fix a coalescer bug wrt how dead copy interval is shortened.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@47966 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -451,6 +451,30 @@ SimpleRegisterCoalescing::UpdateRegDefsUses(unsigned SrcReg, unsigned DstReg,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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,
|
/// JoinCopy - Attempt to join intervals corresponding to SrcReg/DstReg,
|
||||||
/// which are the src/dst of the copy instruction CopyMI. This returns true
|
/// 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
|
/// if the copy was successfully coalesced away. If it is not currently
|
||||||
@@ -599,23 +623,22 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
|
|||||||
SrcInt.FindLiveRangeContaining(li_->getUseIndex(CopyIdx));
|
SrcInt.FindLiveRangeContaining(li_->getUseIndex(CopyIdx));
|
||||||
RemoveStart = SrcStart = SrcLR->start;
|
RemoveStart = SrcStart = SrcLR->start;
|
||||||
RemoveEnd = SrcEnd = SrcLR->end;
|
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 (SrcEnd > li_->getDefIndex(CopyIdx)) {
|
||||||
|
// If there are other uses of SrcReg beyond the copy, there is nothing to do.
|
||||||
isDead = false;
|
isDead = false;
|
||||||
} else {
|
} else {
|
||||||
unsigned LastUseIdx;
|
unsigned LastUseIdx;
|
||||||
MachineOperand *LastUse =
|
MachineOperand *LastUse =
|
||||||
lastRegisterUse(SrcStart, CopyIdx, SrcReg, LastUseIdx);
|
lastRegisterUse(SrcStart, CopyIdx, SrcReg, LastUseIdx);
|
||||||
if (LastUse) {
|
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();
|
LastUse->setIsKill();
|
||||||
isDead = false;
|
isDead = false;
|
||||||
isShorten = true;
|
isShorten = true;
|
||||||
RemoveStart = li_->getDefIndex(LastUseIdx);
|
RemoveStart = li_->getDefIndex(LastUseIdx);
|
||||||
RemoveEnd = SrcEnd;
|
|
||||||
} else {
|
} else {
|
||||||
|
// This live range is truly dead. Remove it.
|
||||||
MachineInstr *SrcMI = li_->getInstructionFromIndex(SrcStart);
|
MachineInstr *SrcMI = li_->getInstructionFromIndex(SrcStart);
|
||||||
if (SrcMI && SrcMI->modifiesRegister(SrcReg, tri_))
|
if (SrcMI && SrcMI->modifiesRegister(SrcReg, tri_))
|
||||||
// A dead def should have a single cycle interval.
|
// A dead def should have a single cycle interval.
|
||||||
@@ -1531,16 +1554,10 @@ bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) {
|
|||||||
if (tii_->isMoveInstr(*mii, srcReg, dstReg) && srcReg == dstReg) {
|
if (tii_->isMoveInstr(*mii, srcReg, dstReg) && srcReg == dstReg) {
|
||||||
// remove from def list
|
// remove from def list
|
||||||
LiveInterval &RegInt = li_->getOrCreateInterval(srcReg);
|
LiveInterval &RegInt = li_->getOrCreateInterval(srcReg);
|
||||||
MachineOperand *MO = mii->findRegisterDefOperand(dstReg, false);
|
|
||||||
// If def of this move instruction is dead, remove its live range from
|
// If def of this move instruction is dead, remove its live range from
|
||||||
// the dstination register's live interval.
|
// the dstination register's live interval.
|
||||||
if (MO->isDead()) {
|
if (mii->registerDefIsDead(dstReg))
|
||||||
unsigned MoveIdx = li_->getDefIndex(li_->getInstructionIndex(mii));
|
ShortenDeadCopyLiveRange(RegInt, mii);
|
||||||
LiveInterval::iterator MLR = RegInt.FindLiveRangeContaining(MoveIdx);
|
|
||||||
RegInt.removeRange(MLR->start, MoveIdx+1, true);
|
|
||||||
if (RegInt.empty())
|
|
||||||
li_->removeInterval(srcReg);
|
|
||||||
}
|
|
||||||
li_->RemoveMachineInstrFromMaps(mii);
|
li_->RemoveMachineInstrFromMaps(mii);
|
||||||
mii = mbbi->erase(mii);
|
mii = mbbi->erase(mii);
|
||||||
++numPeep;
|
++numPeep;
|
||||||
|
@@ -201,6 +201,12 @@ namespace llvm {
|
|||||||
/// subregister.
|
/// subregister.
|
||||||
void UpdateRegDefsUses(unsigned SrcReg, unsigned DstReg, unsigned SubIdx);
|
void UpdateRegDefsUses(unsigned SrcReg, unsigned DstReg, unsigned SubIdx);
|
||||||
|
|
||||||
|
/// 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 ShortenDeadCopyLiveRange(LiveInterval &li, MachineInstr *CopyMI);
|
||||||
|
|
||||||
/// lastRegisterUse - Returns the last use of the specific register between
|
/// lastRegisterUse - Returns the last use of the specific register between
|
||||||
/// cycles Start and End or NULL if there are no uses.
|
/// cycles Start and End or NULL if there are no uses.
|
||||||
MachineOperand *lastRegisterUse(unsigned Start, unsigned End, unsigned Reg,
|
MachineOperand *lastRegisterUse(unsigned Start, unsigned End, unsigned Reg,
|
||||||
|
18
test/CodeGen/PowerPC/2008-03-05-RegScavengerAssert.ll
Normal file
18
test/CodeGen/PowerPC/2008-03-05-RegScavengerAssert.ll
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
; RUN: llvm-as < %s | llc -mtriple=powerpc-apple-darwin -enable-ppc-regscavenger
|
||||||
|
|
||||||
|
declare i8* @bar(i32)
|
||||||
|
|
||||||
|
define void @foo(i8* %pp) nounwind {
|
||||||
|
entry:
|
||||||
|
%tmp2 = tail call i8* @bar( i32 14 ) nounwind ; <i8*> [#uses=0]
|
||||||
|
%tmp28 = bitcast i8* %pp to void ()** ; <void ()**> [#uses=1]
|
||||||
|
%tmp38 = load void ()** %tmp28, align 4 ; <void ()*> [#uses=2]
|
||||||
|
br i1 false, label %bb34, label %bb25
|
||||||
|
bb25: ; preds = %entry
|
||||||
|
%tmp30 = bitcast void ()* %tmp38 to void (i8*)* ; <void (i8*)*> [#uses=1]
|
||||||
|
tail call void %tmp30( i8* null ) nounwind
|
||||||
|
ret void
|
||||||
|
bb34: ; preds = %entry
|
||||||
|
tail call void %tmp38( ) nounwind
|
||||||
|
ret void
|
||||||
|
}
|
Reference in New Issue
Block a user