Save/restore VRSAVE once per function, not once per block.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26793 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2006-03-16 18:25:23 +00:00
parent 41ff717e85
commit 4bb1895072

View File

@ -39,17 +39,21 @@ namespace {
/// instructions for SelectionDAG operations.
///
class PPCDAGToDAGISel : public SelectionDAGISel {
PPCTargetMachine &TM;
PPCTargetLowering PPCLowering;
unsigned GlobalBaseReg;
public:
PPCDAGToDAGISel(PPCTargetMachine &TM)
: SelectionDAGISel(PPCLowering),
PPCLowering(*TM.getTargetLowering()){}
PPCDAGToDAGISel(PPCTargetMachine &tm)
: SelectionDAGISel(PPCLowering), TM(tm),
PPCLowering(*TM.getTargetLowering()) {}
virtual bool runOnFunction(Function &Fn) {
// Make sure we re-emit a set of the global base reg if necessary
GlobalBaseReg = 0;
return SelectionDAGISel::runOnFunction(Fn);
SelectionDAGISel::runOnFunction(Fn);
InsertVRSaveCode(Fn);
return true;
}
/// getI32Imm - Return a target constant with the specified value, of type
@ -121,6 +125,8 @@ namespace {
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
virtual void InstructionSelectBasicBlock(SelectionDAG &DAG);
void InsertVRSaveCode(Function &Fn);
virtual const char *getPassName() const {
return "PowerPC DAG->DAG Pattern Instruction Selection";
}
@ -199,13 +205,19 @@ void PPCDAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) {
// Emit machine code to BB.
ScheduleAndEmitDAG(DAG);
}
/// InsertVRSaveCode - Once the entire function has been instruction selected,
/// all virtual registers are created and all machine instructions are built,
/// check to see if we need to save/restore VRSAVE. If so, do it.
void PPCDAGToDAGISel::InsertVRSaveCode(Function &F) {
// Check to see if this function uses vector registers, which means we have to
// save and restore the VRSAVE register and update it with the regs we use.
//
// In this case, there will be virtual registers of vector type type created
// by the scheduler. Detect them now.
SSARegMap *RegMap = DAG.getMachineFunction().getSSARegMap();
MachineFunction &Fn = MachineFunction::get(&F);
SSARegMap *RegMap = Fn.getSSARegMap();
bool HasVectorVReg = false;
for (unsigned i = MRegisterInfo::FirstVirtualRegister,
e = RegMap->getLastVirtReg()+1; i != e; ++i)
@ -213,7 +225,8 @@ void PPCDAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) {
HasVectorVReg = true;
break;
}
if (!HasVectorVReg) return; // nothing to do.
// If we have a vector register, we want to emit code into the entry and exit
// blocks to save and restore the VRSAVE register. We do this here (instead
// of marking all vector instructions as clobbering VRSAVE) for two reasons:
@ -223,41 +236,41 @@ void PPCDAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) {
// 2. This (more significantly) allows us to create a temporary virtual
// register to hold the saved VRSAVE value, allowing this temporary to be
// register allocated, instead of forcing it to be spilled to the stack.
if (HasVectorVReg) {
// Create two vregs - one to hold the VRSAVE register that is live-in to the
// function and one for the value after having bits or'd into it.
unsigned InVRSAVE = RegMap->createVirtualRegister(&PPC::GPRCRegClass);
unsigned UpdatedVRSAVE = RegMap->createVirtualRegister(&PPC::GPRCRegClass);
MachineFunction &MF = DAG.getMachineFunction();
MachineBasicBlock &EntryBB = *MF.begin();
// Emit the following code into the entry block:
// InVRSAVE = MFVRSAVE
// UpdatedVRSAVE = UPDATE_VRSAVE InVRSAVE
// MTVRSAVE UpdatedVRSAVE
MachineBasicBlock::iterator IP = EntryBB.begin(); // Insert Point
BuildMI(EntryBB, IP, PPC::MFVRSAVE, 0, InVRSAVE);
BuildMI(EntryBB, IP, PPC::UPDATE_VRSAVE, 1, UpdatedVRSAVE).addReg(InVRSAVE);
BuildMI(EntryBB, IP, PPC::MTVRSAVE, 1).addReg(UpdatedVRSAVE);
// Find all return blocks, outputting a restore in each epilog.
const TargetInstrInfo &TII = *DAG.getTarget().getInstrInfo();
for (MachineFunction::iterator BB = MF.begin(), E = MF.end(); BB != E; ++BB)
if (!BB->empty() && TII.isReturn(BB->back().getOpcode())) {
IP = BB->end(); --IP;
// Skip over all terminator instructions, which are part of the return
// sequence.
MachineBasicBlock::iterator I2 = IP;
while (I2 != BB->begin() && TII.isTerminatorInstr((--I2)->getOpcode()))
IP = I2;
// Emit: MTVRSAVE InVRSave
BuildMI(*BB, IP, PPC::MTVRSAVE, 1).addReg(InVRSAVE);
}
// Create two vregs - one to hold the VRSAVE register that is live-in to the
// function and one for the value after having bits or'd into it.
unsigned InVRSAVE = RegMap->createVirtualRegister(&PPC::GPRCRegClass);
unsigned UpdatedVRSAVE = RegMap->createVirtualRegister(&PPC::GPRCRegClass);
MachineBasicBlock &EntryBB = *Fn.begin();
// Emit the following code into the entry block:
// InVRSAVE = MFVRSAVE
// UpdatedVRSAVE = UPDATE_VRSAVE InVRSAVE
// MTVRSAVE UpdatedVRSAVE
MachineBasicBlock::iterator IP = EntryBB.begin(); // Insert Point
BuildMI(EntryBB, IP, PPC::MFVRSAVE, 0, InVRSAVE);
BuildMI(EntryBB, IP, PPC::UPDATE_VRSAVE, 1, UpdatedVRSAVE).addReg(InVRSAVE);
BuildMI(EntryBB, IP, PPC::MTVRSAVE, 1).addReg(UpdatedVRSAVE);
// Find all return blocks, outputting a restore in each epilog.
const TargetInstrInfo &TII = *TM.getInstrInfo();
for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB) {
if (!BB->empty() && TII.isReturn(BB->back().getOpcode())) {
IP = BB->end(); --IP;
// Skip over all terminator instructions, which are part of the return
// sequence.
MachineBasicBlock::iterator I2 = IP;
while (I2 != BB->begin() && TII.isTerminatorInstr((--I2)->getOpcode()))
IP = I2;
// Emit: MTVRSAVE InVRSave
BuildMI(*BB, IP, PPC::MTVRSAVE, 1).addReg(InVRSAVE);
}
}
}
/// getGlobalBaseReg - Output the instructions required to put the
/// base address to use for accessing globals into a register.
///