108 using namespace llvm;
110 #define DEBUG_TYPE "frame-info"
113 cl::desc(
"enable use of redzone on AArch64"),
116 STATISTIC(NumRedZoneFunctions,
"Number of functions using red zone");
164 unsigned Opc = I->getOpcode();
165 bool IsDestroy = Opc == TII->getCallFrameDestroyOpcode();
166 uint64_t CalleePopAmount = IsDestroy ? I->getOperand(1).getImm() : 0;
172 int64_t Amount = I->getOperand(0).getImm();
180 if (CalleePopAmount == 0) {
191 assert(Amount > -0xffffff && Amount < 0xffffff &&
"call frame too large");
194 }
else if (CalleePopAmount != 0) {
197 assert(CalleePopAmount < 0xffffff &&
"call frame too large");
198 emitFrameOffset(MBB, I, DL, AArch64::SP, AArch64::SP, -CalleePopAmount,
220 bool HasFP =
hasFP(MF);
226 int64_t saveAreaOffset = (HasFP ? 2 : 1) * stackGrowth;
227 unsigned TotalSkipped = 0;
228 for (
const auto &Info : CSI) {
229 unsigned Reg = Info.getReg();
239 if (HasFP && (FramePtr == Reg || Reg == AArch64::LR)) {
240 TotalSkipped += stackGrowth;
246 nullptr, DwarfReg, Offset - TotalSkipped));
248 .addCFIIndex(CFIIndex)
257 assert(((MBBI->
getOpcode() == AArch64::STPXpre ||
258 MBBI->
getOpcode() == AArch64::STPDpre) &&
267 assert(FPOffset >= 0 &&
"Bad Framepointer Offset");
272 return MBBI->
getOpcode() == AArch64::STPXi ||
289 bool HasFP =
hasFP(MF);
299 assert(!HasFP &&
"unexpected function without stack frame but with FP");
310 emitFrameOffset(MBB, MBBI, DL, AArch64::SP, AArch64::SP, -NumBytes, TII,
317 .addCFIIndex(CFIIndex)
319 }
else if (NumBytes) {
320 ++NumRedZoneFunctions;
336 assert(NumBytes >= 0 &&
"Negative stack allocation size!?");
342 emitFrameOffset(MBB, MBBI, DL, AArch64::FP, AArch64::SP, FPOffset, TII,
353 unsigned scratchSPReg = AArch64::SP;
354 if (NumBytes && NeedsRealignment) {
356 scratchSPReg = AArch64::X9;
365 emitFrameOffset(MBB, MBBI, DL, scratchSPReg, AArch64::SP, -NumBytes, TII,
368 if (NumBytes && NeedsRealignment) {
370 assert(NrBitsToZero > 1);
371 assert(scratchSPReg != AArch64::SP);
380 uint32_t andMaskEncoded =
382 | ((64-NrBitsToZero) << 6)
383 | ((64-NrBitsToZero-1) << 0)
385 BuildMI(MBB, MBBI, DL, TII->
get(AArch64::ANDXri), AArch64::SP)
402 if (needsFrameMoves) {
474 unsigned Reg = RegInfo->getDwarfRegNum(FramePtr,
true);
478 .addCFIIndex(CFIIndex)
482 unsigned LR = RegInfo->getDwarfRegNum(AArch64::LR,
true);
486 .addCFIIndex(CFIIndex)
493 .addCFIIndex(CFIIndex)
500 .addCFIIndex(CFIIndex)
510 for (
unsigned i = 0; CSRegs[i]; ++i)
511 if (Reg == CSRegs[i])
518 if (MI->
getOpcode() == AArch64::LDPXpost ||
522 if (MI->
getOpcode() == AArch64::LDPXpost ||
544 bool IsTailCallReturn =
false;
545 if (MBB.
end() != MBBI) {
546 DL = MBBI->getDebugLoc();
547 unsigned RetOpcode = MBBI->getOpcode();
548 IsTailCallReturn = RetOpcode == AArch64::TCRETURNdi ||
549 RetOpcode == AArch64::TCRETURNri;
561 uint64_t ArgumentPopSize = 0;
562 if (IsTailCallReturn) {
568 ArgumentPopSize = StackAdjust.
getImm();
603 NumBytes += ArgumentPopSize;
605 unsigned NumRestores = 0;
609 if (LastPopI != MBB.
begin()) {
619 NumBytes -= NumRestores * 16;
620 assert(NumBytes >= 0 &&
"Negative stack allocation size!?");
654 unsigned &FrameReg)
const {
659 int FI,
unsigned &FrameReg,
660 bool PreferFP)
const {
693 (FPOffset >= -256 && Offset > -FPOffset))
699 "In the presence of dynamic stack pointer realignment, "
700 "non-argument objects cannot be accessed through the frame pointer");
711 FrameReg = AArch64::SP;
723 if (Reg != AArch64::LR)
734 const std::vector<CalleeSavedInfo> &CSI,
738 unsigned Count = CSI.size();
740 assert((Count & 1) == 0 &&
"Odd number of callee-saved regs to spill!");
743 DL = MI->getDebugLoc();
745 for (
unsigned i = 0; i < Count; i += 2) {
746 unsigned idx = Count - i - 2;
747 unsigned Reg1 = CSI[idx].getReg();
748 unsigned Reg2 = CSI[idx + 1].getReg();
755 assert(CSI[idx].getFrameIdx() + 1 == CSI[idx + 1].getFrameIdx() &&
756 "Out of order callee saved regs!");
758 assert((Count & 1) == 0 &&
"Odd number of callee-saved regs to spill!");
759 assert((i & 1) == 0 &&
"Odd index for callee-saved reg spill!");
769 if (AArch64::GPR64RegClass.
contains(Reg1)) {
770 assert(AArch64::GPR64RegClass.
contains(Reg2) &&
771 "Expected GPR64 callee-saved register pair!");
774 StrOpc = AArch64::STPXpre;
776 StrOpc = AArch64::STPXi;
777 }
else if (AArch64::FPR64RegClass.
contains(Reg1)) {
778 assert(AArch64::FPR64RegClass.
contains(Reg2) &&
779 "Expected FPR64 callee-saved register pair!");
782 StrOpc = AArch64::STPDpre;
784 StrOpc = AArch64::STPDi;
788 << TRI->
getName(Reg2) <<
") -> fi#(" << CSI[idx].getFrameIdx()
789 <<
", " << CSI[idx + 1].getFrameIdx() <<
")\n");
792 const int Offset = (i == 0) ? -Count : i;
793 assert((Offset >= -64 && Offset <= 63) &&
794 "Offset out of bounds for STP immediate");
796 if (StrOpc == AArch64::STPDpre || StrOpc == AArch64::STPXpre)
812 const std::vector<CalleeSavedInfo> &CSI,
816 unsigned Count = CSI.size();
818 assert((Count & 1) == 0 &&
"Odd number of callee-saved regs to spill!");
821 DL = MI->getDebugLoc();
823 for (
unsigned i = 0; i < Count; i += 2) {
824 unsigned Reg1 = CSI[i].getReg();
825 unsigned Reg2 = CSI[i + 1].getReg();
829 assert(CSI[i].getFrameIdx() + 1 == CSI[i + 1].getFrameIdx() &&
830 "Out of order callee saved regs!");
840 assert((Count & 1) == 0 &&
"Odd number of callee-saved regs to spill!");
841 assert((i & 1) == 0 &&
"Odd index for callee-saved reg spill!");
842 if (AArch64::GPR64RegClass.
contains(Reg1)) {
843 assert(AArch64::GPR64RegClass.
contains(Reg2) &&
844 "Expected GPR64 callee-saved register pair!");
846 LdrOpc = AArch64::LDPXpost;
848 LdrOpc = AArch64::LDPXi;
849 }
else if (AArch64::FPR64RegClass.
contains(Reg1)) {
850 assert(AArch64::FPR64RegClass.
contains(Reg2) &&
851 "Expected FPR64 callee-saved register pair!");
853 LdrOpc = AArch64::LDPDpost;
855 LdrOpc = AArch64::LDPDi;
859 << TRI->
getName(Reg2) <<
") -> fi#(" << CSI[i].getFrameIdx()
860 <<
", " << CSI[i + 1].getFrameIdx() <<
")\n");
864 const int Offset = (i == Count - 2) ? Count : Count - i - 2;
865 assert((Offset >= -64 && Offset <= 63) &&
866 "Offset out of bounds for LDP immediate");
868 if (LdrOpc == AArch64::LDPXpost || LdrOpc == AArch64::LDPDpost)
897 SavedRegs.
set(AArch64::FP);
898 SavedRegs.
set(AArch64::LR);
907 SavedRegs.
set(AArch64::X9);
910 unsigned NumGPRSpilled = 0;
911 unsigned NumFPRSpilled = 0;
912 bool ExtraCSSpill =
false;
913 bool CanEliminateFrame =
true;
914 DEBUG(
dbgs() <<
"*** processFunctionBeforeCalleeSavedScan\nUsed CSRs:");
918 for (
unsigned i = 0; CSRegs[i]; i += 2) {
919 assert(CSRegs[i + 1] &&
"Odd number of callee-saved registers!");
921 const unsigned OddReg = CSRegs[i];
922 const unsigned EvenReg = CSRegs[i + 1];
923 assert((AArch64::GPR64RegClass.
contains(OddReg) &&
924 AArch64::GPR64RegClass.
contains(EvenReg)) ^
925 (AArch64::FPR64RegClass.
contains(OddReg) &&
926 AArch64::FPR64RegClass.
contains(EvenReg)) &&
927 "Register class mismatch!");
929 const bool OddRegUsed = SavedRegs.
test(OddReg);
930 const bool EvenRegUsed = SavedRegs.
test(EvenReg);
934 if (!OddRegUsed && !EvenRegUsed) {
935 if (AArch64::GPR64RegClass.
contains(OddReg)) {
936 UnspilledCSGPRs.push_back(OddReg);
937 UnspilledCSGPRs.push_back(EvenReg);
945 unsigned Reg = AArch64::NoRegister;
948 if (OddRegUsed ^ EvenRegUsed) {
950 Reg = OddRegUsed ? EvenReg : OddReg;
957 assert(((OddReg == AArch64::LR && EvenReg == AArch64::FP) ||
958 (RegInfo->getEncodingValue(OddReg) + 1 ==
959 RegInfo->getEncodingValue(EvenReg))) &&
960 "Register pair of non-adjacent registers!");
961 if (AArch64::GPR64RegClass.
contains(OddReg)) {
967 if (Reg != AArch64::NoRegister && !RegInfo->
isReservedReg(MF, Reg))
972 CanEliminateFrame =
false;
984 DEBUG(
dbgs() <<
"Estimated stack frame size: " << CFSize <<
" bytes.\n");
985 bool BigStack = (CFSize >= 256);
995 if (BigStack && !ExtraCSSpill) {
999 assert(((UnspilledCSGPRs.size() & 1) == 0) &&
"Odd number of registers!");
1001 while (!UnspilledCSGPRs.empty() && Count < 2) {
1002 unsigned Reg = UnspilledCSGPRs.back();
1003 UnspilledCSGPRs.pop_back();
1005 <<
" to get a scratch register.\n");
1007 ExtraCSSpill =
true;
1013 if (!ExtraCSSpill) {
1017 DEBUG(
dbgs() <<
"No available CS registers, allocated fi#" << FI
1018 <<
" as the emergency spill slot.\n");
const MCPhysReg * getCalleeSavedRegs(const MachineFunction *MF) const override
Code Generation virtual methods...
unsigned getStackAlignment() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
void push_back(const T &Elt)
const MachineFunction * getParent() const
getParent - Return the MachineFunction containing this basic block.
A parsed version of the target data layout string in and methods for querying it. ...
void setPhysRegUsed(unsigned Reg)
setPhysRegUsed - Mark the specified register used in this function.
int getDwarfRegNum(unsigned RegNum, bool isEH) const
Map a target register to an equivalent dwarf register number.
bool isReservedReg(const MachineFunction &MF, unsigned Reg) const
AArch64FunctionInfo - This class is derived from MachineFunctionInfo and contains private AArch64-spe...
STATISTIC(NumFunctions,"Total number of functions")
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
int resolveFrameIndexReference(const MachineFunction &MF, int FI, unsigned &FrameReg, bool PreferFP=false) const
iterator getFirstTerminator()
getFirstTerminator - returns an iterator to the first terminator instruction of this basic block...
static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, int Offset)
.cfi_offset Previous value of Register is saved at offset Offset from CFA.
static int getFPOffsetInPrologue(MachineInstr *MBBI)
Get FPOffset by analyzing the first instruction.
void addLiveIn(unsigned Reg)
Adds the specified register as a live in.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
bool isReturnAddressTaken() const
This method may be called any time after instruction selection is complete to determine if there is a...
const Function * getFunction() const
getFunction - Return the LLVM function that this machine code represents
void emitCalleeSavedFrameMoves(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned FramePtr) const
static MCCFIInstruction createDefCfaOffset(MCSymbol *L, int Offset)
.cfi_def_cfa_offset modifies a rule for computing CFA.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
unsigned getMaxAlignment() const
Return the alignment in bytes that this function must be aligned to, which is greater than the defaul...
const std::vector< CalleeSavedInfo > & getCalleeSavedInfo() const
Returns a reference to call saved info vector for the current function.
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects...
static unsigned getPrologueDeath(MachineFunction &MF, unsigned Reg)
unsigned getSize() const
getSize - Return the size of the register in bytes, which is also the size of a stack slot allocated ...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
const HexagonInstrInfo * TII
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool hasReservedCallFrame(const MachineFunction &MF) const override
hasReservedCallFrame - Under normal circumstances, when a frame pointer is not required, we reserve argument space for call sites in the function immediately on entry to the current function.
bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const std::vector< CalleeSavedInfo > &CSI, const TargetRegisterInfo *TRI) const override
restoreCalleeSavedRegisters - Issues instruction(s) to restore all callee saved registers and returns...
int getFrameIndexReference(const MachineFunction &MF, int FI, unsigned &FrameReg) const override
getFrameIndexReference - Provide a base+offset reference to an FI slot for debug info.
Reg
All possible values of the reg field in the ModR/M byte.
unsigned getArgumentStackToRestore() const
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted...
bool isFrameAddressTaken() const
This method may be called any time after instruction selection is complete to determine if there is a...
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
bool hasDebugInfo() const
hasDebugInfo - Returns true if valid debug info is present.
bool cannotEliminateFrame(const MachineFunction &MF) const
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
const MachineInstrBuilder & addImm(int64_t Val) const
addImm - Add a new immediate operand.
PrintReg - Helper class for printing registers on a raw_ostream.
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS) const override
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override
emitProlog/emitEpilog - These methods insert prolog and epilog code into the function.
bool isLiveIn(unsigned Reg) const
bool hasStackFrame() const
bool hasBasePointer(const MachineFunction &MF) const
unsigned LLVM_ATTRIBUTE_UNUSED_RESULT addFrameInst(const MCCFIInstruction &Inst)
iterator getLastNonDebugInstr()
getLastNonDebugInstr - returns an iterator to the last non-debug instruction in the basic block...
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override
unsigned getLocalStackSize() const
unsigned getKillRegState(bool B)
unsigned estimateStackSize(const MachineFunction &MF) const
Estimate and return the size of the stack frame.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
TargetInstrInfo - Interface to description of machine instruction set.
unsigned getDefRegState(bool B)
bundle_iterator< MachineInstr, instr_iterator > iterator
bool hasStackMap() const
This method may be called any time after instruction selection is complete to determine if there is a...
static bool isCalleeSavedRegister(unsigned Reg, const MCPhysReg *CSRegs)
initializer< Ty > init(const Ty &Val)
MCSymbol * createTempSymbol(bool CanBeUnnamed=true)
Create and return a new assembler temporary symbol with a unique but unspecified name.
std::size_t countTrailingZeros(T Val, ZeroBehavior ZB=ZB_Width)
Count number of 0's from the least significant bit to the most stopping at the first 1...
static MCCFIInstruction createDefCfa(MCSymbol *L, unsigned Register, int Offset)
.cfi_def_cfa defines a rule for computing CFA as: take address from Register and add Offset to it...
void setLocalStackSize(unsigned Size)
virtual bool needsStackRealignment(const MachineFunction &MF) const
needsStackRealignment - true if storage within the function requires the stack pointer to be aligned ...
void emitFrameOffset(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, DebugLoc DL, unsigned DestReg, unsigned SrcReg, int Offset, const TargetInstrInfo *TII, MachineInstr::MIFlag=MachineInstr::NoFlags, bool SetNZCV=false)
emitFrameOffset - Emit instructions as needed to set DestReg to SrcReg plus Offset.
unsigned getAlignment() const
getAlignment - Return the minimum required alignment for a register of this class.
DebugLoc findDebugLoc(instr_iterator MBBI)
findDebugLoc - find the next valid DebugLoc starting at MBBI, skipping any DBG_VALUE instructions...
const MachineOperand & getOperand(unsigned i) const
bool needsStackRealignment(const MachineFunction &MF) const override
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
unsigned getFrameRegister(const MachineFunction &MF) const override
MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, const MCInstrDesc &MCID)
BuildMI - Builder interface.
void setHasStackFrame(bool s)
static cl::opt< bool > EnableRedZone("aarch64-redzone", cl::desc("enable use of redzone on AArch64"), cl::init(false), cl::Hidden)
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
void eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const override
eliminateCallFramePseudoInstr - This method is called during prolog/epilog code insertion to eliminat...
virtual bool hasReservedCallFrame(const MachineFunction &MF) const
hasReservedCallFrame - Under normal circumstances, when a frame pointer is not required, we reserve argument space for call sites in the function immediately on entry to the current function.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
virtual void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS=nullptr) const
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
int getFrameIndexOffset(const MachineFunction &MF, int FI) const override
getFrameIndexOffset - Returns the displacement from the frame register to the stack frame of the spec...
bool hasCalls() const
Return true if the current function has any function calls.
virtual const TargetFrameLowering * getFrameLowering() const
const MCContext & getContext() const
const DataLayout * getDataLayout() const
Deprecated in 3.7, will be removed in 3.8.
void addScavengingFrameIndex(int FI)
Add a scavenging frame index.
MachineOperand class - Representation of each machine instruction operand.
bool test(unsigned Idx) const
int getOffsetOfLocalArea() const
getOffsetOfLocalArea - This method returns the offset of the local area from the stack pointer on ent...
Information about stack frame layout on the target.
bool needsUnwindTableEntry() const
True if this function needs an unwind table.
static bool isCSRestore(MachineInstr *MI, const MCPhysReg *CSRegs)
MachineFrameInfo * getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
static cl::opt< AlignMode > Align(cl::desc("Load/store alignment support"), cl::Hidden, cl::init(NoStrictAlign), cl::values(clEnumValN(StrictAlign,"aarch64-strict-align","Disallow all unaligned memory accesses"), clEnumValN(NoStrictAlign,"aarch64-no-strict-align","Allow unaligned memory accesses"), clEnumValEnd))
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
static bool isCSSave(MachineInstr *MBBI)
virtual void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, DebugLoc DL, unsigned DestReg, unsigned SrcReg, bool KillSrc) const
Emit instructions to copy a pair of physical registers.
uint64_t RoundUpToAlignment(uint64_t Value, uint64_t Align)
Returns the next integer (mod 2**64) that is greater than or equal to Value and is a multiple of Alig...
bool hasFP(const MachineFunction &MF) const override
hasFP - Return true if the specified function should have a dedicated frame pointer register...
const MCRegisterInfo * getRegisterInfo() const
Representation of each machine instruction.
bool hasPatchPoint() const
This method may be called any time after instruction selection is complete to determine if there is a...
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const std::vector< CalleeSavedInfo > &CSI, const TargetRegisterInfo *TRI) const override
spillCalleeSavedRegisters - Issues instruction(s) to spill all callee saved registers and returns tru...
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
int CreateStackObject(uint64_t Size, unsigned Alignment, bool isSS, const AllocaInst *Alloca=nullptr)
Create a new statically sized stack object, returning a nonnegative identifier to represent it...
unsigned getReg() const
getReg - Returns the register number.
bool canUseRedZone(const MachineFunction &MF) const
Can this function use the red zone for local allocations.
virtual const TargetInstrInfo * getInstrInfo() const
static const unsigned FramePtr
const char * getName(unsigned RegNo) const
Return the human-readable symbolic target-specific name for the specified physical register...
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
MachineModuleInfo & getMMI() const
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
unsigned getBaseRegister() const
unsigned getPointerSize(unsigned AS=0) const
Layout pointer size FIXME: The defaults need to be removed once all of the backends/clients are updat...
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
addReg - Add a new virtual register operand...
MachineModuleInfo - This class contains meta information specific to a module.