From bfebb419844b1d9c63ad14d0cff51e19935a45a4 Mon Sep 17 00:00:00 2001 From: Cameron Zwarich Date: Sun, 17 Feb 2013 00:10:44 +0000 Subject: [PATCH] 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. llvm-svn: 175382 --- llvm/include/llvm/CodeGen/LiveIntervalAnalysis.h | 15 ++++++++++ llvm/lib/CodeGen/LiveIntervalAnalysis.cpp | 36 ++++++++++++++++++++++++ llvm/lib/CodeGen/MachineBasicBlock.cpp | 29 +++++++++++++++++++ 3 files changed, 80 insertions(+) diff --git a/llvm/include/llvm/CodeGen/LiveIntervalAnalysis.h b/llvm/include/llvm/CodeGen/LiveIntervalAnalysis.h index b6cc111..f422a6f 100644 --- a/llvm/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/llvm/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 &OrigRegs); + // Register mask functions. // // Machine instructions may use a register mask operand to indicate that a diff --git a/llvm/lib/CodeGen/LiveIntervalAnalysis.cpp b/llvm/lib/CodeGen/LiveIntervalAnalysis.cpp index 0d4ec11..3c67be5 100644 --- a/llvm/lib/CodeGen/LiveIntervalAnalysis.cpp +++ b/llvm/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 &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/llvm/lib/CodeGen/MachineBasicBlock.cpp b/llvm/lib/CodeGen/MachineBasicBlock.cpp index df1c7c2..3d75436 100644 --- a/llvm/lib/CodeGen/MachineBasicBlock.cpp +++ b/llvm/lib/CodeGen/MachineBasicBlock.cpp @@ -698,6 +698,24 @@ MachineBasicBlock::SplitCriticalEdge(MachineBasicBlock *Succ, Pass *P) { } } + SmallVector 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 = -- 2.7.4