diff options
| -rw-r--r-- | llvm/lib/Target/PowerPC/PPCFrameLowering.cpp | 81 | ||||
| -rw-r--r-- | llvm/lib/Target/PowerPC/PPCFrameLowering.h | 7 |
2 files changed, 62 insertions, 26 deletions
diff --git a/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp b/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp index c19ab4e51ae..1d592286f43 100644 --- a/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp @@ -1315,36 +1315,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 +1438,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); diff --git a/llvm/lib/Target/PowerPC/PPCFrameLowering.h b/llvm/lib/Target/PowerPC/PPCFrameLowering.h index ea2586f4656..28b0c57f0ff 100644 --- a/llvm/lib/Target/PowerPC/PPCFrameLowering.h +++ b/llvm/lib/Target/PowerPC/PPCFrameLowering.h @@ -66,6 +66,13 @@ class PPCFrameLowering: public TargetFrameLowering { unsigned *SR2 = nullptr) const; bool twoUniqueScratchRegsRequired(MachineBasicBlock *MBB) const; + /** + * \brief Create branch instruction for PPC::TCRETURN* (tail call return) + * + * \param[in] MBB that is terminated by PPC::TCRETURN* + */ + void createTailCallBranchInstr(MachineBasicBlock &MBB) const; + public: PPCFrameLowering(const PPCSubtarget &STI); |

