diff options
Diffstat (limited to 'lib/CodeGen/VirtRegMap.cpp')
-rw-r--r-- | lib/CodeGen/VirtRegMap.cpp | 161 |
1 files changed, 159 insertions, 2 deletions
diff --git a/lib/CodeGen/VirtRegMap.cpp b/lib/CodeGen/VirtRegMap.cpp index bfbe0ef..bb29ffd 100644 --- a/lib/CodeGen/VirtRegMap.cpp +++ b/lib/CodeGen/VirtRegMap.cpp @@ -7,20 +7,32 @@ // //===----------------------------------------------------------------------===// // -// This file implements the virtual register map. +// This file implements the virtual register map. It also implements +// the eliminateVirtRegs() function that given a virtual register map +// and a machine function it eliminates all virtual references by +// replacing them with physical register references and adds spill +// code as necessary. // //===----------------------------------------------------------------------===// +#define DEBUG_TYPE "regalloc" #include "VirtRegMap.h" +#include "llvm/Function.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetInstrInfo.h" #include "Support/Statistic.h" +#include "Support/Debug.h" +#include "Support/STLExtras.h" #include <iostream> using namespace llvm; namespace { - Statistic<> numSpills("ra-linearscan", "Number of register spills"); + Statistic<> numSpills("spiller", "Number of register spills"); + Statistic<> numStores("spiller", "Number of stores added"); + Statistic<> numLoads ("spiller", "Number of loads added"); + } int VirtRegMap::assignVirt2StackSlot(unsigned virtReg) @@ -53,3 +65,148 @@ std::ostream& llvm::operator<<(std::ostream& os, const VirtRegMap& vrm) } return std::cerr << '\n'; } + +namespace { + + class Spiller { + typedef std::vector<unsigned> Phys2VirtMap; + typedef std::vector<bool> PhysFlag; + + MachineFunction& mf_; + const TargetMachine& tm_; + const TargetInstrInfo& tii_; + const MRegisterInfo& mri_; + const VirtRegMap& vrm_; + Phys2VirtMap p2vMap_; + PhysFlag dirty_; + + public: + Spiller(MachineFunction& mf, const VirtRegMap& vrm) + : mf_(mf), + tm_(mf_.getTarget()), + tii_(tm_.getInstrInfo()), + mri_(*tm_.getRegisterInfo()), + vrm_(vrm), + p2vMap_(mri_.getNumRegs()), + dirty_(mri_.getNumRegs()) { + DEBUG(std::cerr << "********** REWRITE MACHINE CODE **********\n"); + DEBUG(std::cerr << "********** Function: " + << mf_.getFunction()->getName() << '\n'); + } + + void eliminateVirtRegs() { + for (MachineFunction::iterator mbbi = mf_.begin(), + mbbe = mf_.end(); mbbi != mbbe; ++mbbi) { + // clear map and dirty flag + p2vMap_.assign(p2vMap_.size(), 0); + dirty_.assign(dirty_.size(), false); + DEBUG(std::cerr << mbbi->getBasicBlock()->getName() << ":\n"); + eliminateVirtRegsInMbb(*mbbi); + } + } + + private: + void vacateJustPhysReg(MachineBasicBlock& mbb, + MachineBasicBlock::iterator mii, + unsigned physReg) { + unsigned virtReg = p2vMap_[physReg]; + if (dirty_[physReg] && vrm_.hasStackSlot(virtReg)) { + mri_.storeRegToStackSlot(mbb, mii, physReg, + vrm_.getStackSlot(virtReg), + mri_.getRegClass(physReg)); + ++numStores; + DEBUG(std::cerr << "*\t"; prior(mii)->print(std::cerr, tm_)); + } + p2vMap_[physReg] = 0; + dirty_[physReg] = false; + } + + void vacatePhysReg(MachineBasicBlock& mbb, + MachineBasicBlock::iterator mii, + unsigned physReg) { + vacateJustPhysReg(mbb, mii, physReg); + for (const unsigned* as = mri_.getAliasSet(physReg); *as; ++as) + vacateJustPhysReg(mbb, mii, *as); + } + + void handleUse(MachineBasicBlock& mbb, + MachineBasicBlock::iterator mii, + unsigned virtReg, + unsigned physReg) { + // check if we are replacing a previous mapping + if (p2vMap_[physReg] != virtReg) { + vacatePhysReg(mbb, mii, physReg); + p2vMap_[physReg] = virtReg; + // load if necessary + if (vrm_.hasStackSlot(virtReg)) { + mri_.loadRegFromStackSlot(mbb, mii, physReg, + vrm_.getStackSlot(virtReg), + mri_.getRegClass(physReg)); + ++numLoads; + DEBUG(std::cerr << "*\t"; prior(mii)->print(std::cerr,tm_)); + } + } + } + + void handleDef(MachineBasicBlock& mbb, + MachineBasicBlock::iterator mii, + unsigned virtReg, + unsigned physReg) { + // check if we are replacing a previous mapping + if (p2vMap_[physReg] != virtReg) + vacatePhysReg(mbb, mii, physReg); + + p2vMap_[physReg] = virtReg; + dirty_[physReg] = true; + } + + void eliminateVirtRegsInMbb(MachineBasicBlock& mbb) { + for (MachineBasicBlock::iterator mii = mbb.begin(), + mie = mbb.end(); mii != mie; ++mii) { + // rewrite all used operands + for (unsigned i = 0, e = mii->getNumOperands(); i != e; ++i) { + MachineOperand& op = mii->getOperand(i); + if (op.isRegister() && op.isUse() && + MRegisterInfo::isVirtualRegister(op.getReg())) { + unsigned physReg = vrm_.getPhys(op.getReg()); + handleUse(mbb, mii, op.getReg(), physReg); + mii->SetMachineOperandReg(i, physReg); + // mark as dirty if this is def&use + if (op.isDef()) dirty_[physReg] = true; + } + } + + // spill implicit defs + const TargetInstrDescriptor& tid =tii_.get(mii->getOpcode()); + for (const unsigned* id = tid.ImplicitDefs; *id; ++id) + vacatePhysReg(mbb, mii, *id); + + // rewrite def operands (def&use was handled with the + // uses so don't check for those here) + for (unsigned i = 0, e = mii->getNumOperands(); i != e; ++i) { + MachineOperand& op = mii->getOperand(i); + if (op.isRegister() && !op.isUse()) + if (MRegisterInfo::isPhysicalRegister(op.getReg())) + vacatePhysReg(mbb, mii, op.getReg()); + else { + unsigned physReg = vrm_.getPhys(op.getReg()); + handleDef(mbb, mii, op.getReg(), physReg); + mii->SetMachineOperandReg(i, physReg); + } + } + + DEBUG(std::cerr << '\t'; mii->print(std::cerr, tm_)); + } + + for (unsigned i = 1, e = p2vMap_.size(); i != e; ++i) + vacateJustPhysReg(mbb, mbb.getFirstTerminator(), i); + + } + }; +} + + +void llvm::eliminateVirtRegs(MachineFunction& mf, const VirtRegMap& vrm) +{ + Spiller(mf, vrm).eliminateVirtRegs(); +} |