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
This commit is contained in:
Chris Lattner 2002-12-25 05:05:46 +00:00
parent 5124aec32f
commit ff863ba610

View File

@ -7,11 +7,13 @@
#include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/Target/MachineInstrInfo.h" #include "llvm/Target/MachineInstrInfo.h"
#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetMachine.h"
#include "Support/Statistic.h" #include "Support/Statistic.h"
#include "Support/CommandLine.h" #include "Support/CommandLine.h"
#include <iostream> #include <iostream>
#include <set>
namespace { namespace {
Statistic<> NumSpilled ("ra-local", "Number of registers spilled"); Statistic<> NumSpilled ("ra-local", "Number of registers spilled");
@ -26,6 +28,14 @@ namespace {
const MachineInstrInfo &MIInfo; const MachineInstrInfo &MIInfo;
unsigned NumBytesAllocated; 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 // Maps SSA Regs => offsets on the stack where these values are stored
std::map<unsigned, unsigned> VirtReg2OffsetMap; std::map<unsigned, unsigned> VirtReg2OffsetMap;
@ -111,11 +121,12 @@ namespace {
/// EmitPrologue/EmitEpilogue - Use the register info object to add a /// EmitPrologue/EmitEpilogue - Use the register info object to add a
/// prologue/epilogue to the function and save/restore any callee saved /// prologue/epilogue to the function and save/restore the callee saved
/// registers we are responsible for. /// registers specified by the CSRegs list.
/// ///
void EmitPrologue(); void EmitPrologue(const std::vector<unsigned> &CSRegs);
void EmitEpilogue(MachineBasicBlock &MBB); void EmitEpilogue(MachineBasicBlock &MBB,
const std::vector<unsigned> &CSRegs);
/// areRegsEqual - This method returns true if the specified registers are /// 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 /// 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) { unsigned VirtReg, unsigned PhysReg) {
// If this is just a marker register, we don't need to spill it. // If this is just a marker register, we don't need to spill it.
if (VirtReg != 0) { if (VirtReg != 0) {
const TargetRegisterClass *RegClass = MF->getRegClass(VirtReg); const TargetRegisterClass *RegClass =
MF->getSSARegMap()->getRegClass(VirtReg);
unsigned stackOffset = getStackSpaceFor(VirtReg, RegClass); unsigned stackOffset = getStackSpaceFor(VirtReg, RegClass);
// Add move instruction(s) // Add move instruction(s)
I = RegInfo.storeReg2RegOffset(MBB, I, PhysReg, RegInfo.getFramePointer(), RegInfo.storeReg2RegOffset(MBB, I, PhysReg, RegInfo.getFramePointer(),
-stackOffset, RegClass->getDataSize()); -stackOffset, RegClass);
++NumSpilled; // Update statistics ++NumSpilled; // Update statistics
Virt2PhysRegMap.erase(VirtReg); // VirtReg no longer available 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 RA::getFreeReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &I,
unsigned VirtReg) { unsigned VirtReg) {
const TargetRegisterClass *RegClass = MF->getRegClass(VirtReg); const TargetRegisterClass *RegClass =
MF->getSSARegMap()->getRegClass(VirtReg);
unsigned PhysReg = 0; unsigned PhysReg = 0;
// First check to see if we have a free register of the requested type... // 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); unsigned PhysReg = getFreeReg(MBB, I, VirtReg);
const TargetRegisterClass *RegClass = MF->getRegClass(VirtReg); const TargetRegisterClass *RC = MF->getSSARegMap()->getRegClass(VirtReg);
unsigned StackOffset = getStackSpaceFor(VirtReg, RegClass); unsigned StackOffset = getStackSpaceFor(VirtReg, RC);
// Add move instruction(s) // Add move instruction(s)
I = RegInfo.loadRegOffset2Reg(MBB, I, PhysReg, RegInfo.getFramePointer(), RegInfo.loadRegOffset2Reg(MBB, I, PhysReg, RegInfo.getFramePointer(),
-StackOffset, RegClass->getDataSize()); -StackOffset, RC);
++NumReloaded; // Update statistics ++NumReloaded; // Update statistics
return PhysReg; return PhysReg;
} }
@ -474,17 +487,17 @@ void RA::EliminatePHINodes(MachineBasicBlock &MBB) {
if (!MII.isBranch(opMI->getOpcode())) if (!MII.isBranch(opMI->getOpcode()))
++opI; ++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 // Retrieve the constant value from this op, move it to target
// register of the phi // register of the phi
if (opVal.isImmediate()) { if (opVal.isImmediate()) {
opI = RegInfo.moveImm2Reg(opBlock, opI, virtualReg, RegInfo.moveImm2Reg(opBlock, opI, virtualReg,
(unsigned) opVal.getImmedValue(), (unsigned) opVal.getImmedValue(), RC);
dataSize);
} else { } else {
opI = RegInfo.moveReg2Reg(opBlock, opI, virtualReg, RegInfo.moveReg2Reg(opBlock, opI, virtualReg,
opVal.getAllocatedRegNum(), dataSize); opVal.getAllocatedRegNum(), RC);
} }
} }
} }
@ -514,6 +527,7 @@ void RA::AllocateBasicBlock(MachineBasicBlock &MBB) {
spillPhysReg(MBB, I, Reg); spillPhysReg(MBB, I, Reg);
PhysRegsUsed[Reg] = 0; // It is free and reserved now PhysRegsUsed[Reg] = 0; // It is free and reserved now
PhysRegsUseOrder.push_back(Reg); PhysRegsUseOrder.push_back(Reg);
PhysRegsModified.insert(Reg); // Register is modified by current Fn
} }
// Loop over the implicit defs, spilling them, as above. // Loop over the implicit defs, spilling them, as above.
@ -532,6 +546,7 @@ void RA::AllocateBasicBlock(MachineBasicBlock &MBB) {
} }
PhysRegsUseOrder.push_back(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 // 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 VirtSrcReg = MI->getOperand(i).getAllocatedRegNum();
unsigned PhysSrcReg = reloadVirtReg(MBB, I, VirtSrcReg); unsigned PhysSrcReg = reloadVirtReg(MBB, I, VirtSrcReg);
MI->SetMachineOperandReg(i, PhysSrcReg); // Assign the input register 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 // Okay, we have allocated all of the source operands and spilled any values
@ -579,6 +595,7 @@ void RA::AllocateBasicBlock(MachineBasicBlock &MBB) {
} else { } else {
DestPhysReg = getFreeReg(MBB, I, DestVirtReg); DestPhysReg = getFreeReg(MBB, I, DestVirtReg);
} }
PhysRegsModified.insert(DestPhysReg); // Register is modified
MI->SetMachineOperandReg(i, DestPhysReg); // Assign the output register 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 /// EmitPrologue - Use the register info object to add a prologue to the
/// function and save any callee saved registers we are responsible for. /// function and save any callee saved registers we are responsible for.
/// ///
void RA::EmitPrologue() { void RA::EmitPrologue(const std::vector<unsigned> &CSRegs) {
// 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 &MBB = MF->front(); // Prolog goes in entry BB
MachineBasicBlock::iterator I = MBB.begin(); MachineBasicBlock::iterator I = MBB.begin();
const unsigned *CSRegs = RegInfo.getCalleeSaveRegs(); for (unsigned i = 0, e = CSRegs.size(); i != e; ++i) {
for (unsigned i = 0; CSRegs[i]; ++i) {
const TargetRegisterClass *RegClass = RegInfo.getRegClass(CSRegs[i]); const TargetRegisterClass *RegClass = RegInfo.getRegClass(CSRegs[i]);
unsigned Offset = getStackSpaceFor(CSRegs[i], RegClass); unsigned Offset = getStackSpaceFor(CSRegs[i], RegClass);
// Insert the spill to the stack frame... // Insert the spill to the stack frame...
++NumSpilled; ++NumSpilled;
I = RegInfo.storeReg2RegOffset(MBB, I, CSRegs[i], RegInfo.getFramePointer(), RegInfo.storeReg2RegOffset(MBB, I, CSRegs[i], RegInfo.getFramePointer(),
-Offset, RegClass->getDataSize()); -Offset, RegClass);
} }
// Add prologue to the function... // Add prologue to the function...
@ -652,17 +664,17 @@ void RA::EmitPrologue() {
/// EmitEpilogue - Use the register info object to add a epilogue to the /// EmitEpilogue - Use the register info object to add a epilogue to the
/// function and restore any callee saved registers we are responsible for. /// function and restore any callee saved registers we are responsible for.
/// ///
void RA::EmitEpilogue(MachineBasicBlock &MBB) { void RA::EmitEpilogue(MachineBasicBlock &MBB,
const std::vector<unsigned> &CSRegs) {
// Insert instructions before the return. // Insert instructions before the return.
MachineBasicBlock::iterator I = MBB.end()-1; MachineBasicBlock::iterator I = MBB.end()-1;
const unsigned *CSRegs = RegInfo.getCalleeSaveRegs(); for (unsigned i = 0, e = CSRegs.size(); i != e; ++i) {
for (unsigned i = 0; CSRegs[i]; ++i) {
const TargetRegisterClass *RegClass = RegInfo.getRegClass(CSRegs[i]); const TargetRegisterClass *RegClass = RegInfo.getRegClass(CSRegs[i]);
unsigned Offset = getStackSpaceFor(CSRegs[i], RegClass); unsigned Offset = getStackSpaceFor(CSRegs[i], RegClass);
++NumReloaded; ++NumReloaded;
I = RegInfo.loadRegOffset2Reg(MBB, I, CSRegs[i], RegInfo.getFramePointer(), RegInfo.loadRegOffset2Reg(MBB, I, CSRegs[i], RegInfo.getFramePointer(),
-Offset, RegClass->getDataSize()); -Offset, RegClass);
--I; // Insert in reverse order --I; // Insert in reverse order
} }
@ -706,9 +718,25 @@ bool RA::runOnMachineFunction(MachineFunction &Fn) {
MBB != MBBe; ++MBB) MBB != MBBe; ++MBB)
AllocateBasicBlock(*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... // Emit a prologue for the function...
EmitPrologue(); EmitPrologue(RegsToSave);
const MachineInstrInfo &MII = TM.getInstrInfo(); const MachineInstrInfo &MII = TM.getInstrInfo();
@ -717,9 +745,10 @@ bool RA::runOnMachineFunction(MachineFunction &Fn) {
MBB != MBBe; ++MBB) { MBB != MBBe; ++MBB) {
// If last instruction is a return instruction, add an epilogue // If last instruction is a return instruction, add an epilogue
if (MII.isReturn(MBB->back()->getOpcode())) if (MII.isReturn(MBB->back()->getOpcode()))
EmitEpilogue(*MBB); EmitEpilogue(*MBB, RegsToSave);
} }
PhysRegsModified.clear();
LastUserOf.clear(); LastUserOf.clear();
cleanupAfterFunction(); cleanupAfterFunction();
return true; return true;