33 cl::desc(
"Align ARM NEON spills in prolog and epilog"));
37 unsigned NumAlignedDPRCS2Regs);
70 if (CFSize >= ((1 << 12) - 1) / 2)
86 for (
unsigned i = 0; CSRegs[i]; ++i)
94 const uint16_t *CSRegs) {
104 if ((MI->
getOpcode() == ARM::LDR_POST_IMM ||
117 unsigned SrcReg,
int NumBytes,
120 unsigned PredReg = 0) {
123 Pred, PredReg, TII, MIFlags);
126 Pred, PredReg, TII, MIFlags);
134 unsigned PredReg = 0) {
136 MIFlags, Pred, PredReg);
149 "This emitPrologue does not support Thumb1!");
156 unsigned FramePtr = RegInfo->getFrameRegister(MF);
160 unsigned GPRCS1Size = 0, GPRCS2Size = 0, DPRCSSize = 0;
161 int FramePtrSpillFI = 0;
171 emitSPUpdate(isARM, MBB, MBBI, dl, TII, -ArgRegsSaveSize,
181 for (
unsigned i = 0, e = CSI.size(); i != e; ++i) {
182 unsigned Reg = CSI[i].getReg();
183 int FI = CSI[i].getFrameIdx();
195 FramePtrSpillFI = FI;
204 FramePtrSpillFI = FI;
222 FramePtrPush = LastPush = MBBI++;
225 bool HasFP =
hasFP(MF);
226 unsigned DPRCSOffset = NumBytes - (GPRCS1Size + GPRCS2Size + DPRCSSize);
227 unsigned GPRCS2Offset = DPRCSOffset + DPRCSSize;
228 unsigned GPRCS1Offset = GPRCS2Offset + GPRCS2Size;
229 int FramePtrOffsetInPush = 0;
231 FramePtrOffsetInPush = MFI->
getObjectOffset(FramePtrSpillFI) + GPRCS1Size;
240 if (GPRCS2Size > 0) {
249 while (MBBI->getOpcode() == ARM::VSTMDDB_UPD)
262 NumBytes = DPRCSOffset;
267 FramePtrOffsetInPush += NumBytes;
292 FramePtr, ARM::SP, FramePtrOffsetInPush,
314 TII.get(ARM::BICri), ARM::SP)
327 TII.get(ARM::t2BICri),
ARM::R4)
342 if (RegInfo->hasBasePointer(MF)) {
345 TII.get(ARM::MOVr), RegInfo->getBaseRegister())
350 RegInfo->getBaseRegister())
364 assert(MBBI->isReturn() &&
"Can only insert epilog into returning blocks");
365 unsigned RetOpcode = MBBI->getOpcode();
373 "This emitEpilogue does not support Thumb1!");
379 unsigned FramePtr = RegInfo->getFrameRegister(MF);
393 const uint16_t *CSRegs = RegInfo->getCalleeSavedRegs(&MF);
394 if (MBBI != MBB.
begin()) {
427 "No scratch register to restore SP from FP!");
437 BuildMI(MBB, MBBI, dl, TII.get(ARM::MOVr), ARM::SP)
452 while (MBBI->getOpcode() == ARM::VLDMDIA_UPD)
459 if (RetOpcode == ARM::TCRETURNdi || RetOpcode == ARM::TCRETURNri) {
465 if (RetOpcode == ARM::TCRETURNdi) {
481 }
else if (RetOpcode == ARM::TCRETURNri) {
483 TII.get(
STI.
isThumb() ? ARM::tTAILJMPr : ARM::TAILJMPr)).
488 for (
unsigned i = 1, e = MBBI->getNumOperands(); i != e; ++i)
497 emitSPUpdate(isARM, MBB, MBBI, dl, TII, ArgRegsSaveSize);
506 unsigned &FrameReg)
const {
512 int FI,
unsigned &FrameReg,
532 assert (
hasFP(MF) &&
"dynamic stack realignment without a FP!");
536 }
else if (hasMovingSP) {
538 "VLAs and dynamic stack alignment, but missing base pointer!");
551 }
else if (hasMovingSP) {
557 if (FPOffset >= -255 && FPOffset < 0) {
566 if (Offset >= 0 && (Offset & 3) == 0 && Offset <= 1020)
570 if (FPOffset >= -255 && FPOffset < 0) {
574 }
else if (Offset > (FPOffset < 0 ? -FPOffset : FPOffset)) {
594 const std::vector<CalleeSavedInfo> &CSI,
595 unsigned StmOpc,
unsigned StrOpc,
597 bool(*
Func)(
unsigned,
bool),
598 unsigned NumAlignedDPRCS2Regs,
599 unsigned MIFlags)
const {
604 if (MI != MBB.
end()) DL = MI->getDebugLoc();
607 unsigned i = CSI.
size();
609 unsigned LastReg = 0;
610 for (; i != 0; --i) {
611 unsigned Reg = CSI[i-1].getReg();
623 if (Reg == ARM::LR) {
635 if (NoGap && LastReg && LastReg != Reg-1)
638 Regs.
push_back(std::make_pair(Reg, isKill));
643 if (Regs.
size() > 1 || StrOpc== 0) {
647 for (
unsigned i = 0, e = Regs.
size(); i < e; ++i)
649 }
else if (Regs.
size() == 1) {
663 const std::vector<CalleeSavedInfo> &CSI,
664 unsigned LdmOpc,
unsigned LdrOpc,
665 bool isVarArg,
bool NoGap,
666 bool(*
Func)(
unsigned,
bool),
667 unsigned NumAlignedDPRCS2Regs)
const {
672 unsigned RetOpcode = MI->getOpcode();
673 bool isTailCall = (RetOpcode == ARM::TCRETURNdi ||
674 RetOpcode == ARM::TCRETURNri);
676 RetOpcode == ARM::SUBS_PC_LR || RetOpcode == ARM::t2SUBS_PC_LR;
679 unsigned i = CSI.
size();
681 unsigned LastReg = 0;
682 bool DeleteRet =
false;
683 for (; i != 0; --i) {
684 unsigned Reg = CSI[i-1].getReg();
691 if (Reg == ARM::LR && !isTailCall && !isVarArg && !isInterrupt &&
702 if (NoGap && LastReg && LastReg != Reg-1)
711 if (Regs.
size() > 1 || LdrOpc == 0) {
715 for (
unsigned i = 0, e = Regs.
size(); i < e; ++i)
722 }
else if (Regs.
size() == 1) {
725 if (Regs[0] == ARM::PC)
728 BuildMI(MBB, MI, DL, TII.
get(LdrOpc), Regs[0])
733 if (LdrOpc == ARM::LDR_POST_REG || LdrOpc == ARM::LDR_POST_IMM) {
749 unsigned NumAlignedDPRCS2Regs,
750 const std::vector<CalleeSavedInfo> &CSI,
761 for (
unsigned i = 0, e = CSI.size(); i != e; ++i) {
762 unsigned DNum = CSI[i].getReg() -
ARM::D8;
765 int FI = CSI[i].getFrameIdx();
793 unsigned Opc = isThumb ? ARM::t2SUBri : ARM::SUBri;
796 .
addImm(8 * NumAlignedDPRCS2Regs)));
799 Opc = isThumb ? ARM::t2BICri : ARM::BICri;
809 Opc = isThumb ? ARM::tMOVr : ARM::MOVr;
822 if (NumAlignedDPRCS2Regs >= 6) {
832 NumAlignedDPRCS2Regs -= 4;
837 unsigned R4BaseReg = NextReg;
840 if (NumAlignedDPRCS2Regs >= 4) {
848 NumAlignedDPRCS2Regs -= 4;
852 if (NumAlignedDPRCS2Regs >= 2) {
859 NumAlignedDPRCS2Regs -= 2;
863 if (NumAlignedDPRCS2Regs) {
879 unsigned NumAlignedDPRCS2Regs) {
884 assert(MI->mayStore() &&
"Expecting spill instruction");
887 switch(NumAlignedDPRCS2Regs) {
890 assert(MI->mayStore() &&
"Expecting spill instruction");
893 assert(MI->mayStore() &&
"Expecting spill instruction");
897 assert(MI->killsRegister(
ARM::R4) &&
"Missed kill flag");
908 unsigned NumAlignedDPRCS2Regs,
909 const std::vector<CalleeSavedInfo> &CSI,
918 for (
unsigned i = 0, e = CSI.size(); i != e; ++i)
920 D8SpillFI = CSI[i].getFrameIdx();
932 unsigned Opc = isThumb ? ARM::t2ADDri : ARM::ADDri;
934 .addFrameIndex(D8SpillFI).
addImm(0)));
940 if (NumAlignedDPRCS2Regs >= 6) {
948 NumAlignedDPRCS2Regs -= 4;
953 unsigned R4BaseReg = NextReg;
956 if (NumAlignedDPRCS2Regs >= 4) {
963 NumAlignedDPRCS2Regs -= 4;
967 if (NumAlignedDPRCS2Regs >= 2) {
973 NumAlignedDPRCS2Regs -= 2;
977 if (NumAlignedDPRCS2Regs)
987 const std::vector<CalleeSavedInfo> &CSI,
995 unsigned PushOpc = AFI->
isThumbFunction() ? ARM::t2STMDB_UPD : ARM::STMDB_UPD;
997 ARM::t2STR_PRE : ARM::STR_PRE_IMM;
998 unsigned FltOpc = ARM::VSTMDDB_UPD;
1010 if (NumAlignedDPRCS2Regs)
1018 const std::vector<CalleeSavedInfo> &CSI,
1030 if (NumAlignedDPRCS2Regs)
1033 unsigned PopOpc = AFI->
isThumbFunction() ? ARM::t2LDMIA_UPD : ARM::LDMIA_UPD;
1034 unsigned LdrOpc = AFI->
isThumbFunction() ? ARM::t2LDR_POST :ARM::LDR_POST_IMM;
1035 unsigned FltOpc = ARM::VLDMDIA_UPD;
1037 NumAlignedDPRCS2Regs);
1038 emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg,
false,
1040 emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg,
false,
1049 unsigned FnSize = 0;
1051 MBBI != E; ++MBBI) {
1067 unsigned Limit = (1 << 12) - 1;
1071 for (
unsigned i = 0, e =
I->getNumOperands(); i != e; ++i) {
1072 if (!
I->getOperand(i).isFI())
continue;
1076 if (
I->getOpcode() == ARM::ADDri) {
1077 Limit = std::min(Limit, (1U << 8) - 1);
1085 Limit = std::min(Limit, (1U << 8) - 1);
1089 Limit = std::min(Limit, ((1U << 8) - 1) * 4);
1095 Limit = std::min(Limit, (1U << 8) - 1);
1147 unsigned NumSpills = 0;
1148 for (; NumSpills < 8; ++NumSpills)
1170 bool CanEliminateFrame =
true;
1171 bool CS1Spilled =
false;
1172 bool LRSpilled =
false;
1173 unsigned NumGPRSpills = 0;
1205 unsigned StackSize = MFI->estimateStackSize(MF);
1206 if (MFI->hasVarSizedObjects() || StackSize > 508)
1220 for (
unsigned i = 0; CSRegs[i]; ++i) {
1221 unsigned Reg = CSRegs[i];
1222 bool Spilled =
false;
1225 CanEliminateFrame =
false;
1228 if (!ARM::GPRRegClass.contains(Reg))
1246 case ARM::R0:
case ARM::R1:
1262 case ARM::R0:
case ARM::R1:
1276 bool ForceLRSpill =
false;
1282 if (FnSize >= (1 << 11)) {
1283 CanEliminateFrame =
false;
1284 ForceLRSpill =
true;
1304 (MFI->estimateStackSize(MF) +
1307 || MFI->hasVarSizedObjects()
1310 bool ExtraCSSpill =
false;
1316 if (!LRSpilled && CS1Spilled) {
1320 LRPos = std::find(UnspilledCS1GPRs.
begin(), UnspilledCS1GPRs.
end(),
1322 if (LRPos != UnspilledCS1GPRs.
end())
1323 UnspilledCS1GPRs.
erase(LRPos);
1325 ForceLRSpill =
false;
1326 ExtraCSSpill =
true;
1338 if (TargetAlign == 8 && (NumGPRSpills & 1)) {
1339 if (CS1Spilled && !UnspilledCS1GPRs.
empty()) {
1340 for (
unsigned i = 0, e = UnspilledCS1GPRs.
size(); i != e; ++i) {
1341 unsigned Reg = UnspilledCS1GPRs[i];
1347 ExtraCSSpill =
true;
1352 unsigned Reg = UnspilledCS2GPRs.
front();
1355 ExtraCSSpill =
true;
1364 if (BigStack && !ExtraCSSpill) {
1367 unsigned NumExtras = TargetAlign / 4;
1369 while (NumExtras && !UnspilledCS1GPRs.
empty()) {
1370 unsigned Reg = UnspilledCS1GPRs.
back();
1381 while (NumExtras && !UnspilledCS2GPRs.
empty()) {
1382 unsigned Reg = UnspilledCS2GPRs.
back();
1390 if (Extras.
size() && NumExtras == 0) {
1391 for (
unsigned i = 0, e = Extras.
size(); i != e; ++i) {
1412 void ARMFrameLowering::
1429 Amount = (Amount+Align-1)/Align*Align;
1433 "This eliminateCallFramePseudoInstr does not support Thumb1!");
1441 if (Opc == ARM::ADJCALLSTACKDOWN || Opc == ARM::tADJCALLSTACKDOWN) {
1449 assert(Opc == ARM::ADJCALLSTACKUP || Opc == ARM::tADJCALLSTACKUP);
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const std::vector< CalleeSavedInfo > &CSI, const TargetRegisterInfo *TRI) const
unsigned getFrameRegister(const MachineFunction &MF) const
unsigned getStackAlignment() const
void push_back(const T &Elt)
const MachineFunction * getParent() const
instr_iterator erase(instr_iterator I)
void setPhysRegUsed(unsigned Reg)
bool hasReservedCallFrame(const MachineFunction &MF) const
const GlobalValue * getGlobal() const
int getFrameIndexOffset(const MachineFunction &MF, int FI) const
static cl::opt< bool > SpillAlignedNEONRegs("align-neon-spills", cl::Hidden, cl::init(true), cl::desc("Align ARM NEON spills in prolog and epilog"))
unsigned getBaseRegister() const
void emitT2RegPlusImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, DebugLoc dl, unsigned DestReg, unsigned BaseReg, int NumBytes, ARMCC::CondCodes Pred, unsigned PredReg, const ARMBaseInstrInfo &TII, unsigned MIFlags=0)
int ResolveFrameIndexReference(const MachineFunction &MF, int FI, unsigned &FrameReg, int SPAdj) const
void addLiveIn(unsigned Reg)
bool isReturnAddressTaken() const
virtual unsigned GetInstSizeInBytes(const MachineInstr *MI) const
const char * getSymbolName() const
bool isThumbFunction() const
const Function * getFunction() const
void setGPRCalleeSavedArea2Offset(unsigned o)
bool hasAttribute(unsigned Index, Attribute::AttrKind Kind) const
Return true if the attribute exists at the given index.
CallingConv::ID getCallingConv() const
unsigned getDPRCalleeSavedAreaSize() const
unsigned getMaxAlignment() const
const std::vector< CalleeSavedInfo > & getCalleeSavedInfo() const
static bool isCSRestore(MachineInstr *MI, const ARMBaseInstrInfo &TII, const uint16_t *CSRegs)
uint64_t getStackSize() const
unsigned getNumAlignedDPRCS2Regs() const
static const MachineInstrBuilder & AddDefaultPred(const MachineInstrBuilder &MIB)
const HexagonInstrInfo * TII
virtual bool hasFP(const MachineFunction &MF) const =0
bool DisableFramePointerElim(const MachineFunction &MF) const
static void checkNumAlignedDPRCS2Regs(MachineFunction &MF)
bool tryFoldSPUpdateIntoPushPop(MachineFunction &MF, MachineInstr *MI, unsigned NumBytes)
Abstract Stack Frame Information.
bool isFrameAddressTaken() const
bool isFixedObjectIndex(int ObjectIdx) const
void setDPRCalleeSavedAreaOffset(unsigned o)
const MachineInstrBuilder & addImm(int64_t Val) const
unsigned getNumOperands() const
void setFramePtrSpillOffset(unsigned o)
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
const MachineBasicBlock & front() const
bool isLiveIn(unsigned Reg) const
bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const
int getOffsetAdjustment() const
void setShouldRestoreSPFromFP(bool s)
unsigned getMatchingSuperReg(unsigned Reg, unsigned SubIdx, const TargetRegisterClass *RC) const
bool canSimplifyCallFramePseudos(const MachineFunction &MF) const
void setLRIsSpilledForFarJump(bool s)
iterator getLastNonDebugInstr()
static bool isARMArea1Register(unsigned Reg, bool isIOS)
bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const std::vector< CalleeSavedInfo > &CSI, const TargetRegisterInfo *TRI) const
bool isThumb1OnlyFunction() const
unsigned getKillRegState(bool B)
unsigned getDefRegState(bool B)
bundle_iterator< MachineInstr, instr_iterator > iterator
void emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, DebugLoc dl, const TargetInstrInfo &TII, unsigned ScratchReg, int64_t NumBytes, MachineInstr::MIFlag MIFlags=MachineInstr::NoFlags)
static MachineBasicBlock::iterator skipAlignedDPRCS2Spills(MachineBasicBlock::iterator MI, unsigned NumAlignedDPRCS2Regs)
initializer< Ty > init(const Ty &Val)
unsigned getTargetFlags() const
static unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO, unsigned IdxMode=0)
bool hasStackFrame() const
virtual bool needsStackRealignment(const MachineFunction &MF) const
unsigned getAlignment() const
bool isReserved(unsigned PhysReg) const
const MachineOperand & getOperand(unsigned i) const
static bool isCalleeSavedRegister(unsigned Reg, const uint16_t *CSRegs)
unsigned getFramePtrSpillOffset() const
bool isSymbol() const
isSymbol - Tests if this is a MO_ExternalSymbol operand.
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
void setGPRCalleeSavedArea2Size(unsigned s)
int64_t getOffset() const
static void emitAlignedDPRCS2Restores(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned NumAlignedDPRCS2Regs, const std::vector< CalleeSavedInfo > &CSI, const TargetRegisterInfo *TRI)
MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, const MCInstrDesc &MCID)
virtual const TargetFrameLowering * getFrameLowering() const
iterator erase(iterator I)
void emitARMRegPlusImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, DebugLoc dl, unsigned DestReg, unsigned BaseReg, int NumBytes, ARMCC::CondCodes Pred, unsigned PredReg, const ARMBaseInstrInfo &TII, unsigned MIFlags=0)
const MCInstrDesc & get(unsigned Opcode) const
static void emitRegPlusImmediate(bool isARM, MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, DebugLoc dl, const ARMBaseInstrInfo &TII, unsigned DestReg, unsigned SrcReg, int NumBytes, unsigned MIFlags=MachineInstr::NoFlags, ARMCC::CondCodes Pred=ARMCC::AL, unsigned PredReg=0)
int64_t getObjectOffset(int ObjectIdx) const
bool canRealignStack(const MachineFunction &MF) const
bool needsStackRealignment(const MachineFunction &MF) const
bool hasCalls() const
hasCalls - Return true if the current function has any function calls.
virtual const TargetInstrInfo * getInstrInfo() const
static const MachineInstrBuilder & AddDefaultCC(const MachineInstrBuilder &MIB)
const STC & getSubtarget() const
static void emitAlignedDPRCS2Spills(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned NumAlignedDPRCS2Regs, const std::vector< CalleeSavedInfo > &CSI, const TargetRegisterInfo *TRI)
void setGPRCalleeSavedArea1Size(unsigned s)
void addOperand(MachineFunction &MF, const MachineOperand &Op)
void addScavengingFrameIndex(int FI)
Add a scavenging frame index.
static bool isARMArea2Register(unsigned Reg, bool isIOS)
bool hasFP(const MachineFunction &MF) const
unsigned getMaxCallFrameSize() const
void setOffsetAdjustment(int Adj)
MachineFrameInfo * getFrameInfo()
AttributeSet getAttributes() const
Return the attribute list for this Function.
const uint16_t * getCalleeSavedRegs(const MachineFunction *MF=0) const
Code Generation virtual methods...
bool hasBasePointer(const MachineFunction &MF) const
int findFirstPredOperandIdx() const
static cl::opt< AlignMode > Align(cl::desc("Load/store alignment support"), cl::Hidden, cl::init(DefaultAlign), cl::values(clEnumValN(DefaultAlign,"arm-default-align","Generate unaligned accesses only on hardware/OS ""combinations that are known to support them"), clEnumValN(StrictAlign,"arm-strict-align","Disallow all unaligned memory accesses"), clEnumValN(NoStrictAlign,"arm-no-strict-align","Allow unaligned memory accesses"), clEnumValEnd))
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned char TargetFlags=0) const
static unsigned estimateRSStackSizeLimit(MachineFunction &MF, const TargetFrameLowering *TFI)
static bool isPopOpcode(int Opc)
static bool isARMLowRegister(unsigned Reg)
bundle_iterator< const MachineInstr, const_instr_iterator > const_iterator
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF, RegScavenger *RS) const
int getFrameIndexReference(const MachineFunction &MF, int FI, unsigned &FrameReg) const
void setHasStackFrame(bool s)
void setGPRCalleeSavedArea1Offset(unsigned o)
MachineRegisterInfo & getRegInfo()
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned char TargetFlags=0) const
void emitPrologue(MachineFunction &MF) const
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
const TargetMachine & getTarget() const
void setDPRCalleeSavedAreaSize(unsigned s)
const MachineInstrBuilder & copyImplicitOps(const MachineInstr *OtherMI)
Copy all the implicit operands from OtherMI onto this one.
virtual const TargetRegisterInfo * getRegisterInfo() const
bool hasVarSizedObjects() const
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const
static bool isARMArea3Register(unsigned Reg, bool isIOS)
unsigned getReg() const
getReg - Returns the register number.
bool cannotEliminateFrame(const MachineFunction &MF) const
static unsigned GetFunctionSizeInBytes(const MachineFunction &MF, const ARMBaseInstrInfo &TII)
unsigned getGPRCalleeSavedArea1Size() const
bool isPhysRegUsed(unsigned Reg) const
BasicBlockListType::iterator iterator
ItTy prior(ItTy it, Dist n)
const MCRegisterInfo & MRI
unsigned getGPRCalleeSavedArea2Size() const
unsigned getArgRegsSaveSize(unsigned Align=0) const
bool isThumb2Function() const
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
void setObjectAlignment(int ObjectIdx, unsigned Align)
setObjectAlignment - Change the alignment of the specified stack object.
DebugLoc getDebugLoc() const
bool shouldRestoreSPFromFP() const