diff options
author | Artyom Skrobov <Artyom.Skrobov@arm.com> | 2015-12-01 19:25:11 +0000 |
---|---|---|
committer | Artyom Skrobov <Artyom.Skrobov@arm.com> | 2015-12-01 19:25:11 +0000 |
commit | 5d1f2524a061492093500288406a11086fb754f8 (patch) | |
tree | 16eb64100fc1ea410157de153b888972fec3fba8 /llvm/lib/Target/ARM/Thumb1FrameLowering.cpp | |
parent | 90cd0a8234305bc9378752f4ac99f089897cef44 (diff) | |
download | bcm5719-llvm-5d1f2524a061492093500288406a11086fb754f8.tar.gz bcm5719-llvm-5d1f2524a061492093500288406a11086fb754f8.zip |
Fix Thumb1 epilogue generation
Summary:
This had been broken for a very long time, but nobody noticed until
D14357 enabled shrink-wrapping by default.
Reviewers: jroelofs, qcolombet
Subscribers: tyomitch, llvm-commits, rengolin
Differential Revision: http://reviews.llvm.org/D14986
llvm-svn: 254444
Diffstat (limited to 'llvm/lib/Target/ARM/Thumb1FrameLowering.cpp')
-rw-r--r-- | llvm/lib/Target/ARM/Thumb1FrameLowering.cpp | 67 |
1 files changed, 55 insertions, 12 deletions
diff --git a/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp b/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp index 064cff6f570..fd96af6cb6e 100644 --- a/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp +++ b/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp @@ -406,11 +406,15 @@ bool Thumb1FrameLowering::needPopSpecialFixUp(const MachineFunction &MF) const { if (AFI->getArgRegsSaveSize()) return true; - bool IsV4PopReturn = false; + // FIXME: this doesn't make sense, and the following patch will remove it. + if (!STI.hasV4TOps()) return false; + + // LR cannot be encoded with Thumb1, i.e., it requires a special fix-up. for (const CalleeSavedInfo &CSI : MF.getFrameInfo()->getCalleeSavedInfo()) if (CSI.getReg() == ARM::LR) - IsV4PopReturn = true; - return IsV4PopReturn && STI.hasV4TOps() && !STI.hasV5TOps(); + return true; + + return false; } bool Thumb1FrameLowering::emitPopSpecialFixUp(MachineBasicBlock &MBB, @@ -422,12 +426,45 @@ bool Thumb1FrameLowering::emitPopSpecialFixUp(MachineBasicBlock &MBB, const ThumbRegisterInfo *RegInfo = static_cast<const ThumbRegisterInfo *>(STI.getRegisterInfo()); - // When we need a special fix up for POP, this means that - // we either cannot use PC in POP or we have to update - // SP after poping the return address. - // In other words, we cannot use a pop {pc} like construction - // here, no matter what. + // If MBBI is a return instruction, or is a tPOP followed by a return + // instruction in the successor BB, we may be able to directly restore + // LR in the PC. + // This is only possible with v5T ops (v4T can't change the Thumb bit via + // a POP PC instruction), and only if we do not need to emit any SP update. + // Otherwise, we need a temporary register to pop the value + // and copy that value into LR. auto MBBI = MBB.getFirstTerminator(); + bool CanRestoreDirectly = STI.hasV5TOps() && !ArgRegsSaveSize; + if (CanRestoreDirectly) { + if (MBBI != MBB.end()) + CanRestoreDirectly = (MBBI->getOpcode() == ARM::tBX_RET || + MBBI->getOpcode() == ARM::tPOP_RET); + else { + assert(MBB.back().getOpcode() == ARM::tPOP); + assert(MBB.succ_size() == 1); + if ((*MBB.succ_begin())->begin()->getOpcode() == ARM::tBX_RET) + MBBI--; // Replace the final tPOP with a tPOP_RET. + else + CanRestoreDirectly = false; + } + } + + if (CanRestoreDirectly) { + if (!DoIt || MBBI->getOpcode() == ARM::tPOP_RET) + return true; + MachineInstrBuilder MIB = + AddDefaultPred( + BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII.get(ARM::tPOP_RET))); + // Copy implicit ops and popped registers, if any. + for (auto MO: MBBI->operands()) + if (MO.isReg() && (MO.isImplicit() || MO.isDef()) && + MO.getReg() != ARM::LR) + MIB.addOperand(MO); + MIB.addReg(ARM::PC, RegState::Define); + // Erase the old instruction (tBX_RET or tPOP). + MBB.erase(MBBI); + return true; + } // Look for a temporary register to use. // First, compute the liveness information. @@ -446,10 +483,10 @@ bool Thumb1FrameLowering::emitPopSpecialFixUp(MachineBasicBlock &MBB, if (MBBI != MBB.end()) { dl = MBBI->getDebugLoc(); auto InstUpToMBBI = MBB.end(); - // The post-decrement is on purpose here. - // We want to have the liveness right before MBBI. - while (InstUpToMBBI-- != MBBI) - UsedRegs.stepBackward(*InstUpToMBBI); + while (InstUpToMBBI != MBBI) + // The pre-decrement is on purpose here. + // We want to have the liveness right before MBBI. + UsedRegs.stepBackward(*--InstUpToMBBI); } // Look for a register that can be directly use in the POP. @@ -495,6 +532,12 @@ bool Thumb1FrameLowering::emitPopSpecialFixUp(MachineBasicBlock &MBB, .addReg(PopReg, RegState::Kill)); } + if (MBBI == MBB.end()) { + MachineInstr& Pop = MBB.back(); + assert(Pop.getOpcode() == ARM::tPOP); + Pop.RemoveOperand(Pop.findRegisterDefOperandIdx(ARM::LR)); + } + assert(PopReg && "Do not know how to get LR"); AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tPOP))) .addReg(PopReg, RegState::Define); |