From edeffb37dc41591b3d3943a5c02c04e55d348524 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Mon, 26 Feb 2007 21:37:37 +0000 Subject: [PATCH] Joining an interval with a dead copy instruction. Shorten the live range to the last use. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@34645 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/LiveIntervalAnalysis.h | 8 ++- lib/CodeGen/LiveIntervalAnalysis.cpp | 66 ++++++++++++++------- 2 files changed, 51 insertions(+), 23 deletions(-) diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index 451905f0889..4f3af88787b 100644 --- a/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -258,9 +258,11 @@ namespace llvm { bool AdjustCopiesBackFrom(LiveInterval &IntA, LiveInterval &IntB, MachineInstr *CopyMI); - /// hasRegisterUse - Returns true if there is any use of the specific - /// reg between indexes Start and End. - bool hasRegisterUse(unsigned Reg, unsigned Start, unsigned End); + /// lastRegisterUse - Returns the last use of the specific register between + /// cycles Start and End. It also returns the use operand by reference. It + /// returns NULL if there are no uses. + MachineInstr *lastRegisterUse(unsigned Reg, unsigned Start, unsigned End, + MachineOperand *&MOU); /// unsetRegisterKill - Unset IsKill property of all uses of specific /// register of the specific instruction. diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp index 809d13464c0..5aeb4601629 100644 --- a/lib/CodeGen/LiveIntervalAnalysis.cpp +++ b/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -900,6 +900,7 @@ bool LiveIntervals::JoinCopy(MachineInstr *CopyMI, // are joined. MachineOperand *mopd = CopyMI->findRegisterDefOperand(DstReg); bool isDead = mopd->isDead(); + bool isShorten = false; unsigned SrcStart = 0; unsigned SrcEnd = 0; if (isDead) { @@ -911,9 +912,22 @@ bool LiveIntervals::JoinCopy(MachineInstr *CopyMI, // 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 > getDefIndex(CopyIdx) || - hasRegisterUse(repSrcReg, SrcStart, CopyIdx)) + if (SrcEnd > getDefIndex(CopyIdx)) isDead = false; + else { + MachineOperand *MOU; + MachineInstr *LastUse = + lastRegisterUse(repSrcReg, SrcStart, CopyIdx, MOU); + if (LastUse) { + // Shorten the liveinterval to the end of last use. + MOU->setIsKill(); + isDead = false; + isShorten = true; + SrcEnd = getUseIndex(getInstructionIndex(LastUse)); + } + } + if (isDead) + isShorten = true; } // Okay, attempt to join these two intervals. On failure, this returns false. @@ -926,15 +940,11 @@ bool LiveIntervals::JoinCopy(MachineInstr *CopyMI, if (SrcStart == 0 && MRegisterInfo::isPhysicalRegister(SrcReg)) { // Live-in to the function but dead. Remove it from MBB live-in set. // JoinIntervals may end up swapping the two intervals. - LiveInterval &LiveInInt = (repSrcReg == DestInt.reg) ? DestInt : SrcInt; - LiveInInt.removeRange(SrcStart, SrcEnd); MachineBasicBlock *MBB = CopyMI->getParent(); MBB->removeLiveIn(SrcReg); } else { MachineInstr *SrcMI = getInstructionFromIndex(SrcStart); if (SrcMI) { - // FIXME: SrcMI == NULL means the register is livein to a non-entry - // MBB. Remove the range from its live interval? MachineOperand *mops = SrcMI->findRegisterDefOperand(SrcReg); if (mops) // FIXME: mops == NULL means SrcMI defines a subregister? @@ -942,6 +952,12 @@ bool LiveIntervals::JoinCopy(MachineInstr *CopyMI, } } } + + if (isShorten) { + // Shorten the live interval. + LiveInterval &LiveInInt = (repSrcReg == DestInt.reg) ? DestInt : SrcInt; + LiveInInt.removeRange(SrcStart, SrcEnd); + } } else { // Coallescing failed. @@ -1481,27 +1497,37 @@ bool LiveIntervals::differingRegisterClasses(unsigned RegA, return !RegClass->contains(RegB); } -/// hasRegisterUse - Returns true if there is any use of the specific -/// reg between indexes Start and End. -bool -LiveIntervals::hasRegisterUse(unsigned Reg, unsigned Start, unsigned End) { - for (unsigned Index = Start+InstrSlots::NUM; Index < End; - Index += InstrSlots::NUM) { +/// lastRegisterUse - Returns the last use of the specific register between +/// cycles Start and End. It also returns the use operand by reference. It +/// returns NULL if there are no uses. +MachineInstr * +LiveIntervals::lastRegisterUse(unsigned Reg, unsigned Start, unsigned End, + MachineOperand *&MOU) { + int e = (End-1) / InstrSlots::NUM * InstrSlots::NUM; + int s = Start; + while (e >= s) { // Skip deleted instructions - while (Index < End && !getInstructionFromIndex(Index)) - Index += InstrSlots::NUM; - if (Index >= End) break; + MachineInstr *MI = getInstructionFromIndex(e); + while ((e - InstrSlots::NUM) >= s && !MI) { + e -= InstrSlots::NUM; + MI = getInstructionFromIndex(e); + } + if (e < s || MI == NULL) + return NULL; - MachineInstr *MI = getInstructionFromIndex(Index); - for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + for (unsigned i = 0, NumOps = MI->getNumOperands(); i != NumOps; ++i) { MachineOperand &MO = MI->getOperand(i); if (MO.isReg() && MO.isUse() && MO.getReg() && - mri_->regsOverlap(rep(MO.getReg()), Reg)) - return true; + mri_->regsOverlap(rep(MO.getReg()), Reg)) { + MOU = &MO; + return MI; + } } + + e -= InstrSlots::NUM; } - return false; + return NULL; } /// unsetRegisterKill - Unset IsKill property of all uses of specific register