From: Evan Cheng Date: Thu, 3 Apr 2008 16:41:54 +0000 (+0000) Subject: - Turn copies of implicit_def into implicit_def instructions. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=db9b1c33294d11c73a212f29080d7da68f4f2403;p=oota-llvm.git - Turn copies of implicit_def into implicit_def instructions. - Be smarter about coalescing copies from implicit_def. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@49168 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/SimpleRegisterCoalescing.cpp b/lib/CodeGen/SimpleRegisterCoalescing.cpp index aa5cda02652..3f124c00406 100644 --- a/lib/CodeGen/SimpleRegisterCoalescing.cpp +++ b/lib/CodeGen/SimpleRegisterCoalescing.cpp @@ -813,7 +813,16 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) { // always canonicalizes DstInt to be it. The output "SrcInt" will not have // been modified, so we can use this information below to update aliases. bool Swapped = false; - if (!JoinIntervals(DstInt, SrcInt, Swapped)) { + // If SrcInt is implicitly defined, it's safe to coalesce. + bool isEmpty = SrcInt.empty(); + if (isEmpty && DstInt.getNumValNums() != 1) { + // Only coalesce an empty interval (defined by implicit_def) with + // another interval that's defined by a single copy. + DOUT << "Not profitable!\n"; + return false; + } + + if (!isEmpty && !JoinIntervals(DstInt, SrcInt, Swapped)) { // Coalescing failed. // If we can eliminate the copy without merging the live ranges, do so now. @@ -906,9 +915,6 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) { } } - DOUT << "\n\t\tJoined. Result = "; ResDstInt->print(DOUT, tri_); - DOUT << "\n"; - // Remember to delete the copy instruction. JoinedCopies.insert(CopyMI); @@ -923,6 +929,20 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) { li_->removeInterval(SrcReg); UpdateRegDefsUses(SrcReg, DstReg, SubIdx); + if (isEmpty) { + // Now the copy is being coalesced away, the val# previously defined + // 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); + VNInfo *ImpVal = LR->valno; + assert(ImpVal->def == CopyIdx); + ResDstInt->removeValNo(ImpVal); + } + + DOUT << "\n\t\tJoined. Result = "; ResDstInt->print(DOUT, tri_); + DOUT << "\n"; + ++numJoins; return true; } @@ -1622,6 +1642,44 @@ static bool isZeroLengthInterval(LiveInterval *li) { return true; } +/// TurnCopyIntoImpDef - If source of the specified copy is an implicit def, +/// turn the copy into an implicit def. +bool +SimpleRegisterCoalescing::TurnCopyIntoImpDef(MachineBasicBlock::iterator &I, + MachineBasicBlock *MBB, + unsigned DstReg, unsigned SrcReg) { + MachineInstr *CopyMI = &*I; + unsigned CopyIdx = li_->getDefIndex(li_->getInstructionIndex(CopyMI)); + if (!li_->hasInterval(SrcReg)) + return false; + LiveInterval &SrcInt = li_->getInterval(SrcReg); + if (!SrcInt.empty()) + return false; + LiveInterval &DstInt = li_->getInterval(DstReg); + LiveInterval::iterator DstLR = DstInt.FindLiveRangeContaining(CopyIdx); + DstInt.removeValNo(DstLR->valno); + CopyMI->setDesc(tii_->get(TargetInstrInfo::IMPLICIT_DEF)); + for (int i = CopyMI->getNumOperands() - 1, e = 0; i > e; --i) + CopyMI->RemoveOperand(i); + bool NoUse = mri_->use_begin(SrcReg) == mri_->use_end(); + if (NoUse) { + for (MachineRegisterInfo::reg_iterator I = mri_->reg_begin(SrcReg), + E = mri_->reg_end(); I != E; ) { + assert(I.getOperand().isDef()); + MachineInstr *DefMI = &*I; + ++I; + // The implicit_def source has no other uses, delete it. + assert(DefMI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF); + li_->RemoveMachineInstrFromMaps(DefMI); + DefMI->eraseFromParent(); + ++numPeep; + } + } + ++I; + return true; +} + + bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) { mf_ = &fn; mri_ = &fn.getRegInfo(); @@ -1679,7 +1737,8 @@ bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) { mii != mie; ) { // if the move will be an identity move delete it unsigned srcReg, dstReg; - if (tii_->isMoveInstr(*mii, srcReg, dstReg) && srcReg == dstReg) { + 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 @@ -1692,7 +1751,7 @@ bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) { li_->RemoveMachineInstrFromMaps(mii); mii = mbbi->erase(mii); ++numPeep; - } else { + } else if (!isMove || !TurnCopyIntoImpDef(mii, mbb, dstReg, srcReg)) { SmallSet UniqueUses; for (unsigned i = 0, e = mii->getNumOperands(); i != e; ++i) { const MachineOperand &mop = mii->getOperand(i); diff --git a/lib/CodeGen/SimpleRegisterCoalescing.h b/lib/CodeGen/SimpleRegisterCoalescing.h index cfac126607c..453760a7e7b 100644 --- a/lib/CodeGen/SimpleRegisterCoalescing.h +++ b/lib/CodeGen/SimpleRegisterCoalescing.h @@ -190,6 +190,12 @@ namespace llvm { bool RemoveCopyByCommutingDef(LiveInterval &IntA, LiveInterval &IntB, MachineInstr *CopyMI); + /// TurnCopyIntoImpDef - If source of the specified copy is an implicit def, + /// turn the copy into an implicit def. + bool TurnCopyIntoImpDef(MachineBasicBlock::iterator &I, + MachineBasicBlock *MBB, + unsigned DstReg, unsigned SrcReg); + /// isBackEdgeCopy - Returns true if CopyMI is a back edge copy. /// bool isBackEdgeCopy(MachineInstr *CopyMI, unsigned DstReg);