Newer
Older
//===-- RegAllocSimple.cpp - A simple generic register allocator ----------===//
//
// This file implements a simple register allocator. *Very* simple.
//
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/Target/MachineInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "Support/Statistic.h"
#include <set>
namespace {
Statistic<> NumSpilled ("ra-simple", "Number of registers spilled");
Statistic<> NumReloaded("ra-simple", "Number of registers reloaded");
class RegAllocSimple : public FunctionPass {
TargetMachine &TM;
MachineFunction *MF;
const MRegisterInfo *RegInfo;
// Maps SSA Regs => offsets on the stack where these values are stored
std::map<unsigned, unsigned> VirtReg2OffsetMap;
// RegsUsed - Keep track of what registers are currently in use.
std::set<unsigned> RegsUsed;
// RegClassIdx - Maps RegClass => which index we can take a register
// from. Since this is a simple register allocator, when we need a register
// of a certain class, we just take the next available one.
std::map<const TargetRegisterClass*, unsigned> RegClassIdx;
public:
Chris Lattner
committed
RegAllocSimple(TargetMachine &tm)
Chris Lattner
committed
: TM(tm), RegInfo(tm.getRegisterInfo()) {
RegsUsed.insert(RegInfo->getFramePointer());
RegsUsed.insert(RegInfo->getStackPointer());
Misha Brukman
committed
cleanupAfterFunction();
bool runOnFunction(Function &Fn) {
return runOnMachineFunction(MachineFunction::get(&Fn));
}
virtual const char *getPassName() const {
return "Simple Register Allocator";
}
private:
/// runOnMachineFunction - Register allocate the whole function
bool runOnMachineFunction(MachineFunction &Fn);
/// AllocateBasicBlock - Register allocate the specified basic block.
void AllocateBasicBlock(MachineBasicBlock &MBB);
/// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions
/// in predecessor basic blocks.
void EliminatePHINodes(MachineBasicBlock &MBB);
Chris Lattner
committed
/// getStackSpaceFor - This returns the offset of the specified virtual
/// register on the stack, allocating space if neccesary.
unsigned getStackSpaceFor(unsigned VirtReg,
const TargetRegisterClass *regClass);
Chris Lattner
committed
/// Given a virtual register, return a compatible physical register that is
/// currently unused.
///
/// Side effect: marks that register as being used until manually cleared
///
unsigned getFreeReg(unsigned virtualReg);
/// Returns all `borrowed' registers back to the free pool
void clearAllRegs() {
Chris Lattner
committed
RegClassIdx.clear();
Misha Brukman
committed
/// Invalidates any references, real or implicit, to physical registers
///
void invalidatePhysRegs(const MachineInstr *MI) {
unsigned Opcode = MI->getOpcode();
const MachineInstrDescriptor &Desc = TM.getInstrInfo().get(Opcode);
Misha Brukman
committed
const unsigned *regs = Desc.ImplicitUses;
while (*regs)
RegsUsed.insert(*regs++);
Misha Brukman
committed
regs = Desc.ImplicitDefs;
while (*regs)
RegsUsed.insert(*regs++);
Misha Brukman
committed
}
void cleanupAfterFunction() {
Chris Lattner
committed
NumBytesAllocated = 4; // FIXME: This is X86 specific
/// Moves value from memory into that register
unsigned reloadVirtReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator &I, unsigned VirtReg);
/// Saves reg value on the stack (maps virtual register to stack value)
void spillVirtReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &I,
unsigned VirtReg, unsigned PhysReg);
}
Chris Lattner
committed
/// getStackSpaceFor - This allocates space for the specified virtual
Chris Lattner
committed
/// register to be held on the stack.
Chris Lattner
committed
unsigned RegAllocSimple::getStackSpaceFor(unsigned VirtReg,
const TargetRegisterClass *regClass) {
// Find the location VirtReg would belong...
std::map<unsigned, unsigned>::iterator I =
VirtReg2OffsetMap.lower_bound(VirtReg);
if (I != VirtReg2OffsetMap.end() && I->first == VirtReg)
return I->second; // Already has space allocated?
unsigned RegSize = regClass->getDataSize();
// Align NumBytesAllocated. We should be using TargetData alignment stuff
// to determine this, but we don't know the LLVM type associated with the
// virtual register. Instead, just align to a multiple of the size for now.
NumBytesAllocated += RegSize-1;
NumBytesAllocated = NumBytesAllocated/RegSize*RegSize;
// Assign the slot...
VirtReg2OffsetMap.insert(I, std::make_pair(VirtReg, NumBytesAllocated));
// Reserve the space!
NumBytesAllocated += RegSize;
return NumBytesAllocated-RegSize;
unsigned RegAllocSimple::getFreeReg(unsigned virtualReg) {
const TargetRegisterClass* regClass = MF->getRegClass(virtualReg);
Chris Lattner
committed
unsigned regIdx = RegClassIdx[regClass]++;
assert(regIdx < regClass->getNumRegs() && "Not enough registers!");
unsigned physReg = regClass->getRegister(regIdx);
Chris Lattner
committed
if (RegsUsed.find(physReg) == RegsUsed.end())
else
return getFreeReg(virtualReg);
}
unsigned RegAllocSimple::reloadVirtReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator &I,
unsigned VirtReg) {
const TargetRegisterClass* regClass = MF->getRegClass(VirtReg);
Chris Lattner
committed
unsigned stackOffset = getStackSpaceFor(VirtReg, regClass);
unsigned PhysReg = getFreeReg(VirtReg);
// Add move instruction(s)
++NumReloaded;
I = RegInfo->loadRegOffset2Reg(MBB, I, PhysReg, RegInfo->getFramePointer(),
-stackOffset, regClass->getDataSize());
return PhysReg;
void RegAllocSimple::spillVirtReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator &I,
unsigned VirtReg, unsigned PhysReg)
{
const TargetRegisterClass* regClass = MF->getRegClass(VirtReg);
Chris Lattner
committed
unsigned stackOffset = getStackSpaceFor(VirtReg, regClass);
++NumSpilled;
I = RegInfo->storeReg2RegOffset(MBB, I, PhysReg, RegInfo->getFramePointer(),
-stackOffset, regClass->getDataSize());
Chris Lattner
committed
/// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions in
/// predecessor basic blocks.
///
Chris Lattner
committed
void RegAllocSimple::EliminatePHINodes(MachineBasicBlock &MBB) {
const MachineInstrInfo &MII = TM.getInstrInfo();
Chris Lattner
committed
while (MBB.front()->getOpcode() == MachineInstrInfo::PHI) {
Chris Lattner
committed
MachineInstr *MI = MBB.front();
Chris Lattner
committed
// Unlink the PHI node from the basic block... but don't delete the PHI yet
Chris Lattner
committed
MBB.erase(MBB.begin());
Chris Lattner
committed
DEBUG(std::cerr << "num ops: " << MI->getNumOperands() << "\n");
assert(MI->getOperand(0).isVirtualRegister() &&
"PHI node doesn't write virt reg?");
unsigned virtualReg = MI->getOperand(0).getAllocatedRegNum();
Chris Lattner
committed
for (int i = MI->getNumOperands() - 1; i >= 2; i-=2) {
MachineOperand &opVal = MI->getOperand(i-1);
// Get the MachineBasicBlock equivalent of the BasicBlock that is the
// source path the phi
MachineBasicBlock &opBlock = *MI->getOperand(i).getMachineBasicBlock();
Chris Lattner
committed
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
// Check to make sure we haven't already emitted the copy for this block.
// This can happen because PHI nodes may have multiple entries for the
// same basic block. It doesn't matter which entry we use though, because
// all incoming values are guaranteed to be the same for a particular bb.
//
// Note that this is N^2 in the number of phi node entries, but since the
// # of entries is tiny, this is not a problem.
//
bool HaveNotEmitted = true;
for (int op = MI->getNumOperands() - 1; op != i; op -= 2)
if (&opBlock == MI->getOperand(op).getMachineBasicBlock()) {
HaveNotEmitted = false;
break;
}
if (HaveNotEmitted) {
MachineBasicBlock::iterator opI = opBlock.end();
MachineInstr *opMI = *--opI;
// must backtrack over ALL the branches in the previous block
while (MII.isBranch(opMI->getOpcode()) && opI != opBlock.begin())
opMI = *--opI;
// move back to the first branch instruction so new instructions
// are inserted right in front of it and not in front of a non-branch
if (!MII.isBranch(opMI->getOpcode()))
++opI;
unsigned dataSize = MF->getRegClass(virtualReg)->getDataSize();
Chris Lattner
committed
// Retrieve the constant value from this op, move it to target
// register of the phi
if (opVal.isImmediate()) {
opI = RegInfo->moveImm2Reg(opBlock, opI, virtualReg,
Chris Lattner
committed
(unsigned) opVal.getImmedValue(),
dataSize);
} else {
opI = RegInfo->moveReg2Reg(opBlock, opI, virtualReg,
opVal.getAllocatedRegNum(), dataSize);
Chris Lattner
committed
}
Chris Lattner
committed
Chris Lattner
committed
// really delete the PHI instruction now!
Chris Lattner
committed
delete MI;
}
}
Chris Lattner
committed
void RegAllocSimple::AllocateBasicBlock(MachineBasicBlock &MBB) {
Chris Lattner
committed
for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) {
// Made to combat the incorrect allocation of r2 = add r1, r1
Chris Lattner
committed
std::map<unsigned, unsigned> Virt2PhysRegMap;
Chris Lattner
committed
MachineInstr *MI = *I;
// a preliminary pass that will invalidate any registers that
// are used by the instruction (including implicit uses)
invalidatePhysRegs(MI);
// Loop over uses, move from memory into registers
for (int i = MI->getNumOperands() - 1; i >= 0; --i) {
MachineOperand &op = MI->getOperand(i);
if (op.isVirtualRegister()) {
Chris Lattner
committed
unsigned virtualReg = (unsigned) op.getAllocatedRegNum();
DEBUG(std::cerr << "op: " << op << "\n");
DEBUG(std::cerr << "\t inst[" << i << "]: ";
MI->print(std::cerr, TM));
// make sure the same virtual register maps to the same physical
// register in any given instruction
Chris Lattner
committed
unsigned physReg = Virt2PhysRegMap[virtualReg];
if (physReg == 0) {
Chris Lattner
committed
if (op.opIsDef()) {
if (TM.getInstrInfo().isTwoAddrInstr(MI->getOpcode()) && i == 0) {
// must be same register number as the first operand
// This maps a = b + c into b += c, and saves b into a's spot
assert(MI->getOperand(1).isRegister() &&
MI->getOperand(1).getAllocatedRegNum() &&
Chris Lattner
committed
MI->getOperand(1).opIsUse() &&
"Two address instruction invalid!");
physReg = MI->getOperand(1).getAllocatedRegNum();
} else {
Chris Lattner
committed
physReg = getFreeReg(virtualReg);
++I;
spillVirtReg(MBB, I, virtualReg, physReg);
--I;
Chris Lattner
committed
} else {
physReg = reloadVirtReg(MBB, I, virtualReg);
Virt2PhysRegMap[virtualReg] = physReg;
Chris Lattner
committed
MI->SetMachineOperandReg(i, physReg);
DEBUG(std::cerr << "virt: " << virtualReg <<
", phys: " << op.getAllocatedRegNum() << "\n");
Chris Lattner
committed
clearAllRegs();
Chris Lattner
committed
}
/// runOnMachineFunction - Register allocate the whole function
///
Chris Lattner
committed
bool RegAllocSimple::runOnMachineFunction(MachineFunction &Fn) {
DEBUG(std::cerr << "Machine Function " << "\n");
MF = &Fn;
// First pass: eliminate PHI instructions by inserting copies into predecessor
// blocks.
for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end();
MBB != MBBe; ++MBB)
EliminatePHINodes(*MBB);
Chris Lattner
committed
// Loop over all of the basic blocks, eliminating virtual register references
Chris Lattner
committed
for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end();
MBB != MBBe; ++MBB)
AllocateBasicBlock(*MBB);
Chris Lattner
committed
// Add prologue to the function...
RegInfo->emitPrologue(Fn, NumBytesAllocated);
Chris Lattner
committed
const MachineInstrInfo &MII = TM.getInstrInfo();
Chris Lattner
committed
// Add epilogue to restore the callee-save registers in each exiting block
for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end();
Chris Lattner
committed
MBB != MBBe; ++MBB) {
Chris Lattner
committed
// If last instruction is a return instruction, add an epilogue
if (MII.isReturn(MBB->back()->getOpcode()))
RegInfo->emitEpilogue(*MBB, NumBytesAllocated);
Chris Lattner
committed
cleanupAfterFunction();
Chris Lattner
committed
return true;
Pass *createSimpleRegisterAllocator(TargetMachine &TM) {
return new RegAllocSimple(TM);
}