[llvm-commits] CVS: llvm/lib/CodeGen/RegAllocLocal.cpp
Chris Lattner
lattner at cs.uiuc.edu
Sat Dec 28 14:43:01 PST 2002
Changes in directory llvm/lib/CodeGen:
RegAllocLocal.cpp updated: 1.8 -> 1.9
---
Log message:
* Convert to be a MachineFunctionPass instance
* Use new FunctionFrameInfo object to manage stack slots instead of doing
it directly
* Adjust to new MRegisterInfo API
* Don't take a TM as a ctor argument
* Don't keep track of which callee saved registers are modified
* Don't emit prolog/epilog code or spill/restore code for callee saved regs
* Use new allocation_order_begin/end iterators to simplify dramatically the
logic for picking registers to allocate
* Machine PHI nodes can no longer contain constant arguments
---
Diffs of the changes:
Index: llvm/lib/CodeGen/RegAllocLocal.cpp
diff -u llvm/lib/CodeGen/RegAllocLocal.cpp:1.8 llvm/lib/CodeGen/RegAllocLocal.cpp:1.9
--- llvm/lib/CodeGen/RegAllocLocal.cpp:1.8 Tue Dec 24 23:05:46 2002
+++ llvm/lib/CodeGen/RegAllocLocal.cpp Sat Dec 28 14:40:43 2002
@@ -5,9 +5,10 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/SSARegMap.h"
+#include "llvm/CodeGen/FunctionFrameInfo.h"
#include "llvm/Target/MachineInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "Support/Statistic.h"
@@ -21,23 +22,14 @@
cl::opt<bool> DisableKill("no-kill", cl::Hidden,
cl::desc("Disable register kill in local-ra"));
- class RA : public FunctionPass {
- TargetMachine &TM;
+ class RA : public MachineFunctionPass {
+ const TargetMachine *TM;
MachineFunction *MF;
- const MRegisterInfo &RegInfo;
- const MachineInstrInfo &MIInfo;
- unsigned NumBytesAllocated;
-
- // PhysRegsModified - Keep track of which physical registers are actually
- // modified by the function we are code generating. This set allows us to
- // only spill caller-saved registers that we actually change.
- //
- // FIXME: this would be much nicer & faster as a bitset.
- //
- std::set<unsigned> PhysRegsModified;
-
- // Maps SSA Regs => offsets on the stack where these values are stored
- std::map<unsigned, unsigned> VirtReg2OffsetMap;
+ const MRegisterInfo *RegInfo;
+
+ // StackSlotForVirtReg - Maps SSA Regs => frame index where these values are
+ // spilled
+ std::map<unsigned, int> StackSlotForVirtReg;
// Virt2PhysRegMap - This map contains entries for each virtual register
// that is currently available in a physical register.
@@ -85,16 +77,6 @@
}
public:
-
- RA(TargetMachine &tm)
- : TM(tm), RegInfo(*tm.getRegisterInfo()), MIInfo(tm.getInstrInfo()) {
- cleanupAfterFunction();
- }
-
- bool runOnFunction(Function &Fn) {
- return runOnMachineFunction(MachineFunction::get(&Fn));
- }
-
virtual const char *getPassName() const {
return "Local Register Allocator";
}
@@ -120,42 +102,21 @@
std::map<unsigned, MachineInstr*> &LastUseOfVReg) const;
- /// EmitPrologue/EmitEpilogue - Use the register info object to add a
- /// prologue/epilogue to the function and save/restore the callee saved
- /// registers specified by the CSRegs list.
- ///
- void EmitPrologue(const std::vector<unsigned> &CSRegs);
- void EmitEpilogue(MachineBasicBlock &MBB,
- const std::vector<unsigned> &CSRegs);
-
/// areRegsEqual - This method returns true if the specified registers are
/// related to each other. To do this, it checks to see if they are equal
/// or if the first register is in the alias set of the second register.
///
bool areRegsEqual(unsigned R1, unsigned R2) const {
if (R1 == R2) return true;
- if (const unsigned *AliasSet = RegInfo.getAliasSet(R2))
+ if (const unsigned *AliasSet = RegInfo->getAliasSet(R2))
for (unsigned i = 0; AliasSet[i]; ++i)
if (AliasSet[i] == R1) return true;
return false;
}
- /// isAllocatableRegister - A register may be used by the program if it's
- /// not the stack or frame pointer.
- bool isAllocatableRegister(unsigned R) const {
- unsigned FP = RegInfo.getFramePointer(), SP = RegInfo.getStackPointer();
- return !areRegsEqual(FP, R) && !areRegsEqual(SP, R);
- }
-
- /// getStackSpaceFor - This returns the offset of the specified virtual
+ /// getStackSpaceFor - This returns the frame index 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
- }
+ int getStackSpaceFor(unsigned VirtReg, const TargetRegisterClass *RC);
void removePhysReg(unsigned PhysReg);
@@ -174,7 +135,7 @@
std::map<unsigned, unsigned>::iterator PI = PhysRegsUsed.find(PhysReg);
if (PI != PhysRegsUsed.end()) { // Only spill it if it's used!
spillVirtReg(MBB, I, PI->second, PhysReg);
- } else if (const unsigned *AliasSet = RegInfo.getAliasSet(PhysReg)) {
+ } else if (const unsigned *AliasSet = RegInfo->getAliasSet(PhysReg)) {
// If the selected register aliases any other registers, we must make
// sure that one of the aliases isn't alive...
for (unsigned i = 0; AliasSet[i]; ++i) {
@@ -215,29 +176,22 @@
/// getStackSpaceFor - This allocates space for the specified virtual
/// register to be held on the stack.
-unsigned RA::getStackSpaceFor(unsigned VirtReg,
- const TargetRegisterClass *RegClass) {
+int RA::getStackSpaceFor(unsigned VirtReg,
+ const TargetRegisterClass *RC) {
// Find the location VirtReg would belong...
- std::map<unsigned, unsigned>::iterator I =
- VirtReg2OffsetMap.lower_bound(VirtReg);
+ std::map<unsigned, int>::iterator I =
+ StackSlotForVirtReg.lower_bound(VirtReg);
- if (I != VirtReg2OffsetMap.end() && I->first == VirtReg)
+ if (I != StackSlotForVirtReg.end() && I->first == VirtReg)
return I->second; // Already has space allocated?
- unsigned RegSize = RegClass->getDataSize();
+ // Allocate a new stack object for this spill location...
+ int FrameIdx =
+ MF->getFrameInfo()->CreateStackObject(RC->getSize(), RC->getAlignment());
- // 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;
+ StackSlotForVirtReg.insert(I, std::make_pair(VirtReg, FrameIdx));
+ return FrameIdx;
}
@@ -264,11 +218,10 @@
if (VirtReg != 0) {
const TargetRegisterClass *RegClass =
MF->getSSARegMap()->getRegClass(VirtReg);
- unsigned stackOffset = getStackSpaceFor(VirtReg, RegClass);
+ int FrameIndex = getStackSpaceFor(VirtReg, RegClass);
// Add move instruction(s)
- RegInfo.storeReg2RegOffset(MBB, I, PhysReg, RegInfo.getFramePointer(),
- -stackOffset, RegClass);
+ RegInfo->storeRegToStackSlot(MBB, I, PhysReg, FrameIndex, RegClass);
++NumSpilled; // Update statistics
Virt2PhysRegMap.erase(VirtReg); // VirtReg no longer available
}
@@ -286,7 +239,7 @@
// If the selected register aliases any other allocated registers, it is
// not free!
- if (const unsigned *AliasSet = RegInfo.getAliasSet(PhysReg))
+ if (const unsigned *AliasSet = RegInfo->getAliasSet(PhysReg))
for (unsigned i = 0; AliasSet[i]; ++i)
if (PhysRegsUsed.count(AliasSet[i])) // Aliased register in use?
return false; // Can't use this reg then.
@@ -301,20 +254,22 @@
///
unsigned RA::getFreeReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &I,
unsigned VirtReg) {
- const TargetRegisterClass *RegClass =
- MF->getSSARegMap()->getRegClass(VirtReg);
- unsigned PhysReg = 0;
+ const TargetRegisterClass *RC = MF->getSSARegMap()->getRegClass(VirtReg);
+
+ // Get iterators defining the range of registers that are valid to allocate in
+ // this class, which also specifies the preferred allocation order.
+ TargetRegisterClass::iterator RI = RC->allocation_order_begin(*MF);
+ TargetRegisterClass::iterator RE = RC->allocation_order_end(*MF);
// First check to see if we have a free register of the requested type...
- for (TargetRegisterClass::iterator It = RegClass->begin(),E = RegClass->end();
- It != E; ++It) {
- unsigned R = *It;
+ unsigned PhysReg = 0;
+ for (; RI != RE; ++RI) {
+ unsigned R = *RI;
if (isPhysRegAvailable(R)) { // Is reg unused?
- if (isAllocatableRegister(R)) { // And is not a frame register?
- // Found an unused register!
- PhysReg = R;
- break;
- }
+ // Found an unused register!
+ PhysReg = R;
+ assert(PhysReg != 0 && "Cannot use register!");
+ break;
}
}
@@ -331,25 +286,21 @@
unsigned R = PhysRegsUseOrder[i];
// If the current register is compatible, use it.
- if (isAllocatableRegister(R)) {
- if (RegInfo.getRegClass(R) == RegClass) {
- PhysReg = R;
- break;
- } else {
- // If one of the registers aliased to the current register is
- // compatible, use it.
- if (const unsigned *AliasSet = RegInfo.getAliasSet(R))
- for (unsigned a = 0; AliasSet[a]; ++a)
- if (RegInfo.getRegClass(AliasSet[a]) == RegClass) {
- PhysReg = AliasSet[a]; // Take an aliased register
- break;
- }
- }
+ if (RegInfo->getRegClass(R) == RC) {
+ PhysReg = R;
+ break;
+ } else {
+ // If one of the registers aliased to the current register is
+ // compatible, use it.
+ if (const unsigned *AliasSet = RegInfo->getAliasSet(R))
+ for (unsigned a = 0; AliasSet[a]; ++a)
+ if (RegInfo->getRegClass(AliasSet[a]) == RC) {
+ PhysReg = AliasSet[a]; // Take an aliased register
+ break;
+ }
}
}
- assert(isAllocatableRegister(PhysReg) && "Register is not allocatable!");
-
assert(PhysReg && "Physical register not assigned!?!?");
// At this point PhysRegsUseOrder[i] is the least recently used register of
@@ -391,11 +342,10 @@
unsigned PhysReg = getFreeReg(MBB, I, VirtReg);
const TargetRegisterClass *RC = MF->getSSARegMap()->getRegClass(VirtReg);
- unsigned StackOffset = getStackSpaceFor(VirtReg, RC);
+ int FrameIndex = getStackSpaceFor(VirtReg, RC);
// Add move instruction(s)
- RegInfo.loadRegOffset2Reg(MBB, I, PhysReg, RegInfo.getFramePointer(),
- -StackOffset, RC);
+ RegInfo->loadRegFromStackSlot(MBB, I, PhysReg, FrameIndex, RC);
++NumReloaded; // Update statistics
return PhysReg;
}
@@ -440,7 +390,7 @@
/// predecessor basic blocks.
///
void RA::EliminatePHINodes(MachineBasicBlock &MBB) {
- const MachineInstrInfo &MII = TM.getInstrInfo();
+ const MachineInstrInfo &MII = TM->getInstrInfo();
while (MBB.front()->getOpcode() == MachineInstrInfo::PHI) {
MachineInstr *MI = MBB.front();
@@ -490,15 +440,9 @@
const TargetRegisterClass *RC =
MF->getSSARegMap()->getRegClass(virtualReg);
- // Retrieve the constant value from this op, move it to target
- // register of the phi
- if (opVal.isImmediate()) {
- RegInfo.moveImm2Reg(opBlock, opI, virtualReg,
- (unsigned) opVal.getImmedValue(), RC);
- } else {
- RegInfo.moveReg2Reg(opBlock, opI, virtualReg,
- opVal.getAllocatedRegNum(), RC);
- }
+ assert(opVal.isVirtualRegister() &&
+ "Machine PHI Operands must all be virtual registers!");
+ RegInfo->copyRegToReg(opBlock, opI, virtualReg, opVal.getReg(), RC);
}
}
@@ -513,7 +457,7 @@
MachineBasicBlock::iterator I = MBB.begin();
for (; I != MBB.end(); ++I) {
MachineInstr *MI = *I;
- const MachineInstrDescriptor &MID = MIInfo.get(MI->getOpcode());
+ const MachineInstrDescriptor &MID = TM->getInstrInfo().get(MI->getOpcode());
// Loop over all of the operands of the instruction, spilling registers that
// are defined, and marking explicit destinations in the PhysRegsUsed map.
@@ -527,7 +471,6 @@
spillPhysReg(MBB, I, Reg);
PhysRegsUsed[Reg] = 0; // It is free and reserved now
PhysRegsUseOrder.push_back(Reg);
- PhysRegsModified.insert(Reg); // Register is modified by current Fn
}
// Loop over the implicit defs, spilling them, as above.
@@ -546,7 +489,6 @@
}
PhysRegsUseOrder.push_back(Reg);
PhysRegsUsed[Reg] = 0; // It is free and reserved now
- PhysRegsModified.insert(Reg); // Register is modified by current Fn
}
// Loop over the implicit uses, making sure that they are at the head of the
@@ -565,7 +507,6 @@
unsigned VirtSrcReg = MI->getOperand(i).getAllocatedRegNum();
unsigned PhysSrcReg = reloadVirtReg(MBB, I, VirtSrcReg);
MI->SetMachineOperandReg(i, PhysSrcReg); // Assign the input register
- PhysRegsModified.insert(PhysSrcReg); // Register is modified
}
// Okay, we have allocated all of the source operands and spilled any values
@@ -579,7 +520,7 @@
unsigned DestVirtReg = MI->getOperand(i).getAllocatedRegNum();
unsigned DestPhysReg;
- if (TM.getInstrInfo().isTwoAddrInstr(MI->getOpcode()) && i == 0) {
+ 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() &&
@@ -595,7 +536,6 @@
} else {
DestPhysReg = getFreeReg(MBB, I, DestVirtReg);
}
- PhysRegsModified.insert(DestPhysReg); // Register is modified
MI->SetMachineOperandReg(i, DestPhysReg); // Assign the output register
}
@@ -619,7 +559,7 @@
}
// Rewind the iterator to point to the first flow control instruction...
- const MachineInstrInfo &MII = TM.getInstrInfo();
+ const MachineInstrInfo &MII = TM->getInstrInfo();
I = MBB.end();
do {
--I;
@@ -639,54 +579,13 @@
}
-/// EmitPrologue - Use the register info object to add a prologue to the
-/// function and save any callee saved registers we are responsible for.
-///
-void RA::EmitPrologue(const std::vector<unsigned> &CSRegs) {
- MachineBasicBlock &MBB = MF->front(); // Prolog goes in entry BB
- MachineBasicBlock::iterator I = MBB.begin();
-
- for (unsigned i = 0, e = CSRegs.size(); i != e; ++i) {
- const TargetRegisterClass *RegClass = RegInfo.getRegClass(CSRegs[i]);
- unsigned Offset = getStackSpaceFor(CSRegs[i], RegClass);
-
- // Insert the spill to the stack frame...
- ++NumSpilled;
- RegInfo.storeReg2RegOffset(MBB, I, CSRegs[i], RegInfo.getFramePointer(),
- -Offset, RegClass);
- }
-
- // 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 RA::EmitEpilogue(MachineBasicBlock &MBB,
- const std::vector<unsigned> &CSRegs) {
- // Insert instructions before the return.
- MachineBasicBlock::iterator I = MBB.end()-1;
-
- for (unsigned i = 0, e = CSRegs.size(); i != e; ++i) {
- const TargetRegisterClass *RegClass = RegInfo.getRegClass(CSRegs[i]);
- unsigned Offset = getStackSpaceFor(CSRegs[i], RegClass);
- ++NumReloaded;
- RegInfo.loadRegOffset2Reg(MBB, I, CSRegs[i], RegInfo.getFramePointer(),
- -Offset, RegClass);
- --I; // Insert in reverse order
- }
-
- RegInfo.emitEpilogue(MBB, NumBytesAllocated);
-}
-
-
/// runOnMachineFunction - Register allocate the whole function
///
bool RA::runOnMachineFunction(MachineFunction &Fn) {
DEBUG(std::cerr << "Machine Function " << "\n");
MF = &Fn;
+ TM = &Fn.getTarget();
+ RegInfo = TM->getRegisterInfo();
// First pass: eliminate PHI instructions by inserting copies into predecessor
// blocks, and calculate a simple approximation of killing uses for virtual
@@ -718,42 +617,11 @@
MBB != MBBe; ++MBB)
AllocateBasicBlock(*MBB);
- // Figure out which callee saved registers are modified by the current
- // function, thus needing to be saved and restored in the prolog/epilog.
- //
- const unsigned *CSRegs = RegInfo.getCalleeSaveRegs();
- std::vector<unsigned> RegsToSave;
- for (unsigned i = 0; CSRegs[i]; ++i) {
- unsigned Reg = CSRegs[i];
- if (PhysRegsModified.count(Reg)) // If modified register...
- RegsToSave.push_back(Reg);
- else if (const unsigned *AliasSet = RegInfo.getAliasSet(Reg))
- for (unsigned j = 0; AliasSet[j]; ++j) // Check alias registers too...
- if (PhysRegsModified.count(AliasSet[j])) {
- RegsToSave.push_back(Reg);
- break;
- }
- }
-
- // Emit a prologue for the function...
- EmitPrologue(RegsToSave);
-
- 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()))
- EmitEpilogue(*MBB, RegsToSave);
- }
-
- PhysRegsModified.clear();
LastUserOf.clear();
- cleanupAfterFunction();
+ StackSlotForVirtReg.clear();
return true;
}
-Pass *createLocalRegisterAllocator(TargetMachine &TM) {
- return new RA(TM);
+Pass *createLocalRegisterAllocator() {
+ return new RA();
}
More information about the llvm-commits
mailing list