From ff863ba610cd577e8589fbc94b2fc00d74f8294a Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Wed, 25 Dec 2002 05:05:46 +0000 Subject: [PATCH] Adjust to simpler spill interface Only spill and reload caller saved registers that are actually modified. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@5145 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/RegAllocLocal.cpp | 99 ++++++++++++++++++++++------------- 1 file changed, 64 insertions(+), 35 deletions(-) diff --git a/lib/CodeGen/RegAllocLocal.cpp b/lib/CodeGen/RegAllocLocal.cpp index fb9cca42723..e9d5918f821 100644 --- a/lib/CodeGen/RegAllocLocal.cpp +++ b/lib/CodeGen/RegAllocLocal.cpp @@ -7,11 +7,13 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/SSARegMap.h" #include "llvm/Target/MachineInstrInfo.h" #include "llvm/Target/TargetMachine.h" #include "Support/Statistic.h" #include "Support/CommandLine.h" #include +#include namespace { Statistic<> NumSpilled ("ra-local", "Number of registers spilled"); @@ -25,6 +27,14 @@ namespace { 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 PhysRegsModified; // Maps SSA Regs => offsets on the stack where these values are stored std::map VirtReg2OffsetMap; @@ -111,11 +121,12 @@ namespace { /// 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. + /// prologue/epilogue to the function and save/restore the callee saved + /// registers specified by the CSRegs list. /// - void EmitPrologue(); - void EmitEpilogue(MachineBasicBlock &MBB); + 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 @@ -251,12 +262,13 @@ 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); + const TargetRegisterClass *RegClass = + MF->getSSARegMap()->getRegClass(VirtReg); unsigned stackOffset = getStackSpaceFor(VirtReg, RegClass); // Add move instruction(s) - I = RegInfo.storeReg2RegOffset(MBB, I, PhysReg, RegInfo.getFramePointer(), - -stackOffset, RegClass->getDataSize()); + RegInfo.storeReg2RegOffset(MBB, I, PhysReg, RegInfo.getFramePointer(), + -stackOffset, RegClass); ++NumSpilled; // Update statistics Virt2PhysRegMap.erase(VirtReg); // VirtReg no longer available } @@ -289,7 +301,8 @@ bool RA::isPhysRegAvailable(unsigned PhysReg) const { /// unsigned RA::getFreeReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &I, unsigned VirtReg) { - const TargetRegisterClass *RegClass = MF->getRegClass(VirtReg); + const TargetRegisterClass *RegClass = + MF->getSSARegMap()->getRegClass(VirtReg); unsigned PhysReg = 0; // First check to see if we have a free register of the requested type... @@ -377,12 +390,12 @@ unsigned RA::reloadVirtReg(MachineBasicBlock &MBB, unsigned PhysReg = getFreeReg(MBB, I, VirtReg); - const TargetRegisterClass *RegClass = MF->getRegClass(VirtReg); - unsigned StackOffset = getStackSpaceFor(VirtReg, RegClass); + const TargetRegisterClass *RC = MF->getSSARegMap()->getRegClass(VirtReg); + unsigned StackOffset = getStackSpaceFor(VirtReg, RC); // Add move instruction(s) - I = RegInfo.loadRegOffset2Reg(MBB, I, PhysReg, RegInfo.getFramePointer(), - -StackOffset, RegClass->getDataSize()); + RegInfo.loadRegOffset2Reg(MBB, I, PhysReg, RegInfo.getFramePointer(), + -StackOffset, RC); ++NumReloaded; // Update statistics return PhysReg; } @@ -474,17 +487,17 @@ void RA::EliminatePHINodes(MachineBasicBlock &MBB) { if (!MII.isBranch(opMI->getOpcode())) ++opI; - unsigned dataSize = MF->getRegClass(virtualReg)->getDataSize(); + 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()) { - opI = RegInfo.moveImm2Reg(opBlock, opI, virtualReg, - (unsigned) opVal.getImmedValue(), - dataSize); + RegInfo.moveImm2Reg(opBlock, opI, virtualReg, + (unsigned) opVal.getImmedValue(), RC); } else { - opI = RegInfo.moveReg2Reg(opBlock, opI, virtualReg, - opVal.getAllocatedRegNum(), dataSize); + RegInfo.moveReg2Reg(opBlock, opI, virtualReg, + opVal.getAllocatedRegNum(), RC); } } } @@ -514,6 +527,7 @@ 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. @@ -531,7 +545,8 @@ void RA::AllocateBasicBlock(MachineBasicBlock &MBB) { removePhysReg(Reg); } PhysRegsUseOrder.push_back(Reg); - PhysRegsUsed[Reg] = 0; // It is free and reserved now + 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 @@ -550,6 +565,7 @@ 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,6 +595,7 @@ 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 } @@ -625,23 +642,18 @@ 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() { - // Get a list of the callee saved registers, so that we can save them on entry - // to the function. - // - +void RA::EmitPrologue(const std::vector &CSRegs) { 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) { + 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; - I = RegInfo.storeReg2RegOffset(MBB, I, CSRegs[i], RegInfo.getFramePointer(), - -Offset, RegClass->getDataSize()); + RegInfo.storeReg2RegOffset(MBB, I, CSRegs[i], RegInfo.getFramePointer(), + -Offset, RegClass); } // Add prologue to the function... @@ -652,17 +664,17 @@ void RA::EmitPrologue() { /// 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) { +void RA::EmitEpilogue(MachineBasicBlock &MBB, + const std::vector &CSRegs) { // Insert instructions before the return. MachineBasicBlock::iterator I = MBB.end()-1; - const unsigned *CSRegs = RegInfo.getCalleeSaveRegs(); - for (unsigned i = 0; CSRegs[i]; ++i) { + for (unsigned i = 0, e = CSRegs.size(); i != e; ++i) { const TargetRegisterClass *RegClass = RegInfo.getRegClass(CSRegs[i]); unsigned Offset = getStackSpaceFor(CSRegs[i], RegClass); ++NumReloaded; - I = RegInfo.loadRegOffset2Reg(MBB, I, CSRegs[i], RegInfo.getFramePointer(), - -Offset, RegClass->getDataSize()); + RegInfo.loadRegOffset2Reg(MBB, I, CSRegs[i], RegInfo.getFramePointer(), + -Offset, RegClass); --I; // Insert in reverse order } @@ -706,9 +718,25 @@ 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(); + EmitPrologue(RegsToSave); const MachineInstrInfo &MII = TM.getInstrInfo(); @@ -717,9 +745,10 @@ bool RA::runOnMachineFunction(MachineFunction &Fn) { MBB != MBBe; ++MBB) { // If last instruction is a return instruction, add an epilogue if (MII.isReturn(MBB->back()->getOpcode())) - EmitEpilogue(*MBB); + EmitEpilogue(*MBB, RegsToSave); } + PhysRegsModified.clear(); LastUserOf.clear(); cleanupAfterFunction(); return true;