Initial checkin of "local" register allocator. Bugs are still present.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@5078 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/RegAllocLocal.cpp b/lib/CodeGen/RegAllocLocal.cpp
new file mode 100644
index 0000000..a372390
--- /dev/null
+++ b/lib/CodeGen/RegAllocLocal.cpp
@@ -0,0 +1,490 @@
+//===-- RegAllocLocal.cpp - A BasicBlock generic register allocator -------===//
+//
+// This register allocator allocates registers to a basic block at a time,
+// attempting to keep values in registers and reusing registers as appropriate.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/Target/MachineInstrInfo.h"
+#include "llvm/Target/TargetMachine.h"
+#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");
+
+ class RA : public FunctionPass {
+ TargetMachine &TM;
+ MachineFunction *MF;
+ const MRegisterInfo *RegInfo;
+ unsigned NumBytesAllocated;
+ PhysRegClassMap PhysRegClasses;
+
+ // Maps SSA Regs => offsets on the stack where these values are stored
+ std::map<unsigned, unsigned> VirtReg2OffsetMap;
+
+ // Virt2PhysRegMap - This map contains entries for each virtual register
+ // that is currently available in a physical register.
+ //
+ std::map<unsigned, unsigned> Virt2PhysRegMap;
+
+ // PhysRegsUsed - This map contains entries for each physical register that
+ // currently has a value (ie, it is in Virt2PhysRegMap). The value mapped
+ // to is the virtual register corresponding to the physical register (the
+ // inverse of the Virt2PhysRegMap), or 0. The value is set to 0 if this
+ // register is pinned because it is used by a future instruction.
+ //
+ std::map<unsigned, unsigned> PhysRegsUsed;
+
+ // PhysRegsUseOrder - This contains a list of the physical registers that
+ // currently have a virtual register value in them. This list provides an
+ // ordering of registers, imposing a reallocation order. This list is only
+ // used if all registers are allocated and we have to spill one, in which
+ // case we spill the least recently used register. Entries at the front of
+ // the list are the least recently used registers, entries at the back are
+ // the most recently used.
+ //
+ std::vector<unsigned> PhysRegsUseOrder;
+
+ void MarkPhysRegRecentlyUsed(unsigned Reg) {
+ assert(std::find(PhysRegsUseOrder.begin(), PhysRegsUseOrder.end(), Reg) !=
+ PhysRegsUseOrder.end() && "Register isn't used yet!");
+ if (PhysRegsUseOrder.back() != Reg) {
+ for (unsigned i = PhysRegsUseOrder.size(); ; --i)
+ if (PhysRegsUseOrder[i-1] == Reg) { // remove from middle
+ PhysRegsUseOrder.erase(PhysRegsUseOrder.begin()+i-1);
+ PhysRegsUseOrder.push_back(Reg); // Add it to the end of the list
+ return;
+ }
+ }
+ }
+
+ public:
+
+ RA(TargetMachine &tm)
+ : TM(tm), RegInfo(tm.getRegisterInfo()), PhysRegClasses(RegInfo) {
+ cleanupAfterFunction();
+ }
+
+ bool runOnFunction(Function &Fn) {
+ return runOnMachineFunction(MachineFunction::get(&Fn));
+ }
+
+ virtual const char *getPassName() const {
+ return "Local 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);
+
+
+ /// getStackSpaceFor - This returns the offset of the specified virtual
+ /// register on the stack, allocating space if neccesary.
+ unsigned getStackSpaceFor(unsigned VirtReg,
+ const TargetRegisterClass *regClass);
+
+ void cleanupAfterFunction() {
+ VirtReg2OffsetMap.clear();
+ NumBytesAllocated = 4; // FIXME: This is X86 specific
+ }
+
+
+ /// spillVirtReg - This method spills the value specified by PhysReg into
+ /// the virtual register slot specified by VirtReg. It then updates the RA
+ /// data structures to indicate the fact that PhysReg is now available.
+ ///
+ void spillVirtReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &I,
+ unsigned VirtReg, unsigned PhysReg);
+
+ void AssignVirtToPhysReg(unsigned VirtReg, unsigned PhysReg);
+
+
+ /// getFreeReg - Find a physical register to hold the specified virtual
+ /// register. If all compatible physical registers are used, this method
+ /// spills the last used virtual register to the stack, and uses that
+ /// register.
+ ///
+ unsigned getFreeReg(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator &I,
+ unsigned virtualReg);
+
+ /// reloadVirtReg - This method loads the specified virtual register into a
+ /// physical register, returning the physical register chosen. This updates
+ /// the regalloc data structures to reflect the fact that the virtual reg is
+ /// now alive in a physical register, and the previous one isn't.
+ ///
+ unsigned reloadVirtReg(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator &I, unsigned VirtReg);
+ };
+
+}
+
+/// getStackSpaceFor - This allocates space for the specified virtual
+/// register to be held on the stack.
+unsigned RA::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;
+}
+
+/// spillVirtReg - This method spills the value specified by PhysReg into the
+/// virtual register slot specified by VirtReg. It then updates the RA data
+/// structures to indicate the fact that PhysReg is now available.
+///
+void RA::spillVirtReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &I,
+ unsigned VirtReg, unsigned PhysReg) {
+ // If this is just a marker register, we don't need to spill it.
+ if (VirtReg != 0) {
+ const TargetRegisterClass *RegClass = MF->getRegClass(VirtReg);
+ unsigned stackOffset = getStackSpaceFor(VirtReg, RegClass);
+
+ // Add move instruction(s)
+ I = RegInfo->storeReg2RegOffset(MBB, I, PhysReg, RegInfo->getFramePointer(),
+ -stackOffset, RegClass->getDataSize());
+ ++NumSpilled; // Update statistics
+ Virt2PhysRegMap.erase(VirtReg); // VirtReg no longer available
+ }
+ PhysRegsUsed.erase(PhysReg); // PhyReg no longer used
+
+ std::vector<unsigned>::iterator It =
+ std::find(PhysRegsUseOrder.begin(), PhysRegsUseOrder.end(), PhysReg);
+ assert(It != PhysRegsUseOrder.end() &&
+ "Spilled a physical register, but it was not in use list!");
+ PhysRegsUseOrder.erase(It);
+}
+
+/// getFreeReg - Find a physical register to hold the specified virtual
+/// register. If all compatible physical registers are used, this method spills
+/// the last used virtual register to the stack, and uses that register.
+///
+unsigned RA::getFreeReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &I,
+ unsigned VirtReg) {
+ const TargetRegisterClass *RegClass = MF->getRegClass(VirtReg);
+ unsigned PhysReg = 0;
+
+ for (TargetRegisterClass::iterator It = RegClass->begin(),E = RegClass->end();
+ It != E; ++It) {
+ unsigned R = *It;
+ if (PhysRegsUsed.find(R) == PhysRegsUsed.end()) // Is reg unused?
+ /// FIXME: Hack
+ if (R != RegInfo->getFramePointer() && R != RegInfo->getStackPointer() &&
+ R != 13 && R != 14) {
+ // Found an unused register!
+ PhysReg = R;
+ break;
+ }
+ }
+
+ // If we didn't find an unused register, scavange one now!
+ if (PhysReg == 0) {
+ unsigned i = 0;
+ while (PhysRegClasses[PhysRegsUseOrder[i]] != RegClass) {
+ ++i;
+ assert(i != PhysRegsUseOrder.size() &&
+ "Couldn't find a register of the appropriate class!");
+ }
+
+ // At this point PhysRegsUseOrder[i] is the least recently used register of
+ // compatible register class. Spill it to memory and reap its remains.
+ PhysReg = PhysRegsUseOrder[i];
+ spillVirtReg(MBB, I, PhysRegsUsed[PhysReg], PhysReg);
+ }
+
+ // Now that we know which register we need to assign this to, do it now!
+ AssignVirtToPhysReg(VirtReg, PhysReg);
+ return PhysReg;
+}
+
+void RA::AssignVirtToPhysReg(unsigned VirtReg, unsigned PhysReg) {
+ assert(PhysRegsUsed.find(PhysReg) == PhysRegsUsed.end() &&
+ "Phys reg already assigned!");
+ // Update information to note the fact that this register was just used, and
+ // it holds VirtReg.
+ PhysRegsUsed[PhysReg] = VirtReg;
+ Virt2PhysRegMap[VirtReg] = PhysReg;
+ PhysRegsUseOrder.push_back(PhysReg); // New use of PhysReg
+}
+
+
+/// reloadVirtReg - This method loads the specified virtual register into a
+/// physical register, returning the physical register chosen. This updates the
+/// regalloc data structures to reflect the fact that the virtual reg is now
+/// alive in a physical register, and the previous one isn't.
+///
+unsigned RA::reloadVirtReg(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator &I,
+ unsigned VirtReg) {
+ std::map<unsigned, unsigned>::iterator It = Virt2PhysRegMap.find(VirtReg);
+ if (It != Virt2PhysRegMap.end()) {
+ MarkPhysRegRecentlyUsed(It->second);
+ return It->second; // Already have this value available!
+ }
+
+ unsigned PhysReg = getFreeReg(MBB, I, VirtReg);
+
+ const TargetRegisterClass *RegClass = MF->getRegClass(VirtReg);
+ unsigned StackOffset = getStackSpaceFor(VirtReg, RegClass);
+
+ // Add move instruction(s)
+ I = RegInfo->loadRegOffset2Reg(MBB, I, PhysReg, RegInfo->getFramePointer(),
+ -StackOffset, RegClass->getDataSize());
+ ++NumReloaded; // Update statistics
+ return PhysReg;
+}
+
+/// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions in
+/// predecessor basic blocks.
+///
+void RA::EliminatePHINodes(MachineBasicBlock &MBB) {
+ const MachineInstrInfo &MII = TM.getInstrInfo();
+
+ while (MBB.front()->getOpcode() == MachineInstrInfo::PHI) {
+ MachineInstr *MI = MBB.front();
+ // Unlink the PHI node from the basic block... but don't delete the PHI yet
+ MBB.erase(MBB.begin());
+
+ 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();
+
+ 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();
+
+ // 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();
+
+ // Retrieve the constant value from this op, move it to target
+ // register of the phi
+ if (opVal.isImmediate()) {
+ opI = RegInfo->moveImm2Reg(opBlock, opI, virtualReg,
+ (unsigned) opVal.getImmedValue(),
+ dataSize);
+ } else {
+ opI = RegInfo->moveReg2Reg(opBlock, opI, virtualReg,
+ opVal.getAllocatedRegNum(), dataSize);
+ }
+ }
+ }
+
+ // really delete the PHI instruction now!
+ delete MI;
+ }
+}
+
+void RA::AllocateBasicBlock(MachineBasicBlock &MBB) {
+ // loop over each instruction
+ MachineBasicBlock::iterator I = MBB.begin();
+ for (; I != MBB.end(); ++I) {
+ MachineInstr *MI = *I;
+
+ // Loop over all of the operands of the instruction, spilling registers that
+ // are defined, and marking explicit destinations in the PhysRegsUsed map.
+ for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i)
+ if (MI->getOperand(i).opIsDef() &&
+ MI->getOperand(i).isPhysicalRegister()) {
+ unsigned Reg = MI->getOperand(i).getAllocatedRegNum();
+ unsigned VMap = PhysRegsUsed[Reg];
+ if (VMap) { // Spill the value in this register...
+ spillVirtReg(MBB, I, VMap, Reg);
+ PhysRegsUsed[Reg] = 0; // It's free now, and it's reserved
+ }
+ PhysRegsUseOrder.push_back(Reg);
+ }
+
+ // FIXME: Loop over the implicit defs, spilling them, as above.
+
+
+ // FIXME: Loop over the implicit uses, making sure that they are at the head
+ // of the use order list, so they don't get reallocated.
+
+ // Loop over all of the operands again, getting the used operands into
+ // registers. This has the potiential to spill incoming values because we
+ // are out of registers.
+ //
+ for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i)
+ if (MI->getOperand(i).opIsUse() &&
+ MI->getOperand(i).isVirtualRegister()) {
+ unsigned VirtSrcReg = MI->getOperand(i).getAllocatedRegNum();
+ unsigned PhysSrcReg = reloadVirtReg(MBB, I, VirtSrcReg);
+ MI->SetMachineOperandReg(i, PhysSrcReg); // Assign the input register
+ }
+
+ // Okay, we have allocated all of the source operands and spilled any values
+ // that would be destroyed by defs of this instruction. Loop over the
+ // implicit defs and assign them to a register, spilling the incoming value
+ // if we need to scavange a register.
+
+ for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i)
+ if (MI->getOperand(i).opIsDef() &&
+ !MI->getOperand(i).isPhysicalRegister()) {
+ unsigned DestVirtReg = MI->getOperand(i).getAllocatedRegNum();
+ unsigned DestPhysReg;
+
+ 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() &&
+ MI->getOperand(1).opIsUse() &&
+ "Two address instruction invalid!");
+ DestPhysReg = MI->getOperand(1).getAllocatedRegNum();
+
+ // Spill the incoming value, because we are about to change the
+ // register contents.
+ spillVirtReg(MBB, I, PhysRegsUsed[DestPhysReg], DestPhysReg);
+ AssignVirtToPhysReg(DestVirtReg, DestPhysReg);
+ } else {
+ DestPhysReg = getFreeReg(MBB, I, DestVirtReg);
+ }
+ MI->SetMachineOperandReg(i, DestPhysReg); // Assign the output register
+ }
+ }
+
+ // Rewind the iterator to point to the first flow control instruction...
+ const MachineInstrInfo &MII = TM.getInstrInfo();
+ I = MBB.end();
+ do {
+ --I;
+ } while ((MII.isReturn((*I)->getOpcode()) ||
+ MII.isBranch((*I)->getOpcode())) && I != MBB.begin());
+
+ if (!MII.isReturn((*I)->getOpcode()) && !MII.isBranch((*I)->getOpcode()))
+ ++I;
+
+ // Spill all physical registers holding virtual registers now.
+ while (!PhysRegsUsed.empty())
+ spillVirtReg(MBB, I, PhysRegsUsed.begin()->second,
+ PhysRegsUsed.begin()->first);
+
+ assert(Virt2PhysRegMap.empty() && "Virtual registers still in phys regs?");
+ assert(PhysRegsUseOrder.empty() && "Physical regs still allocated?");
+}
+
+/// runOnMachineFunction - Register allocate the whole function
+///
+bool RA::runOnMachineFunction(MachineFunction &Fn) {
+ DEBUG(std::cerr << "Machine Function " << "\n");
+ MF = &Fn;
+
+ // First pass: eliminate PHI instructions by inserting copies into predecessor
+ // 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)
+ EliminatePHINodes(*MBB);
+
+ // Loop over all of the basic blocks, eliminating virtual register references
+ for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end();
+ MBB != MBBe; ++MBB)
+ AllocateBasicBlock(*MBB);
+
+ // Round stack allocation up to a nice alignment to keep the stack aligned
+ // FIXME: This is X86 specific! Move to frame manager
+ NumBytesAllocated = (NumBytesAllocated + 3) & ~3;
+
+ // Add prologue to the function...
+ RegInfo->emitPrologue(Fn, NumBytesAllocated);
+
+ const MachineInstrInfo &MII = TM.getInstrInfo();
+
+ // Add epilogue to restore the callee-save registers in each exiting block
+ for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end();
+ MBB != MBBe; ++MBB) {
+ // If last instruction is a return instruction, add an epilogue
+ if (MII.isReturn(MBB->back()->getOpcode()))
+ RegInfo->emitEpilogue(*MBB, NumBytesAllocated);
+ }
+
+ cleanupAfterFunction();
+ return true;
+}
+
+Pass *createLocalRegisterAllocator(TargetMachine &TM) {
+ return new RA(TM);
+}