From 580f9be7ff6ddbdf6914fc9243ab21fa21ffd34e Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 28 Dec 2002 20:40:43 +0000 Subject: [PATCH] * 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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@5195 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/RegAllocLocal.cpp | 260 +++++++++------------------------- 1 file changed, 64 insertions(+), 196 deletions(-) diff --git a/lib/CodeGen/RegAllocLocal.cpp b/lib/CodeGen/RegAllocLocal.cpp index e9d5918f821..206f798e76a 100644 --- a/lib/CodeGen/RegAllocLocal.cpp +++ b/lib/CodeGen/RegAllocLocal.cpp @@ -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 @@ namespace { cl::opt 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; + const MRegisterInfo *RegInfo; - // 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 PhysRegsModified; - - // Maps SSA Regs => offsets on the stack where these values are stored - std::map VirtReg2OffsetMap; + // StackSlotForVirtReg - Maps SSA Regs => frame index where these values are + // spilled + std::map StackSlotForVirtReg; // Virt2PhysRegMap - This map contains entries for each virtual register // that is currently available in a physical register. @@ -85,16 +77,6 @@ namespace { } 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 @@ namespace { std::map &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 &CSRegs); - void EmitEpilogue(MachineBasicBlock &MBB, - const std::vector &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 @@ namespace { std::map::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 @@ namespace { /// 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::iterator I = - VirtReg2OffsetMap.lower_bound(VirtReg); + std::map::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 @@ void RA::spillVirtReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &I, 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 @@ bool RA::isPhysRegAvailable(unsigned PhysReg) const { // 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 @@ bool RA::isPhysRegAvailable(unsigned PhysReg) const { /// 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 RA::getFreeReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &I, 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 RA::reloadVirtReg(MachineBasicBlock &MBB, 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 @@ void RA::CalculateLastUseOfVReg(MachineBasicBlock &MBB, /// 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 @@ void RA::EliminatePHINodes(MachineBasicBlock &MBB) { 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 @@ void RA::AllocateBasicBlock(MachineBasicBlock &MBB) { 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 @@ void RA::AllocateBasicBlock(MachineBasicBlock &MBB) { 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 @@ void RA::AllocateBasicBlock(MachineBasicBlock &MBB) { } 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 @@ void RA::AllocateBasicBlock(MachineBasicBlock &MBB) { 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 @@ void RA::AllocateBasicBlock(MachineBasicBlock &MBB) { 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 @@ void RA::AllocateBasicBlock(MachineBasicBlock &MBB) { } else { DestPhysReg = getFreeReg(MBB, I, DestVirtReg); } - PhysRegsModified.insert(DestPhysReg); // Register is modified MI->SetMachineOperandReg(i, DestPhysReg); // Assign the output register } @@ -619,7 +559,7 @@ void RA::AllocateBasicBlock(MachineBasicBlock &MBB) { } // 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 @@ void RA::AllocateBasicBlock(MachineBasicBlock &MBB) { } -/// 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 &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 &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 @@ bool RA::runOnMachineFunction(MachineFunction &Fn) { 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 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(); }