diff --git a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index a392ba9ba70..539ccb25e0d 100644 --- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -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. ///