diff options
Diffstat (limited to 'lib/Target/PowerPC/PPCFrameLowering.cpp')
-rw-r--r-- | lib/Target/PowerPC/PPCFrameLowering.cpp | 131 |
1 files changed, 86 insertions, 45 deletions
diff --git a/lib/Target/PowerPC/PPCFrameLowering.cpp b/lib/Target/PowerPC/PPCFrameLowering.cpp index 3fd509ae27f4..c480430dd29a 100644 --- a/lib/Target/PowerPC/PPCFrameLowering.cpp +++ b/lib/Target/PowerPC/PPCFrameLowering.cpp @@ -76,9 +76,7 @@ static unsigned computeBasePointerSaveOffset(const PPCSubtarget &STI) { // SVR4 ABI: First slot in the general register save area. return STI.isPPC64() ? -16U - : (STI.getTargetMachine().getRelocationModel() == Reloc::PIC_) - ? -12U - : -8U; + : STI.getTargetMachine().isPositionIndependent() ? -12U : -8U; } PPCFrameLowering::PPCFrameLowering(const PPCSubtarget &STI) @@ -596,7 +594,7 @@ PPCFrameLowering::findScratchRegister(MachineBasicBlock *MBB, (!UseAtEnd && (&MBB->getParent()->front() == MBB))) return true; - RS.enterBasicBlock(MBB); + RS.enterBasicBlock(*MBB); if (UseAtEnd && !MBB->empty()) { // The scratch register will be used at the end of the block, so must @@ -653,7 +651,7 @@ PPCFrameLowering::findScratchRegister(MachineBasicBlock *MBB, // Now that we've done our best to provide both registers, double check // whether we were unable to provide enough. - if (BV.count() < (TwoUniqueRegsRequired ? 2 : 1)) + if (BV.count() < (TwoUniqueRegsRequired ? 2U : 1U)) return false; return true; @@ -838,13 +836,20 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF, // If we need to spill the CR and the LR but we don't have two separate // registers available, we must spill them one at a time if (MustSaveCR && SingleScratchReg && MustSaveLR) { - // FIXME: In the ELFv2 ABI, we are not required to save all CR fields. - // If only one or two CR fields are clobbered, it could be more - // efficient to use mfocrf to selectively save just those fields. + // In the ELFv2 ABI, we are not required to save all CR fields. + // If only one or two CR fields are clobbered, it is more efficient to use + // mfocrf to selectively save just those fields, because mfocrf has short + // latency compares to mfcr. + unsigned MfcrOpcode = PPC::MFCR8; + unsigned CrState = RegState::ImplicitKill; + if (isELFv2ABI && MustSaveCRs.size() == 1) { + MfcrOpcode = PPC::MFOCRF8; + CrState = RegState::Kill; + } MachineInstrBuilder MIB = - BuildMI(MBB, MBBI, dl, TII.get(PPC::MFCR8), TempReg); + BuildMI(MBB, MBBI, dl, TII.get(MfcrOpcode), TempReg); for (unsigned i = 0, e = MustSaveCRs.size(); i != e; ++i) - MIB.addReg(MustSaveCRs[i], RegState::ImplicitKill); + MIB.addReg(MustSaveCRs[i], CrState); BuildMI(MBB, MBBI, dl, TII.get(PPC::STW8)) .addReg(TempReg, getKillRegState(true)) .addImm(8) @@ -856,13 +861,20 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF, if (MustSaveCR && !(SingleScratchReg && MustSaveLR)) { // will only occur for PPC64 - // FIXME: In the ELFv2 ABI, we are not required to save all CR fields. - // If only one or two CR fields are clobbered, it could be more - // efficient to use mfocrf to selectively save just those fields. + // In the ELFv2 ABI, we are not required to save all CR fields. + // If only one or two CR fields are clobbered, it is more efficient to use + // mfocrf to selectively save just those fields, because mfocrf has short + // latency compares to mfcr. + unsigned MfcrOpcode = PPC::MFCR8; + unsigned CrState = RegState::ImplicitKill; + if (isELFv2ABI && MustSaveCRs.size() == 1) { + MfcrOpcode = PPC::MFOCRF8; + CrState = RegState::Kill; + } MachineInstrBuilder MIB = - BuildMI(MBB, MBBI, dl, TII.get(PPC::MFCR8), TempReg); + BuildMI(MBB, MBBI, dl, TII.get(MfcrOpcode), TempReg); for (unsigned i = 0, e = MustSaveCRs.size(); i != e; ++i) - MIB.addReg(MustSaveCRs[i], RegState::ImplicitKill); + MIB.addReg(MustSaveCRs[i], CrState); } if (HasFP) @@ -889,7 +901,7 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF, if (MustSaveLR) // FIXME: On PPC32 SVR4, we must not spill before claiming the stackframe. BuildMI(MBB, MBBI, dl, StoreInst) - .addReg(ScratchReg) + .addReg(ScratchReg, getKillRegState(true)) .addImm(LROffset) .addReg(SPReg); @@ -1315,36 +1327,53 @@ void PPCFrameLowering::emitEpilogue(MachineFunction &MF, .addReg(FPReg) .addReg(ScratchReg); } - } else if (RetOpcode == PPC::TCRETURNdi) { - MBBI = MBB.getLastNonDebugInstr(); - MachineOperand &JumpTarget = MBBI->getOperand(0); - BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILB)). - addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset()); - } else if (RetOpcode == PPC::TCRETURNri) { - MBBI = MBB.getLastNonDebugInstr(); - assert(MBBI->getOperand(0).isReg() && "Expecting register operand."); - BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILBCTR)); - } else if (RetOpcode == PPC::TCRETURNai) { - MBBI = MBB.getLastNonDebugInstr(); - MachineOperand &JumpTarget = MBBI->getOperand(0); - BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILBA)).addImm(JumpTarget.getImm()); - } else if (RetOpcode == PPC::TCRETURNdi8) { - MBBI = MBB.getLastNonDebugInstr(); - MachineOperand &JumpTarget = MBBI->getOperand(0); - BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILB8)). - addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset()); - } else if (RetOpcode == PPC::TCRETURNri8) { - MBBI = MBB.getLastNonDebugInstr(); - assert(MBBI->getOperand(0).isReg() && "Expecting register operand."); - BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILBCTR8)); - } else if (RetOpcode == PPC::TCRETURNai8) { - MBBI = MBB.getLastNonDebugInstr(); - MachineOperand &JumpTarget = MBBI->getOperand(0); - BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILBA8)).addImm(JumpTarget.getImm()); + } else { + createTailCallBranchInstr(MBB); } } } +void PPCFrameLowering::createTailCallBranchInstr(MachineBasicBlock &MBB) const { + MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator(); + DebugLoc dl; + + if (MBBI != MBB.end()) + dl = MBBI->getDebugLoc(); + + const PPCInstrInfo &TII = + *static_cast<const PPCInstrInfo *>(Subtarget.getInstrInfo()); + + // Create branch instruction for pseudo tail call return instruction + unsigned RetOpcode = MBBI->getOpcode(); + if (RetOpcode == PPC::TCRETURNdi) { + MBBI = MBB.getLastNonDebugInstr(); + MachineOperand &JumpTarget = MBBI->getOperand(0); + BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILB)). + addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset()); + } else if (RetOpcode == PPC::TCRETURNri) { + MBBI = MBB.getLastNonDebugInstr(); + assert(MBBI->getOperand(0).isReg() && "Expecting register operand."); + BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILBCTR)); + } else if (RetOpcode == PPC::TCRETURNai) { + MBBI = MBB.getLastNonDebugInstr(); + MachineOperand &JumpTarget = MBBI->getOperand(0); + BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILBA)).addImm(JumpTarget.getImm()); + } else if (RetOpcode == PPC::TCRETURNdi8) { + MBBI = MBB.getLastNonDebugInstr(); + MachineOperand &JumpTarget = MBBI->getOperand(0); + BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILB8)). + addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset()); + } else if (RetOpcode == PPC::TCRETURNri8) { + MBBI = MBB.getLastNonDebugInstr(); + assert(MBBI->getOperand(0).isReg() && "Expecting register operand."); + BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILBCTR8)); + } else if (RetOpcode == PPC::TCRETURNai8) { + MBBI = MBB.getLastNonDebugInstr(); + MachineOperand &JumpTarget = MBBI->getOperand(0); + BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILBA8)).addImm(JumpTarget.getImm()); + } +} + void PPCFrameLowering::determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS) const { @@ -1421,6 +1450,18 @@ void PPCFrameLowering::processFunctionBeforeFrameFinalized(MachineFunction &MF, MachineFrameInfo *FFI = MF.getFrameInfo(); const std::vector<CalleeSavedInfo> &CSI = FFI->getCalleeSavedInfo(); + // If the function is shrink-wrapped, and if the function has a tail call, the + // tail call might not be in the new RestoreBlock, so real branch instruction + // won't be generated by emitEpilogue(), because shrink-wrap has chosen new + // RestoreBlock. So we handle this case here. + if (FFI->getSavePoint() && FFI->hasTailCall()) { + MachineBasicBlock *RestoreBlock = FFI->getRestorePoint(); + for (MachineBasicBlock &MBB : MF) { + if (MBB.isReturnBlock() && (&MBB) != RestoreBlock) + createTailCallBranchInstr(MBB); + } + } + // Early exit if no callee saved registers are modified! if (CSI.empty() && !needsFP(MF)) { addScavengingSpillSlot(MF, RS); @@ -1770,7 +1811,7 @@ restoreCRs(bool isPPC64, bool is31, .addReg(MoveReg, getKillRegState(true))); } -void PPCFrameLowering:: +MachineBasicBlock::iterator PPCFrameLowering:: eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { const TargetInstrInfo &TII = *Subtarget.getInstrInfo(); @@ -1787,7 +1828,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, unsigned LISInstr = is64Bit ? PPC::LIS8 : PPC::LIS; unsigned ORIInstr = is64Bit ? PPC::ORI8 : PPC::ORI; MachineInstr *MI = I; - DebugLoc dl = MI->getDebugLoc(); + const DebugLoc &dl = MI->getDebugLoc(); if (isInt<16>(CalleeAmt)) { BuildMI(MBB, I, dl, TII.get(ADDIInstr), StackReg) @@ -1807,7 +1848,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, } } // Simply discard ADJCALLSTACKDOWN, ADJCALLSTACKUP instructions. - MBB.erase(I); + return MBB.erase(I); } bool |