aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCameron Zwarich <zwarich@apple.com>2013-02-17 00:10:44 +0000
committerCameron Zwarich <zwarich@apple.com>2013-02-17 00:10:44 +0000
commitf0b2535344e8c9e2912da78010918a44c5a18cab (patch)
tree74335c2750bc468334a70f31581aee40cf255c0d
parentcc54889cd58322b8766525f43cc1f7cb52e4692e (diff)
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.h15
-rw-r--r--lib/CodeGen/LiveIntervalAnalysis.cpp36
-rw-r--r--lib/CodeGen/MachineBasicBlock.cpp29
3 files changed, 80 insertions, 0 deletions
diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h
index b6cc111b73..f422a6f3e9 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 0d4ec11266..3c67be5e8f 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 df1c7c2a66..3d754366ee 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 =