#include "Support/Statistic.h"
#include <iostream>
-/// PhysRegClassMap - Construct a mapping of physical register numbers to their
-/// register classes.
-///
-/// NOTE: This class will eventually be pulled out to somewhere shared.
-///
-class PhysRegClassMap {
- std::map<unsigned, const TargetRegisterClass*> PhysReg2RegClassMap;
-public:
- PhysRegClassMap(const MRegisterInfo &RI) {
- for (MRegisterInfo::const_iterator I = RI.regclass_begin(),
- E = RI.regclass_end(); I != E; ++I)
- for (unsigned i=0; i < (*I)->getNumRegs(); ++i)
- PhysReg2RegClassMap[(*I)->getRegister(i)] = *I;
- }
-
- const TargetRegisterClass *operator[](unsigned Reg) {
- assert(PhysReg2RegClassMap[Reg] && "Register is not a known physreg!");
- return PhysReg2RegClassMap[Reg];
- }
-
- const TargetRegisterClass *get(unsigned Reg) { return operator[](Reg); }
-};
-
namespace {
Statistic<> NumSpilled ("ra-local", "Number of registers spilled");
Statistic<> NumReloaded("ra-local", "Number of registers reloaded");
const MRegisterInfo &RegInfo;
const MachineInstrInfo &MIInfo;
unsigned NumBytesAllocated;
- PhysRegClassMap PhysRegClasses;
// Maps SSA Regs => offsets on the stack where these values are stored
std::map<unsigned, unsigned> VirtReg2OffsetMap;
public:
RA(TargetMachine &tm)
- : TM(tm), RegInfo(*tm.getRegisterInfo()), MIInfo(tm.getInstrInfo()),
- PhysRegClasses(RegInfo) {
+ : TM(tm), RegInfo(*tm.getRegisterInfo()), MIInfo(tm.getInstrInfo()) {
cleanupAfterFunction();
}
unsigned R = PhysRegsUseOrder[i];
// If the current register is compatible, use it.
if (isAllocatableRegister(R)) {
- if (PhysRegClasses[R] == RegClass) {
+ if (RegInfo.getRegClass(R) == RegClass) {
PhysReg = R;
break;
} else {
// compatible, use it.
if (const unsigned *AliasSet = RegInfo.getAliasSet(R))
for (unsigned a = 0; AliasSet[a]; ++a)
- if (PhysRegClasses[AliasSet[a]] == RegClass) {
+ if (RegInfo.getRegClass(AliasSet[a]) == RegClass) {
PhysReg = AliasSet[a]; // Take an aliased register
break;
}
const unsigned *CSRegs = RegInfo.getCalleeSaveRegs();
for (unsigned i = 0; CSRegs[i]; ++i) {
- const TargetRegisterClass *RegClass = PhysRegClasses[CSRegs[i]];
+ const TargetRegisterClass *RegClass = RegInfo.getRegClass(CSRegs[i]);
unsigned Offset = getStackSpaceFor(CSRegs[i], RegClass);
// Insert the spill to the stack frame...
const unsigned *CSRegs = RegInfo.getCalleeSaveRegs();
for (unsigned i = 0; CSRegs[i]; ++i) {
- const TargetRegisterClass *RegClass = PhysRegClasses[CSRegs[i]];
+ const TargetRegisterClass *RegClass = RegInfo.getRegClass(CSRegs[i]);
unsigned Offset = getStackSpaceFor(CSRegs[i], RegClass);
++NumReloaded;
I = RegInfo.loadRegOffset2Reg(MBB, I, CSRegs[i], RegInfo.getFramePointer(),
// blocks.
// FIXME: In this pass, count how many uses of each VReg exist!
for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end();
- MBB != MBBe; ++MBB)
+ MBB != MBBe; ++MBB) {
EliminatePHINodes(*MBB);
+ }
// Loop over all of the basic blocks, eliminating virtual register references
for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end();
/// in predecessor basic blocks.
void EliminatePHINodes(MachineBasicBlock &MBB);
+ /// EmitPrologue/EmitEpilogue - Use the register info object to add a
+ /// prologue/epilogue to the function and save/restore any callee saved
+ /// registers we are responsible for.
+ ///
+ void EmitPrologue();
+ void EmitEpilogue(MachineBasicBlock &MBB);
+
/// getStackSpaceFor - This returns the offset of the specified virtual
/// register on the stack, allocating space if neccesary.
}
}
+
+/// EmitPrologue - Use the register info object to add a prologue to the
+/// function and save any callee saved registers we are responsible for.
+///
+void RegAllocSimple::EmitPrologue() {
+ // Get a list of the callee saved registers, so that we can save them on entry
+ // to the function.
+ //
+ MachineBasicBlock &MBB = MF->front(); // Prolog goes in entry BB
+ MachineBasicBlock::iterator I = MBB.begin();
+
+ const unsigned *CSRegs = RegInfo->getCalleeSaveRegs();
+ for (unsigned i = 0; CSRegs[i]; ++i) {
+ const TargetRegisterClass *RegClass = RegInfo->getRegClass(CSRegs[i]);
+ unsigned Offset = getStackSpaceFor(CSRegs[i], RegClass);
+
+ // Insert the spill to the stack frame...
+ I = RegInfo->storeReg2RegOffset(MBB, I,CSRegs[i],RegInfo->getFramePointer(),
+ -Offset, RegClass->getDataSize());
+ ++NumSpilled;
+ }
+
+ // Add prologue to the function...
+ RegInfo->emitPrologue(*MF, NumBytesAllocated);
+}
+
+
+/// EmitEpilogue - Use the register info object to add a epilogue to the
+/// function and restore any callee saved registers we are responsible for.
+///
+void RegAllocSimple::EmitEpilogue(MachineBasicBlock &MBB) {
+ // Insert instructions before the return.
+ MachineBasicBlock::iterator I = --MBB.end();
+
+ const unsigned *CSRegs = RegInfo->getCalleeSaveRegs();
+ for (unsigned i = 0; CSRegs[i]; ++i) {
+ const TargetRegisterClass *RegClass = RegInfo->getRegClass(CSRegs[i]);
+ unsigned Offset = getStackSpaceFor(CSRegs[i], RegClass);
+
+ I = RegInfo->loadRegOffset2Reg(MBB, I, CSRegs[i],RegInfo->getFramePointer(),
+ -Offset, RegClass->getDataSize());
+ --I; // Insert in reverse order
+ ++NumReloaded;
+ }
+
+ RegInfo->emitEpilogue(MBB, NumBytesAllocated);
+}
+
+
/// runOnMachineFunction - Register allocate the whole function
///
bool RegAllocSimple::runOnMachineFunction(MachineFunction &Fn) {
// FIXME: This is X86 specific! Move to frame manager
NumBytesAllocated = (NumBytesAllocated + 3) & ~3;
- // Add prologue to the function...
- RegInfo->emitPrologue(Fn, NumBytesAllocated);
+ // Emit a prologue for the function...
+ EmitPrologue();
const MachineInstrInfo &MII = TM.getInstrInfo();
MBB != MBBe; ++MBB) {
// If last instruction is a return instruction, add an epilogue
if (MII.isReturn(MBB->back()->getOpcode()))
- RegInfo->emitEpilogue(*MBB, NumBytesAllocated);
+ EmitEpilogue(*MBB);
}
cleanupAfterFunction();