From df1aeeeb9093ef64937c8b2fda4c9270a2c13209 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Tue, 12 May 2009 23:07:00 +0000 Subject: [PATCH] Teach TransferDeadness to delete truly dead instructions if they do not produce side effects. llvm-svn: 71606 --- llvm/lib/CodeGen/RegAllocLinearScan.cpp | 31 +++++++++--- llvm/lib/CodeGen/VirtRegRewriter.cpp | 50 ++++++++++++++----- .../CodeGen/X86/2007-03-01-SpillerCrash.ll | 1 + 3 files changed, 61 insertions(+), 21 deletions(-) diff --git a/llvm/lib/CodeGen/RegAllocLinearScan.cpp b/llvm/lib/CodeGen/RegAllocLinearScan.cpp index 2c30bd81c66c..c5ce455b0ae5 100644 --- a/llvm/lib/CodeGen/RegAllocLinearScan.cpp +++ b/llvm/lib/CodeGen/RegAllocLinearScan.cpp @@ -350,29 +350,44 @@ unsigned RALinScan::attemptTrivialCoalescing(LiveInterval &cur, unsigned Reg) { if (!vni->def || vni->def == ~1U || vni->def == ~0U) return Reg; MachineInstr *CopyMI = li_->getInstructionFromIndex(vni->def); - unsigned SrcReg, DstReg, SrcSubReg, DstSubReg; + unsigned SrcReg, DstReg, SrcSubReg, DstSubReg, PhysReg; if (!CopyMI || !tii_->isMoveInstr(*CopyMI, SrcReg, DstReg, SrcSubReg, DstSubReg)) return Reg; + PhysReg = SrcReg; if (TargetRegisterInfo::isVirtualRegister(SrcReg)) { if (!vrm_->isAssignedReg(SrcReg)) return Reg; - else - SrcReg = vrm_->getPhys(SrcReg); + PhysReg = vrm_->getPhys(SrcReg); } - if (Reg == SrcReg) + if (Reg == PhysReg) return Reg; const TargetRegisterClass *RC = mri_->getRegClass(cur.reg); - if (!RC->contains(SrcReg)) + if (!RC->contains(PhysReg)) return Reg; // Try to coalesce. - if (!li_->conflictsWithPhysRegDef(cur, *vrm_, SrcReg)) { - DOUT << "Coalescing: " << cur << " -> " << tri_->getName(SrcReg) + if (!li_->conflictsWithPhysRegDef(cur, *vrm_, PhysReg)) { + DOUT << "Coalescing: " << cur << " -> " << tri_->getName(PhysReg) << '\n'; vrm_->clearVirt(cur.reg); - vrm_->assignVirt2Phys(cur.reg, SrcReg); + vrm_->assignVirt2Phys(cur.reg, PhysReg); + + // Remove unnecessary kills since a copy does not clobber the register. + if (li_->hasInterval(SrcReg)) { + LiveInterval &SrcLI = li_->getInterval(SrcReg); + for (MachineRegisterInfo::reg_iterator I = mri_->reg_begin(cur.reg), + E = mri_->reg_end(); I != E; ++I) { + MachineOperand &O = I.getOperand(); + if (!O.isUse() || !O.isKill()) + continue; + MachineInstr *MI = &*I; + if (SrcLI.liveAt(li_->getDefIndex(li_->getInstructionIndex(MI)))) + O.setIsKill(false); + } + } + ++NumCoalesce; return SrcReg; } diff --git a/llvm/lib/CodeGen/VirtRegRewriter.cpp b/llvm/lib/CodeGen/VirtRegRewriter.cpp index 025ce1bd3092..3cbecf4a0d8f 100644 --- a/llvm/lib/CodeGen/VirtRegRewriter.cpp +++ b/llvm/lib/CodeGen/VirtRegRewriter.cpp @@ -851,6 +851,14 @@ void AssignPhysToVirtReg(MachineInstr *MI, unsigned VirtReg, unsigned PhysReg) { } } +namespace { + struct RefSorter { + bool operator()(const std::pair &A, + const std::pair &B) { + return A.second < B.second; + } + }; +} // ***************************** // // Local Spiller Implementation // @@ -1313,9 +1321,10 @@ private: /// removed. Find the last def or use and mark it as dead / kill. void TransferDeadness(MachineBasicBlock *MBB, unsigned CurDist, unsigned Reg, BitVector &RegKills, - std::vector &KillOps) { - int LastUDDist = -1; - MachineInstr *LastUDMI = NULL; + std::vector &KillOps, + VirtRegMap &VRM) { + SmallPtrSet Seens; + SmallVector,8> Refs; for (MachineRegisterInfo::reg_iterator RI = RegInfo->reg_begin(Reg), RE = RegInfo->reg_end(); RI != RE; ++RI) { MachineInstr *UDMI = &*RI; @@ -1324,13 +1333,18 @@ private: DenseMap::iterator DI = DistanceMap.find(UDMI); if (DI == DistanceMap.end() || DI->second > CurDist) continue; - if ((int)DI->second < LastUDDist) - continue; - LastUDDist = DI->second; - LastUDMI = UDMI; + if (Seens.insert(UDMI)) + Refs.push_back(std::make_pair(UDMI, DI->second)); } - if (LastUDMI) { + if (Refs.empty()) + return; + std::sort(Refs.begin(), Refs.end(), RefSorter()); + + while (!Refs.empty()) { + MachineInstr *LastUDMI = Refs.back().first; + Refs.pop_back(); + MachineOperand *LastUD = NULL; for (unsigned i = 0, e = LastUDMI->getNumOperands(); i != e; ++i) { MachineOperand &MO = LastUDMI->getOperand(i); @@ -1339,14 +1353,24 @@ private: if (!LastUD || (LastUD->isUse() && MO.isDef())) LastUD = &MO; if (LastUDMI->isRegTiedToDefOperand(i)) - return; + break; } - if (LastUD->isDef()) - LastUD->setIsDead(); - else { + if (LastUD->isDef()) { + // If the instruction has no side effect, delete it and propagate + // backward further. Otherwise, mark is dead and we are done. + const TargetInstrDesc &TID = LastUDMI->getDesc(); + if (TID.mayStore() || TID.isCall() || TID.isTerminator() || + TID.hasUnmodeledSideEffects()) { + LastUD->setIsDead(); + break; + } + VRM.RemoveMachineInstrFromMaps(LastUDMI); + MBB->erase(LastUDMI); + } else { LastUD->setIsKill(); RegKills.set(Reg); KillOps[Reg] = LastUD; + break; } } } @@ -2027,7 +2051,7 @@ private: TRI->isSubRegister(KillRegs[0], Dst) || TRI->isSuperRegister(KillRegs[0], Dst)); // Last def is now dead. - TransferDeadness(&MBB, Dist, Src, RegKills, KillOps); + TransferDeadness(&MBB, Dist, Src, RegKills, KillOps, VRM); } VRM.RemoveMachineInstrFromMaps(&MI); MBB.erase(&MI); diff --git a/llvm/test/CodeGen/X86/2007-03-01-SpillerCrash.ll b/llvm/test/CodeGen/X86/2007-03-01-SpillerCrash.ll index 2663686d56f6..d4176f1d78cb 100644 --- a/llvm/test/CodeGen/X86/2007-03-01-SpillerCrash.ll +++ b/llvm/test/CodeGen/X86/2007-03-01-SpillerCrash.ll @@ -1,4 +1,5 @@ ; RUN: llvm-as < %s | llc -mtriple=x86_64-apple-darwin8 -mattr=+sse2 +; RUN: llvm-as < %s | llc -mtriple=x86_64-apple-darwin8 -mattr=+sse2 | not grep movhlps define void @test() nounwind { test.exit: