2017-09-20 21:35:51 +00:00
|
|
|
//===- Thumb1FrameLowering.cpp - Thumb1 Frame Information -----------------===//
|
2010-11-15 00:06:54 +00:00
|
|
|
//
|
2019-01-19 08:50:56 +00:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2010-11-15 00:06:54 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2011-01-10 12:39:04 +00:00
|
|
|
// This file contains the Thumb1 implementation of TargetFrameLowering class.
|
2010-11-15 00:06:54 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-06-06 11:49:48 +00:00
|
|
|
#include "Thumb1FrameLowering.h"
|
2017-01-26 23:40:06 +00:00
|
|
|
#include "ARMBaseInstrInfo.h"
|
|
|
|
#include "ARMBaseRegisterInfo.h"
|
2010-11-15 00:06:54 +00:00
|
|
|
#include "ARMMachineFunctionInfo.h"
|
2017-01-26 23:40:06 +00:00
|
|
|
#include "ARMSubtarget.h"
|
|
|
|
#include "Thumb1InstrInfo.h"
|
|
|
|
#include "ThumbRegisterInfo.h"
|
2017-09-20 21:35:51 +00:00
|
|
|
#include "Utils/ARMBaseInfo.h"
|
2017-01-26 23:40:06 +00:00
|
|
|
#include "llvm/ADT/BitVector.h"
|
2017-06-06 11:49:48 +00:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2017-01-26 23:40:06 +00:00
|
|
|
#include "llvm/ADT/SmallVector.h"
|
2015-07-20 21:42:14 +00:00
|
|
|
#include "llvm/CodeGen/LivePhysRegs.h"
|
2017-01-26 23:40:06 +00:00
|
|
|
#include "llvm/CodeGen/MachineBasicBlock.h"
|
2010-11-15 00:06:54 +00:00
|
|
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
|
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
2017-01-26 23:40:06 +00:00
|
|
|
#include "llvm/CodeGen/MachineInstr.h"
|
2010-11-15 00:06:54 +00:00
|
|
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
2014-02-14 17:19:07 +00:00
|
|
|
#include "llvm/CodeGen/MachineModuleInfo.h"
|
2017-06-06 11:49:48 +00:00
|
|
|
#include "llvm/CodeGen/MachineOperand.h"
|
Fix epilogue codegen to avoid leaving the stack pointer in an invalid
state. Previously Thumb2 would restore sp from fp like this:
mov sp, r7
sub, sp, #4
If an interrupt is taken after the 'mov' but before the 'sub', callee-saved
registers might be clobbered by the interrupt handler. Instead, try
restoring directly from sp:
add sp, #4
Or, if necessary (with VLA, etc.) use a scratch register to compute sp and
then restore it:
sub.w r4, r7, #8
mov sp, r7
rdar://8465407
llvm-svn: 119977
2010-11-22 18:12:04 +00:00
|
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
2017-11-08 01:01:31 +00:00
|
|
|
#include "llvm/CodeGen/TargetInstrInfo.h"
|
2017-11-17 01:07:10 +00:00
|
|
|
#include "llvm/CodeGen/TargetOpcodes.h"
|
|
|
|
#include "llvm/CodeGen/TargetSubtargetInfo.h"
|
2017-01-26 23:40:06 +00:00
|
|
|
#include "llvm/IR/DebugLoc.h"
|
2017-09-20 21:35:51 +00:00
|
|
|
#include "llvm/MC/MCContext.h"
|
2017-01-26 23:40:06 +00:00
|
|
|
#include "llvm/MC/MCDwarf.h"
|
2017-09-20 21:35:51 +00:00
|
|
|
#include "llvm/MC/MCRegisterInfo.h"
|
2017-01-26 23:40:06 +00:00
|
|
|
#include "llvm/Support/Compiler.h"
|
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2017-09-20 21:35:51 +00:00
|
|
|
#include "llvm/Support/MathExtras.h"
|
2017-08-30 22:28:30 +00:00
|
|
|
#include <bitset>
|
2017-01-26 23:40:06 +00:00
|
|
|
#include <cassert>
|
|
|
|
#include <iterator>
|
|
|
|
#include <vector>
|
2010-11-15 00:06:54 +00:00
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
2014-06-26 19:29:59 +00:00
|
|
|
Thumb1FrameLowering::Thumb1FrameLowering(const ARMSubtarget &sti)
|
|
|
|
: ARMFrameLowering(sti) {}
|
|
|
|
|
2011-09-13 20:30:37 +00:00
|
|
|
bool Thumb1FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const{
|
2016-07-28 18:40:00 +00:00
|
|
|
const MachineFrameInfo &MFI = MF.getFrameInfo();
|
|
|
|
unsigned CFSize = MFI.getMaxCallFrameSize();
|
2010-11-18 21:19:35 +00:00
|
|
|
// It's not always a good idea to include the call frame as part of the
|
|
|
|
// stack frame. ARM (especially Thumb) has small immediate offset to
|
|
|
|
// address the stack frame. So a large call frame can cause poor codegen
|
|
|
|
// and may even makes it impossible to scavenge a register.
|
|
|
|
if (CFSize >= ((1 << 8) - 1) * 4 / 2) // Half of imm8 * 4
|
|
|
|
return false;
|
|
|
|
|
2016-07-28 18:40:00 +00:00
|
|
|
return !MFI.hasVarSizedObjects();
|
2010-11-18 21:19:35 +00:00
|
|
|
}
|
|
|
|
|
2016-06-12 15:39:02 +00:00
|
|
|
static void emitSPUpdate(MachineBasicBlock &MBB,
|
|
|
|
MachineBasicBlock::iterator &MBBI,
|
|
|
|
const TargetInstrInfo &TII, const DebugLoc &dl,
|
|
|
|
const ThumbRegisterInfo &MRI, int NumBytes,
|
|
|
|
unsigned MIFlags = MachineInstr::NoFlags) {
|
2011-03-05 18:43:32 +00:00
|
|
|
emitThumbRegPlusImmediate(MBB, MBBI, dl, ARM::SP, ARM::SP, NumBytes, TII,
|
2011-03-05 18:43:50 +00:00
|
|
|
MRI, MIFlags);
|
2010-11-15 00:06:54 +00:00
|
|
|
}
|
|
|
|
|
2016-03-31 18:33:38 +00:00
|
|
|
MachineBasicBlock::iterator Thumb1FrameLowering::
|
2013-02-21 20:05:00 +00:00
|
|
|
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
|
|
|
|
MachineBasicBlock::iterator I) const {
|
|
|
|
const Thumb1InstrInfo &TII =
|
2015-01-29 00:19:33 +00:00
|
|
|
*static_cast<const Thumb1InstrInfo *>(STI.getInstrInfo());
|
2015-03-12 22:48:50 +00:00
|
|
|
const ThumbRegisterInfo *RegInfo =
|
|
|
|
static_cast<const ThumbRegisterInfo *>(STI.getRegisterInfo());
|
2013-02-21 20:05:00 +00:00
|
|
|
if (!hasReservedCallFrame(MF)) {
|
|
|
|
// If we have alloca, convert as follows:
|
|
|
|
// ADJCALLSTACKDOWN -> sub, sp, sp, amount
|
|
|
|
// ADJCALLSTACKUP -> add, sp, sp, amount
|
2016-07-08 20:21:17 +00:00
|
|
|
MachineInstr &Old = *I;
|
|
|
|
DebugLoc dl = Old.getDebugLoc();
|
2017-04-19 03:12:05 +00:00
|
|
|
unsigned Amount = TII.getFrameSize(Old);
|
2013-02-21 20:05:00 +00:00
|
|
|
if (Amount != 0) {
|
|
|
|
// We need to keep the stack aligned properly. To do this, we round the
|
|
|
|
// amount of space needed for the outgoing arguments up to the next
|
|
|
|
// alignment boundary.
|
2017-04-19 03:12:05 +00:00
|
|
|
Amount = alignTo(Amount, getStackAlignment());
|
2013-02-21 20:05:00 +00:00
|
|
|
|
|
|
|
// Replace the pseudo instruction with a new instruction...
|
2016-07-08 20:21:17 +00:00
|
|
|
unsigned Opc = Old.getOpcode();
|
2013-02-21 20:05:00 +00:00
|
|
|
if (Opc == ARM::ADJCALLSTACKDOWN || Opc == ARM::tADJCALLSTACKDOWN) {
|
|
|
|
emitSPUpdate(MBB, I, TII, dl, *RegInfo, -Amount);
|
|
|
|
} else {
|
|
|
|
assert(Opc == ARM::ADJCALLSTACKUP || Opc == ARM::tADJCALLSTACKUP);
|
|
|
|
emitSPUpdate(MBB, I, TII, dl, *RegInfo, Amount);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-03-31 18:33:38 +00:00
|
|
|
return MBB.erase(I);
|
2013-02-21 20:05:00 +00:00
|
|
|
}
|
|
|
|
|
[ShrinkWrap] Add (a simplified version) of shrink-wrapping.
This patch introduces a new pass that computes the safe point to insert the
prologue and epilogue of the function.
The interest is to find safe points that are cheaper than the entry and exits
blocks.
As an example and to avoid regressions to be introduce, this patch also
implements the required bits to enable the shrink-wrapping pass for AArch64.
** Context **
Currently we insert the prologue and epilogue of the method/function in the
entry and exits blocks. Although this is correct, we can do a better job when
those are not immediately required and insert them at less frequently executed
places.
The job of the shrink-wrapping pass is to identify such places.
** Motivating example **
Let us consider the following function that perform a call only in one branch of
a if:
define i32 @f(i32 %a, i32 %b) {
%tmp = alloca i32, align 4
%tmp2 = icmp slt i32 %a, %b
br i1 %tmp2, label %true, label %false
true:
store i32 %a, i32* %tmp, align 4
%tmp4 = call i32 @doSomething(i32 0, i32* %tmp)
br label %false
false:
%tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ]
ret i32 %tmp.0
}
On AArch64 this code generates (removing the cfi directives to ease
readabilities):
_f: ; @f
; BB#0:
stp x29, x30, [sp, #-16]!
mov x29, sp
sub sp, sp, #16 ; =16
cmp w0, w1
b.ge LBB0_2
; BB#1: ; %true
stur w0, [x29, #-4]
sub x1, x29, #4 ; =4
mov w0, wzr
bl _doSomething
LBB0_2: ; %false
mov sp, x29
ldp x29, x30, [sp], #16
ret
With shrink-wrapping we could generate:
_f: ; @f
; BB#0:
cmp w0, w1
b.ge LBB0_2
; BB#1: ; %true
stp x29, x30, [sp, #-16]!
mov x29, sp
sub sp, sp, #16 ; =16
stur w0, [x29, #-4]
sub x1, x29, #4 ; =4
mov w0, wzr
bl _doSomething
add sp, x29, #16 ; =16
ldp x29, x30, [sp], #16
LBB0_2: ; %false
ret
Therefore, we would pay the overhead of setting up/destroying the frame only if
we actually do the call.
** Proposed Solution **
This patch introduces a new machine pass that perform the shrink-wrapping
analysis (See the comments at the beginning of ShrinkWrap.cpp for more details).
It then stores the safe save and restore point into the MachineFrameInfo
attached to the MachineFunction.
This information is then used by the PrologEpilogInserter (PEI) to place the
related code at the right place. This pass runs right before the PEI.
Unlike the original paper of Chow from PLDI’88, this implementation of
shrink-wrapping does not use expensive data-flow analysis and does not need hack
to properly avoid frequently executed point. Instead, it relies on dominance and
loop properties.
The pass is off by default and each target can opt-in by setting the
EnableShrinkWrap boolean to true in their derived class of TargetPassConfig.
This setting can also be overwritten on the command line by using
-enable-shrink-wrap.
Before you try out the pass for your target, make sure you properly fix your
emitProlog/emitEpilog/adjustForXXX method to cope with basic blocks that are not
necessarily the entry block.
** Design Decisions **
1. ShrinkWrap is its own pass right now. It could frankly be merged into PEI but
for debugging and clarity I thought it was best to have its own file.
2. Right now, we only support one save point and one restore point. At some
point we can expand this to several save point and restore point, the impacted
component would then be:
- The pass itself: New algorithm needed.
- MachineFrameInfo: Hold a list or set of Save/Restore point instead of one
pointer.
- PEI: Should loop over the save point and restore point.
Anyhow, at least for this first iteration, I do not believe this is interesting
to support the complex cases. We should revisit that when we motivating
examples.
Differential Revision: http://reviews.llvm.org/D9210
<rdar://problem/3201744>
llvm-svn: 236507
2015-05-05 17:38:16 +00:00
|
|
|
void Thumb1FrameLowering::emitPrologue(MachineFunction &MF,
|
|
|
|
MachineBasicBlock &MBB) const {
|
2010-11-15 00:06:54 +00:00
|
|
|
MachineBasicBlock::iterator MBBI = MBB.begin();
|
2016-07-28 18:40:00 +00:00
|
|
|
MachineFrameInfo &MFI = MF.getFrameInfo();
|
2010-11-15 00:06:54 +00:00
|
|
|
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
2014-02-14 17:19:07 +00:00
|
|
|
MachineModuleInfo &MMI = MF.getMMI();
|
|
|
|
const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo();
|
2015-03-12 22:48:50 +00:00
|
|
|
const ThumbRegisterInfo *RegInfo =
|
|
|
|
static_cast<const ThumbRegisterInfo *>(STI.getRegisterInfo());
|
2010-11-15 00:06:54 +00:00
|
|
|
const Thumb1InstrInfo &TII =
|
2015-01-29 00:19:33 +00:00
|
|
|
*static_cast<const Thumb1InstrInfo *>(STI.getInstrInfo());
|
2010-11-15 00:06:54 +00:00
|
|
|
|
2015-03-11 18:54:22 +00:00
|
|
|
unsigned ArgRegsSaveSize = AFI->getArgRegsSaveSize();
|
2016-07-28 18:40:00 +00:00
|
|
|
unsigned NumBytes = MFI.getStackSize();
|
2015-11-05 21:54:58 +00:00
|
|
|
assert(NumBytes >= ArgRegsSaveSize &&
|
|
|
|
"ArgRegsSaveSize is included in NumBytes");
|
2016-07-28 18:40:00 +00:00
|
|
|
const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
|
2015-11-05 21:54:58 +00:00
|
|
|
|
|
|
|
// Debug location must be unknown since the first debug location is used
|
|
|
|
// to determine the end of the prologue.
|
|
|
|
DebugLoc dl;
|
2018-07-30 19:41:25 +00:00
|
|
|
|
2015-11-05 21:54:58 +00:00
|
|
|
unsigned FramePtr = RegInfo->getFrameRegister(MF);
|
|
|
|
unsigned BasePtr = RegInfo->getBaseRegister();
|
|
|
|
int CFAOffset = 0;
|
2010-11-15 00:06:54 +00:00
|
|
|
|
|
|
|
// Thumb add/sub sp, imm8 instructions implicitly multiply the offset by 4.
|
|
|
|
NumBytes = (NumBytes + 3) & ~3;
|
2016-07-28 18:40:00 +00:00
|
|
|
MFI.setStackSize(NumBytes);
|
2010-11-15 00:06:54 +00:00
|
|
|
|
|
|
|
// Determine the sizes of each callee-save spill areas and record which frame
|
|
|
|
// belongs to which callee-save spill areas.
|
|
|
|
unsigned GPRCS1Size = 0, GPRCS2Size = 0, DPRCSSize = 0;
|
|
|
|
int FramePtrSpillFI = 0;
|
|
|
|
|
2014-02-14 17:19:07 +00:00
|
|
|
if (ArgRegsSaveSize) {
|
2013-04-30 07:19:58 +00:00
|
|
|
emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, -ArgRegsSaveSize,
|
2011-03-05 18:43:50 +00:00
|
|
|
MachineInstr::FrameSetup);
|
2014-02-14 17:19:07 +00:00
|
|
|
CFAOffset -= ArgRegsSaveSize;
|
2016-11-30 23:48:42 +00:00
|
|
|
unsigned CFIIndex = MF.addFrameInst(
|
2014-03-07 06:08:31 +00:00
|
|
|
MCCFIInstruction::createDefCfaOffset(nullptr, CFAOffset));
|
|
|
|
BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
|
2014-12-22 23:09:14 +00:00
|
|
|
.addCFIIndex(CFIIndex)
|
|
|
|
.setMIFlags(MachineInstr::FrameSetup);
|
2014-02-14 17:19:07 +00:00
|
|
|
}
|
2010-11-15 00:06:54 +00:00
|
|
|
|
|
|
|
if (!AFI->hasStackFrame()) {
|
2014-03-05 15:25:27 +00:00
|
|
|
if (NumBytes - ArgRegsSaveSize != 0) {
|
|
|
|
emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, -(NumBytes - ArgRegsSaveSize),
|
2011-03-05 18:43:50 +00:00
|
|
|
MachineInstr::FrameSetup);
|
2014-03-05 15:25:27 +00:00
|
|
|
CFAOffset -= NumBytes - ArgRegsSaveSize;
|
2016-11-30 23:48:42 +00:00
|
|
|
unsigned CFIIndex = MF.addFrameInst(
|
2014-03-07 06:08:31 +00:00
|
|
|
MCCFIInstruction::createDefCfaOffset(nullptr, CFAOffset));
|
|
|
|
BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
|
2014-12-22 23:09:14 +00:00
|
|
|
.addCFIIndex(CFIIndex)
|
|
|
|
.setMIFlags(MachineInstr::FrameSetup);
|
2014-02-14 17:19:07 +00:00
|
|
|
}
|
2010-11-15 00:06:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
|
|
|
|
unsigned Reg = CSI[i].getReg();
|
|
|
|
int FI = CSI[i].getFrameIdx();
|
|
|
|
switch (Reg) {
|
2014-02-14 17:19:07 +00:00
|
|
|
case ARM::R8:
|
|
|
|
case ARM::R9:
|
|
|
|
case ARM::R10:
|
|
|
|
case ARM::R11:
|
[ARM] Generate consistent frame records for Thumb2
There is not an official documented ABI for frame pointers in Thumb2,
but we should try to emit something which is useful.
We use r7 as the frame pointer for Thumb code, which currently means
that if a function needs to save a high register (r8-r11), it will get
pushed to the stack between the frame pointer (r7) and link register
(r14). This means that while a stack unwinder can follow the chain of
frame pointers up the stack, it cannot know the offset to lr, so does
not know which functions correspond to the stack frames.
To fix this, we need to push the callee-saved registers in two batches,
with the first push saving the low registers, fp and lr, and the second
push saving the high registers. This is already implemented, but
previously only used for iOS. This patch turns it on for all Thumb2
targets when frame pointers are required by the ABI, and the frame
pointer is r7 (Windows uses r11, so this isn't a problem there). If
frame pointer elimination is enabled we still emit a single push/pop
even if we need a frame pointer for other reasons, to avoid increasing
code size.
We must also ensure that lr is pushed to the stack when using a frame
pointer, so that we end up with a complete frame record. Situations that
could cause this were rare, because we already push lr in most
situations so that we can return using the pop instruction.
Differential Revision: https://reviews.llvm.org/D23516
llvm-svn: 279506
2016-08-23 09:19:22 +00:00
|
|
|
if (STI.splitFramePushPop(MF)) {
|
2014-02-14 17:19:07 +00:00
|
|
|
GPRCS2Size += 4;
|
|
|
|
break;
|
|
|
|
}
|
2016-08-17 05:10:15 +00:00
|
|
|
LLVM_FALLTHROUGH;
|
2010-11-15 00:06:54 +00:00
|
|
|
case ARM::R4:
|
|
|
|
case ARM::R5:
|
|
|
|
case ARM::R6:
|
|
|
|
case ARM::R7:
|
|
|
|
case ARM::LR:
|
|
|
|
if (Reg == FramePtr)
|
|
|
|
FramePtrSpillFI = FI;
|
|
|
|
GPRCS1Size += 4;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
DPRCSSize += 8;
|
|
|
|
}
|
|
|
|
}
|
2015-11-05 21:54:58 +00:00
|
|
|
|
|
|
|
if (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tPUSH) {
|
|
|
|
++MBBI;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Determine starting offsets of spill areas.
|
2014-03-05 15:25:27 +00:00
|
|
|
unsigned DPRCSOffset = NumBytes - ArgRegsSaveSize - (GPRCS1Size + GPRCS2Size + DPRCSSize);
|
2010-11-15 00:06:54 +00:00
|
|
|
unsigned GPRCS2Offset = DPRCSOffset + DPRCSSize;
|
|
|
|
unsigned GPRCS1Offset = GPRCS2Offset + GPRCS2Size;
|
2013-02-20 12:21:33 +00:00
|
|
|
bool HasFP = hasFP(MF);
|
|
|
|
if (HasFP)
|
2016-07-28 18:40:00 +00:00
|
|
|
AFI->setFramePtrSpillOffset(MFI.getObjectOffset(FramePtrSpillFI) +
|
2013-02-20 12:21:33 +00:00
|
|
|
NumBytes);
|
2010-11-15 00:06:54 +00:00
|
|
|
AFI->setGPRCalleeSavedArea1Offset(GPRCS1Offset);
|
|
|
|
AFI->setGPRCalleeSavedArea2Offset(GPRCS2Offset);
|
|
|
|
AFI->setDPRCalleeSavedAreaOffset(DPRCSOffset);
|
|
|
|
NumBytes = DPRCSOffset;
|
Fix epilogue codegen to avoid leaving the stack pointer in an invalid
state. Previously Thumb2 would restore sp from fp like this:
mov sp, r7
sub, sp, #4
If an interrupt is taken after the 'mov' but before the 'sub', callee-saved
registers might be clobbered by the interrupt handler. Instead, try
restoring directly from sp:
add sp, #4
Or, if necessary (with VLA, etc.) use a scratch register to compute sp and
then restore it:
sub.w r4, r7, #8
mov sp, r7
rdar://8465407
llvm-svn: 119977
2010-11-22 18:12:04 +00:00
|
|
|
|
2013-11-08 17:18:07 +00:00
|
|
|
int FramePtrOffsetInBlock = 0;
|
2014-02-14 17:19:07 +00:00
|
|
|
unsigned adjustedGPRCS1Size = GPRCS1Size;
|
2016-10-11 21:14:03 +00:00
|
|
|
if (GPRCS1Size > 0 && GPRCS2Size == 0 &&
|
|
|
|
tryFoldSPUpdateIntoPushPop(STI, MF, &*std::prev(MBBI), NumBytes)) {
|
2013-11-08 17:18:07 +00:00
|
|
|
FramePtrOffsetInBlock = NumBytes;
|
2014-02-14 17:19:07 +00:00
|
|
|
adjustedGPRCS1Size += NumBytes;
|
2013-11-08 17:18:07 +00:00
|
|
|
NumBytes = 0;
|
|
|
|
}
|
|
|
|
|
2014-02-14 17:19:07 +00:00
|
|
|
if (adjustedGPRCS1Size) {
|
|
|
|
CFAOffset -= adjustedGPRCS1Size;
|
2016-11-30 23:48:42 +00:00
|
|
|
unsigned CFIIndex = MF.addFrameInst(
|
2014-03-07 06:08:31 +00:00
|
|
|
MCCFIInstruction::createDefCfaOffset(nullptr, CFAOffset));
|
|
|
|
BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
|
2014-12-22 23:09:14 +00:00
|
|
|
.addCFIIndex(CFIIndex)
|
|
|
|
.setMIFlags(MachineInstr::FrameSetup);
|
2014-02-14 17:19:07 +00:00
|
|
|
}
|
|
|
|
for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(),
|
|
|
|
E = CSI.end(); I != E; ++I) {
|
|
|
|
unsigned Reg = I->getReg();
|
|
|
|
int FI = I->getFrameIdx();
|
|
|
|
switch (Reg) {
|
|
|
|
case ARM::R8:
|
|
|
|
case ARM::R9:
|
|
|
|
case ARM::R10:
|
|
|
|
case ARM::R11:
|
|
|
|
case ARM::R12:
|
[ARM] Generate consistent frame records for Thumb2
There is not an official documented ABI for frame pointers in Thumb2,
but we should try to emit something which is useful.
We use r7 as the frame pointer for Thumb code, which currently means
that if a function needs to save a high register (r8-r11), it will get
pushed to the stack between the frame pointer (r7) and link register
(r14). This means that while a stack unwinder can follow the chain of
frame pointers up the stack, it cannot know the offset to lr, so does
not know which functions correspond to the stack frames.
To fix this, we need to push the callee-saved registers in two batches,
with the first push saving the low registers, fp and lr, and the second
push saving the high registers. This is already implemented, but
previously only used for iOS. This patch turns it on for all Thumb2
targets when frame pointers are required by the ABI, and the frame
pointer is r7 (Windows uses r11, so this isn't a problem there). If
frame pointer elimination is enabled we still emit a single push/pop
even if we need a frame pointer for other reasons, to avoid increasing
code size.
We must also ensure that lr is pushed to the stack when using a frame
pointer, so that we end up with a complete frame record. Situations that
could cause this were rare, because we already push lr in most
situations so that we can return using the pop instruction.
Differential Revision: https://reviews.llvm.org/D23516
llvm-svn: 279506
2016-08-23 09:19:22 +00:00
|
|
|
if (STI.splitFramePushPop(MF))
|
2014-02-14 17:19:07 +00:00
|
|
|
break;
|
2017-07-07 16:40:06 +00:00
|
|
|
LLVM_FALLTHROUGH;
|
2014-02-14 17:19:07 +00:00
|
|
|
case ARM::R0:
|
|
|
|
case ARM::R1:
|
|
|
|
case ARM::R2:
|
|
|
|
case ARM::R3:
|
|
|
|
case ARM::R4:
|
|
|
|
case ARM::R5:
|
|
|
|
case ARM::R6:
|
|
|
|
case ARM::R7:
|
|
|
|
case ARM::LR:
|
2016-11-30 23:48:42 +00:00
|
|
|
unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
|
2016-07-28 18:40:00 +00:00
|
|
|
nullptr, MRI->getDwarfRegNum(Reg, true), MFI.getObjectOffset(FI)));
|
2014-03-07 06:08:31 +00:00
|
|
|
BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
|
2014-12-22 23:09:14 +00:00
|
|
|
.addCFIIndex(CFIIndex)
|
|
|
|
.setMIFlags(MachineInstr::FrameSetup);
|
2014-02-14 17:19:07 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Fix epilogue codegen to avoid leaving the stack pointer in an invalid
state. Previously Thumb2 would restore sp from fp like this:
mov sp, r7
sub, sp, #4
If an interrupt is taken after the 'mov' but before the 'sub', callee-saved
registers might be clobbered by the interrupt handler. Instead, try
restoring directly from sp:
add sp, #4
Or, if necessary (with VLA, etc.) use a scratch register to compute sp and
then restore it:
sub.w r4, r7, #8
mov sp, r7
rdar://8465407
llvm-svn: 119977
2010-11-22 18:12:04 +00:00
|
|
|
// Adjust FP so it point to the stack slot that contains the previous FP.
|
2013-02-20 12:21:33 +00:00
|
|
|
if (HasFP) {
|
2015-09-22 11:15:07 +00:00
|
|
|
FramePtrOffsetInBlock +=
|
2016-07-28 18:40:00 +00:00
|
|
|
MFI.getObjectOffset(FramePtrSpillFI) + GPRCS1Size + ArgRegsSaveSize;
|
2017-01-13 09:37:56 +00:00
|
|
|
BuildMI(MBB, MBBI, dl, TII.get(ARM::tADDrSPi), FramePtr)
|
|
|
|
.addReg(ARM::SP)
|
|
|
|
.addImm(FramePtrOffsetInBlock / 4)
|
|
|
|
.setMIFlags(MachineInstr::FrameSetup)
|
|
|
|
.add(predOps(ARMCC::AL));
|
2014-02-14 17:19:07 +00:00
|
|
|
if(FramePtrOffsetInBlock) {
|
|
|
|
CFAOffset += FramePtrOffsetInBlock;
|
2016-11-30 23:48:42 +00:00
|
|
|
unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createDefCfa(
|
2014-03-07 06:08:31 +00:00
|
|
|
nullptr, MRI->getDwarfRegNum(FramePtr, true), CFAOffset));
|
|
|
|
BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
|
2014-12-22 23:09:14 +00:00
|
|
|
.addCFIIndex(CFIIndex)
|
|
|
|
.setMIFlags(MachineInstr::FrameSetup);
|
2014-03-07 06:08:31 +00:00
|
|
|
} else {
|
|
|
|
unsigned CFIIndex =
|
2016-11-30 23:48:42 +00:00
|
|
|
MF.addFrameInst(MCCFIInstruction::createDefCfaRegister(
|
2014-03-07 06:08:31 +00:00
|
|
|
nullptr, MRI->getDwarfRegNum(FramePtr, true)));
|
|
|
|
BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
|
2014-12-22 23:09:14 +00:00
|
|
|
.addCFIIndex(CFIIndex)
|
|
|
|
.setMIFlags(MachineInstr::FrameSetup);
|
2014-03-07 06:08:31 +00:00
|
|
|
}
|
2011-06-13 21:18:25 +00:00
|
|
|
if (NumBytes > 508)
|
|
|
|
// If offset is > 508 then sp cannot be adjusted in a single instruction,
|
Fix epilogue codegen to avoid leaving the stack pointer in an invalid
state. Previously Thumb2 would restore sp from fp like this:
mov sp, r7
sub, sp, #4
If an interrupt is taken after the 'mov' but before the 'sub', callee-saved
registers might be clobbered by the interrupt handler. Instead, try
restoring directly from sp:
add sp, #4
Or, if necessary (with VLA, etc.) use a scratch register to compute sp and
then restore it:
sub.w r4, r7, #8
mov sp, r7
rdar://8465407
llvm-svn: 119977
2010-11-22 18:12:04 +00:00
|
|
|
// try restoring from fp instead.
|
|
|
|
AFI->setShouldRestoreSPFromFP(true);
|
|
|
|
}
|
|
|
|
|
2016-10-11 21:14:03 +00:00
|
|
|
// Skip past the spilling of r8-r11, which could consist of multiple tPUSH
|
|
|
|
// and tMOVr instructions. We don't need to add any call frame information
|
|
|
|
// in-between these instructions, because they do not modify the high
|
|
|
|
// registers.
|
|
|
|
while (true) {
|
|
|
|
MachineBasicBlock::iterator OldMBBI = MBBI;
|
|
|
|
// Skip a run of tMOVr instructions
|
|
|
|
while (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tMOVr)
|
|
|
|
MBBI++;
|
|
|
|
if (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tPUSH) {
|
|
|
|
MBBI++;
|
|
|
|
} else {
|
|
|
|
// We have reached an instruction which is not a push, so the previous
|
|
|
|
// run of tMOVr instructions (which may have been empty) was not part of
|
|
|
|
// the prologue. Reset MBBI back to the last PUSH of the prologue.
|
|
|
|
MBBI = OldMBBI;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Emit call frame information for the callee-saved high registers.
|
|
|
|
for (auto &I : CSI) {
|
|
|
|
unsigned Reg = I.getReg();
|
|
|
|
int FI = I.getFrameIdx();
|
|
|
|
switch (Reg) {
|
|
|
|
case ARM::R8:
|
|
|
|
case ARM::R9:
|
|
|
|
case ARM::R10:
|
|
|
|
case ARM::R11:
|
|
|
|
case ARM::R12: {
|
2016-11-30 23:48:42 +00:00
|
|
|
unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
|
2016-10-11 21:14:03 +00:00
|
|
|
nullptr, MRI->getDwarfRegNum(Reg, true), MFI.getObjectOffset(FI)));
|
|
|
|
BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
|
|
|
|
.addCFIIndex(CFIIndex)
|
|
|
|
.setMIFlags(MachineInstr::FrameSetup);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-14 17:19:07 +00:00
|
|
|
if (NumBytes) {
|
2010-11-15 00:06:54 +00:00
|
|
|
// Insert it after all the callee-save spills.
|
2011-03-05 18:43:50 +00:00
|
|
|
emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, -NumBytes,
|
|
|
|
MachineInstr::FrameSetup);
|
2014-02-14 17:19:07 +00:00
|
|
|
if (!HasFP) {
|
|
|
|
CFAOffset -= NumBytes;
|
2016-11-30 23:48:42 +00:00
|
|
|
unsigned CFIIndex = MF.addFrameInst(
|
2014-03-07 06:08:31 +00:00
|
|
|
MCCFIInstruction::createDefCfaOffset(nullptr, CFAOffset));
|
|
|
|
BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
|
2014-12-22 23:09:14 +00:00
|
|
|
.addCFIIndex(CFIIndex)
|
|
|
|
.setMIFlags(MachineInstr::FrameSetup);
|
2014-02-14 17:19:07 +00:00
|
|
|
}
|
|
|
|
}
|
2010-11-15 00:06:54 +00:00
|
|
|
|
2013-02-20 12:21:33 +00:00
|
|
|
if (STI.isTargetELF() && HasFP)
|
2016-07-28 18:40:00 +00:00
|
|
|
MFI.setOffsetAdjustment(MFI.getOffsetAdjustment() -
|
|
|
|
AFI->getFramePtrSpillOffset());
|
2010-11-15 00:06:54 +00:00
|
|
|
|
|
|
|
AFI->setGPRCalleeSavedArea1Size(GPRCS1Size);
|
|
|
|
AFI->setGPRCalleeSavedArea2Size(GPRCS2Size);
|
|
|
|
AFI->setDPRCalleeSavedAreaSize(DPRCSSize);
|
|
|
|
|
2017-10-22 11:56:35 +00:00
|
|
|
if (RegInfo->needsStackRealignment(MF)) {
|
|
|
|
const unsigned NrBitsToZero = countTrailingZeros(MFI.getMaxAlignment());
|
|
|
|
// Emit the following sequence, using R4 as a temporary, since we cannot use
|
|
|
|
// SP as a source or destination register for the shifts:
|
|
|
|
// mov r4, sp
|
|
|
|
// lsrs r4, r4, #NrBitsToZero
|
|
|
|
// lsls r4, r4, #NrBitsToZero
|
|
|
|
// mov sp, r4
|
|
|
|
BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), ARM::R4)
|
|
|
|
.addReg(ARM::SP, RegState::Kill)
|
|
|
|
.add(predOps(ARMCC::AL));
|
|
|
|
|
|
|
|
BuildMI(MBB, MBBI, dl, TII.get(ARM::tLSRri), ARM::R4)
|
|
|
|
.addDef(ARM::CPSR)
|
|
|
|
.addReg(ARM::R4, RegState::Kill)
|
|
|
|
.addImm(NrBitsToZero)
|
|
|
|
.add(predOps(ARMCC::AL));
|
|
|
|
|
|
|
|
BuildMI(MBB, MBBI, dl, TII.get(ARM::tLSLri), ARM::R4)
|
|
|
|
.addDef(ARM::CPSR)
|
|
|
|
.addReg(ARM::R4, RegState::Kill)
|
|
|
|
.addImm(NrBitsToZero)
|
|
|
|
.add(predOps(ARMCC::AL));
|
|
|
|
|
|
|
|
BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), ARM::SP)
|
|
|
|
.addReg(ARM::R4, RegState::Kill)
|
|
|
|
.add(predOps(ARMCC::AL));
|
|
|
|
|
|
|
|
AFI->setShouldRestoreSPFromFP(true);
|
|
|
|
}
|
2011-10-15 00:28:24 +00:00
|
|
|
|
2010-11-15 00:06:54 +00:00
|
|
|
// If we need a base pointer, set it up here. It's whatever the value
|
|
|
|
// of the stack pointer is at this point. Any variable size objects
|
|
|
|
// will be allocated after this, so we can still use the base pointer
|
|
|
|
// to reference locals.
|
|
|
|
if (RegInfo->hasBasePointer(MF))
|
2017-01-13 09:37:56 +00:00
|
|
|
BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), BasePtr)
|
|
|
|
.addReg(ARM::SP)
|
|
|
|
.add(predOps(ARMCC::AL));
|
2011-03-05 18:43:50 +00:00
|
|
|
|
2011-01-11 00:16:04 +00:00
|
|
|
// If the frame has variable sized objects then the epilogue must restore
|
|
|
|
// the sp from fp. We can assume there's an FP here since hasFP already
|
|
|
|
// checks for hasVarSizedObjects.
|
2016-07-28 18:40:00 +00:00
|
|
|
if (MFI.hasVarSizedObjects())
|
2011-01-11 00:16:04 +00:00
|
|
|
AFI->setShouldRestoreSPFromFP(true);
|
2017-01-18 15:01:22 +00:00
|
|
|
|
|
|
|
// In some cases, virtual registers have been introduced, e.g. by uses of
|
|
|
|
// emitThumbRegPlusImmInReg.
|
|
|
|
MF.getProperties().reset(MachineFunctionProperties::Property::NoVRegs);
|
2010-11-15 00:06:54 +00:00
|
|
|
}
|
|
|
|
|
2016-07-08 20:21:17 +00:00
|
|
|
static bool isCSRestore(MachineInstr &MI, const MCPhysReg *CSRegs) {
|
|
|
|
if (MI.getOpcode() == ARM::tLDRspi && MI.getOperand(1).isFI() &&
|
|
|
|
isCalleeSavedRegister(MI.getOperand(0).getReg(), CSRegs))
|
2010-11-15 00:06:54 +00:00
|
|
|
return true;
|
2016-07-08 20:21:17 +00:00
|
|
|
else if (MI.getOpcode() == ARM::tPOP) {
|
2010-11-15 00:06:54 +00:00
|
|
|
return true;
|
2016-10-11 21:14:03 +00:00
|
|
|
} else if (MI.getOpcode() == ARM::tMOVr) {
|
|
|
|
unsigned Dst = MI.getOperand(0).getReg();
|
|
|
|
unsigned Src = MI.getOperand(1).getReg();
|
|
|
|
return ((ARM::tGPRRegClass.contains(Src) || Src == ARM::LR) &&
|
|
|
|
ARM::hGPRRegClass.contains(Dst));
|
2010-11-15 00:06:54 +00:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-01-10 12:39:04 +00:00
|
|
|
void Thumb1FrameLowering::emitEpilogue(MachineFunction &MF,
|
2010-11-15 00:06:54 +00:00
|
|
|
MachineBasicBlock &MBB) const {
|
2015-07-20 21:42:14 +00:00
|
|
|
MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator();
|
|
|
|
DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
2016-07-28 18:40:00 +00:00
|
|
|
MachineFrameInfo &MFI = MF.getFrameInfo();
|
2010-11-15 00:06:54 +00:00
|
|
|
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
2015-03-12 22:48:50 +00:00
|
|
|
const ThumbRegisterInfo *RegInfo =
|
|
|
|
static_cast<const ThumbRegisterInfo *>(STI.getRegisterInfo());
|
2010-11-15 00:06:54 +00:00
|
|
|
const Thumb1InstrInfo &TII =
|
2015-01-29 00:19:33 +00:00
|
|
|
*static_cast<const Thumb1InstrInfo *>(STI.getInstrInfo());
|
2010-11-15 00:06:54 +00:00
|
|
|
|
2015-03-11 18:54:22 +00:00
|
|
|
unsigned ArgRegsSaveSize = AFI->getArgRegsSaveSize();
|
2016-07-28 18:40:00 +00:00
|
|
|
int NumBytes = (int)MFI.getStackSize();
|
2014-03-05 18:53:36 +00:00
|
|
|
assert((unsigned)NumBytes >= ArgRegsSaveSize &&
|
2014-03-05 15:25:27 +00:00
|
|
|
"ArgRegsSaveSize is included in NumBytes");
|
2015-03-11 21:41:28 +00:00
|
|
|
const MCPhysReg *CSRegs = RegInfo->getCalleeSavedRegs(&MF);
|
2010-11-15 00:06:54 +00:00
|
|
|
unsigned FramePtr = RegInfo->getFrameRegister(MF);
|
|
|
|
|
|
|
|
if (!AFI->hasStackFrame()) {
|
2014-03-05 15:25:27 +00:00
|
|
|
if (NumBytes - ArgRegsSaveSize != 0)
|
|
|
|
emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, NumBytes - ArgRegsSaveSize);
|
2010-11-15 00:06:54 +00:00
|
|
|
} else {
|
|
|
|
// Unwind MBBI to point to first LDR / VLDRD.
|
|
|
|
if (MBBI != MBB.begin()) {
|
|
|
|
do
|
|
|
|
--MBBI;
|
2016-07-08 20:21:17 +00:00
|
|
|
while (MBBI != MBB.begin() && isCSRestore(*MBBI, CSRegs));
|
|
|
|
if (!isCSRestore(*MBBI, CSRegs))
|
2010-11-15 00:06:54 +00:00
|
|
|
++MBBI;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Move SP to start of FP callee save spill area.
|
|
|
|
NumBytes -= (AFI->getGPRCalleeSavedArea1Size() +
|
|
|
|
AFI->getGPRCalleeSavedArea2Size() +
|
2014-03-05 15:25:27 +00:00
|
|
|
AFI->getDPRCalleeSavedAreaSize() +
|
|
|
|
ArgRegsSaveSize);
|
2010-11-15 00:06:54 +00:00
|
|
|
|
|
|
|
if (AFI->shouldRestoreSPFromFP()) {
|
|
|
|
NumBytes = AFI->getFramePtrSpillOffset() - NumBytes;
|
|
|
|
// Reset SP based on frame pointer only if the stack frame extends beyond
|
2011-01-11 00:16:04 +00:00
|
|
|
// frame pointer stack slot, the target is ELF and the function has FP, or
|
|
|
|
// the target uses var sized objects.
|
Fix epilogue codegen to avoid leaving the stack pointer in an invalid
state. Previously Thumb2 would restore sp from fp like this:
mov sp, r7
sub, sp, #4
If an interrupt is taken after the 'mov' but before the 'sub', callee-saved
registers might be clobbered by the interrupt handler. Instead, try
restoring directly from sp:
add sp, #4
Or, if necessary (with VLA, etc.) use a scratch register to compute sp and
then restore it:
sub.w r4, r7, #8
mov sp, r7
rdar://8465407
llvm-svn: 119977
2010-11-22 18:12:04 +00:00
|
|
|
if (NumBytes) {
|
2016-07-28 18:40:00 +00:00
|
|
|
assert(!MFI.getPristineRegs(MF).test(ARM::R4) &&
|
Fix epilogue codegen to avoid leaving the stack pointer in an invalid
state. Previously Thumb2 would restore sp from fp like this:
mov sp, r7
sub, sp, #4
If an interrupt is taken after the 'mov' but before the 'sub', callee-saved
registers might be clobbered by the interrupt handler. Instead, try
restoring directly from sp:
add sp, #4
Or, if necessary (with VLA, etc.) use a scratch register to compute sp and
then restore it:
sub.w r4, r7, #8
mov sp, r7
rdar://8465407
llvm-svn: 119977
2010-11-22 18:12:04 +00:00
|
|
|
"No scratch register to restore SP from FP!");
|
2011-03-05 18:43:32 +00:00
|
|
|
emitThumbRegPlusImmediate(MBB, MBBI, dl, ARM::R4, FramePtr, -NumBytes,
|
|
|
|
TII, *RegInfo);
|
2017-01-13 09:37:56 +00:00
|
|
|
BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), ARM::SP)
|
|
|
|
.addReg(ARM::R4)
|
|
|
|
.add(predOps(ARMCC::AL));
|
Fix epilogue codegen to avoid leaving the stack pointer in an invalid
state. Previously Thumb2 would restore sp from fp like this:
mov sp, r7
sub, sp, #4
If an interrupt is taken after the 'mov' but before the 'sub', callee-saved
registers might be clobbered by the interrupt handler. Instead, try
restoring directly from sp:
add sp, #4
Or, if necessary (with VLA, etc.) use a scratch register to compute sp and
then restore it:
sub.w r4, r7, #8
mov sp, r7
rdar://8465407
llvm-svn: 119977
2010-11-22 18:12:04 +00:00
|
|
|
} else
|
2017-01-13 09:37:56 +00:00
|
|
|
BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), ARM::SP)
|
|
|
|
.addReg(FramePtr)
|
|
|
|
.add(predOps(ARMCC::AL));
|
2010-11-15 00:06:54 +00:00
|
|
|
} else {
|
2015-07-20 21:42:14 +00:00
|
|
|
if (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tBX_RET &&
|
2016-07-08 20:21:17 +00:00
|
|
|
&MBB.front() != &*MBBI && std::prev(MBBI)->getOpcode() == ARM::tPOP) {
|
2014-03-02 12:27:27 +00:00
|
|
|
MachineBasicBlock::iterator PMBBI = std::prev(MBBI);
|
2016-07-08 20:21:17 +00:00
|
|
|
if (!tryFoldSPUpdateIntoPushPop(STI, MF, &*PMBBI, NumBytes))
|
2013-11-08 17:18:07 +00:00
|
|
|
emitSPUpdate(MBB, PMBBI, TII, dl, *RegInfo, NumBytes);
|
2016-07-08 20:21:17 +00:00
|
|
|
} else if (!tryFoldSPUpdateIntoPushPop(STI, MF, &*MBBI, NumBytes))
|
2010-11-15 00:06:54 +00:00
|
|
|
emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, NumBytes);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-22 16:34:37 +00:00
|
|
|
if (needPopSpecialFixUp(MF)) {
|
|
|
|
bool Done = emitPopSpecialFixUp(MBB, /* DoIt */ true);
|
|
|
|
(void)Done;
|
|
|
|
assert(Done && "Emission of the special fixup failed!?");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Thumb1FrameLowering::canUseAsEpilogue(const MachineBasicBlock &MBB) const {
|
|
|
|
if (!needPopSpecialFixUp(*MBB.getParent()))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
MachineBasicBlock *TmpMBB = const_cast<MachineBasicBlock *>(&MBB);
|
|
|
|
return emitPopSpecialFixUp(*TmpMBB, /* DoIt */ false);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Thumb1FrameLowering::needPopSpecialFixUp(const MachineFunction &MF) const {
|
|
|
|
ARMFunctionInfo *AFI =
|
|
|
|
const_cast<MachineFunction *>(&MF)->getInfo<ARMFunctionInfo>();
|
|
|
|
if (AFI->getArgRegsSaveSize())
|
|
|
|
return true;
|
|
|
|
|
2015-12-01 19:25:11 +00:00
|
|
|
// LR cannot be encoded with Thumb1, i.e., it requires a special fix-up.
|
2016-07-28 18:40:00 +00:00
|
|
|
for (const CalleeSavedInfo &CSI : MF.getFrameInfo().getCalleeSavedInfo())
|
2014-08-05 21:32:21 +00:00
|
|
|
if (CSI.getReg() == ARM::LR)
|
2015-12-01 19:25:11 +00:00
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
2015-07-22 16:34:37 +00:00
|
|
|
}
|
2015-07-20 21:42:14 +00:00
|
|
|
|
[ARM] Fix incorrect conversion of a tail call to an ordinary call
When we emit a tail call for Armv8-M, but then discover that the caller needs to
save/restore `LR`, we convert the tail call to an ordinary one, since restoring
`LR` takes extra instructions, which may negate the benefits of the tail
call. If the callee, however, takes stack arguments, this conversion is
incorrect, since nothing has been done to pass the stack arguments.
Thus the patch reverts https://reviews.llvm.org/rL294000
Also, we improve the instruction sequence for popping `LR` in the case when we
couldn't immediately find a scratch low register, but we can use as a temporary
one of the callee-saved low registers and restore `LR` before popping other
callee-saves.
Differential Revision: https://reviews.llvm.org/D39599
llvm-svn: 318143
2017-11-14 10:36:52 +00:00
|
|
|
static void findTemporariesForLR(const BitVector &GPRsNoLRSP,
|
|
|
|
const BitVector &PopFriendly,
|
|
|
|
const LivePhysRegs &UsedRegs, unsigned &PopReg,
|
|
|
|
unsigned &TmpReg) {
|
|
|
|
PopReg = TmpReg = 0;
|
|
|
|
for (auto Reg : GPRsNoLRSP.set_bits()) {
|
|
|
|
if (!UsedRegs.contains(Reg)) {
|
|
|
|
// Remember the first pop-friendly register and exit.
|
|
|
|
if (PopFriendly.test(Reg)) {
|
|
|
|
PopReg = Reg;
|
|
|
|
TmpReg = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Otherwise, remember that the register will be available to
|
|
|
|
// save a pop-friendly register.
|
|
|
|
TmpReg = Reg;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-22 16:34:37 +00:00
|
|
|
bool Thumb1FrameLowering::emitPopSpecialFixUp(MachineBasicBlock &MBB,
|
|
|
|
bool DoIt) const {
|
|
|
|
MachineFunction &MF = *MBB.getParent();
|
|
|
|
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
|
|
|
unsigned ArgRegsSaveSize = AFI->getArgRegsSaveSize();
|
|
|
|
const TargetInstrInfo &TII = *STI.getInstrInfo();
|
|
|
|
const ThumbRegisterInfo *RegInfo =
|
|
|
|
static_cast<const ThumbRegisterInfo *>(STI.getRegisterInfo());
|
2014-08-05 21:32:21 +00:00
|
|
|
|
2015-12-01 19:25:11 +00:00
|
|
|
// 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.
|
2015-07-22 16:34:37 +00:00
|
|
|
auto MBBI = MBB.getFirstTerminator();
|
2015-12-01 19:25:11 +00:00
|
|
|
bool CanRestoreDirectly = STI.hasV5TOps() && !ArgRegsSaveSize;
|
|
|
|
if (CanRestoreDirectly) {
|
2015-12-28 21:40:45 +00:00
|
|
|
if (MBBI != MBB.end() && MBBI->getOpcode() != ARM::tB)
|
2015-12-01 19:25:11 +00:00
|
|
|
CanRestoreDirectly = (MBBI->getOpcode() == ARM::tBX_RET ||
|
|
|
|
MBBI->getOpcode() == ARM::tPOP_RET);
|
|
|
|
else {
|
2015-12-28 21:40:45 +00:00
|
|
|
auto MBBI_prev = MBBI;
|
|
|
|
MBBI_prev--;
|
|
|
|
assert(MBBI_prev->getOpcode() == ARM::tPOP);
|
2015-12-01 19:25:11 +00:00
|
|
|
assert(MBB.succ_size() == 1);
|
|
|
|
if ((*MBB.succ_begin())->begin()->getOpcode() == ARM::tBX_RET)
|
2015-12-28 21:40:45 +00:00
|
|
|
MBBI = MBBI_prev; // Replace the final tPOP with a tPOP_RET.
|
2015-12-01 19:25:11 +00:00
|
|
|
else
|
|
|
|
CanRestoreDirectly = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (CanRestoreDirectly) {
|
|
|
|
if (!DoIt || MBBI->getOpcode() == ARM::tPOP_RET)
|
|
|
|
return true;
|
|
|
|
MachineInstrBuilder MIB =
|
2017-01-13 09:37:56 +00:00
|
|
|
BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII.get(ARM::tPOP_RET))
|
|
|
|
.add(predOps(ARMCC::AL));
|
2015-12-01 19:25:11 +00:00
|
|
|
// Copy implicit ops and popped registers, if any.
|
|
|
|
for (auto MO: MBBI->operands())
|
2015-12-28 21:40:45 +00:00
|
|
|
if (MO.isReg() && (MO.isImplicit() || MO.isDef()))
|
2017-01-13 09:58:52 +00:00
|
|
|
MIB.add(MO);
|
2015-12-01 19:25:11 +00:00
|
|
|
MIB.addReg(ARM::PC, RegState::Define);
|
|
|
|
// Erase the old instruction (tBX_RET or tPOP).
|
|
|
|
MBB.erase(MBBI);
|
|
|
|
return true;
|
|
|
|
}
|
2014-08-05 21:32:21 +00:00
|
|
|
|
2015-07-22 16:34:37 +00:00
|
|
|
// Look for a temporary register to use.
|
|
|
|
// First, compute the liveness information.
|
2017-05-26 21:51:00 +00:00
|
|
|
const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
|
|
|
|
LivePhysRegs UsedRegs(TRI);
|
2016-05-03 00:24:32 +00:00
|
|
|
UsedRegs.addLiveOuts(MBB);
|
2015-07-22 16:34:37 +00:00
|
|
|
// The semantic of pristines changed recently and now,
|
|
|
|
// the callee-saved registers that are touched in the function
|
|
|
|
// are not part of the pristines set anymore.
|
|
|
|
// Add those callee-saved now.
|
2017-05-26 21:51:00 +00:00
|
|
|
const MCPhysReg *CSRegs = TRI.getCalleeSavedRegs(&MF);
|
2015-07-22 16:34:37 +00:00
|
|
|
for (unsigned i = 0; CSRegs[i]; ++i)
|
|
|
|
UsedRegs.addReg(CSRegs[i]);
|
|
|
|
|
|
|
|
DebugLoc dl = DebugLoc();
|
|
|
|
if (MBBI != MBB.end()) {
|
|
|
|
dl = MBBI->getDebugLoc();
|
|
|
|
auto InstUpToMBBI = MBB.end();
|
2015-12-01 19:25:11 +00:00
|
|
|
while (InstUpToMBBI != MBBI)
|
|
|
|
// The pre-decrement is on purpose here.
|
|
|
|
// We want to have the liveness right before MBBI.
|
|
|
|
UsedRegs.stepBackward(*--InstUpToMBBI);
|
2015-07-22 16:34:37 +00:00
|
|
|
}
|
2014-08-05 21:32:21 +00:00
|
|
|
|
2015-07-22 16:34:37 +00:00
|
|
|
// Look for a register that can be directly use in the POP.
|
|
|
|
unsigned PopReg = 0;
|
|
|
|
// And some temporary register, just in case.
|
|
|
|
unsigned TemporaryReg = 0;
|
|
|
|
BitVector PopFriendly =
|
2017-05-26 21:51:00 +00:00
|
|
|
TRI.getAllocatableSet(MF, TRI.getRegClass(ARM::tGPRRegClassID));
|
2018-01-08 11:32:37 +00:00
|
|
|
// R7 may be used as a frame pointer, hence marked as not generally
|
|
|
|
// allocatable, however there's no reason to not use it as a temporary for
|
|
|
|
// restoring LR.
|
|
|
|
if (STI.useR7AsFramePointer())
|
|
|
|
PopFriendly.set(ARM::R7);
|
|
|
|
|
2015-07-22 16:34:37 +00:00
|
|
|
assert(PopFriendly.any() && "No allocatable pop-friendly register?!");
|
|
|
|
// Rebuild the GPRs from the high registers because they are removed
|
|
|
|
// form the GPR reg class for thumb1.
|
|
|
|
BitVector GPRsNoLRSP =
|
2017-05-26 21:51:00 +00:00
|
|
|
TRI.getAllocatableSet(MF, TRI.getRegClass(ARM::hGPRRegClassID));
|
2015-07-22 16:34:37 +00:00
|
|
|
GPRsNoLRSP |= PopFriendly;
|
|
|
|
GPRsNoLRSP.reset(ARM::LR);
|
|
|
|
GPRsNoLRSP.reset(ARM::SP);
|
|
|
|
GPRsNoLRSP.reset(ARM::PC);
|
[ARM] Fix incorrect conversion of a tail call to an ordinary call
When we emit a tail call for Armv8-M, but then discover that the caller needs to
save/restore `LR`, we convert the tail call to an ordinary one, since restoring
`LR` takes extra instructions, which may negate the benefits of the tail
call. If the callee, however, takes stack arguments, this conversion is
incorrect, since nothing has been done to pass the stack arguments.
Thus the patch reverts https://reviews.llvm.org/rL294000
Also, we improve the instruction sequence for popping `LR` in the case when we
couldn't immediately find a scratch low register, but we can use as a temporary
one of the callee-saved low registers and restore `LR` before popping other
callee-saves.
Differential Revision: https://reviews.llvm.org/D39599
llvm-svn: 318143
2017-11-14 10:36:52 +00:00
|
|
|
findTemporariesForLR(GPRsNoLRSP, PopFriendly, UsedRegs, PopReg, TemporaryReg);
|
|
|
|
|
2018-01-08 11:32:37 +00:00
|
|
|
// If we couldn't find a pop-friendly register, try restoring LR before
|
|
|
|
// popping the other callee-saved registers, so we could use one of them as a
|
|
|
|
// temporary.
|
[ARM] Fix incorrect conversion of a tail call to an ordinary call
When we emit a tail call for Armv8-M, but then discover that the caller needs to
save/restore `LR`, we convert the tail call to an ordinary one, since restoring
`LR` takes extra instructions, which may negate the benefits of the tail
call. If the callee, however, takes stack arguments, this conversion is
incorrect, since nothing has been done to pass the stack arguments.
Thus the patch reverts https://reviews.llvm.org/rL294000
Also, we improve the instruction sequence for popping `LR` in the case when we
couldn't immediately find a scratch low register, but we can use as a temporary
one of the callee-saved low registers and restore `LR` before popping other
callee-saves.
Differential Revision: https://reviews.llvm.org/D39599
llvm-svn: 318143
2017-11-14 10:36:52 +00:00
|
|
|
bool UseLDRSP = false;
|
|
|
|
if (!PopReg && MBBI != MBB.begin()) {
|
|
|
|
auto PrevMBBI = MBBI;
|
|
|
|
PrevMBBI--;
|
|
|
|
if (PrevMBBI->getOpcode() == ARM::tPOP) {
|
2018-01-08 11:32:37 +00:00
|
|
|
UsedRegs.stepBackward(*PrevMBBI);
|
[ARM] Fix incorrect conversion of a tail call to an ordinary call
When we emit a tail call for Armv8-M, but then discover that the caller needs to
save/restore `LR`, we convert the tail call to an ordinary one, since restoring
`LR` takes extra instructions, which may negate the benefits of the tail
call. If the callee, however, takes stack arguments, this conversion is
incorrect, since nothing has been done to pass the stack arguments.
Thus the patch reverts https://reviews.llvm.org/rL294000
Also, we improve the instruction sequence for popping `LR` in the case when we
couldn't immediately find a scratch low register, but we can use as a temporary
one of the callee-saved low registers and restore `LR` before popping other
callee-saves.
Differential Revision: https://reviews.llvm.org/D39599
llvm-svn: 318143
2017-11-14 10:36:52 +00:00
|
|
|
findTemporariesForLR(GPRsNoLRSP, PopFriendly, UsedRegs, PopReg, TemporaryReg);
|
2018-01-08 11:32:37 +00:00
|
|
|
if (PopReg) {
|
|
|
|
MBBI = PrevMBBI;
|
|
|
|
UseLDRSP = true;
|
|
|
|
}
|
2015-07-20 21:42:14 +00:00
|
|
|
}
|
2015-07-22 16:34:37 +00:00
|
|
|
}
|
2015-07-20 21:42:14 +00:00
|
|
|
|
2015-07-22 16:34:37 +00:00
|
|
|
if (!DoIt && !PopReg && !TemporaryReg)
|
|
|
|
return false;
|
2015-07-20 21:42:14 +00:00
|
|
|
|
2015-07-22 16:34:37 +00:00
|
|
|
assert((PopReg || TemporaryReg) && "Cannot get LR");
|
|
|
|
|
[ARM] Fix incorrect conversion of a tail call to an ordinary call
When we emit a tail call for Armv8-M, but then discover that the caller needs to
save/restore `LR`, we convert the tail call to an ordinary one, since restoring
`LR` takes extra instructions, which may negate the benefits of the tail
call. If the callee, however, takes stack arguments, this conversion is
incorrect, since nothing has been done to pass the stack arguments.
Thus the patch reverts https://reviews.llvm.org/rL294000
Also, we improve the instruction sequence for popping `LR` in the case when we
couldn't immediately find a scratch low register, but we can use as a temporary
one of the callee-saved low registers and restore `LR` before popping other
callee-saves.
Differential Revision: https://reviews.llvm.org/D39599
llvm-svn: 318143
2017-11-14 10:36:52 +00:00
|
|
|
if (UseLDRSP) {
|
|
|
|
assert(PopReg && "Do not know how to get LR");
|
|
|
|
// Load the LR via LDR tmp, [SP, #off]
|
|
|
|
BuildMI(MBB, MBBI, dl, TII.get(ARM::tLDRspi))
|
|
|
|
.addReg(PopReg, RegState::Define)
|
|
|
|
.addReg(ARM::SP)
|
2017-11-27 10:13:14 +00:00
|
|
|
.addImm(MBBI->getNumExplicitOperands() - 2)
|
[ARM] Fix incorrect conversion of a tail call to an ordinary call
When we emit a tail call for Armv8-M, but then discover that the caller needs to
save/restore `LR`, we convert the tail call to an ordinary one, since restoring
`LR` takes extra instructions, which may negate the benefits of the tail
call. If the callee, however, takes stack arguments, this conversion is
incorrect, since nothing has been done to pass the stack arguments.
Thus the patch reverts https://reviews.llvm.org/rL294000
Also, we improve the instruction sequence for popping `LR` in the case when we
couldn't immediately find a scratch low register, but we can use as a temporary
one of the callee-saved low registers and restore `LR` before popping other
callee-saves.
Differential Revision: https://reviews.llvm.org/D39599
llvm-svn: 318143
2017-11-14 10:36:52 +00:00
|
|
|
.add(predOps(ARMCC::AL));
|
|
|
|
// Move from the temporary register to the LR.
|
|
|
|
BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr))
|
|
|
|
.addReg(ARM::LR, RegState::Define)
|
|
|
|
.addReg(PopReg, RegState::Kill)
|
|
|
|
.add(predOps(ARMCC::AL));
|
|
|
|
// Advance past the pop instruction.
|
|
|
|
MBBI++;
|
|
|
|
// Increment the SP.
|
|
|
|
emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, ArgRegsSaveSize + 4);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-07-22 16:34:37 +00:00
|
|
|
if (TemporaryReg) {
|
|
|
|
assert(!PopReg && "Unnecessary MOV is about to be inserted");
|
|
|
|
PopReg = PopFriendly.find_first();
|
2017-01-13 09:37:56 +00:00
|
|
|
BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr))
|
|
|
|
.addReg(TemporaryReg, RegState::Define)
|
|
|
|
.addReg(PopReg, RegState::Kill)
|
|
|
|
.add(predOps(ARMCC::AL));
|
2015-07-22 16:34:37 +00:00
|
|
|
}
|
2014-08-05 21:32:21 +00:00
|
|
|
|
2015-12-28 21:40:45 +00:00
|
|
|
if (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tPOP_RET) {
|
2015-12-08 19:59:01 +00:00
|
|
|
// We couldn't use the direct restoration above, so
|
|
|
|
// perform the opposite conversion: tPOP_RET to tPOP.
|
|
|
|
MachineInstrBuilder MIB =
|
2017-01-13 09:37:56 +00:00
|
|
|
BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII.get(ARM::tPOP))
|
|
|
|
.add(predOps(ARMCC::AL));
|
2015-12-28 21:40:45 +00:00
|
|
|
bool Popped = false;
|
2015-12-08 19:59:01 +00:00
|
|
|
for (auto MO: MBBI->operands())
|
|
|
|
if (MO.isReg() && (MO.isImplicit() || MO.isDef()) &&
|
|
|
|
MO.getReg() != ARM::PC) {
|
2017-01-13 09:58:52 +00:00
|
|
|
MIB.add(MO);
|
2015-12-08 19:59:01 +00:00
|
|
|
if (!MO.isImplicit())
|
2015-12-28 21:40:45 +00:00
|
|
|
Popped = true;
|
2015-12-08 19:59:01 +00:00
|
|
|
}
|
|
|
|
// Is there anything left to pop?
|
|
|
|
if (!Popped)
|
|
|
|
MBB.erase(MIB.getInstr());
|
|
|
|
// Erase the old instruction.
|
|
|
|
MBB.erase(MBBI);
|
2017-01-13 09:37:56 +00:00
|
|
|
MBBI = BuildMI(MBB, MBB.end(), dl, TII.get(ARM::tBX_RET))
|
|
|
|
.add(predOps(ARMCC::AL));
|
2015-12-01 19:25:11 +00:00
|
|
|
}
|
|
|
|
|
2015-07-22 16:34:37 +00:00
|
|
|
assert(PopReg && "Do not know how to get LR");
|
2017-01-13 09:37:56 +00:00
|
|
|
BuildMI(MBB, MBBI, dl, TII.get(ARM::tPOP))
|
|
|
|
.add(predOps(ARMCC::AL))
|
2015-07-22 16:34:37 +00:00
|
|
|
.addReg(PopReg, RegState::Define);
|
|
|
|
|
|
|
|
emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, ArgRegsSaveSize);
|
|
|
|
|
2017-01-13 09:37:56 +00:00
|
|
|
BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr))
|
|
|
|
.addReg(ARM::LR, RegState::Define)
|
|
|
|
.addReg(PopReg, RegState::Kill)
|
|
|
|
.add(predOps(ARMCC::AL));
|
2015-07-22 16:34:37 +00:00
|
|
|
|
2015-12-28 21:40:45 +00:00
|
|
|
if (TemporaryReg)
|
2017-01-13 09:37:56 +00:00
|
|
|
BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr))
|
|
|
|
.addReg(PopReg, RegState::Define)
|
|
|
|
.addReg(TemporaryReg, RegState::Kill)
|
|
|
|
.add(predOps(ARMCC::AL));
|
2015-07-22 16:34:37 +00:00
|
|
|
|
|
|
|
return true;
|
2010-11-15 00:06:54 +00:00
|
|
|
}
|
2010-11-27 23:05:03 +00:00
|
|
|
|
2017-09-20 21:35:51 +00:00
|
|
|
using ARMRegSet = std::bitset<ARM::NUM_TARGET_REGS>;
|
2017-08-30 22:28:30 +00:00
|
|
|
|
2016-10-11 21:14:03 +00:00
|
|
|
// Return the first iteraror after CurrentReg which is present in EnabledRegs,
|
|
|
|
// or OrderEnd if no further registers are in that set. This does not advance
|
|
|
|
// the iterator fiorst, so returns CurrentReg if it is in EnabledRegs.
|
2017-08-30 22:28:30 +00:00
|
|
|
static const unsigned *findNextOrderedReg(const unsigned *CurrentReg,
|
|
|
|
const ARMRegSet &EnabledRegs,
|
|
|
|
const unsigned *OrderEnd) {
|
|
|
|
while (CurrentReg != OrderEnd && !EnabledRegs[*CurrentReg])
|
2016-10-11 21:14:03 +00:00
|
|
|
++CurrentReg;
|
|
|
|
return CurrentReg;
|
|
|
|
}
|
|
|
|
|
2011-01-10 12:39:04 +00:00
|
|
|
bool Thumb1FrameLowering::
|
2010-11-27 23:05:03 +00:00
|
|
|
spillCalleeSavedRegisters(MachineBasicBlock &MBB,
|
|
|
|
MachineBasicBlock::iterator MI,
|
|
|
|
const std::vector<CalleeSavedInfo> &CSI,
|
|
|
|
const TargetRegisterInfo *TRI) const {
|
|
|
|
if (CSI.empty())
|
|
|
|
return false;
|
|
|
|
|
2015-11-05 21:54:58 +00:00
|
|
|
DebugLoc DL;
|
|
|
|
const TargetInstrInfo &TII = *STI.getInstrInfo();
|
2016-10-11 21:14:03 +00:00
|
|
|
MachineFunction &MF = *MBB.getParent();
|
|
|
|
const ARMBaseRegisterInfo *RegInfo = static_cast<const ARMBaseRegisterInfo *>(
|
|
|
|
MF.getSubtarget().getRegisterInfo());
|
|
|
|
|
2017-08-30 22:28:30 +00:00
|
|
|
ARMRegSet LoRegsToSave; // r0-r7, lr
|
|
|
|
ARMRegSet HiRegsToSave; // r8-r11
|
|
|
|
ARMRegSet CopyRegs; // Registers which can be used after pushing
|
|
|
|
// LoRegs for saving HiRegs.
|
2015-11-05 21:54:58 +00:00
|
|
|
|
|
|
|
for (unsigned i = CSI.size(); i != 0; --i) {
|
2010-11-27 23:05:03 +00:00
|
|
|
unsigned Reg = CSI[i-1].getReg();
|
|
|
|
|
2016-10-11 21:14:03 +00:00
|
|
|
if (ARM::tGPRRegClass.contains(Reg) || Reg == ARM::LR) {
|
2017-08-30 22:28:30 +00:00
|
|
|
LoRegsToSave[Reg] = true;
|
2016-10-11 21:14:03 +00:00
|
|
|
} else if (ARM::hGPRRegClass.contains(Reg) && Reg != ARM::LR) {
|
2017-08-30 22:28:30 +00:00
|
|
|
HiRegsToSave[Reg] = true;
|
2016-10-11 21:14:03 +00:00
|
|
|
} else {
|
|
|
|
llvm_unreachable("callee-saved register of unexpected class");
|
[Thumb] Save/restore high registers in Thumb1 pro/epilogues
The high registers are not allocatable in Thumb1 functions, but they
could still be used by inline assembly, so we need to save and restore
the callee-saved high registers (r8-r11) in the prologue and epilogue.
This is complicated by the fact that the Thumb1 push and pop
instructions cannot access these registers. Therefore, we have to move
them down into low registers before pushing, and move them back after
popping into low registers.
In most functions, we will have low registers that are also being
pushed/popped, which we can use as the temporary registers for
saving/restoring the high registers. However, this is not guaranteed, so
we may need to push some extra low registers to ensure that the high
registers can be saved/restored. For correctness, it would be sufficient
to use just one low register, but if we have enough low registers
available then we only need one push/pop instruction, rather than one
per high register.
We can also use the argument/return registers when they are not live,
and the link register when saving (but not restoring), reducing the
number of extra registers we need to push.
There are still a few extreme edge cases where we need two push/pop
instructions, because not enough low registers can be made live in the
prologue or epilogue.
In addition to the regression tests included here, I've also tested this
using a script to generate functions which clobber different
combinations of registers, have different numbers of argument and return
registers (including variadic arguments), allocate different fixed sized
objects on the stack, and do or don't use variable sized allocas and the
__builtin_return_address intrinsic (all of which affect the available
registers in the prologue and epilogue). I ran these functions in a test
harness which verifies that all of the callee-saved registers are
correctly preserved.
Differential Revision: https://reviews.llvm.org/D24228
llvm-svn: 283867
2016-10-11 10:12:25 +00:00
|
|
|
}
|
|
|
|
|
2016-10-11 21:14:03 +00:00
|
|
|
if ((ARM::tGPRRegClass.contains(Reg) || Reg == ARM::LR) &&
|
|
|
|
!MF.getRegInfo().isLiveIn(Reg) &&
|
|
|
|
!(hasFP(MF) && Reg == RegInfo->getFrameRegister(MF)))
|
2017-08-30 22:28:30 +00:00
|
|
|
CopyRegs[Reg] = true;
|
2016-10-11 21:14:03 +00:00
|
|
|
}
|
[Thumb] Save/restore high registers in Thumb1 pro/epilogues
The high registers are not allocatable in Thumb1 functions, but they
could still be used by inline assembly, so we need to save and restore
the callee-saved high registers (r8-r11) in the prologue and epilogue.
This is complicated by the fact that the Thumb1 push and pop
instructions cannot access these registers. Therefore, we have to move
them down into low registers before pushing, and move them back after
popping into low registers.
In most functions, we will have low registers that are also being
pushed/popped, which we can use as the temporary registers for
saving/restoring the high registers. However, this is not guaranteed, so
we may need to push some extra low registers to ensure that the high
registers can be saved/restored. For correctness, it would be sufficient
to use just one low register, but if we have enough low registers
available then we only need one push/pop instruction, rather than one
per high register.
We can also use the argument/return registers when they are not live,
and the link register when saving (but not restoring), reducing the
number of extra registers we need to push.
There are still a few extreme edge cases where we need two push/pop
instructions, because not enough low registers can be made live in the
prologue or epilogue.
In addition to the regression tests included here, I've also tested this
using a script to generate functions which clobber different
combinations of registers, have different numbers of argument and return
registers (including variadic arguments), allocate different fixed sized
objects on the stack, and do or don't use variable sized allocas and the
__builtin_return_address intrinsic (all of which affect the available
registers in the prologue and epilogue). I ran these functions in a test
harness which verifies that all of the callee-saved registers are
correctly preserved.
Differential Revision: https://reviews.llvm.org/D24228
llvm-svn: 283867
2016-10-11 10:12:25 +00:00
|
|
|
|
2016-10-11 21:14:03 +00:00
|
|
|
// Unused argument registers can be used for the high register saving.
|
|
|
|
for (unsigned ArgReg : {ARM::R0, ARM::R1, ARM::R2, ARM::R3})
|
|
|
|
if (!MF.getRegInfo().isLiveIn(ArgReg))
|
2017-08-30 22:28:30 +00:00
|
|
|
CopyRegs[ArgReg] = true;
|
2016-10-11 21:14:03 +00:00
|
|
|
|
|
|
|
// Push the low registers and lr
|
2017-05-31 01:21:30 +00:00
|
|
|
const MachineRegisterInfo &MRI = MF.getRegInfo();
|
2017-08-30 22:28:30 +00:00
|
|
|
if (!LoRegsToSave.none()) {
|
2017-01-13 09:37:56 +00:00
|
|
|
MachineInstrBuilder MIB =
|
|
|
|
BuildMI(MBB, MI, DL, TII.get(ARM::tPUSH)).add(predOps(ARMCC::AL));
|
2016-10-11 21:14:03 +00:00
|
|
|
for (unsigned Reg : {ARM::R4, ARM::R5, ARM::R6, ARM::R7, ARM::LR}) {
|
2017-08-30 22:28:30 +00:00
|
|
|
if (LoRegsToSave[Reg]) {
|
2017-05-31 01:21:30 +00:00
|
|
|
bool isKill = !MRI.isLiveIn(Reg);
|
|
|
|
if (isKill && !MRI.isReserved(Reg))
|
2016-10-11 21:14:03 +00:00
|
|
|
MBB.addLiveIn(Reg);
|
|
|
|
|
|
|
|
MIB.addReg(Reg, getKillRegState(isKill));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
MIB.setMIFlags(MachineInstr::FrameSetup);
|
[Thumb] Save/restore high registers in Thumb1 pro/epilogues
The high registers are not allocatable in Thumb1 functions, but they
could still be used by inline assembly, so we need to save and restore
the callee-saved high registers (r8-r11) in the prologue and epilogue.
This is complicated by the fact that the Thumb1 push and pop
instructions cannot access these registers. Therefore, we have to move
them down into low registers before pushing, and move them back after
popping into low registers.
In most functions, we will have low registers that are also being
pushed/popped, which we can use as the temporary registers for
saving/restoring the high registers. However, this is not guaranteed, so
we may need to push some extra low registers to ensure that the high
registers can be saved/restored. For correctness, it would be sufficient
to use just one low register, but if we have enough low registers
available then we only need one push/pop instruction, rather than one
per high register.
We can also use the argument/return registers when they are not live,
and the link register when saving (but not restoring), reducing the
number of extra registers we need to push.
There are still a few extreme edge cases where we need two push/pop
instructions, because not enough low registers can be made live in the
prologue or epilogue.
In addition to the regression tests included here, I've also tested this
using a script to generate functions which clobber different
combinations of registers, have different numbers of argument and return
registers (including variadic arguments), allocate different fixed sized
objects on the stack, and do or don't use variable sized allocas and the
__builtin_return_address intrinsic (all of which affect the available
registers in the prologue and epilogue). I ran these functions in a test
harness which verifies that all of the callee-saved registers are
correctly preserved.
Differential Revision: https://reviews.llvm.org/D24228
llvm-svn: 283867
2016-10-11 10:12:25 +00:00
|
|
|
}
|
2016-10-11 21:14:03 +00:00
|
|
|
|
|
|
|
// Push the high registers. There are no store instructions that can access
|
|
|
|
// these registers directly, so we have to move them to low registers, and
|
|
|
|
// push them. This might take multiple pushes, as it is possible for there to
|
|
|
|
// be fewer low registers available than high registers which need saving.
|
|
|
|
|
|
|
|
// These are in reverse order so that in the case where we need to use
|
|
|
|
// multiple PUSH instructions, the order of the registers on the stack still
|
|
|
|
// matches the unwind info. They need to be swicthed back to ascending order
|
|
|
|
// before adding to the PUSH instruction.
|
|
|
|
static const unsigned AllCopyRegs[] = {ARM::LR, ARM::R7, ARM::R6,
|
|
|
|
ARM::R5, ARM::R4, ARM::R3,
|
|
|
|
ARM::R2, ARM::R1, ARM::R0};
|
|
|
|
static const unsigned AllHighRegs[] = {ARM::R11, ARM::R10, ARM::R9, ARM::R8};
|
|
|
|
|
|
|
|
const unsigned *AllCopyRegsEnd = std::end(AllCopyRegs);
|
|
|
|
const unsigned *AllHighRegsEnd = std::end(AllHighRegs);
|
|
|
|
|
|
|
|
// Find the first register to save.
|
|
|
|
const unsigned *HiRegToSave = findNextOrderedReg(
|
|
|
|
std::begin(AllHighRegs), HiRegsToSave, AllHighRegsEnd);
|
|
|
|
|
|
|
|
while (HiRegToSave != AllHighRegsEnd) {
|
|
|
|
// Find the first low register to use.
|
|
|
|
const unsigned *CopyReg =
|
|
|
|
findNextOrderedReg(std::begin(AllCopyRegs), CopyRegs, AllCopyRegsEnd);
|
|
|
|
|
|
|
|
// Create the PUSH, but don't insert it yet (the MOVs need to come first).
|
2017-01-13 09:37:56 +00:00
|
|
|
MachineInstrBuilder PushMIB =
|
|
|
|
BuildMI(MF, DL, TII.get(ARM::tPUSH)).add(predOps(ARMCC::AL));
|
2016-10-11 21:14:03 +00:00
|
|
|
|
|
|
|
SmallVector<unsigned, 4> RegsToPush;
|
|
|
|
while (HiRegToSave != AllHighRegsEnd && CopyReg != AllCopyRegsEnd) {
|
2017-08-30 22:28:30 +00:00
|
|
|
if (HiRegsToSave[*HiRegToSave]) {
|
2017-05-31 01:21:30 +00:00
|
|
|
bool isKill = !MRI.isLiveIn(*HiRegToSave);
|
|
|
|
if (isKill && !MRI.isReserved(*HiRegToSave))
|
2016-10-11 21:14:03 +00:00
|
|
|
MBB.addLiveIn(*HiRegToSave);
|
|
|
|
|
|
|
|
// Emit a MOV from the high reg to the low reg.
|
2017-01-13 09:37:56 +00:00
|
|
|
BuildMI(MBB, MI, DL, TII.get(ARM::tMOVr))
|
|
|
|
.addReg(*CopyReg, RegState::Define)
|
|
|
|
.addReg(*HiRegToSave, getKillRegState(isKill))
|
|
|
|
.add(predOps(ARMCC::AL));
|
2016-10-11 21:14:03 +00:00
|
|
|
|
|
|
|
// Record the register that must be added to the PUSH.
|
|
|
|
RegsToPush.push_back(*CopyReg);
|
|
|
|
|
|
|
|
CopyReg = findNextOrderedReg(++CopyReg, CopyRegs, AllCopyRegsEnd);
|
|
|
|
HiRegToSave =
|
|
|
|
findNextOrderedReg(++HiRegToSave, HiRegsToSave, AllHighRegsEnd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add the low registers to the PUSH, in ascending order.
|
2017-01-26 23:40:06 +00:00
|
|
|
for (unsigned Reg : llvm::reverse(RegsToPush))
|
2016-10-11 21:14:03 +00:00
|
|
|
PushMIB.addReg(Reg, RegState::Kill);
|
|
|
|
|
|
|
|
// Insert the PUSH instruction after the MOVs.
|
|
|
|
MBB.insert(MI, PushMIB);
|
|
|
|
}
|
|
|
|
|
2010-11-27 23:05:03 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-01-10 12:39:04 +00:00
|
|
|
bool Thumb1FrameLowering::
|
2010-11-27 23:05:03 +00:00
|
|
|
restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
|
|
|
|
MachineBasicBlock::iterator MI,
|
2017-08-10 16:17:32 +00:00
|
|
|
std::vector<CalleeSavedInfo> &CSI,
|
2010-11-27 23:05:03 +00:00
|
|
|
const TargetRegisterInfo *TRI) const {
|
|
|
|
if (CSI.empty())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
MachineFunction &MF = *MBB.getParent();
|
|
|
|
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
2015-01-29 00:19:33 +00:00
|
|
|
const TargetInstrInfo &TII = *STI.getInstrInfo();
|
2016-10-11 21:14:03 +00:00
|
|
|
const ARMBaseRegisterInfo *RegInfo = static_cast<const ARMBaseRegisterInfo *>(
|
|
|
|
MF.getSubtarget().getRegisterInfo());
|
2010-11-27 23:05:03 +00:00
|
|
|
|
2013-04-30 07:19:58 +00:00
|
|
|
bool isVarArg = AFI->getArgRegsSaveSize() > 0;
|
2015-07-22 16:34:37 +00:00
|
|
|
DebugLoc DL = MI != MBB.end() ? MI->getDebugLoc() : DebugLoc();
|
2016-10-11 21:14:03 +00:00
|
|
|
|
2017-08-30 22:28:30 +00:00
|
|
|
ARMRegSet LoRegsToRestore;
|
|
|
|
ARMRegSet HiRegsToRestore;
|
2016-10-11 21:14:03 +00:00
|
|
|
// Low registers (r0-r7) which can be used to restore the high registers.
|
2017-08-30 22:28:30 +00:00
|
|
|
ARMRegSet CopyRegs;
|
2016-10-11 21:14:03 +00:00
|
|
|
|
|
|
|
for (CalleeSavedInfo I : CSI) {
|
|
|
|
unsigned Reg = I.getReg();
|
|
|
|
|
|
|
|
if (ARM::tGPRRegClass.contains(Reg) || Reg == ARM::LR) {
|
2017-08-30 22:28:30 +00:00
|
|
|
LoRegsToRestore[Reg] = true;
|
2016-10-11 21:14:03 +00:00
|
|
|
} else if (ARM::hGPRRegClass.contains(Reg) && Reg != ARM::LR) {
|
2017-08-30 22:28:30 +00:00
|
|
|
HiRegsToRestore[Reg] = true;
|
2016-10-11 21:14:03 +00:00
|
|
|
} else {
|
|
|
|
llvm_unreachable("callee-saved register of unexpected class");
|
|
|
|
}
|
|
|
|
|
|
|
|
// If this is a low register not used as the frame pointer, we may want to
|
|
|
|
// use it for restoring the high registers.
|
|
|
|
if ((ARM::tGPRRegClass.contains(Reg)) &&
|
|
|
|
!(hasFP(MF) && Reg == RegInfo->getFrameRegister(MF)))
|
2017-08-30 22:28:30 +00:00
|
|
|
CopyRegs[Reg] = true;
|
2016-10-11 21:14:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// If this is a return block, we may be able to use some unused return value
|
|
|
|
// registers for restoring the high regs.
|
|
|
|
auto Terminator = MBB.getFirstTerminator();
|
|
|
|
if (Terminator != MBB.end() && Terminator->getOpcode() == ARM::tBX_RET) {
|
2017-08-30 22:28:30 +00:00
|
|
|
CopyRegs[ARM::R0] = true;
|
|
|
|
CopyRegs[ARM::R1] = true;
|
|
|
|
CopyRegs[ARM::R2] = true;
|
|
|
|
CopyRegs[ARM::R3] = true;
|
2016-10-11 21:14:03 +00:00
|
|
|
for (auto Op : Terminator->implicit_operands()) {
|
|
|
|
if (Op.isReg())
|
2017-08-30 22:28:30 +00:00
|
|
|
CopyRegs[Op.getReg()] = false;
|
2016-10-11 21:14:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static const unsigned AllCopyRegs[] = {ARM::R0, ARM::R1, ARM::R2, ARM::R3,
|
|
|
|
ARM::R4, ARM::R5, ARM::R6, ARM::R7};
|
|
|
|
static const unsigned AllHighRegs[] = {ARM::R8, ARM::R9, ARM::R10, ARM::R11};
|
|
|
|
|
|
|
|
const unsigned *AllCopyRegsEnd = std::end(AllCopyRegs);
|
|
|
|
const unsigned *AllHighRegsEnd = std::end(AllHighRegs);
|
|
|
|
|
|
|
|
// Find the first register to restore.
|
|
|
|
auto HiRegToRestore = findNextOrderedReg(std::begin(AllHighRegs),
|
|
|
|
HiRegsToRestore, AllHighRegsEnd);
|
|
|
|
|
|
|
|
while (HiRegToRestore != AllHighRegsEnd) {
|
2017-08-30 22:28:30 +00:00
|
|
|
assert(!CopyRegs.none());
|
2016-10-11 21:14:03 +00:00
|
|
|
// Find the first low register to use.
|
|
|
|
auto CopyReg =
|
|
|
|
findNextOrderedReg(std::begin(AllCopyRegs), CopyRegs, AllCopyRegsEnd);
|
|
|
|
|
|
|
|
// Create the POP instruction.
|
2017-01-13 09:37:56 +00:00
|
|
|
MachineInstrBuilder PopMIB =
|
|
|
|
BuildMI(MBB, MI, DL, TII.get(ARM::tPOP)).add(predOps(ARMCC::AL));
|
2016-10-11 21:14:03 +00:00
|
|
|
|
|
|
|
while (HiRegToRestore != AllHighRegsEnd && CopyReg != AllCopyRegsEnd) {
|
|
|
|
// Add the low register to the POP.
|
|
|
|
PopMIB.addReg(*CopyReg, RegState::Define);
|
|
|
|
|
|
|
|
// Create the MOV from low to high register.
|
2017-01-13 09:37:56 +00:00
|
|
|
BuildMI(MBB, MI, DL, TII.get(ARM::tMOVr))
|
|
|
|
.addReg(*HiRegToRestore, RegState::Define)
|
|
|
|
.addReg(*CopyReg, RegState::Kill)
|
|
|
|
.add(predOps(ARMCC::AL));
|
2016-10-11 21:14:03 +00:00
|
|
|
|
|
|
|
CopyReg = findNextOrderedReg(++CopyReg, CopyRegs, AllCopyRegsEnd);
|
|
|
|
HiRegToRestore =
|
|
|
|
findNextOrderedReg(++HiRegToRestore, HiRegsToRestore, AllHighRegsEnd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-13 09:37:56 +00:00
|
|
|
MachineInstrBuilder MIB =
|
|
|
|
BuildMI(MF, DL, TII.get(ARM::tPOP)).add(predOps(ARMCC::AL));
|
2010-11-27 23:05:03 +00:00
|
|
|
|
2015-12-28 21:40:45 +00:00
|
|
|
bool NeedsPop = false;
|
2010-11-27 23:05:03 +00:00
|
|
|
for (unsigned i = CSI.size(); i != 0; --i) {
|
2017-09-28 23:12:06 +00:00
|
|
|
CalleeSavedInfo &Info = CSI[i-1];
|
|
|
|
unsigned Reg = Info.getReg();
|
2016-10-11 21:14:03 +00:00
|
|
|
|
|
|
|
// High registers (excluding lr) have already been dealt with
|
|
|
|
if (!(ARM::tGPRRegClass.contains(Reg) || Reg == ARM::LR))
|
|
|
|
continue;
|
|
|
|
|
2015-12-28 21:40:45 +00:00
|
|
|
if (Reg == ARM::LR) {
|
2017-09-28 23:12:06 +00:00
|
|
|
Info.setRestored(false);
|
[ARM] Fix incorrect conversion of a tail call to an ordinary call
When we emit a tail call for Armv8-M, but then discover that the caller needs to
save/restore `LR`, we convert the tail call to an ordinary one, since restoring
`LR` takes extra instructions, which may negate the benefits of the tail
call. If the callee, however, takes stack arguments, this conversion is
incorrect, since nothing has been done to pass the stack arguments.
Thus the patch reverts https://reviews.llvm.org/rL294000
Also, we improve the instruction sequence for popping `LR` in the case when we
couldn't immediately find a scratch low register, but we can use as a temporary
one of the callee-saved low registers and restore `LR` before popping other
callee-saves.
Differential Revision: https://reviews.llvm.org/D39599
llvm-svn: 318143
2017-11-14 10:36:52 +00:00
|
|
|
if (!MBB.succ_empty() ||
|
|
|
|
MI->getOpcode() == ARM::TCRETURNdi ||
|
|
|
|
MI->getOpcode() == ARM::TCRETURNri)
|
2015-12-28 21:40:45 +00:00
|
|
|
// LR may only be popped into PC, as part of return sequence.
|
|
|
|
// If this isn't the return sequence, we'll need emitPopSpecialFixUp
|
|
|
|
// to restore LR the hard way.
|
[ARM] Fix incorrect conversion of a tail call to an ordinary call
When we emit a tail call for Armv8-M, but then discover that the caller needs to
save/restore `LR`, we convert the tail call to an ordinary one, since restoring
`LR` takes extra instructions, which may negate the benefits of the tail
call. If the callee, however, takes stack arguments, this conversion is
incorrect, since nothing has been done to pass the stack arguments.
Thus the patch reverts https://reviews.llvm.org/rL294000
Also, we improve the instruction sequence for popping `LR` in the case when we
couldn't immediately find a scratch low register, but we can use as a temporary
one of the callee-saved low registers and restore `LR` before popping other
callee-saves.
Differential Revision: https://reviews.llvm.org/D39599
llvm-svn: 318143
2017-11-14 10:36:52 +00:00
|
|
|
// FIXME: if we don't pass any stack arguments it would be actually
|
|
|
|
// advantageous *and* correct to do the conversion to an ordinary call
|
|
|
|
// instruction here.
|
2014-08-05 21:32:21 +00:00
|
|
|
continue;
|
[ARM] Fix incorrect conversion of a tail call to an ordinary call
When we emit a tail call for Armv8-M, but then discover that the caller needs to
save/restore `LR`, we convert the tail call to an ordinary one, since restoring
`LR` takes extra instructions, which may negate the benefits of the tail
call. If the callee, however, takes stack arguments, this conversion is
incorrect, since nothing has been done to pass the stack arguments.
Thus the patch reverts https://reviews.llvm.org/rL294000
Also, we improve the instruction sequence for popping `LR` in the case when we
couldn't immediately find a scratch low register, but we can use as a temporary
one of the callee-saved low registers and restore `LR` before popping other
callee-saves.
Differential Revision: https://reviews.llvm.org/D39599
llvm-svn: 318143
2017-11-14 10:36:52 +00:00
|
|
|
// Special epilogue for vararg functions. See emitEpilogue
|
|
|
|
if (isVarArg)
|
|
|
|
continue;
|
|
|
|
// ARMv4T requires BX, see emitEpilogue
|
|
|
|
if (!STI.hasV5TOps())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Pop LR into PC.
|
|
|
|
Reg = ARM::PC;
|
|
|
|
(*MIB).setDesc(TII.get(ARM::tPOP_RET));
|
|
|
|
if (MI != MBB.end())
|
|
|
|
MIB.copyImplicitOps(*MI);
|
|
|
|
MI = MBB.erase(MI);
|
2010-11-27 23:05:03 +00:00
|
|
|
}
|
|
|
|
MIB.addReg(Reg, getDefRegState(true));
|
2015-12-28 21:40:45 +00:00
|
|
|
NeedsPop = true;
|
2010-11-27 23:05:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// It's illegal to emit pop instruction without operands.
|
2015-12-28 21:40:45 +00:00
|
|
|
if (NeedsPop)
|
2010-11-27 23:05:03 +00:00
|
|
|
MBB.insert(MI, &*MIB);
|
|
|
|
else
|
|
|
|
MF.DeleteMachineInstr(MIB);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|