summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp
diff options
context:
space:
mode:
authorArtyom Skrobov <Artyom.Skrobov@arm.com>2015-12-01 19:25:11 +0000
committerArtyom Skrobov <Artyom.Skrobov@arm.com>2015-12-01 19:25:11 +0000
commit5d1f2524a061492093500288406a11086fb754f8 (patch)
tree16eb64100fc1ea410157de153b888972fec3fba8 /llvm/lib/Target/ARM/Thumb1FrameLowering.cpp
parent90cd0a8234305bc9378752f4ac99f089897cef44 (diff)
downloadbcm5719-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.cpp67
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);
OpenPOWER on IntegriCloud