diff options
author | Cameron Zwarich <zwarich@apple.com> | 2013-02-17 00:10:44 +0000 |
---|---|---|
committer | Cameron Zwarich <zwarich@apple.com> | 2013-02-17 00:10:44 +0000 |
commit | f0b2535344e8c9e2912da78010918a44c5a18cab (patch) | |
tree | 74335c2750bc468334a70f31581aee40cf255c0d | |
parent | cc54889cd58322b8766525f43cc1f7cb52e4692e (diff) | |
download | external_llvm-f0b2535344e8c9e2912da78010918a44c5a18cab.zip external_llvm-f0b2535344e8c9e2912da78010918a44c5a18cab.tar.gz external_llvm-f0b2535344e8c9e2912da78010918a44c5a18cab.tar.bz2 |
Add support for updating the LiveIntervals of registers used by 'exotic'
terminators that actually have register uses when splitting critical edges.
This commit also introduces a method repairIntervalsInRange() on LiveIntervals,
which allows for repairing LiveIntervals in a small range after an arbitrary
target hook modifies, inserts, and removes instructions. It's pretty limited
right now, but I hope to extend it to support all of the things that are done
by the convertToThreeAddress() target hooks.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@175382 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/llvm/CodeGen/LiveIntervalAnalysis.h | 15 | ||||
-rw-r--r-- | lib/CodeGen/LiveIntervalAnalysis.cpp | 36 | ||||
-rw-r--r-- | lib/CodeGen/MachineBasicBlock.cpp | 29 |
3 files changed, 80 insertions, 0 deletions
diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index b6cc111..f422a6f 100644 --- a/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -281,6 +281,21 @@ namespace llvm { void handleMoveIntoBundle(MachineInstr* MI, MachineInstr* BundleStart, bool UpdateFlags = false); + /// repairIntervalsInRange - Update live intervals for instructions in a + /// small range of reverse iterators. It is intended for use after target + /// hooks that may insert or remove instructions, and is only efficient for + /// a small number of instructions. + /// + /// OrigRegs is a vector of registers that were originally used by the + /// instructions in the range between the two iterators. + /// + /// Currently, the only only changes that are supported are simple removal + /// and addition of uses. + void repairIntervalsInRange(MachineBasicBlock *MBB, + MachineBasicBlock::reverse_iterator RBegin, + MachineBasicBlock::reverse_iterator REnd, + SmallVectorImpl<unsigned> &OrigRegs); + // Register mask functions. // // Machine instructions may use a register mask operand to indicate that a diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp index 0d4ec11..3c67be5 100644 --- a/lib/CodeGen/LiveIntervalAnalysis.cpp +++ b/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -1032,3 +1032,39 @@ void LiveIntervals::handleMoveIntoBundle(MachineInstr* MI, HMEditor HME(*this, *MRI, *TRI, OldIndex, NewIndex, UpdateFlags); HME.updateAllRanges(MI); } + +void +LiveIntervals::repairIntervalsInRange(MachineBasicBlock *MBB, + MachineBasicBlock::reverse_iterator RBegin, + MachineBasicBlock::reverse_iterator REnd, + SmallVectorImpl<unsigned> &OrigRegs) { + for (unsigned i = 0, e = OrigRegs.size(); i != e; ++i) { + unsigned Reg = OrigRegs[i]; + if (!TargetRegisterInfo::isVirtualRegister(Reg)) + continue; + + LiveInterval &LI = getInterval(Reg); + SlotIndex startIdx = (REnd == MBB->rend()) ? getMBBStartIdx(MBB) + : getInstructionIndex(&*REnd); + for (MachineBasicBlock::reverse_iterator I = RBegin; I != REnd; ++I) { + MachineInstr *MI = &*I; + SlotIndex instrIdx = getInstructionIndex(MI); + + for (MachineInstr::mop_iterator OI = MI->operands_begin(), + OE = MI->operands_end(); OI != OE; ++OI) { + const MachineOperand &MO = *OI; + if (!MO.isReg() || MO.getReg() != Reg) + continue; + + assert(MO.isUse() && "Register defs are not yet supported."); + + if (!LI.liveAt(instrIdx)) { + LiveRange *LR = LI.getLiveRangeContaining(startIdx.getRegSlot()); + assert(LR && "Used registers must be live-in."); + LR->end = instrIdx.getRegSlot(); + break; + } + } + } + } +} diff --git a/lib/CodeGen/MachineBasicBlock.cpp b/lib/CodeGen/MachineBasicBlock.cpp index df1c7c2..3d75436 100644 --- a/lib/CodeGen/MachineBasicBlock.cpp +++ b/lib/CodeGen/MachineBasicBlock.cpp @@ -698,6 +698,24 @@ MachineBasicBlock::SplitCriticalEdge(MachineBasicBlock *Succ, Pass *P) { } } + SmallVector<unsigned, 4> UsedRegs; + if (LIS) { + for (instr_iterator I = getFirstInstrTerminator(), E = instr_end(); + I != E; ++I) { + MachineInstr *MI = I; + + for (MachineInstr::mop_iterator OI = MI->operands_begin(), + OE = MI->operands_end(); OI != OE; ++OI) { + if (!OI->isReg() || OI->getReg() == 0) + continue; + + unsigned Reg = OI->getReg(); + if (std::find(UsedRegs.begin(), UsedRegs.end(), Reg) == UsedRegs.end()) + UsedRegs.push_back(Reg); + } + } + } + ReplaceUsesOfBlockWith(Succ, NMBB); // If updateTerminator() removes instructions, we need to remove them from @@ -830,6 +848,17 @@ MachineBasicBlock::SplitCriticalEdge(MachineBasicBlock *Succ, Pass *P) { LI.removeRange(StartIndex, EndIndex); } } + + // Update all intervals for registers whose uses may have been modified by + // updateTerminator(). + iterator FirstTerminator = getFirstTerminator(); + MachineInstr *FirstTerminatorMI = FirstTerminator; + if (FirstTerminatorMI->isBundled()) + FirstTerminatorMI = getBundleStart(FirstTerminatorMI); + reverse_iterator PreTerminators = + (FirstTerminator == begin()) ? rend() + : reverse_iterator(FirstTerminatorMI); + LIS->repairIntervalsInRange(this, rbegin(), PreTerminators, UsedRegs); } if (MachineDominatorTree *MDT = |