2004-02-23 23:08:11 +00:00
|
|
|
//===-- llvm/CodeGen/VirtRegMap.cpp - Virtual Register Map ----------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file was developed by the LLVM research group and is distributed under
|
|
|
|
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2004-02-24 08:58:30 +00:00
|
|
|
// 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.
|
2004-02-23 23:08:11 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2004-02-24 08:58:30 +00:00
|
|
|
#define DEBUG_TYPE "regalloc"
|
2004-02-23 23:08:11 +00:00
|
|
|
#include "VirtRegMap.h"
|
2004-02-24 08:58:30 +00:00
|
|
|
#include "llvm/Function.h"
|
2004-02-23 23:08:11 +00:00
|
|
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
2004-03-01 20:05:10 +00:00
|
|
|
#include "llvm/CodeGen/MachineInstr.h"
|
2004-02-23 23:08:11 +00:00
|
|
|
#include "llvm/Target/TargetMachine.h"
|
2004-02-24 08:58:30 +00:00
|
|
|
#include "llvm/Target/TargetInstrInfo.h"
|
2004-03-01 23:18:15 +00:00
|
|
|
#include "Support/CommandLine.h"
|
2004-02-24 08:58:30 +00:00
|
|
|
#include "Support/Debug.h"
|
2004-02-27 04:51:35 +00:00
|
|
|
#include "Support/DenseMap.h"
|
2004-03-01 23:18:15 +00:00
|
|
|
#include "Support/Statistic.h"
|
2004-02-24 08:58:30 +00:00
|
|
|
#include "Support/STLExtras.h"
|
2004-02-23 23:08:11 +00:00
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
namespace {
|
2004-02-24 08:58:30 +00:00
|
|
|
Statistic<> numSpills("spiller", "Number of register spills");
|
|
|
|
Statistic<> numStores("spiller", "Number of stores added");
|
|
|
|
Statistic<> numLoads ("spiller", "Number of loads added");
|
|
|
|
|
2004-03-01 23:18:15 +00:00
|
|
|
enum SpillerName { local };
|
|
|
|
|
|
|
|
cl::opt<SpillerName>
|
|
|
|
SpillerOpt("spiller",
|
|
|
|
cl::desc("Spiller to use: (default: local)"),
|
|
|
|
cl::Prefix,
|
|
|
|
cl::values(clEnumVal(local, " local spiller"),
|
|
|
|
0),
|
|
|
|
cl::init(local));
|
2004-02-23 23:08:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int VirtRegMap::assignVirt2StackSlot(unsigned virtReg)
|
|
|
|
{
|
|
|
|
assert(MRegisterInfo::isVirtualRegister(virtReg));
|
2004-02-25 21:55:45 +00:00
|
|
|
assert(v2ssMap_[virtReg] == NO_STACK_SLOT &&
|
2004-02-23 23:08:11 +00:00
|
|
|
"attempt to assign stack slot to already spilled register");
|
|
|
|
const TargetRegisterClass* rc =
|
|
|
|
mf_->getSSARegMap()->getRegClass(virtReg);
|
|
|
|
int frameIndex = mf_->getFrameInfo()->CreateStackObject(rc);
|
2004-02-25 21:55:45 +00:00
|
|
|
v2ssMap_[virtReg] = frameIndex;
|
2004-02-23 23:08:11 +00:00
|
|
|
++numSpills;
|
|
|
|
return frameIndex;
|
|
|
|
}
|
|
|
|
|
2004-03-01 20:05:10 +00:00
|
|
|
void VirtRegMap::virtFolded(unsigned virtReg,
|
|
|
|
MachineInstr* oldMI,
|
|
|
|
MachineInstr* newMI)
|
|
|
|
{
|
|
|
|
// move previous memory references folded to new instruction
|
|
|
|
MI2VirtMap::iterator i, e;
|
|
|
|
std::vector<MI2VirtMap::mapped_type> regs;
|
|
|
|
for (tie(i, e) = mi2vMap_.equal_range(oldMI); i != e; ) {
|
|
|
|
regs.push_back(i->second);
|
|
|
|
mi2vMap_.erase(i++);
|
|
|
|
}
|
|
|
|
for (unsigned i = 0, e = regs.size(); i != e; ++i)
|
|
|
|
mi2vMap_.insert(std::make_pair(newMI, i));
|
|
|
|
|
|
|
|
// add new memory reference
|
|
|
|
mi2vMap_.insert(std::make_pair(newMI, virtReg));
|
|
|
|
}
|
|
|
|
|
2004-02-23 23:08:11 +00:00
|
|
|
std::ostream& llvm::operator<<(std::ostream& os, const VirtRegMap& vrm)
|
|
|
|
{
|
|
|
|
const MRegisterInfo* mri = vrm.mf_->getTarget().getRegisterInfo();
|
|
|
|
|
|
|
|
std::cerr << "********** REGISTER MAP **********\n";
|
2004-02-25 21:55:45 +00:00
|
|
|
for (unsigned i = MRegisterInfo::FirstVirtualRegister,
|
|
|
|
e = vrm.mf_->getSSARegMap()->getLastVirtReg(); i <= e; ++i) {
|
2004-02-23 23:08:11 +00:00
|
|
|
if (vrm.v2pMap_[i] != VirtRegMap::NO_PHYS_REG)
|
2004-02-25 21:55:45 +00:00
|
|
|
std::cerr << "[reg" << i << " -> "
|
2004-02-23 23:08:11 +00:00
|
|
|
<< mri->getName(vrm.v2pMap_[i]) << "]\n";
|
|
|
|
}
|
2004-02-25 21:55:45 +00:00
|
|
|
for (unsigned i = MRegisterInfo::FirstVirtualRegister,
|
|
|
|
e = vrm.mf_->getSSARegMap()->getLastVirtReg(); i <= e; ++i) {
|
2004-02-23 23:08:11 +00:00
|
|
|
if (vrm.v2ssMap_[i] != VirtRegMap::NO_STACK_SLOT)
|
2004-02-25 21:55:45 +00:00
|
|
|
std::cerr << "[reg" << i << " -> fi#"
|
2004-02-23 23:08:11 +00:00
|
|
|
<< vrm.v2ssMap_[i] << "]\n";
|
|
|
|
}
|
|
|
|
return std::cerr << '\n';
|
|
|
|
}
|
2004-02-24 08:58:30 +00:00
|
|
|
|
2004-03-01 23:18:15 +00:00
|
|
|
Spiller::~Spiller()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2004-02-24 08:58:30 +00:00
|
|
|
namespace {
|
|
|
|
|
2004-03-01 23:18:15 +00:00
|
|
|
class LocalSpiller : public Spiller {
|
2004-02-24 08:58:30 +00:00
|
|
|
typedef std::vector<unsigned> Phys2VirtMap;
|
|
|
|
typedef std::vector<bool> PhysFlag;
|
2004-02-27 04:51:35 +00:00
|
|
|
typedef DenseMap<MachineInstr*, VirtReg2IndexFunctor> Virt2MI;
|
2004-02-24 08:58:30 +00:00
|
|
|
|
2004-03-01 23:18:15 +00:00
|
|
|
MachineFunction* mf_;
|
|
|
|
const TargetMachine* tm_;
|
|
|
|
const TargetInstrInfo* tii_;
|
|
|
|
const MRegisterInfo* mri_;
|
|
|
|
const VirtRegMap* vrm_;
|
2004-02-24 08:58:30 +00:00
|
|
|
Phys2VirtMap p2vMap_;
|
|
|
|
PhysFlag dirty_;
|
2004-02-27 04:51:35 +00:00
|
|
|
Virt2MI lastDef_;
|
2004-02-24 08:58:30 +00:00
|
|
|
|
|
|
|
public:
|
2004-03-01 23:18:15 +00:00
|
|
|
bool runOnMachineFunction(MachineFunction& mf, const VirtRegMap& vrm) {
|
|
|
|
mf_ = &mf;
|
|
|
|
tm_ = &mf_->getTarget();
|
|
|
|
tii_ = &tm_->getInstrInfo();
|
|
|
|
mri_ = tm_->getRegisterInfo();
|
|
|
|
vrm_ = &vrm;
|
|
|
|
p2vMap_.assign(mri_->getNumRegs(), 0);
|
|
|
|
dirty_.assign(mri_->getNumRegs(), false);
|
|
|
|
|
2004-02-24 08:58:30 +00:00
|
|
|
DEBUG(std::cerr << "********** REWRITE MACHINE CODE **********\n");
|
|
|
|
DEBUG(std::cerr << "********** Function: "
|
2004-03-01 23:18:15 +00:00
|
|
|
<< mf_->getFunction()->getName() << '\n');
|
2004-02-24 08:58:30 +00:00
|
|
|
|
2004-03-01 23:18:15 +00:00
|
|
|
for (MachineFunction::iterator mbbi = mf_->begin(),
|
|
|
|
mbbe = mf_->end(); mbbi != mbbe; ++mbbi) {
|
|
|
|
lastDef_.grow(mf_->getSSARegMap()->getLastVirtReg());
|
2004-02-26 23:22:23 +00:00
|
|
|
DEBUG(std::cerr << mbbi->getBasicBlock()->getName() << ":\n");
|
|
|
|
eliminateVirtRegsInMbb(*mbbi);
|
2004-02-27 04:51:35 +00:00
|
|
|
// clear map, dirty flag and last ref
|
2004-02-24 08:58:30 +00:00
|
|
|
p2vMap_.assign(p2vMap_.size(), 0);
|
|
|
|
dirty_.assign(dirty_.size(), false);
|
2004-02-27 04:51:35 +00:00
|
|
|
lastDef_.clear();
|
2004-02-24 08:58:30 +00:00
|
|
|
}
|
2004-03-01 23:18:15 +00:00
|
|
|
return true;
|
2004-02-24 08:58:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
void vacateJustPhysReg(MachineBasicBlock& mbb,
|
|
|
|
MachineBasicBlock::iterator mii,
|
|
|
|
unsigned physReg) {
|
|
|
|
unsigned virtReg = p2vMap_[physReg];
|
2004-03-01 23:18:15 +00:00
|
|
|
if (dirty_[physReg] && vrm_->hasStackSlot(virtReg)) {
|
2004-02-27 04:51:35 +00:00
|
|
|
assert(lastDef_[virtReg] && "virtual register is mapped "
|
|
|
|
"to a register and but was not defined!");
|
|
|
|
MachineBasicBlock::iterator lastDef = lastDef_[virtReg];
|
|
|
|
MachineBasicBlock::iterator nextLastRef = next(lastDef);
|
2004-03-01 23:18:15 +00:00
|
|
|
mri_->storeRegToStackSlot(*lastDef->getParent(),
|
2004-02-27 04:51:35 +00:00
|
|
|
nextLastRef,
|
|
|
|
physReg,
|
2004-03-01 23:18:15 +00:00
|
|
|
vrm_->getStackSlot(virtReg),
|
|
|
|
mri_->getRegClass(physReg));
|
2004-02-24 08:58:30 +00:00
|
|
|
++numStores;
|
2004-03-01 20:05:10 +00:00
|
|
|
DEBUG(std::cerr << "added: ";
|
2004-03-01 23:18:15 +00:00
|
|
|
prior(nextLastRef)->print(std::cerr, *tm_);
|
2004-03-01 20:05:10 +00:00
|
|
|
std::cerr << "after: ";
|
2004-03-01 23:18:15 +00:00
|
|
|
lastDef->print(std::cerr, *tm_));
|
2004-02-27 04:51:35 +00:00
|
|
|
lastDef_[virtReg] = 0;
|
2004-02-24 08:58:30 +00:00
|
|
|
}
|
|
|
|
p2vMap_[physReg] = 0;
|
|
|
|
dirty_[physReg] = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void vacatePhysReg(MachineBasicBlock& mbb,
|
|
|
|
MachineBasicBlock::iterator mii,
|
|
|
|
unsigned physReg) {
|
|
|
|
vacateJustPhysReg(mbb, mii, physReg);
|
2004-03-01 23:18:15 +00:00
|
|
|
for (const unsigned* as = mri_->getAliasSet(physReg); *as; ++as)
|
2004-02-24 08:58:30 +00:00
|
|
|
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
|
2004-03-01 23:18:15 +00:00
|
|
|
if (vrm_->hasStackSlot(virtReg)) {
|
|
|
|
mri_->loadRegFromStackSlot(mbb, mii, physReg,
|
|
|
|
vrm_->getStackSlot(virtReg),
|
|
|
|
mri_->getRegClass(physReg));
|
2004-02-24 08:58:30 +00:00
|
|
|
++numLoads;
|
2004-03-01 20:05:10 +00:00
|
|
|
DEBUG(std::cerr << "added: ";
|
2004-03-01 23:18:15 +00:00
|
|
|
prior(mii)->print(std::cerr, *tm_));
|
2004-02-27 04:51:35 +00:00
|
|
|
lastDef_[virtReg] = mii;
|
2004-02-24 08:58:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2004-02-27 04:51:35 +00:00
|
|
|
lastDef_[virtReg] = mii;
|
2004-02-24 08:58:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void eliminateVirtRegsInMbb(MachineBasicBlock& mbb) {
|
|
|
|
for (MachineBasicBlock::iterator mii = mbb.begin(),
|
|
|
|
mie = mbb.end(); mii != mie; ++mii) {
|
2004-03-01 20:05:10 +00:00
|
|
|
|
|
|
|
// if we have references to memory operands make sure
|
|
|
|
// we clear all physical registers that may contain
|
|
|
|
// the value of the spilled virtual register
|
|
|
|
VirtRegMap::MI2VirtMap::const_iterator i, e;
|
2004-03-01 23:18:15 +00:00
|
|
|
for (tie(i, e) = vrm_->getFoldedVirts(mii); i != e; ++i) {
|
|
|
|
unsigned physReg = vrm_->getPhys(i->second);
|
2004-03-01 20:05:10 +00:00
|
|
|
if (physReg) vacateJustPhysReg(mbb, mii, physReg);
|
|
|
|
}
|
|
|
|
|
2004-02-24 08:58:30 +00:00
|
|
|
// rewrite all used operands
|
|
|
|
for (unsigned i = 0, e = mii->getNumOperands(); i != e; ++i) {
|
|
|
|
MachineOperand& op = mii->getOperand(i);
|
2004-02-25 23:21:52 +00:00
|
|
|
if (op.isRegister() && op.getReg() && op.isUse() &&
|
2004-02-24 08:58:30 +00:00
|
|
|
MRegisterInfo::isVirtualRegister(op.getReg())) {
|
2004-02-27 04:51:35 +00:00
|
|
|
unsigned virtReg = op.getReg();
|
2004-03-01 23:18:15 +00:00
|
|
|
unsigned physReg = vrm_->getPhys(virtReg);
|
2004-02-27 04:51:35 +00:00
|
|
|
handleUse(mbb, mii, virtReg, physReg);
|
2004-02-24 08:58:30 +00:00
|
|
|
mii->SetMachineOperandReg(i, physReg);
|
|
|
|
// mark as dirty if this is def&use
|
2004-02-27 04:51:35 +00:00
|
|
|
if (op.isDef()) {
|
|
|
|
dirty_[physReg] = true;
|
|
|
|
lastDef_[virtReg] = mii;
|
|
|
|
}
|
2004-02-24 08:58:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// spill implicit defs
|
2004-03-01 23:18:15 +00:00
|
|
|
const TargetInstrDescriptor& tid = tii_->get(mii->getOpcode());
|
2004-02-24 08:58:30 +00:00
|
|
|
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);
|
2004-02-25 23:21:52 +00:00
|
|
|
if (op.isRegister() && op.getReg() && !op.isUse())
|
2004-02-24 08:58:30 +00:00
|
|
|
if (MRegisterInfo::isPhysicalRegister(op.getReg()))
|
|
|
|
vacatePhysReg(mbb, mii, op.getReg());
|
|
|
|
else {
|
2004-03-01 23:18:15 +00:00
|
|
|
unsigned physReg = vrm_->getPhys(op.getReg());
|
2004-02-24 08:58:30 +00:00
|
|
|
handleDef(mbb, mii, op.getReg(), physReg);
|
|
|
|
mii->SetMachineOperandReg(i, physReg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-03-01 23:18:15 +00:00
|
|
|
DEBUG(std::cerr << '\t'; mii->print(std::cerr, *tm_));
|
2004-02-24 08:58:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (unsigned i = 1, e = p2vMap_.size(); i != e; ++i)
|
|
|
|
vacateJustPhysReg(mbb, mbb.getFirstTerminator(), i);
|
|
|
|
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2004-03-01 23:18:15 +00:00
|
|
|
llvm::Spiller* llvm::createSpiller()
|
2004-02-24 08:58:30 +00:00
|
|
|
{
|
2004-03-01 23:18:15 +00:00
|
|
|
switch (SpillerOpt) {
|
|
|
|
default:
|
|
|
|
std::cerr << "no spiller selected";
|
|
|
|
abort();
|
|
|
|
case local:
|
|
|
|
return new LocalSpiller();
|
|
|
|
}
|
2004-02-24 08:58:30 +00:00
|
|
|
}
|