Index: include/llvm/CodeGen/RegisterScavenging.h =================================================================== --- include/llvm/CodeGen/RegisterScavenging.h +++ include/llvm/CodeGen/RegisterScavenging.h @@ -74,6 +74,12 @@ /// Start tracking liveness from the begin of basic block \p MBB. void enterBasicBlock(MachineBasicBlock &MBB); + /// Start tracking liveness from the end of basic block \p MBB. + /// Use backward() to move towards the beginning of the block. This is + /// preferred to enterBasicBlock() and forward() because it does not depend + /// on the presence of kill flags. + void enterBasicBlockEnd(MachineBasicBlock &MBB); + /// Move the internal MBB iterator and update register states. void forward(); @@ -93,6 +99,17 @@ while (MBBI != I) unprocess(); } + /// Update internal register state and move MBB iterator backwards. + /// Contrary to unprocess() this method gives precise results even in the + /// absence of kill flags. + void backward(); + + /// Call backward() as long as the internal iterator does not point to \p I. + void backward(MachineBasicBlock::iterator I) { + while (MBBI != I) + backward(); + } + /// Move the internal MBB iterator but do not update register states. void skipTo(MachineBasicBlock::iterator I) { if (I == MachineBasicBlock::iterator(nullptr)) @@ -167,6 +184,9 @@ /// Add all Reg Units that Reg contains to BV. void addRegUnits(BitVector &BV, unsigned Reg); + /// Remove all Reg Units that \p Reg contains from \p BV. + void removeRegUnits(BitVector &BV, unsigned Reg); + /// Return the candidate register that is unused for the longest after /// StartMI. UseMI is set to the instruction where the search stopped. /// @@ -176,9 +196,11 @@ unsigned InstrLimit, MachineBasicBlock::iterator &UseMI); - /// Allow resetting register state info for multiple - /// passes over/within the same function. - void initRegState(); + /// Initialize RegisterScavenger. + void init(MachineBasicBlock &MBB); + + /// Mark live-in registers of basic block as used. + void setLiveInsUsed(const MachineBasicBlock &MBB); }; } // End llvm namespace Index: lib/CodeGen/RegisterScavenging.cpp =================================================================== --- lib/CodeGen/RegisterScavenging.cpp +++ lib/CodeGen/RegisterScavenging.cpp @@ -39,28 +39,7 @@ } } -void RegScavenger::initRegState() { - for (SmallVectorImpl::iterator I = Scavenged.begin(), - IE = Scavenged.end(); I != IE; ++I) { - I->Reg = 0; - I->Restore = nullptr; - } - - // All register units start out unused. - RegUnitsAvailable.set(); - - // Live-in registers are in use. - for (const auto &LI : MBB->liveins()) - setRegUsed(LI.PhysReg, LI.LaneMask); - - // Pristine CSRs are also unavailable. - const MachineFunction &MF = *MBB->getParent(); - BitVector PR = MF.getFrameInfo()->getPristineRegs(MF); - for (int I = PR.find_first(); I>0; I = PR.find_next(I)) - setRegUsed(I); -} - -void RegScavenger::enterBasicBlock(MachineBasicBlock &MBB) { +void RegScavenger::init(MachineBasicBlock &MBB) { MachineFunction &MF = *MBB.getParent(); TII = MF.getSubtarget().getInstrInfo(); TRI = MF.getSubtarget().getRegisterInfo(); @@ -84,16 +63,56 @@ } this->MBB = &MBB; - initRegState(); + for (SmallVectorImpl::iterator I = Scavenged.begin(), + IE = Scavenged.end(); I != IE; ++I) { + I->Reg = 0; + I->Restore = nullptr; + } + + // All register units start out unused. + RegUnitsAvailable.set(); + + // Pristine CSRs are not available. + BitVector PR = MF.getFrameInfo()->getPristineRegs(MF); + for (int I = PR.find_first(); I>0; I = PR.find_next(I)) + setRegUsed(I); Tracking = false; } +void RegScavenger::setLiveInsUsed(const MachineBasicBlock &MBB) { + for (const auto &LI : MBB.liveins()) + setRegUsed(LI.PhysReg, LI.LaneMask); +} + +void RegScavenger::enterBasicBlock(MachineBasicBlock &MBB) { + init(MBB); + setLiveInsUsed(MBB); +} + +void RegScavenger::enterBasicBlockEnd(MachineBasicBlock &MBB) { + init(MBB); + // Merge live-ins of successors to get live-outs. + for (const MachineBasicBlock *Succ : MBB.successors()) + setLiveInsUsed(*Succ); + + // Move internal iterator at the last instruction of the block. + if (MBB.begin() != MBB.end()) { + MBBI = std::prev(MBB.end()); + Tracking = true; + } +} + void RegScavenger::addRegUnits(BitVector &BV, unsigned Reg) { for (MCRegUnitIterator RUI(Reg, TRI); RUI.isValid(); ++RUI) BV.set(*RUI); } +void RegScavenger::removeRegUnits(BitVector &BV, unsigned Reg) { + for (MCRegUnitIterator RUI(Reg, TRI); RUI.isValid(); ++RUI) + BV.reset(*RUI); +} + void RegScavenger::determineKillsAndDefs() { assert(Tracking && "Must be tracking to determine kills and defs"); @@ -248,6 +267,48 @@ setUsed(DefRegUnits); } +void RegScavenger::backward() { + assert(Tracking && "Must be tracking to determine kills and defs"); + + const MachineInstr &MI = *MBBI; + // Defined or clobbered registers are available now. + for (const MachineOperand &MO : MI.operands()) { + if (MO.isRegMask()) { + for (unsigned RU = 0, RUEnd = TRI->getNumRegUnits(); RU != RUEnd; + ++RU) { + for (MCRegUnitRootIterator RURI(RU, TRI); RURI.isValid(); ++RURI) { + if (MO.clobbersPhysReg(*RURI)) { + RegUnitsAvailable.set(RU); + break; + } + } + } + } else if (MO.isReg() && MO.isDef()) { + unsigned Reg = MO.getReg(); + if (!Reg || TargetRegisterInfo::isVirtualRegister(Reg) || + isReserved(Reg)) + continue; + addRegUnits(RegUnitsAvailable, Reg); + } + } + // Mark read registers as unavailable. + for (const MachineOperand &MO : MI.uses()) { + if (MO.isReg() && MO.readsReg()) { + unsigned Reg = MO.getReg(); + if (!Reg || TargetRegisterInfo::isVirtualRegister(Reg) || + isReserved(Reg)) + continue; + removeRegUnits(RegUnitsAvailable, Reg); + } + } + + if (MBBI == MBB->begin()) { + MBBI = MachineBasicBlock::iterator(nullptr); + Tracking = false; + } else + --MBBI; +} + bool RegScavenger::isRegUsed(unsigned Reg, bool includeReserved) const { if (includeReserved && isReserved(Reg)) return true;