X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FRegisterScavenging.cpp;h=06baa81c03b6d218bb2556048f837fc66667a860;hb=249ded3fa8884f91fded869fb6e251b8aebb0376;hp=0938e3a04e6f742eed75f60f0ee3cf9862cf7f03;hpb=403c45dfcc74585b02339b5f55f739672e3d141a;p=oota-llvm.git diff --git a/lib/CodeGen/RegisterScavenging.cpp b/lib/CodeGen/RegisterScavenging.cpp index 0938e3a04e6..06baa81c03b 100644 --- a/lib/CodeGen/RegisterScavenging.cpp +++ b/lib/CodeGen/RegisterScavenging.cpp @@ -2,8 +2,8 @@ // // The LLVM Compiler Infrastructure // -// This file was developed by the Evan Cheng and is distributed under the -// University of Illinois Open Source License. See LICENSE.TXT for details. +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // @@ -19,50 +19,102 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineInstr.h" -#include "llvm/Target/MRegisterInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/STLExtras.h" using namespace llvm; -RegScavenger::RegScavenger(MachineBasicBlock *mbb) - : MBB(mbb), MBBI(mbb->begin()) { - const MachineFunction &MF = *MBB->getParent(); +void RegScavenger::enterBasicBlock(MachineBasicBlock *mbb) { + const MachineFunction &MF = *mbb->getParent(); const TargetMachine &TM = MF.getTarget(); - const MRegisterInfo *RegInfo = TM.getRegisterInfo(); + TII = TM.getInstrInfo(); + RegInfo = TM.getRegisterInfo(); - NumPhysRegs = RegInfo->getNumRegs(); - RegStates.resize(NumPhysRegs, true); + assert((NumPhysRegs == 0 || NumPhysRegs == RegInfo->getNumRegs()) && + "Target changed?"); - // Create reserved registers bitvector. - ReservedRegs = RegInfo->getReservedRegs(MF); - RegStates ^= ReservedRegs; + if (!MBB) { + NumPhysRegs = RegInfo->getNumRegs(); + RegsAvailable.resize(NumPhysRegs); - // Create callee-saved registers bitvector. - CalleeSavedRegs.resize(NumPhysRegs); - const unsigned *CSRegs = RegInfo->getCalleeSavedRegs(); - if (CSRegs != NULL) - for (unsigned i = 0; CSRegs[i]; ++i) - CalleeSavedRegs.set(CSRegs[i]); + // Create reserved registers bitvector. + ReservedRegs = RegInfo->getReservedRegs(MF); + + // Create callee-saved registers bitvector. + CalleeSavedRegs.resize(NumPhysRegs); + const unsigned *CSRegs = RegInfo->getCalleeSavedRegs(); + if (CSRegs != NULL) + for (unsigned i = 0; CSRegs[i]; ++i) + CalleeSavedRegs.set(CSRegs[i]); + } + + MBB = mbb; + ScavengedReg = 0; + ScavengedRC = NULL; + + // All registers started out unused. + RegsAvailable.set(); + + // Reserved registers are always used. + RegsAvailable ^= ReservedRegs; // Live-in registers are in use. if (!MBB->livein_empty()) for (MachineBasicBlock::const_livein_iterator I = MBB->livein_begin(), E = MBB->livein_end(); I != E; ++I) setUsed(*I); + + Tracking = false; +} + +void RegScavenger::restoreScavengedReg() { + if (!ScavengedReg) + return; + + TII->loadRegFromStackSlot(*MBB, MBBI, ScavengedReg, + ScavengingFrameIndex, ScavengedRC); + MachineBasicBlock::iterator II = prior(MBBI); + RegInfo->eliminateFrameIndex(II, 0, this); + setUsed(ScavengedReg); + ScavengedReg = 0; + ScavengedRC = NULL; } void RegScavenger::forward() { + // Move ptr forward. + if (!Tracking) { + MBBI = MBB->begin(); + Tracking = true; + } else { + assert(MBBI != MBB->end() && "Already at the end of the basic block!"); + MBBI = next(MBBI); + } + MachineInstr *MI = MBBI; + const TargetInstrDesc &TID = MI->getDesc(); + + // Reaching a terminator instruction. Restore a scavenged register (which + // must be life out. + if (TID.isTerminator()) + restoreScavengedReg(); + // Process uses first. BitVector ChangedRegs(NumPhysRegs); for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { const MachineOperand &MO = MI->getOperand(i); - if (!MO.isReg() || !MO.isUse()) + if (!MO.isRegister() || !MO.isUse()) continue; unsigned Reg = MO.getReg(); if (Reg == 0) continue; - assert(isUsed(Reg)); + if (!isUsed(Reg)) { + // Register has been scavenged. Restore it! + if (Reg != ScavengedReg) + assert(false && "Using an undefined register!"); + else + restoreScavengedReg(); + } if (MO.isKill() && !isReserved(Reg)) ChangedRegs.set(Reg); } @@ -71,33 +123,42 @@ void RegScavenger::forward() { setUnused(ChangedRegs); // Process defs. - const TargetInstrDescriptor *TID = MI->getInstrDescriptor(); for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { const MachineOperand &MO = MI->getOperand(i); - if (!MO.isReg() || !MO.isDef()) + if (!MO.isRegister() || !MO.isDef()) + continue; + unsigned Reg = MO.getReg(); + // If it's dead upon def, then it is now free. + if (MO.isDead()) { + setUnused(Reg); continue; + } // Skip two-address destination operand. - if (TID->findTiedToSrcOperand(i) != -1) + if (TID.findTiedToSrcOperand(i) != -1) { + assert(isUsed(Reg) && "Using an undefined register!"); continue; - unsigned Reg = MO.getReg(); - assert(isUnused(Reg) || isReserved(Reg)); - if (!MO.isDead()) - setUsed(Reg); + } + assert((isUnused(Reg) || isReserved(Reg)) && + "Re-defining a live register!"); + setUsed(Reg); } - - ++MBBI; } void RegScavenger::backward() { - MachineInstr *MI = --MBBI; + assert(Tracking && "Not tracking states!"); + assert(MBBI != MBB->begin() && "Already at start of basic block!"); + // Move ptr backward. + MBBI = prior(MBBI); + + MachineInstr *MI = MBBI; // Process defs first. - const TargetInstrDescriptor *TID = MI->getInstrDescriptor(); + const TargetInstrDesc &TID = MI->getDesc(); for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { const MachineOperand &MO = MI->getOperand(i); - if (!MO.isReg() || !MO.isDef()) + if (!MO.isRegister() || !MO.isDef()) continue; // Skip two-address destination operand. - if (TID->findTiedToSrcOperand(i) != -1) + if (TID.findTiedToSrcOperand(i) != -1) continue; unsigned Reg = MO.getReg(); assert(isUsed(Reg)); @@ -109,7 +170,7 @@ void RegScavenger::backward() { BitVector ChangedRegs(NumPhysRegs); for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { const MachineOperand &MO = MI->getOperand(i); - if (!MO.isReg() || !MO.isUse()) + if (!MO.isRegister() || !MO.isUse()) continue; unsigned Reg = MO.getReg(); if (Reg == 0) @@ -120,6 +181,13 @@ void RegScavenger::backward() { setUsed(ChangedRegs); } +void RegScavenger::getRegsUsed(BitVector &used, bool includeReserved) { + if (includeReserved) + used = ~RegsAvailable; + else + used = ~RegsAvailable & ~ReservedRegs; +} + /// CreateRegClassMask - Set the bits that represent the registers in the /// TargetRegisterClass. static void CreateRegClassMask(const TargetRegisterClass *RC, BitVector &Mask) { @@ -128,19 +196,97 @@ static void CreateRegClassMask(const TargetRegisterClass *RC, BitVector &Mask) { Mask.set(*I); } +unsigned RegScavenger::FindUnusedReg(const TargetRegisterClass *RegClass, + const BitVector &Candidates) const { + // Mask off the registers which are not in the TargetRegisterClass. + BitVector RegsAvailableCopy(NumPhysRegs, false); + CreateRegClassMask(RegClass, RegsAvailableCopy); + RegsAvailableCopy &= RegsAvailable; + + // Restrict the search to candidates. + RegsAvailableCopy &= Candidates; + + // Returns the first unused (bit is set) register, or 0 is none is found. + int Reg = RegsAvailableCopy.find_first(); + return (Reg == -1) ? 0 : Reg; +} + unsigned RegScavenger::FindUnusedReg(const TargetRegisterClass *RegClass, bool ExCalleeSaved) const { // Mask off the registers which are not in the TargetRegisterClass. - BitVector RegStatesCopy(NumPhysRegs, false); - CreateRegClassMask(RegClass, RegStatesCopy); - RegStatesCopy &= RegStates; + BitVector RegsAvailableCopy(NumPhysRegs, false); + CreateRegClassMask(RegClass, RegsAvailableCopy); + RegsAvailableCopy &= RegsAvailable; // If looking for a non-callee-saved register, mask off all the callee-saved // registers. if (ExCalleeSaved) - RegStatesCopy &= ~CalleeSavedRegs; + RegsAvailableCopy &= ~CalleeSavedRegs; // Returns the first unused (bit is set) register, or 0 is none is found. - int Reg = RegStatesCopy.find_first(); + int Reg = RegsAvailableCopy.find_first(); return (Reg == -1) ? 0 : Reg; } + +/// calcDistanceToUse - Calculate the distance to the first use of the +/// specified register. +static unsigned calcDistanceToUse(MachineBasicBlock *MBB, + MachineBasicBlock::iterator I, unsigned Reg) { + unsigned Dist = 0; + I = next(I); + while (I != MBB->end()) { + Dist++; + if (I->findRegisterUseOperandIdx(Reg) != -1) + return Dist; + I = next(I); + } + return Dist + 1; +} + +unsigned RegScavenger::scavengeRegister(const TargetRegisterClass *RC, + MachineBasicBlock::iterator I, + int SPAdj) { + assert(ScavengingFrameIndex >= 0 && + "Cannot scavenge a register without an emergency spill slot!"); + + // Mask off the registers which are not in the TargetRegisterClass. + BitVector Candidates(NumPhysRegs, false); + CreateRegClassMask(RC, Candidates); + Candidates ^= ReservedRegs; // Do not include reserved registers. + + // Exclude all the registers being used by the instruction. + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) { + MachineOperand &MO = I->getOperand(i); + if (MO.isRegister()) + Candidates.reset(MO.getReg()); + } + + // Find the register whose use is furthest away. + unsigned SReg = 0; + unsigned MaxDist = 0; + int Reg = Candidates.find_first(); + while (Reg != -1) { + unsigned Dist = calcDistanceToUse(MBB, I, Reg); + if (Dist >= MaxDist) { + MaxDist = Dist; + SReg = Reg; + } + Reg = Candidates.find_next(Reg); + } + + if (ScavengedReg != 0) { + // First restore previously scavenged register. + TII->loadRegFromStackSlot(*MBB, I, ScavengedReg, + ScavengingFrameIndex, ScavengedRC); + MachineBasicBlock::iterator II = prior(I); + RegInfo->eliminateFrameIndex(II, SPAdj, this); + } + + TII->storeRegToStackSlot(*MBB, I, SReg, true, ScavengingFrameIndex, RC); + MachineBasicBlock::iterator II = prior(I); + RegInfo->eliminateFrameIndex(II, SPAdj, this); + ScavengedReg = SReg; + ScavengedRC = RC; + + return SReg; +}