From: Evan Cheng Date: Wed, 5 Mar 2008 22:09:42 +0000 (+0000) Subject: Fix a coalescer bug wrt how dead copy interval is shortened. X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;ds=sidebyside;h=ecb2a8b9bc727308a0ccfbd92c87b7533c68aab8;p=oota-llvm.git 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 --- diff --git a/lib/CodeGen/SimpleRegisterCoalescing.cpp b/lib/CodeGen/SimpleRegisterCoalescing.cpp index 03b27aca18d..d7c2d962b5a 100644 --- a/lib/CodeGen/SimpleRegisterCoalescing.cpp +++ b/lib/CodeGen/SimpleRegisterCoalescing.cpp @@ -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, /// 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 @@ -599,23 +623,22 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) { 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 && SrcMI->modifiesRegister(SrcReg, tri_)) // 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) { // remove from def list LiveInterval &RegInt = li_->getOrCreateInterval(srcReg); - MachineOperand *MO = mii->findRegisterDefOperand(dstReg, false); // 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; diff --git a/lib/CodeGen/SimpleRegisterCoalescing.h b/lib/CodeGen/SimpleRegisterCoalescing.h index 1c216203020..543d4704d10 100644 --- a/lib/CodeGen/SimpleRegisterCoalescing.h +++ b/lib/CodeGen/SimpleRegisterCoalescing.h @@ -201,6 +201,12 @@ namespace llvm { /// subregister. 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 /// cycles Start and End or NULL if there are no uses. MachineOperand *lastRegisterUse(unsigned Start, unsigned End, unsigned Reg, diff --git a/test/CodeGen/PowerPC/2008-03-05-RegScavengerAssert.ll b/test/CodeGen/PowerPC/2008-03-05-RegScavengerAssert.ll new file mode 100644 index 00000000000..4f27b84607a --- /dev/null +++ b/test/CodeGen/PowerPC/2008-03-05-RegScavengerAssert.ll @@ -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 ; [#uses=0] + %tmp28 = bitcast i8* %pp to void ()** ; [#uses=1] + %tmp38 = load void ()** %tmp28, align 4 ; [#uses=2] + br i1 false, label %bb34, label %bb25 +bb25: ; preds = %entry + %tmp30 = bitcast void ()* %tmp38 to void (i8*)* ; [#uses=1] + tail call void %tmp30( i8* null ) nounwind + ret void +bb34: ; preds = %entry + tail call void %tmp38( ) nounwind + ret void +}