2009-11-07 22:00:39 +00:00
|
|
|
//===- Thumb1RegisterInfo.cpp - Thumb-1 Register Information ----*- C++ -*-===//
|
2009-06-27 12:16:40 +00:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2009-11-07 22:00:39 +00:00
|
|
|
// This file contains the Thumb-1 implementation of the TargetRegisterInfo
|
|
|
|
// class.
|
2009-06-27 12:16:40 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "ARM.h"
|
|
|
|
#include "ARMAddressingModes.h"
|
2009-07-08 20:28:28 +00:00
|
|
|
#include "ARMBaseInstrInfo.h"
|
2009-06-27 12:16:40 +00:00
|
|
|
#include "ARMMachineFunctionInfo.h"
|
|
|
|
#include "ARMSubtarget.h"
|
2009-07-02 22:18:33 +00:00
|
|
|
#include "Thumb1InstrInfo.h"
|
|
|
|
#include "Thumb1RegisterInfo.h"
|
2009-06-27 12:16:40 +00:00
|
|
|
#include "llvm/Constants.h"
|
|
|
|
#include "llvm/DerivedTypes.h"
|
2009-07-14 23:09:55 +00:00
|
|
|
#include "llvm/Function.h"
|
|
|
|
#include "llvm/LLVMContext.h"
|
2009-06-27 12:16:40 +00:00
|
|
|
#include "llvm/CodeGen/MachineConstantPool.h"
|
|
|
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
|
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
|
|
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
|
|
|
#include "llvm/CodeGen/MachineLocation.h"
|
|
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
|
|
|
#include "llvm/Target/TargetFrameInfo.h"
|
|
|
|
#include "llvm/Target/TargetMachine.h"
|
|
|
|
#include "llvm/ADT/BitVector.h"
|
|
|
|
#include "llvm/ADT/SmallVector.h"
|
2010-03-09 19:07:28 +00:00
|
|
|
#include "llvm/Support/CommandLine.h"
|
2009-07-08 18:01:40 +00:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2009-07-08 20:53:28 +00:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2009-06-27 12:16:40 +00:00
|
|
|
|
2010-04-15 17:34:58 +00:00
|
|
|
namespace llvm {
|
2010-03-09 19:07:28 +00:00
|
|
|
extern cl::opt<bool> ReuseFrameIndexVals;
|
2010-04-15 17:34:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
using namespace llvm;
|
2010-03-09 19:07:28 +00:00
|
|
|
|
2009-07-08 18:31:39 +00:00
|
|
|
Thumb1RegisterInfo::Thumb1RegisterInfo(const ARMBaseInstrInfo &tii,
|
2009-07-02 22:18:33 +00:00
|
|
|
const ARMSubtarget &sti)
|
2009-06-27 12:16:40 +00:00
|
|
|
: ARMBaseRegisterInfo(tii, sti) {
|
|
|
|
}
|
|
|
|
|
|
|
|
/// emitLoadConstPool - Emits a load from constpool to materialize the
|
|
|
|
/// specified immediate.
|
2009-07-02 22:18:33 +00:00
|
|
|
void Thumb1RegisterInfo::emitLoadConstPool(MachineBasicBlock &MBB,
|
|
|
|
MachineBasicBlock::iterator &MBBI,
|
2009-07-08 20:28:28 +00:00
|
|
|
DebugLoc dl,
|
2009-07-16 09:20:10 +00:00
|
|
|
unsigned DestReg, unsigned SubIdx,
|
|
|
|
int Val,
|
2009-07-08 18:31:39 +00:00
|
|
|
ARMCC::CondCodes Pred,
|
|
|
|
unsigned PredReg) const {
|
2009-06-27 12:16:40 +00:00
|
|
|
MachineFunction &MF = *MBB.getParent();
|
|
|
|
MachineConstantPool *ConstantPool = MF.getConstantPool();
|
2010-04-15 01:51:59 +00:00
|
|
|
const Constant *C = ConstantInt::get(
|
2009-08-13 21:58:54 +00:00
|
|
|
Type::getInt32Ty(MBB.getParent()->getFunction()->getContext()), Val);
|
2009-06-27 12:16:40 +00:00
|
|
|
unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4);
|
|
|
|
|
2009-07-16 09:20:10 +00:00
|
|
|
BuildMI(MBB, MBBI, dl, TII.get(ARM::tLDRcp))
|
|
|
|
.addReg(DestReg, getDefRegState(true), SubIdx)
|
|
|
|
.addConstantPoolIndex(Idx).addImm(Pred).addReg(PredReg);
|
2009-06-27 12:16:40 +00:00
|
|
|
}
|
|
|
|
|
2010-07-20 06:52:21 +00:00
|
|
|
bool Thumb1RegisterInfo::hasReservedCallFrame(const MachineFunction &MF) const {
|
2009-06-27 12:16:40 +00:00
|
|
|
const MachineFrameInfo *FFI = MF.getFrameInfo();
|
|
|
|
unsigned CFSize = FFI->getMaxCallFrameSize();
|
|
|
|
// 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;
|
|
|
|
|
|
|
|
return !MF.getFrameInfo()->hasVarSizedObjects();
|
|
|
|
}
|
|
|
|
|
2009-07-11 06:43:01 +00:00
|
|
|
|
2009-06-27 12:16:40 +00:00
|
|
|
/// emitThumbRegPlusImmInReg - Emits a series of instructions to materialize
|
|
|
|
/// a destreg = basereg + immediate in Thumb code. Materialize the immediate
|
|
|
|
/// in a register using mov / mvn sequences or load the immediate from a
|
|
|
|
/// constpool entry.
|
|
|
|
static
|
|
|
|
void emitThumbRegPlusImmInReg(MachineBasicBlock &MBB,
|
|
|
|
MachineBasicBlock::iterator &MBBI,
|
|
|
|
unsigned DestReg, unsigned BaseReg,
|
|
|
|
int NumBytes, bool CanChangeCC,
|
|
|
|
const TargetInstrInfo &TII,
|
2010-10-19 23:27:08 +00:00
|
|
|
const ARMBaseRegisterInfo& MRI,
|
2009-06-27 12:16:40 +00:00
|
|
|
DebugLoc dl) {
|
Start of revamping the register scavenging in PEI. ARM Thumb1 is the driving
interest for this, as it currently reserves a register rather than using
the scavenger for matierializing constants as needed.
Instead of scavenging registers on the fly while eliminating frame indices,
new virtual registers are created, and then a scavenged collectively in a
post-pass over the function. This isolates the bits that need to interact
with the scavenger, and sets the stage for more intelligent use, and reuse,
of scavenged registers.
For the time being, this is disabled by default. Once the bugs are worked out,
the current scavenging calls in replaceFrameIndices() will be removed and
the post-pass scavenging will be the default. Until then,
-enable-frame-index-scavenging enables the new code. Currently, only the
Thumb1 back end is set up to use it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@82734 91177308-0d34-0410-b5e6-96231b3b80d8
2009-09-24 23:52:18 +00:00
|
|
|
MachineFunction &MF = *MBB.getParent();
|
2009-06-27 12:59:03 +00:00
|
|
|
bool isHigh = !isARMLowRegister(DestReg) ||
|
|
|
|
(BaseReg != 0 && !isARMLowRegister(BaseReg));
|
2009-06-27 12:16:40 +00:00
|
|
|
bool isSub = false;
|
|
|
|
// Subtract doesn't have high register version. Load the negative value
|
|
|
|
// if either base or dest register is a high register. Also, if do not
|
|
|
|
// issue sub as part of the sequence if condition register is to be
|
|
|
|
// preserved.
|
|
|
|
if (NumBytes < 0 && !isHigh && CanChangeCC) {
|
|
|
|
isSub = true;
|
|
|
|
NumBytes = -NumBytes;
|
|
|
|
}
|
|
|
|
unsigned LdReg = DestReg;
|
|
|
|
if (DestReg == ARM::SP) {
|
|
|
|
assert(BaseReg == ARM::SP && "Unexpected!");
|
2009-10-08 01:46:59 +00:00
|
|
|
LdReg = MF.getRegInfo().createVirtualRegister(ARM::tGPRRegisterClass);
|
2009-06-27 12:16:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (NumBytes <= 255 && NumBytes >= 0)
|
2009-07-19 19:16:46 +00:00
|
|
|
AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg))
|
2009-07-11 06:43:01 +00:00
|
|
|
.addImm(NumBytes);
|
2009-06-27 12:16:40 +00:00
|
|
|
else if (NumBytes < 0 && NumBytes >= -255) {
|
2009-07-19 19:16:46 +00:00
|
|
|
AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg))
|
2009-07-11 06:43:01 +00:00
|
|
|
.addImm(NumBytes);
|
2009-07-19 19:16:46 +00:00
|
|
|
AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tRSB), LdReg))
|
2009-06-27 12:16:40 +00:00
|
|
|
.addReg(LdReg, RegState::Kill);
|
|
|
|
} else
|
2009-07-16 09:20:10 +00:00
|
|
|
MRI.emitLoadConstPool(MBB, MBBI, dl, LdReg, 0, NumBytes);
|
2009-06-27 12:16:40 +00:00
|
|
|
|
|
|
|
// Emit add / sub.
|
|
|
|
int Opc = (isSub) ? ARM::tSUBrr : (isHigh ? ARM::tADDhirr : ARM::tADDrr);
|
2009-07-11 06:43:01 +00:00
|
|
|
MachineInstrBuilder MIB =
|
|
|
|
BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg);
|
|
|
|
if (Opc != ARM::tADDhirr)
|
2009-07-19 19:16:46 +00:00
|
|
|
MIB = AddDefaultT1CC(MIB);
|
2009-06-27 12:16:40 +00:00
|
|
|
if (DestReg == ARM::SP || isSub)
|
|
|
|
MIB.addReg(BaseReg).addReg(LdReg, RegState::Kill);
|
|
|
|
else
|
|
|
|
MIB.addReg(LdReg).addReg(BaseReg, RegState::Kill);
|
2009-07-11 06:43:01 +00:00
|
|
|
AddDefaultPred(MIB);
|
2009-06-27 12:16:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// calcNumMI - Returns the number of instructions required to materialize
|
|
|
|
/// the specific add / sub r, c instruction.
|
|
|
|
static unsigned calcNumMI(int Opc, int ExtraOpc, unsigned Bytes,
|
|
|
|
unsigned NumBits, unsigned Scale) {
|
|
|
|
unsigned NumMIs = 0;
|
|
|
|
unsigned Chunk = ((1 << NumBits) - 1) * Scale;
|
|
|
|
|
|
|
|
if (Opc == ARM::tADDrSPi) {
|
|
|
|
unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes;
|
|
|
|
Bytes -= ThisVal;
|
|
|
|
NumMIs++;
|
|
|
|
NumBits = 8;
|
|
|
|
Scale = 1; // Followed by a number of tADDi8.
|
|
|
|
Chunk = ((1 << NumBits) - 1) * Scale;
|
|
|
|
}
|
|
|
|
|
|
|
|
NumMIs += Bytes / Chunk;
|
|
|
|
if ((Bytes % Chunk) != 0)
|
|
|
|
NumMIs++;
|
|
|
|
if (ExtraOpc)
|
|
|
|
NumMIs++;
|
|
|
|
return NumMIs;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// emitThumbRegPlusImmediate - Emits a series of instructions to materialize
|
|
|
|
/// a destreg = basereg + immediate in Thumb code.
|
2010-10-19 23:27:08 +00:00
|
|
|
void llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB,
|
|
|
|
MachineBasicBlock::iterator &MBBI,
|
|
|
|
unsigned DestReg, unsigned BaseReg,
|
|
|
|
int NumBytes, const TargetInstrInfo &TII,
|
|
|
|
const ARMBaseRegisterInfo& MRI,
|
|
|
|
DebugLoc dl) {
|
2009-06-27 12:16:40 +00:00
|
|
|
bool isSub = NumBytes < 0;
|
|
|
|
unsigned Bytes = (unsigned)NumBytes;
|
|
|
|
if (isSub) Bytes = -NumBytes;
|
|
|
|
bool isMul4 = (Bytes & 3) == 0;
|
|
|
|
bool isTwoAddr = false;
|
|
|
|
bool DstNotEqBase = false;
|
|
|
|
unsigned NumBits = 1;
|
|
|
|
unsigned Scale = 1;
|
|
|
|
int Opc = 0;
|
|
|
|
int ExtraOpc = 0;
|
2009-07-11 06:43:01 +00:00
|
|
|
bool NeedCC = false;
|
|
|
|
bool NeedPred = false;
|
2009-06-27 12:16:40 +00:00
|
|
|
|
|
|
|
if (DestReg == BaseReg && BaseReg == ARM::SP) {
|
|
|
|
assert(isMul4 && "Thumb sp inc / dec size must be multiple of 4!");
|
|
|
|
NumBits = 7;
|
|
|
|
Scale = 4;
|
|
|
|
Opc = isSub ? ARM::tSUBspi : ARM::tADDspi;
|
|
|
|
isTwoAddr = true;
|
|
|
|
} else if (!isSub && BaseReg == ARM::SP) {
|
|
|
|
// r1 = add sp, 403
|
|
|
|
// =>
|
|
|
|
// r1 = add sp, 100 * 4
|
|
|
|
// r1 = add r1, 3
|
|
|
|
if (!isMul4) {
|
|
|
|
Bytes &= ~3;
|
|
|
|
ExtraOpc = ARM::tADDi3;
|
|
|
|
}
|
|
|
|
NumBits = 8;
|
|
|
|
Scale = 4;
|
|
|
|
Opc = ARM::tADDrSPi;
|
|
|
|
} else {
|
|
|
|
// sp = sub sp, c
|
|
|
|
// r1 = sub sp, c
|
|
|
|
// r8 = sub sp, c
|
|
|
|
if (DestReg != BaseReg)
|
|
|
|
DstNotEqBase = true;
|
|
|
|
NumBits = 8;
|
2009-07-20 06:59:32 +00:00
|
|
|
if (DestReg == ARM::SP) {
|
|
|
|
Opc = isSub ? ARM::tSUBspi : ARM::tADDspi;
|
|
|
|
assert(isMul4 && "Thumb sp inc / dec size must be multiple of 4!");
|
|
|
|
NumBits = 7;
|
|
|
|
Scale = 4;
|
|
|
|
} else {
|
|
|
|
Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8;
|
|
|
|
NumBits = 8;
|
|
|
|
NeedPred = NeedCC = true;
|
|
|
|
}
|
2009-06-27 12:16:40 +00:00
|
|
|
isTwoAddr = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned NumMIs = calcNumMI(Opc, ExtraOpc, Bytes, NumBits, Scale);
|
|
|
|
unsigned Threshold = (DestReg == ARM::SP) ? 3 : 2;
|
|
|
|
if (NumMIs > Threshold) {
|
|
|
|
// This will expand into too many instructions. Load the immediate from a
|
|
|
|
// constpool entry.
|
|
|
|
emitThumbRegPlusImmInReg(MBB, MBBI, DestReg, BaseReg, NumBytes, true, TII,
|
|
|
|
MRI, dl);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (DstNotEqBase) {
|
2009-06-27 12:59:03 +00:00
|
|
|
if (isARMLowRegister(DestReg) && isARMLowRegister(BaseReg)) {
|
2009-06-27 12:16:40 +00:00
|
|
|
// If both are low registers, emit DestReg = add BaseReg, max(Imm, 7)
|
|
|
|
unsigned Chunk = (1 << 3) - 1;
|
|
|
|
unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes;
|
|
|
|
Bytes -= ThisVal;
|
2009-07-11 06:43:01 +00:00
|
|
|
const TargetInstrDesc &TID = TII.get(isSub ? ARM::tSUBi3 : ARM::tADDi3);
|
|
|
|
const MachineInstrBuilder MIB =
|
2009-07-19 19:16:46 +00:00
|
|
|
AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TID, DestReg));
|
2009-07-11 06:43:01 +00:00
|
|
|
AddDefaultPred(MIB.addReg(BaseReg, RegState::Kill).addImm(ThisVal));
|
2009-06-27 12:16:40 +00:00
|
|
|
} else {
|
|
|
|
BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg)
|
|
|
|
.addReg(BaseReg, RegState::Kill);
|
|
|
|
}
|
|
|
|
BaseReg = DestReg;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned Chunk = ((1 << NumBits) - 1) * Scale;
|
|
|
|
while (Bytes) {
|
|
|
|
unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes;
|
|
|
|
Bytes -= ThisVal;
|
|
|
|
ThisVal /= Scale;
|
|
|
|
// Build the new tADD / tSUB.
|
2009-07-11 06:43:01 +00:00
|
|
|
if (isTwoAddr) {
|
|
|
|
MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg);
|
|
|
|
if (NeedCC)
|
2009-07-19 19:16:46 +00:00
|
|
|
MIB = AddDefaultT1CC(MIB);
|
2009-07-11 06:43:01 +00:00
|
|
|
MIB .addReg(DestReg).addImm(ThisVal);
|
|
|
|
if (NeedPred)
|
|
|
|
MIB = AddDefaultPred(MIB);
|
|
|
|
}
|
2009-06-27 12:16:40 +00:00
|
|
|
else {
|
|
|
|
bool isKill = BaseReg != ARM::SP;
|
2009-07-11 06:43:01 +00:00
|
|
|
MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg);
|
|
|
|
if (NeedCC)
|
2009-07-19 19:16:46 +00:00
|
|
|
MIB = AddDefaultT1CC(MIB);
|
2009-07-11 06:43:01 +00:00
|
|
|
MIB.addReg(BaseReg, getKillRegState(isKill)).addImm(ThisVal);
|
|
|
|
if (NeedPred)
|
|
|
|
MIB = AddDefaultPred(MIB);
|
2009-06-27 12:16:40 +00:00
|
|
|
BaseReg = DestReg;
|
|
|
|
|
|
|
|
if (Opc == ARM::tADDrSPi) {
|
|
|
|
// r4 = add sp, imm
|
|
|
|
// r4 = add r4, imm
|
|
|
|
// ...
|
|
|
|
NumBits = 8;
|
|
|
|
Scale = 1;
|
|
|
|
Chunk = ((1 << NumBits) - 1) * Scale;
|
|
|
|
Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8;
|
2009-07-11 06:43:01 +00:00
|
|
|
NeedPred = NeedCC = isTwoAddr = true;
|
2009-06-27 12:16:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-11 06:43:01 +00:00
|
|
|
if (ExtraOpc) {
|
|
|
|
const TargetInstrDesc &TID = TII.get(ExtraOpc);
|
2009-07-19 19:16:46 +00:00
|
|
|
AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TID, DestReg))
|
2009-07-11 06:43:01 +00:00
|
|
|
.addReg(DestReg, RegState::Kill)
|
|
|
|
.addImm(((unsigned)NumBytes) & 3));
|
|
|
|
}
|
2009-06-27 12:16:40 +00:00
|
|
|
}
|
|
|
|
|
2009-06-27 12:59:03 +00:00
|
|
|
static void emitSPUpdate(MachineBasicBlock &MBB,
|
|
|
|
MachineBasicBlock::iterator &MBBI,
|
|
|
|
const TargetInstrInfo &TII, DebugLoc dl,
|
2009-07-02 22:18:33 +00:00
|
|
|
const Thumb1RegisterInfo &MRI,
|
2009-06-27 12:59:03 +00:00
|
|
|
int NumBytes) {
|
2009-06-27 12:16:40 +00:00
|
|
|
emitThumbRegPlusImmediate(MBB, MBBI, ARM::SP, ARM::SP, NumBytes, TII,
|
2009-06-27 12:59:03 +00:00
|
|
|
MRI, dl);
|
2009-06-27 12:16:40 +00:00
|
|
|
}
|
|
|
|
|
2009-07-02 22:18:33 +00:00
|
|
|
void Thumb1RegisterInfo::
|
2009-06-27 12:16:40 +00:00
|
|
|
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
|
|
|
|
MachineBasicBlock::iterator I) const {
|
|
|
|
if (!hasReservedCallFrame(MF)) {
|
|
|
|
// If we have alloca, convert as follows:
|
|
|
|
// ADJCALLSTACKDOWN -> sub, sp, sp, amount
|
|
|
|
// ADJCALLSTACKUP -> add, sp, sp, amount
|
|
|
|
MachineInstr *Old = I;
|
|
|
|
DebugLoc dl = Old->getDebugLoc();
|
|
|
|
unsigned Amount = Old->getOperand(0).getImm();
|
|
|
|
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.
|
|
|
|
unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment();
|
|
|
|
Amount = (Amount+Align-1)/Align*Align;
|
|
|
|
|
|
|
|
// Replace the pseudo instruction with a new instruction...
|
|
|
|
unsigned Opc = Old->getOpcode();
|
|
|
|
if (Opc == ARM::ADJCALLSTACKDOWN || Opc == ARM::tADJCALLSTACKDOWN) {
|
2009-06-27 12:59:03 +00:00
|
|
|
emitSPUpdate(MBB, I, TII, dl, *this, -Amount);
|
2009-06-27 12:16:40 +00:00
|
|
|
} else {
|
|
|
|
assert(Opc == ARM::ADJCALLSTACKUP || Opc == ARM::tADJCALLSTACKUP);
|
2009-06-27 12:59:03 +00:00
|
|
|
emitSPUpdate(MBB, I, TII, dl, *this, Amount);
|
2009-06-27 12:16:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
MBB.erase(I);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// emitThumbConstant - Emit a series of instructions to materialize a
|
|
|
|
/// constant.
|
|
|
|
static void emitThumbConstant(MachineBasicBlock &MBB,
|
|
|
|
MachineBasicBlock::iterator &MBBI,
|
|
|
|
unsigned DestReg, int Imm,
|
|
|
|
const TargetInstrInfo &TII,
|
2009-07-02 22:18:33 +00:00
|
|
|
const Thumb1RegisterInfo& MRI,
|
2009-06-27 12:16:40 +00:00
|
|
|
DebugLoc dl) {
|
|
|
|
bool isSub = Imm < 0;
|
|
|
|
if (isSub) Imm = -Imm;
|
|
|
|
|
|
|
|
int Chunk = (1 << 8) - 1;
|
|
|
|
int ThisVal = (Imm > Chunk) ? Chunk : Imm;
|
|
|
|
Imm -= ThisVal;
|
2009-07-19 19:16:46 +00:00
|
|
|
AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8),
|
|
|
|
DestReg))
|
2009-07-11 06:43:01 +00:00
|
|
|
.addImm(ThisVal));
|
2009-06-27 12:16:40 +00:00
|
|
|
if (Imm > 0)
|
|
|
|
emitThumbRegPlusImmediate(MBB, MBBI, DestReg, DestReg, Imm, TII, MRI, dl);
|
2009-07-11 06:43:01 +00:00
|
|
|
if (isSub) {
|
|
|
|
const TargetInstrDesc &TID = TII.get(ARM::tRSB);
|
2009-07-19 19:16:46 +00:00
|
|
|
AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TID, DestReg))
|
2009-07-11 06:43:01 +00:00
|
|
|
.addReg(DestReg, RegState::Kill));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void removeOperands(MachineInstr &MI, unsigned i) {
|
|
|
|
unsigned Op = i;
|
|
|
|
for (unsigned e = MI.getNumOperands(); i != e; ++i)
|
|
|
|
MI.RemoveOperand(Op);
|
2009-06-27 12:16:40 +00:00
|
|
|
}
|
|
|
|
|
2010-08-19 17:52:13 +00:00
|
|
|
bool Thumb1RegisterInfo::
|
|
|
|
rewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx,
|
|
|
|
unsigned FrameReg, int &Offset,
|
|
|
|
const ARMBaseInstrInfo &TII) const {
|
2009-06-27 12:16:40 +00:00
|
|
|
MachineInstr &MI = *II;
|
|
|
|
MachineBasicBlock &MBB = *MI.getParent();
|
|
|
|
DebugLoc dl = MI.getDebugLoc();
|
|
|
|
unsigned Opcode = MI.getOpcode();
|
|
|
|
const TargetInstrDesc &Desc = MI.getDesc();
|
|
|
|
unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);
|
|
|
|
|
|
|
|
if (Opcode == ARM::tADDrSPi) {
|
2010-08-19 17:52:13 +00:00
|
|
|
Offset += MI.getOperand(FrameRegIdx+1).getImm();
|
2009-06-27 12:16:40 +00:00
|
|
|
|
|
|
|
// Can't use tADDrSPi if it's based off the frame pointer.
|
|
|
|
unsigned NumBits = 0;
|
|
|
|
unsigned Scale = 1;
|
|
|
|
if (FrameReg != ARM::SP) {
|
|
|
|
Opcode = ARM::tADDi3;
|
2009-07-11 06:43:01 +00:00
|
|
|
MI.setDesc(TII.get(Opcode));
|
2009-06-27 12:16:40 +00:00
|
|
|
NumBits = 3;
|
|
|
|
} else {
|
|
|
|
NumBits = 8;
|
|
|
|
Scale = 4;
|
|
|
|
assert((Offset & 3) == 0 &&
|
|
|
|
"Thumb add/sub sp, #imm immediate must be multiple of 4!");
|
|
|
|
}
|
|
|
|
|
2010-01-19 21:08:28 +00:00
|
|
|
unsigned PredReg;
|
|
|
|
if (Offset == 0 && getInstrPredicate(&MI, PredReg) == ARMCC::AL) {
|
2009-06-27 12:16:40 +00:00
|
|
|
// Turn it into a move.
|
2009-07-26 23:59:01 +00:00
|
|
|
MI.setDesc(TII.get(ARM::tMOVgpr2tgpr));
|
2010-08-19 17:52:13 +00:00
|
|
|
MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
|
2010-01-19 21:08:28 +00:00
|
|
|
// Remove offset and remaining explicit predicate operands.
|
2010-08-19 17:52:13 +00:00
|
|
|
do MI.RemoveOperand(FrameRegIdx+1);
|
|
|
|
while (MI.getNumOperands() > FrameRegIdx+1 &&
|
|
|
|
(!MI.getOperand(FrameRegIdx+1).isReg() ||
|
|
|
|
!MI.getOperand(FrameRegIdx+1).isImm()));
|
|
|
|
return true;
|
2009-06-27 12:16:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Common case: small offset, fits into instruction.
|
|
|
|
unsigned Mask = (1 << NumBits) - 1;
|
|
|
|
if (((Offset / Scale) & ~Mask) == 0) {
|
|
|
|
// Replace the FrameIndex with sp / fp
|
2009-07-11 06:43:01 +00:00
|
|
|
if (Opcode == ARM::tADDi3) {
|
2010-08-19 17:52:13 +00:00
|
|
|
removeOperands(MI, FrameRegIdx);
|
2009-07-11 06:43:01 +00:00
|
|
|
MachineInstrBuilder MIB(&MI);
|
2009-07-19 19:16:46 +00:00
|
|
|
AddDefaultPred(AddDefaultT1CC(MIB).addReg(FrameReg)
|
2009-07-20 06:59:32 +00:00
|
|
|
.addImm(Offset / Scale));
|
2009-07-11 06:43:01 +00:00
|
|
|
} else {
|
2010-08-19 17:52:13 +00:00
|
|
|
MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
|
|
|
|
MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset / Scale);
|
2009-07-11 06:43:01 +00:00
|
|
|
}
|
2010-08-19 17:52:13 +00:00
|
|
|
return true;
|
2009-06-27 12:16:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
unsigned DestReg = MI.getOperand(0).getReg();
|
|
|
|
unsigned Bytes = (Offset > 0) ? Offset : -Offset;
|
|
|
|
unsigned NumMIs = calcNumMI(Opcode, 0, Bytes, NumBits, Scale);
|
|
|
|
// MI would expand into a large number of instructions. Don't try to
|
|
|
|
// simplify the immediate.
|
|
|
|
if (NumMIs > 2) {
|
|
|
|
emitThumbRegPlusImmediate(MBB, II, DestReg, FrameReg, Offset, TII,
|
|
|
|
*this, dl);
|
|
|
|
MBB.erase(II);
|
2010-08-19 17:52:13 +00:00
|
|
|
return true;
|
2009-06-27 12:16:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (Offset > 0) {
|
|
|
|
// Translate r0 = add sp, imm to
|
|
|
|
// r0 = add sp, 255*4
|
|
|
|
// r0 = add r0, (imm - 255*4)
|
2009-07-11 06:43:01 +00:00
|
|
|
if (Opcode == ARM::tADDi3) {
|
2010-08-19 17:52:13 +00:00
|
|
|
removeOperands(MI, FrameRegIdx);
|
2009-07-11 06:43:01 +00:00
|
|
|
MachineInstrBuilder MIB(&MI);
|
2009-07-19 19:16:46 +00:00
|
|
|
AddDefaultPred(AddDefaultT1CC(MIB).addReg(FrameReg).addImm(Mask));
|
2009-07-11 06:43:01 +00:00
|
|
|
} else {
|
2010-08-19 17:52:13 +00:00
|
|
|
MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
|
|
|
|
MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Mask);
|
2009-07-11 06:43:01 +00:00
|
|
|
}
|
2009-06-27 12:16:40 +00:00
|
|
|
Offset = (Offset - Mask * Scale);
|
2009-12-03 00:50:42 +00:00
|
|
|
MachineBasicBlock::iterator NII = llvm::next(II);
|
2009-06-27 12:16:40 +00:00
|
|
|
emitThumbRegPlusImmediate(MBB, NII, DestReg, DestReg, Offset, TII,
|
|
|
|
*this, dl);
|
|
|
|
} else {
|
|
|
|
// Translate r0 = add sp, -imm to
|
|
|
|
// r0 = -imm (this is then translated into a series of instructons)
|
|
|
|
// r0 = add r0, sp
|
|
|
|
emitThumbConstant(MBB, II, DestReg, Offset, TII, *this, dl);
|
2009-07-28 07:38:35 +00:00
|
|
|
|
2009-06-27 12:16:40 +00:00
|
|
|
MI.setDesc(TII.get(ARM::tADDhirr));
|
2010-08-19 17:52:13 +00:00
|
|
|
MI.getOperand(FrameRegIdx).ChangeToRegister(DestReg, false, false, true);
|
|
|
|
MI.getOperand(FrameRegIdx+1).ChangeToRegister(FrameReg, false);
|
2009-07-28 07:38:35 +00:00
|
|
|
if (Opcode == ARM::tADDi3) {
|
|
|
|
MachineInstrBuilder MIB(&MI);
|
|
|
|
AddDefaultPred(MIB);
|
|
|
|
}
|
2009-06-27 12:16:40 +00:00
|
|
|
}
|
2010-08-19 17:52:13 +00:00
|
|
|
return true;
|
2009-06-27 12:16:40 +00:00
|
|
|
} else {
|
|
|
|
unsigned ImmIdx = 0;
|
|
|
|
int InstrOffs = 0;
|
|
|
|
unsigned NumBits = 0;
|
|
|
|
unsigned Scale = 1;
|
|
|
|
switch (AddrMode) {
|
2009-06-29 07:51:04 +00:00
|
|
|
case ARMII::AddrModeT1_s: {
|
2010-08-19 17:52:13 +00:00
|
|
|
ImmIdx = FrameRegIdx+1;
|
2009-06-27 12:16:40 +00:00
|
|
|
InstrOffs = MI.getOperand(ImmIdx).getImm();
|
|
|
|
NumBits = (FrameReg == ARM::SP) ? 8 : 5;
|
|
|
|
Scale = 4;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
2009-07-14 16:55:14 +00:00
|
|
|
llvm_unreachable("Unsupported addressing mode!");
|
2009-06-27 12:16:40 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
Offset += InstrOffs * Scale;
|
|
|
|
assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!");
|
|
|
|
|
|
|
|
// Common case: small offset, fits into instruction.
|
|
|
|
MachineOperand &ImmOp = MI.getOperand(ImmIdx);
|
|
|
|
int ImmedOffset = Offset / Scale;
|
|
|
|
unsigned Mask = (1 << NumBits) - 1;
|
|
|
|
if ((unsigned)Offset <= Mask * Scale) {
|
|
|
|
// Replace the FrameIndex with sp
|
2010-08-19 17:52:13 +00:00
|
|
|
MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
|
2009-06-27 12:16:40 +00:00
|
|
|
ImmOp.ChangeToImmediate(ImmedOffset);
|
2010-08-19 17:52:13 +00:00
|
|
|
return true;
|
2009-06-27 12:16:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool isThumSpillRestore = Opcode == ARM::tRestore || Opcode == ARM::tSpill;
|
2009-06-29 07:51:04 +00:00
|
|
|
if (AddrMode == ARMII::AddrModeT1_s) {
|
2009-06-27 12:16:40 +00:00
|
|
|
// Thumb tLDRspi, tSTRspi. These will change to instructions that use
|
|
|
|
// a different base register.
|
|
|
|
NumBits = 5;
|
|
|
|
Mask = (1 << NumBits) - 1;
|
|
|
|
}
|
|
|
|
// If this is a thumb spill / restore, we will be using a constpool load to
|
|
|
|
// materialize the offset.
|
2009-06-29 07:51:04 +00:00
|
|
|
if (AddrMode == ARMII::AddrModeT1_s && isThumSpillRestore)
|
2009-06-27 12:16:40 +00:00
|
|
|
ImmOp.ChangeToImmediate(0);
|
|
|
|
else {
|
|
|
|
// Otherwise, it didn't fit. Pull in what we can to simplify the immed.
|
|
|
|
ImmedOffset = ImmedOffset & Mask;
|
|
|
|
ImmOp.ChangeToImmediate(ImmedOffset);
|
|
|
|
Offset &= ~(Mask*Scale);
|
|
|
|
}
|
|
|
|
}
|
2010-08-19 17:52:13 +00:00
|
|
|
return Offset == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Thumb1RegisterInfo::resolveFrameIndex(MachineBasicBlock::iterator I,
|
|
|
|
unsigned BaseReg, int64_t Offset) const {
|
|
|
|
MachineInstr &MI = *I;
|
|
|
|
int Off = Offset; // ARM doesn't need the general 64-bit offsets
|
|
|
|
unsigned i = 0;
|
|
|
|
|
|
|
|
while (!MI.getOperand(i).isFI()) {
|
|
|
|
++i;
|
|
|
|
assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
|
|
|
|
}
|
|
|
|
bool Done = false;
|
|
|
|
Done = rewriteFrameIndex(MI, i, BaseReg, Off, TII);
|
|
|
|
assert (Done && "Unable to resolve frame index!");
|
|
|
|
}
|
|
|
|
|
|
|
|
/// saveScavengerRegister - Spill the register so it can be used by the
|
|
|
|
/// register scavenger. Return true.
|
|
|
|
bool
|
|
|
|
Thumb1RegisterInfo::saveScavengerRegister(MachineBasicBlock &MBB,
|
|
|
|
MachineBasicBlock::iterator I,
|
|
|
|
MachineBasicBlock::iterator &UseMI,
|
|
|
|
const TargetRegisterClass *RC,
|
|
|
|
unsigned Reg) const {
|
|
|
|
// Thumb1 can't use the emergency spill slot on the stack because
|
|
|
|
// ldr/str immediate offsets must be positive, and if we're referencing
|
|
|
|
// off the frame pointer (if, for example, there are alloca() calls in
|
|
|
|
// the function, the offset will be negative. Use R12 instead since that's
|
|
|
|
// a call clobbered register that we know won't be used in Thumb1 mode.
|
|
|
|
DebugLoc DL;
|
|
|
|
BuildMI(MBB, I, DL, TII.get(ARM::tMOVtgpr2gpr)).
|
|
|
|
addReg(ARM::R12, RegState::Define).addReg(Reg, RegState::Kill);
|
|
|
|
|
|
|
|
// The UseMI is where we would like to restore the register. If there's
|
|
|
|
// interference with R12 before then, however, we'll need to restore it
|
|
|
|
// before that instead and adjust the UseMI.
|
|
|
|
bool done = false;
|
|
|
|
for (MachineBasicBlock::iterator II = I; !done && II != UseMI ; ++II) {
|
|
|
|
if (II->isDebugValue())
|
|
|
|
continue;
|
|
|
|
// If this instruction affects R12, adjust our restore point.
|
|
|
|
for (unsigned i = 0, e = II->getNumOperands(); i != e; ++i) {
|
|
|
|
const MachineOperand &MO = II->getOperand(i);
|
|
|
|
if (!MO.isReg() || MO.isUndef() || !MO.getReg() ||
|
|
|
|
TargetRegisterInfo::isVirtualRegister(MO.getReg()))
|
|
|
|
continue;
|
|
|
|
if (MO.getReg() == ARM::R12) {
|
|
|
|
UseMI = II;
|
|
|
|
done = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Restore the register from R12
|
|
|
|
BuildMI(MBB, UseMI, DL, TII.get(ARM::tMOVgpr2tgpr)).
|
|
|
|
addReg(Reg, RegState::Define).addReg(ARM::R12, RegState::Kill);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-08-26 23:32:16 +00:00
|
|
|
void
|
2010-08-19 17:52:13 +00:00
|
|
|
Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
2010-08-26 23:32:16 +00:00
|
|
|
int SPAdj, RegScavenger *RS) const {
|
2010-08-19 17:52:13 +00:00
|
|
|
unsigned VReg = 0;
|
|
|
|
unsigned i = 0;
|
|
|
|
MachineInstr &MI = *II;
|
|
|
|
MachineBasicBlock &MBB = *MI.getParent();
|
|
|
|
MachineFunction &MF = *MBB.getParent();
|
|
|
|
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
|
|
|
DebugLoc dl = MI.getDebugLoc();
|
|
|
|
|
|
|
|
while (!MI.getOperand(i).isFI()) {
|
|
|
|
++i;
|
|
|
|
assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned FrameReg = ARM::SP;
|
|
|
|
int FrameIndex = MI.getOperand(i).getIndex();
|
|
|
|
int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) +
|
|
|
|
MF.getFrameInfo()->getStackSize() + SPAdj;
|
|
|
|
|
Simplify ARM callee-saved register handling by removing the distinction
between the high and low registers for prologue/epilogue code. This was
a Darwin-only thing that wasn't providing a realistic benefit anymore.
Combining the save areas simplifies the compiler code and results in better
ARM/Thumb2 codegen.
For example, previously we would generate code like:
push {r4, r5, r6, r7, lr}
add r7, sp, #12
stmdb sp!, {r8, r10, r11}
With this change, we combine the register saves and generate:
push {r4, r5, r6, r7, r8, r10, r11, lr}
add r7, sp, #12
rdar://8445635
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@114340 91177308-0d34-0410-b5e6-96231b3b80d8
2010-09-20 19:32:20 +00:00
|
|
|
if (AFI->isGPRCalleeSavedAreaFrame(FrameIndex))
|
|
|
|
Offset -= AFI->getGPRCalleeSavedAreaOffset();
|
2010-08-19 17:52:13 +00:00
|
|
|
else if (MF.getFrameInfo()->hasVarSizedObjects()) {
|
|
|
|
assert(SPAdj == 0 && hasFP(MF) && "Unexpected");
|
|
|
|
// There are alloca()'s in this function, must reference off the frame
|
2010-09-03 18:37:12 +00:00
|
|
|
// pointer or base pointer instead.
|
|
|
|
if (!hasBasePointer(MF)) {
|
|
|
|
FrameReg = getFrameRegister(MF);
|
|
|
|
Offset -= AFI->getFramePtrSpillOffset();
|
|
|
|
} else
|
|
|
|
FrameReg = BasePtr;
|
2010-08-19 17:52:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Special handling of dbg_value instructions.
|
|
|
|
if (MI.isDebugValue()) {
|
|
|
|
MI.getOperand(i). ChangeToRegister(FrameReg, false /*isDef*/);
|
|
|
|
MI.getOperand(i+1).ChangeToImmediate(Offset);
|
2010-08-26 23:32:16 +00:00
|
|
|
return;
|
2010-08-19 17:52:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Modify MI as necessary to handle as much of 'Offset' as possible
|
|
|
|
assert(AFI->isThumbFunction() &&
|
|
|
|
"This eliminateFrameIndex only supports Thumb1!");
|
|
|
|
if (rewriteFrameIndex(MI, i, FrameReg, Offset, TII))
|
2010-08-26 23:32:16 +00:00
|
|
|
return;
|
2009-06-27 12:16:40 +00:00
|
|
|
|
|
|
|
// If we get here, the immediate doesn't fit into the instruction. We folded
|
|
|
|
// as much as possible above, handle the rest, providing a register that is
|
|
|
|
// SP+LargeImm.
|
|
|
|
assert(Offset && "This code isn't needed if offset already handled!");
|
|
|
|
|
2010-08-19 17:52:13 +00:00
|
|
|
unsigned Opcode = MI.getOpcode();
|
|
|
|
const TargetInstrDesc &Desc = MI.getDesc();
|
|
|
|
|
2009-07-11 06:43:01 +00:00
|
|
|
// Remove predicate first.
|
|
|
|
int PIdx = MI.findFirstPredOperandIdx();
|
|
|
|
if (PIdx != -1)
|
|
|
|
removeOperands(MI, PIdx);
|
|
|
|
|
2009-06-27 12:16:40 +00:00
|
|
|
if (Desc.mayLoad()) {
|
|
|
|
// Use the destination register to materialize sp + offset.
|
|
|
|
unsigned TmpReg = MI.getOperand(0).getReg();
|
|
|
|
bool UseRR = false;
|
|
|
|
if (Opcode == ARM::tRestore) {
|
|
|
|
if (FrameReg == ARM::SP)
|
|
|
|
emitThumbRegPlusImmInReg(MBB, II, TmpReg, FrameReg,
|
|
|
|
Offset, false, TII, *this, dl);
|
|
|
|
else {
|
2009-07-16 09:20:10 +00:00
|
|
|
emitLoadConstPool(MBB, II, dl, TmpReg, 0, Offset);
|
2009-06-27 12:16:40 +00:00
|
|
|
UseRR = true;
|
|
|
|
}
|
2009-07-11 06:43:01 +00:00
|
|
|
} else {
|
2009-06-27 12:16:40 +00:00
|
|
|
emitThumbRegPlusImmediate(MBB, II, TmpReg, FrameReg, Offset, TII,
|
|
|
|
*this, dl);
|
2009-07-11 06:43:01 +00:00
|
|
|
}
|
|
|
|
|
2009-06-27 12:16:40 +00:00
|
|
|
MI.setDesc(TII.get(ARM::tLDR));
|
|
|
|
MI.getOperand(i).ChangeToRegister(TmpReg, false, false, true);
|
|
|
|
if (UseRR)
|
|
|
|
// Use [reg, reg] addrmode.
|
|
|
|
MI.addOperand(MachineOperand::CreateReg(FrameReg, false));
|
|
|
|
else // tLDR has an extra register operand.
|
|
|
|
MI.addOperand(MachineOperand::CreateReg(0, false));
|
|
|
|
} else if (Desc.mayStore()) {
|
2009-10-07 17:12:56 +00:00
|
|
|
VReg = MF.getRegInfo().createVirtualRegister(ARM::tGPRRegisterClass);
|
Start of revamping the register scavenging in PEI. ARM Thumb1 is the driving
interest for this, as it currently reserves a register rather than using
the scavenger for matierializing constants as needed.
Instead of scavenging registers on the fly while eliminating frame indices,
new virtual registers are created, and then a scavenged collectively in a
post-pass over the function. This isolates the bits that need to interact
with the scavenger, and sets the stage for more intelligent use, and reuse,
of scavenged registers.
For the time being, this is disabled by default. Once the bugs are worked out,
the current scavenging calls in replaceFrameIndices() will be removed and
the post-pass scavenging will be the default. Until then,
-enable-frame-index-scavenging enables the new code. Currently, only the
Thumb1 back end is set up to use it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@82734 91177308-0d34-0410-b5e6-96231b3b80d8
2009-09-24 23:52:18 +00:00
|
|
|
bool UseRR = false;
|
2009-10-07 17:12:56 +00:00
|
|
|
|
Start of revamping the register scavenging in PEI. ARM Thumb1 is the driving
interest for this, as it currently reserves a register rather than using
the scavenger for matierializing constants as needed.
Instead of scavenging registers on the fly while eliminating frame indices,
new virtual registers are created, and then a scavenged collectively in a
post-pass over the function. This isolates the bits that need to interact
with the scavenger, and sets the stage for more intelligent use, and reuse,
of scavenged registers.
For the time being, this is disabled by default. Once the bugs are worked out,
the current scavenging calls in replaceFrameIndices() will be removed and
the post-pass scavenging will be the default. Until then,
-enable-frame-index-scavenging enables the new code. Currently, only the
Thumb1 back end is set up to use it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@82734 91177308-0d34-0410-b5e6-96231b3b80d8
2009-09-24 23:52:18 +00:00
|
|
|
if (Opcode == ARM::tSpill) {
|
|
|
|
if (FrameReg == ARM::SP)
|
2009-10-07 17:12:56 +00:00
|
|
|
emitThumbRegPlusImmInReg(MBB, II, VReg, FrameReg,
|
Start of revamping the register scavenging in PEI. ARM Thumb1 is the driving
interest for this, as it currently reserves a register rather than using
the scavenger for matierializing constants as needed.
Instead of scavenging registers on the fly while eliminating frame indices,
new virtual registers are created, and then a scavenged collectively in a
post-pass over the function. This isolates the bits that need to interact
with the scavenger, and sets the stage for more intelligent use, and reuse,
of scavenged registers.
For the time being, this is disabled by default. Once the bugs are worked out,
the current scavenging calls in replaceFrameIndices() will be removed and
the post-pass scavenging will be the default. Until then,
-enable-frame-index-scavenging enables the new code. Currently, only the
Thumb1 back end is set up to use it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@82734 91177308-0d34-0410-b5e6-96231b3b80d8
2009-09-24 23:52:18 +00:00
|
|
|
Offset, false, TII, *this, dl);
|
|
|
|
else {
|
2009-10-07 17:12:56 +00:00
|
|
|
emitLoadConstPool(MBB, II, dl, VReg, 0, Offset);
|
Start of revamping the register scavenging in PEI. ARM Thumb1 is the driving
interest for this, as it currently reserves a register rather than using
the scavenger for matierializing constants as needed.
Instead of scavenging registers on the fly while eliminating frame indices,
new virtual registers are created, and then a scavenged collectively in a
post-pass over the function. This isolates the bits that need to interact
with the scavenger, and sets the stage for more intelligent use, and reuse,
of scavenged registers.
For the time being, this is disabled by default. Once the bugs are worked out,
the current scavenging calls in replaceFrameIndices() will be removed and
the post-pass scavenging will be the default. Until then,
-enable-frame-index-scavenging enables the new code. Currently, only the
Thumb1 back end is set up to use it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@82734 91177308-0d34-0410-b5e6-96231b3b80d8
2009-09-24 23:52:18 +00:00
|
|
|
UseRR = true;
|
|
|
|
}
|
|
|
|
} else
|
2009-10-07 17:12:56 +00:00
|
|
|
emitThumbRegPlusImmediate(MBB, II, VReg, FrameReg, Offset, TII,
|
Start of revamping the register scavenging in PEI. ARM Thumb1 is the driving
interest for this, as it currently reserves a register rather than using
the scavenger for matierializing constants as needed.
Instead of scavenging registers on the fly while eliminating frame indices,
new virtual registers are created, and then a scavenged collectively in a
post-pass over the function. This isolates the bits that need to interact
with the scavenger, and sets the stage for more intelligent use, and reuse,
of scavenged registers.
For the time being, this is disabled by default. Once the bugs are worked out,
the current scavenging calls in replaceFrameIndices() will be removed and
the post-pass scavenging will be the default. Until then,
-enable-frame-index-scavenging enables the new code. Currently, only the
Thumb1 back end is set up to use it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@82734 91177308-0d34-0410-b5e6-96231b3b80d8
2009-09-24 23:52:18 +00:00
|
|
|
*this, dl);
|
|
|
|
MI.setDesc(TII.get(ARM::tSTR));
|
2009-10-07 17:12:56 +00:00
|
|
|
MI.getOperand(i).ChangeToRegister(VReg, false, false, true);
|
Start of revamping the register scavenging in PEI. ARM Thumb1 is the driving
interest for this, as it currently reserves a register rather than using
the scavenger for matierializing constants as needed.
Instead of scavenging registers on the fly while eliminating frame indices,
new virtual registers are created, and then a scavenged collectively in a
post-pass over the function. This isolates the bits that need to interact
with the scavenger, and sets the stage for more intelligent use, and reuse,
of scavenged registers.
For the time being, this is disabled by default. Once the bugs are worked out,
the current scavenging calls in replaceFrameIndices() will be removed and
the post-pass scavenging will be the default. Until then,
-enable-frame-index-scavenging enables the new code. Currently, only the
Thumb1 back end is set up to use it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@82734 91177308-0d34-0410-b5e6-96231b3b80d8
2009-09-24 23:52:18 +00:00
|
|
|
if (UseRR) // Use [reg, reg] addrmode.
|
|
|
|
MI.addOperand(MachineOperand::CreateReg(FrameReg, false));
|
|
|
|
else // tSTR has an extra register operand.
|
|
|
|
MI.addOperand(MachineOperand::CreateReg(0, false));
|
2009-06-27 12:16:40 +00:00
|
|
|
} else
|
|
|
|
assert(false && "Unexpected opcode!");
|
2009-07-11 06:43:01 +00:00
|
|
|
|
|
|
|
// Add predicate back if it's needed.
|
|
|
|
if (MI.getDesc().isPredicable()) {
|
|
|
|
MachineInstrBuilder MIB(&MI);
|
|
|
|
AddDefaultPred(MIB);
|
|
|
|
}
|
2009-06-27 12:16:40 +00:00
|
|
|
}
|
|
|
|
|
2009-07-02 22:18:33 +00:00
|
|
|
void Thumb1RegisterInfo::emitPrologue(MachineFunction &MF) const {
|
2009-06-27 12:16:40 +00:00
|
|
|
MachineBasicBlock &MBB = MF.front();
|
|
|
|
MachineBasicBlock::iterator MBBI = MBB.begin();
|
|
|
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
|
|
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
|
|
|
unsigned VARegSaveSize = AFI->getVarArgsRegSaveSize();
|
|
|
|
unsigned NumBytes = MFI->getStackSize();
|
|
|
|
const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
|
2010-04-02 20:16:16 +00:00
|
|
|
DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
2009-06-27 12:16:40 +00:00
|
|
|
|
|
|
|
// Thumb add/sub sp, imm8 instructions implicitly multiply the offset by 4.
|
|
|
|
NumBytes = (NumBytes + 3) & ~3;
|
|
|
|
MFI->setStackSize(NumBytes);
|
|
|
|
|
|
|
|
// Determine the sizes of each callee-save spill areas and record which frame
|
|
|
|
// belongs to which callee-save spill areas.
|
Simplify ARM callee-saved register handling by removing the distinction
between the high and low registers for prologue/epilogue code. This was
a Darwin-only thing that wasn't providing a realistic benefit anymore.
Combining the save areas simplifies the compiler code and results in better
ARM/Thumb2 codegen.
For example, previously we would generate code like:
push {r4, r5, r6, r7, lr}
add r7, sp, #12
stmdb sp!, {r8, r10, r11}
With this change, we combine the register saves and generate:
push {r4, r5, r6, r7, r8, r10, r11, lr}
add r7, sp, #12
rdar://8445635
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@114340 91177308-0d34-0410-b5e6-96231b3b80d8
2010-09-20 19:32:20 +00:00
|
|
|
unsigned GPRCSSize = 0, DPRCSSize = 0;
|
2009-06-27 12:16:40 +00:00
|
|
|
int FramePtrSpillFI = 0;
|
|
|
|
|
|
|
|
if (VARegSaveSize)
|
2009-06-27 12:59:03 +00:00
|
|
|
emitSPUpdate(MBB, MBBI, TII, dl, *this, -VARegSaveSize);
|
2009-06-27 12:16:40 +00:00
|
|
|
|
|
|
|
if (!AFI->hasStackFrame()) {
|
|
|
|
if (NumBytes != 0)
|
2009-06-27 12:59:03 +00:00
|
|
|
emitSPUpdate(MBB, MBBI, TII, dl, *this, -NumBytes);
|
2009-06-27 12:16:40 +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) {
|
|
|
|
case ARM::R4:
|
|
|
|
case ARM::R5:
|
|
|
|
case ARM::R6:
|
|
|
|
case ARM::R7:
|
|
|
|
case ARM::R8:
|
|
|
|
case ARM::R9:
|
|
|
|
case ARM::R10:
|
|
|
|
case ARM::R11:
|
Simplify ARM callee-saved register handling by removing the distinction
between the high and low registers for prologue/epilogue code. This was
a Darwin-only thing that wasn't providing a realistic benefit anymore.
Combining the save areas simplifies the compiler code and results in better
ARM/Thumb2 codegen.
For example, previously we would generate code like:
push {r4, r5, r6, r7, lr}
add r7, sp, #12
stmdb sp!, {r8, r10, r11}
With this change, we combine the register saves and generate:
push {r4, r5, r6, r7, r8, r10, r11, lr}
add r7, sp, #12
rdar://8445635
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@114340 91177308-0d34-0410-b5e6-96231b3b80d8
2010-09-20 19:32:20 +00:00
|
|
|
case ARM::LR:
|
2009-06-27 12:16:40 +00:00
|
|
|
if (Reg == FramePtr)
|
|
|
|
FramePtrSpillFI = FI;
|
Simplify ARM callee-saved register handling by removing the distinction
between the high and low registers for prologue/epilogue code. This was
a Darwin-only thing that wasn't providing a realistic benefit anymore.
Combining the save areas simplifies the compiler code and results in better
ARM/Thumb2 codegen.
For example, previously we would generate code like:
push {r4, r5, r6, r7, lr}
add r7, sp, #12
stmdb sp!, {r8, r10, r11}
With this change, we combine the register saves and generate:
push {r4, r5, r6, r7, r8, r10, r11, lr}
add r7, sp, #12
rdar://8445635
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@114340 91177308-0d34-0410-b5e6-96231b3b80d8
2010-09-20 19:32:20 +00:00
|
|
|
AFI->addGPRCalleeSavedAreaFrame(FI);
|
|
|
|
GPRCSSize += 4;
|
2009-06-27 12:16:40 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
AFI->addDPRCalleeSavedAreaFrame(FI);
|
|
|
|
DPRCSSize += 8;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tPUSH) {
|
|
|
|
++MBBI;
|
|
|
|
if (MBBI != MBB.end())
|
|
|
|
dl = MBBI->getDebugLoc();
|
|
|
|
}
|
|
|
|
|
2010-08-10 19:30:19 +00:00
|
|
|
// Adjust FP so it point to the stack slot that contains the previous FP.
|
|
|
|
if (hasFP(MF)) {
|
2009-09-06 08:33:48 +00:00
|
|
|
BuildMI(MBB, MBBI, dl, TII.get(ARM::tADDrSPi), FramePtr)
|
2009-06-27 12:16:40 +00:00
|
|
|
.addFrameIndex(FramePtrSpillFI).addImm(0);
|
2010-08-10 19:30:19 +00:00
|
|
|
AFI->setShouldRestoreSPFromFP(true);
|
2009-06-27 12:16:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Determine starting offsets of spill areas.
|
Simplify ARM callee-saved register handling by removing the distinction
between the high and low registers for prologue/epilogue code. This was
a Darwin-only thing that wasn't providing a realistic benefit anymore.
Combining the save areas simplifies the compiler code and results in better
ARM/Thumb2 codegen.
For example, previously we would generate code like:
push {r4, r5, r6, r7, lr}
add r7, sp, #12
stmdb sp!, {r8, r10, r11}
With this change, we combine the register saves and generate:
push {r4, r5, r6, r7, r8, r10, r11, lr}
add r7, sp, #12
rdar://8445635
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@114340 91177308-0d34-0410-b5e6-96231b3b80d8
2010-09-20 19:32:20 +00:00
|
|
|
unsigned DPRCSOffset = NumBytes - (GPRCSSize + DPRCSSize);
|
|
|
|
unsigned GPRCSOffset = DPRCSOffset + DPRCSSize;
|
2009-06-27 12:16:40 +00:00
|
|
|
AFI->setFramePtrSpillOffset(MFI->getObjectOffset(FramePtrSpillFI) + NumBytes);
|
Simplify ARM callee-saved register handling by removing the distinction
between the high and low registers for prologue/epilogue code. This was
a Darwin-only thing that wasn't providing a realistic benefit anymore.
Combining the save areas simplifies the compiler code and results in better
ARM/Thumb2 codegen.
For example, previously we would generate code like:
push {r4, r5, r6, r7, lr}
add r7, sp, #12
stmdb sp!, {r8, r10, r11}
With this change, we combine the register saves and generate:
push {r4, r5, r6, r7, r8, r10, r11, lr}
add r7, sp, #12
rdar://8445635
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@114340 91177308-0d34-0410-b5e6-96231b3b80d8
2010-09-20 19:32:20 +00:00
|
|
|
AFI->setGPRCalleeSavedAreaOffset(GPRCSOffset);
|
2009-06-27 12:16:40 +00:00
|
|
|
AFI->setDPRCalleeSavedAreaOffset(DPRCSOffset);
|
|
|
|
|
|
|
|
NumBytes = DPRCSOffset;
|
|
|
|
if (NumBytes) {
|
|
|
|
// Insert it after all the callee-save spills.
|
2009-06-27 12:59:03 +00:00
|
|
|
emitSPUpdate(MBB, MBBI, TII, dl, *this, -NumBytes);
|
2009-06-27 12:16:40 +00:00
|
|
|
}
|
|
|
|
|
2010-08-10 19:30:19 +00:00
|
|
|
if (STI.isTargetELF() && hasFP(MF))
|
2009-06-27 12:16:40 +00:00
|
|
|
MFI->setOffsetAdjustment(MFI->getOffsetAdjustment() -
|
|
|
|
AFI->getFramePtrSpillOffset());
|
|
|
|
|
Simplify ARM callee-saved register handling by removing the distinction
between the high and low registers for prologue/epilogue code. This was
a Darwin-only thing that wasn't providing a realistic benefit anymore.
Combining the save areas simplifies the compiler code and results in better
ARM/Thumb2 codegen.
For example, previously we would generate code like:
push {r4, r5, r6, r7, lr}
add r7, sp, #12
stmdb sp!, {r8, r10, r11}
With this change, we combine the register saves and generate:
push {r4, r5, r6, r7, r8, r10, r11, lr}
add r7, sp, #12
rdar://8445635
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@114340 91177308-0d34-0410-b5e6-96231b3b80d8
2010-09-20 19:32:20 +00:00
|
|
|
AFI->setGPRCalleeSavedAreaSize(GPRCSSize);
|
2009-06-27 12:16:40 +00:00
|
|
|
AFI->setDPRCalleeSavedAreaSize(DPRCSSize);
|
2010-09-03 18:37:12 +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 (hasBasePointer(MF))
|
|
|
|
BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr), BasePtr).addReg(ARM::SP);
|
2009-06-27 12:16:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool isCalleeSavedRegister(unsigned Reg, const unsigned *CSRegs) {
|
|
|
|
for (unsigned i = 0; CSRegs[i]; ++i)
|
|
|
|
if (Reg == CSRegs[i])
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool isCSRestore(MachineInstr *MI, const unsigned *CSRegs) {
|
2010-03-06 03:28:39 +00:00
|
|
|
if (MI->getOpcode() == ARM::tRestore &&
|
|
|
|
MI->getOperand(1).isFI() &&
|
|
|
|
isCalleeSavedRegister(MI->getOperand(0).getReg(), CSRegs))
|
|
|
|
return true;
|
|
|
|
else if (MI->getOpcode() == ARM::tPOP) {
|
2010-03-13 01:08:20 +00:00
|
|
|
// The first two operands are predicates. The last two are
|
2010-03-06 03:28:39 +00:00
|
|
|
// imp-def and imp-use of SP. Check everything in between.
|
2010-03-13 01:08:20 +00:00
|
|
|
for (int i = 2, e = MI->getNumOperands() - 2; i != e; ++i)
|
2010-03-06 03:28:39 +00:00
|
|
|
if (!isCalleeSavedRegister(MI->getOperand(i).getReg(), CSRegs))
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2009-06-27 12:16:40 +00:00
|
|
|
}
|
|
|
|
|
2009-07-02 22:18:33 +00:00
|
|
|
void Thumb1RegisterInfo::emitEpilogue(MachineFunction &MF,
|
|
|
|
MachineBasicBlock &MBB) const {
|
2009-06-27 12:16:40 +00:00
|
|
|
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
|
|
|
assert((MBBI->getOpcode() == ARM::tBX_RET ||
|
|
|
|
MBBI->getOpcode() == ARM::tPOP_RET) &&
|
|
|
|
"Can only insert epilog into returning blocks");
|
|
|
|
DebugLoc dl = MBBI->getDebugLoc();
|
|
|
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
|
|
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
|
|
|
unsigned VARegSaveSize = AFI->getVarArgsRegSaveSize();
|
|
|
|
int NumBytes = (int)MFI->getStackSize();
|
2010-03-06 03:28:39 +00:00
|
|
|
const unsigned *CSRegs = getCalleeSavedRegs();
|
2009-06-27 12:16:40 +00:00
|
|
|
|
|
|
|
if (!AFI->hasStackFrame()) {
|
|
|
|
if (NumBytes != 0)
|
2009-06-27 12:59:03 +00:00
|
|
|
emitSPUpdate(MBB, MBBI, TII, dl, *this, NumBytes);
|
2009-06-27 12:16:40 +00:00
|
|
|
} else {
|
2009-11-09 00:11:35 +00:00
|
|
|
// Unwind MBBI to point to first LDR / VLDRD.
|
2009-06-27 12:16:40 +00:00
|
|
|
if (MBBI != MBB.begin()) {
|
|
|
|
do
|
|
|
|
--MBBI;
|
|
|
|
while (MBBI != MBB.begin() && isCSRestore(MBBI, CSRegs));
|
|
|
|
if (!isCSRestore(MBBI, CSRegs))
|
|
|
|
++MBBI;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Move SP to start of FP callee save spill area.
|
Simplify ARM callee-saved register handling by removing the distinction
between the high and low registers for prologue/epilogue code. This was
a Darwin-only thing that wasn't providing a realistic benefit anymore.
Combining the save areas simplifies the compiler code and results in better
ARM/Thumb2 codegen.
For example, previously we would generate code like:
push {r4, r5, r6, r7, lr}
add r7, sp, #12
stmdb sp!, {r8, r10, r11}
With this change, we combine the register saves and generate:
push {r4, r5, r6, r7, r8, r10, r11, lr}
add r7, sp, #12
rdar://8445635
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@114340 91177308-0d34-0410-b5e6-96231b3b80d8
2010-09-20 19:32:20 +00:00
|
|
|
NumBytes -= (AFI->getGPRCalleeSavedAreaSize() +
|
2009-06-27 12:16:40 +00:00
|
|
|
AFI->getDPRCalleeSavedAreaSize());
|
|
|
|
|
2010-08-10 19:30:19 +00:00
|
|
|
if (AFI->shouldRestoreSPFromFP()) {
|
2009-06-27 12:16:40 +00:00
|
|
|
NumBytes = AFI->getFramePtrSpillOffset() - NumBytes;
|
|
|
|
// Reset SP based on frame pointer only if the stack frame extends beyond
|
|
|
|
// frame pointer stack slot or target is ELF and the function has FP.
|
|
|
|
if (NumBytes)
|
|
|
|
emitThumbRegPlusImmediate(MBB, MBBI, ARM::SP, FramePtr, -NumBytes,
|
|
|
|
TII, *this, dl);
|
|
|
|
else
|
2009-07-26 23:59:01 +00:00
|
|
|
BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVtgpr2gpr), ARM::SP)
|
2009-06-27 12:16:40 +00:00
|
|
|
.addReg(FramePtr);
|
|
|
|
} else {
|
|
|
|
if (MBBI->getOpcode() == ARM::tBX_RET &&
|
|
|
|
&MBB.front() != MBBI &&
|
|
|
|
prior(MBBI)->getOpcode() == ARM::tPOP) {
|
|
|
|
MachineBasicBlock::iterator PMBBI = prior(MBBI);
|
2009-06-27 12:59:03 +00:00
|
|
|
emitSPUpdate(MBB, PMBBI, TII, dl, *this, NumBytes);
|
2009-06-27 12:16:40 +00:00
|
|
|
} else
|
2009-06-27 12:59:03 +00:00
|
|
|
emitSPUpdate(MBB, MBBI, TII, dl, *this, NumBytes);
|
2009-06-27 12:16:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VARegSaveSize) {
|
2010-03-10 19:59:47 +00:00
|
|
|
// Unlike T2 and ARM mode, the T1 pop instruction cannot restore
|
|
|
|
// to LR, and we can't pop the value directly to the PC since
|
|
|
|
// we need to update the SP after popping the value. Therefore, we
|
|
|
|
// pop the old LR into R3 as a temporary.
|
|
|
|
|
2010-03-06 03:28:39 +00:00
|
|
|
// Move back past the callee-saved register restoration
|
|
|
|
while (MBBI != MBB.end() && isCSRestore(MBBI, CSRegs))
|
|
|
|
++MBBI;
|
2009-06-27 12:16:40 +00:00
|
|
|
// Epilogue for vararg functions: pop LR to R3 and branch off it.
|
Start of revamping the register scavenging in PEI. ARM Thumb1 is the driving
interest for this, as it currently reserves a register rather than using
the scavenger for matierializing constants as needed.
Instead of scavenging registers on the fly while eliminating frame indices,
new virtual registers are created, and then a scavenged collectively in a
post-pass over the function. This isolates the bits that need to interact
with the scavenger, and sets the stage for more intelligent use, and reuse,
of scavenged registers.
For the time being, this is disabled by default. Once the bugs are worked out,
the current scavenging calls in replaceFrameIndices() will be removed and
the post-pass scavenging will be the default. Until then,
-enable-frame-index-scavenging enables the new code. Currently, only the
Thumb1 back end is set up to use it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@82734 91177308-0d34-0410-b5e6-96231b3b80d8
2009-09-24 23:52:18 +00:00
|
|
|
AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tPOP)))
|
|
|
|
.addReg(ARM::R3, RegState::Define);
|
2009-06-27 12:16:40 +00:00
|
|
|
|
2009-06-27 12:59:03 +00:00
|
|
|
emitSPUpdate(MBB, MBBI, TII, dl, *this, VARegSaveSize);
|
2009-06-27 12:16:40 +00:00
|
|
|
|
Start of revamping the register scavenging in PEI. ARM Thumb1 is the driving
interest for this, as it currently reserves a register rather than using
the scavenger for matierializing constants as needed.
Instead of scavenging registers on the fly while eliminating frame indices,
new virtual registers are created, and then a scavenged collectively in a
post-pass over the function. This isolates the bits that need to interact
with the scavenger, and sets the stage for more intelligent use, and reuse,
of scavenged registers.
For the time being, this is disabled by default. Once the bugs are worked out,
the current scavenging calls in replaceFrameIndices() will be removed and
the post-pass scavenging will be the default. Until then,
-enable-frame-index-scavenging enables the new code. Currently, only the
Thumb1 back end is set up to use it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@82734 91177308-0d34-0410-b5e6-96231b3b80d8
2009-09-24 23:52:18 +00:00
|
|
|
BuildMI(MBB, MBBI, dl, TII.get(ARM::tBX_RET_vararg))
|
|
|
|
.addReg(ARM::R3, RegState::Kill);
|
2010-03-06 03:28:39 +00:00
|
|
|
// erase the old tBX_RET instruction
|
2009-06-27 12:16:40 +00:00
|
|
|
MBB.erase(MBBI);
|
|
|
|
}
|
|
|
|
}
|