diff options
author | Chuang-Yu Cheng <cycheng@multicorewareinc.com> | 2016-04-01 06:44:32 +0000 |
---|---|---|
committer | Chuang-Yu Cheng <cycheng@multicorewareinc.com> | 2016-04-01 06:44:32 +0000 |
commit | f8b592f213816911adcd9c2e86a04d007ef3f6b1 (patch) | |
tree | d7470b461d257201c566f24bda6e65b13904c62f /llvm/lib/Target/PowerPC/PPCFrameLowering.cpp | |
parent | d7ad221c161dbf048c1d4f4f3ce3c24bbb203a13 (diff) | |
download | llvm-f8b592f213816911adcd9c2e86a04d007ef3f6b1.zip llvm-f8b592f213816911adcd9c2e86a04d007ef3f6b1.tar.gz llvm-f8b592f213816911adcd9c2e86a04d007ef3f6b1.tar.bz2 |
[PPC64] Bug fix: when enabling sibling-call-opt and shrink-wrapping, the tail call branch instruction might disappear
Bug Pattern:
# BB#0: # %entry
cmpldi 3, 0
beq- 0, .LBB0_2
# BB#1: # %exit
lwz 4, 0(3)
#TC_RETURNd8 LVComputationKind 0
.LBB0_2: # %cond.false
mflr 0
std 0, 16(1)
stdu 1, -96(1)
.Ltmp0:
.cfi_def_cfa_offset 96
.Ltmp1:
.cfi_offset lr, 16
bl __assert_fail
nop
The branch instruction for tail call return is not generated, because the
shrink-wrapping pass choosing a new Restore Point: %cond.false, so %exit
block is not sent to emitEpilogue, that's why the branch is not generated.
Thanks Kit's opinions!
Reviewers: nemanjai hfinkel tjablin kbarton
http://reviews.llvm.org/D17606
llvm-svn: 265112
Diffstat (limited to 'llvm/lib/Target/PowerPC/PPCFrameLowering.cpp')
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCFrameLowering.cpp | 81 |
1 files changed, 55 insertions, 26 deletions
diff --git a/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp b/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp index c19ab4e..1d59228 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); |