27#define DEBUG_TYPE "csky-frame-lowering"
51void CSKYFrameLowering::determineFrameLayout(
MachineFunction &MF)
const {
60 if (RI->hasStackRealignment(MF)) {
62 FrameSize += (MaxStackAlign.
value() - StackAlign.
value());
63 StackAlign = MaxStackAlign;
71 FrameSize =
alignTo(FrameSize, StackAlign);
99 determineFrameLayout(MF);
103 uint64_t StackSize = MFI.getStackSize();
106 if (StackSize == 0 && !MFI.adjustsStack())
109 const auto &CSI = MFI.getCalleeSavedInfo();
131 std::advance(
MBBI, CSI.size());
135 for (
const auto &Entry : CSI) {
136 int64_t
Offset = MFI.getObjectOffset(Entry.getFrameIdx());
139 unsigned Num =
TRI->getRegSizeInBits(Reg, MRI) / 32;
140 for (
unsigned i = 0; i < Num; i++) {
142 nullptr, RI->getDwarfRegNum(Reg,
true) + i,
Offset + i * 4));
156 nullptr, RI->getDwarfRegNum(
FPReg,
true)));
162 -(
static_cast<int64_t
>(StackSize - ActualSize)),
167 if (RI->hasStackRealignment(MF)) {
168 Align MaxAlignment = MFI.getMaxAlign();
171 if (STI.hasE2() &&
isUInt<12>(~(-(
int)MaxAlignment.value()))) {
174 .
addImm(~(-(
int)MaxAlignment.value()));
176 unsigned ShiftAmount =
Log2(MaxAlignment);
212 -(
static_cast<int64_t
>(StackSize - ActualSize)),
235 MBBI =
MBB.getFirstTerminator();
237 MBBI =
MBB.getLastNonDebugInstr();
242 if (!
MBBI->isTerminator())
246 const auto &CSI = MFI.getCalleeSavedInfo();
247 uint64_t StackSize = MFI.getStackSize();
249 uint64_t ActualSize =
255 auto LastFrameDestroy =
MBBI;
257 LastFrameDestroy = std::prev(
MBBI, CSI.size());
265 adjustReg(
MBB, LastFrameDestroy,
DL,
SPReg,
SPReg, (StackSize - ActualSize),
276 for (
auto &
MBB : MF) {
278 FnSize +=
TII.getInstSizeInBytes(
MI);
286 unsigned Limit = (1 << 12) - 1;
288 for (
auto &
MBB : MF) {
289 for (
auto &
MI :
MBB) {
290 if (
MI.isDebugInstr())
293 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
294 if (!
MI.getOperand(i).isFI())
297 if (
MI.getOpcode() == CSKY::SPILL_CARRY ||
298 MI.getOpcode() == CSKY::RESTORE_CARRY ||
299 MI.getOpcode() == CSKY::STORE_PAIR ||
300 MI.getOpcode() == CSKY::LOAD_PAIR) {
301 Limit = std::min(Limit, ((1U << 12) - 1) * 4);
305 if (
MI.getOpcode() == CSKY::ADDI32) {
306 Limit = std::min(Limit, (1U << 12));
310 if (
MI.getOpcode() == CSKY::ADDI16XZ) {
311 Limit = std::min(Limit, (1U << 3));
317 if (
MI.getOpcode() == CSKY::ADDI16)
325 "Unhandled addressing mode in stack size limit calculation");
327 Limit = std::min(Limit, (1U << 12) - 1);
330 Limit = std::min(Limit, ((1U << 12) - 1) * 2);
333 Limit = std::min(Limit, ((1U << 12) - 1) * 4);
336 Limit = std::min(Limit, (1U << 5) - 1);
339 Limit = std::min(Limit, ((1U << 5) - 1) * 2);
342 Limit = std::min(Limit, ((1U << 5) - 1) * 4);
345 Limit = std::min(Limit, ((1U << 8) - 1) * 4);
368 SavedRegs.
set(CSKY::R8);
372 SavedRegs.
set(CSKY::R7);
379 static const MCPhysReg CSRegs[] = {CSKY::R0, CSKY::R1, CSKY::R2, CSKY::R3,
380 CSKY::R12, CSKY::R13, 0};
382 for (
unsigned i = 0; CSRegs[i]; ++i)
383 SavedRegs.
set(CSRegs[i]);
385 if (STI.hasHighRegisters()) {
387 static const MCPhysReg CSHRegs[] = {CSKY::R18, CSKY::R19, CSKY::R20,
388 CSKY::R21, CSKY::R22, CSKY::R23,
389 CSKY::R24, CSKY::R25, 0};
391 for (
unsigned i = 0; CSHRegs[i]; ++i)
392 SavedRegs.
set(CSHRegs[i]);
396 CSKY::F8_32, CSKY::F9_32, CSKY::F10_32,
397 CSKY::F11_32, CSKY::F12_32, CSKY::F13_32,
398 CSKY::F14_32, CSKY::F15_32, 0};
400 CSKY::F8_64, CSKY::F9_64, CSKY::F10_64,
401 CSKY::F11_64, CSKY::F12_64, CSKY::F13_64,
402 CSKY::F14_64, CSKY::F15_64, 0};
405 if (STI.hasFPUv2DoubleFloat() || STI.hasFPUv3DoubleFloat())
407 else if (STI.hasFPUv2SingleFloat() || STI.hasFPUv3SingleFloat())
413 for (
unsigned i = 0; Regs[i]; ++i)
414 if (CSKY::FPR32RegClass.
contains(Regs[i]) ||
415 CSKY::FPR64RegClass.
contains(Regs[i])) {
417 for (; FRegs[x]; ++x)
418 if (FRegs[x] == Regs[i])
421 SavedRegs.
set(Regs[i]);
426 unsigned CSStackSize = 0;
427 for (
unsigned Reg : SavedRegs.
set_bits()) {
428 auto RegSize =
TRI->getRegSizeInBits(Reg, MRI) / 8;
438 if (BigFrame || CFI->
isCRSpilled() || !STI.hasE2()) {
440 unsigned size =
TRI->getSpillSize(*RC);
449 if (FnSize >= ((1 << (16 - 1)) * 2))
450 SavedRegs.
set(CSKY::R15);
471 if (
MI !=
MBB.end() && !
MI->isDebugInstr())
472 DL =
MI->getDebugLoc();
474 for (
auto &CS : CSI) {
478 TII.storeRegToStackSlot(
MBB,
MI, Reg,
true, CS.getFrameIdx(), RC,
494 if (
MI !=
MBB.end() && !
MI->isDebugInstr())
495 DL =
MI->getDebugLoc();
497 for (
auto &CS :
reverse(CSI)) {
501 assert(
MI !=
MBB.begin() &&
"loadRegFromStackSlot didn't insert any code!");
520 int64_t Amount =
MI->getOperand(0).getImm();
526 if (
MI->getOpcode() == CSKY::ADJCALLSTACKDOWN)
533 return MBB.erase(
MI);
543 if (DestReg == SrcReg && Val == 0)
555 TII->get(Val < 0 ? CSKY::SUBI16SPSP : CSKY::ADDI16SPSP), CSKY::R14)
564 Op = Val < 0 ? CSKY::SUBU32 : CSKY::ADDU32;
566 assert(SrcReg == DestReg);
567 Op = Val < 0 ? CSKY::SUBU16XZ : CSKY::ADDU16XZ;
585 const auto &CSI = MFI.getCalleeSavedInfo();
590 int Offset = MFI.getObjectOffset(FI) + MFI.getOffsetAdjustment();
593 MinCSFI = CSI[0].getFrameIdx();
594 MaxCSFI = CSI[CSI.size() - 1].getFrameIdx();
597 if (FI >= MinCSFI && FI <= MaxCSFI) {
598 FrameReg = CSKY::R14;
602 if (!MFI.isFixedObjectIndex(FI)) {
604 Offset += MFI.getStackSize();
610 if (MFI.isFixedObjectIndex(FI) &&
hasFP(MF)) {
615 Offset += MFI.getStackSize();
static unsigned estimateRSStackSizeLimit(MachineFunction &MF)
Look at each instruction that references stack frames and return the stack size limit beyond which so...
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static unsigned EstimateFunctionSizeInBytes(const MachineFunction &MF, const ARMBaseInstrInfo &TII, const ARMSubtarget &STI, const ARMBaseRegisterInfo *RegInfo, BitVector &SavedRegs, bool BigFrameOffsets)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static Register getBPReg(const CSKYSubtarget &STI)
static Register getFPReg(const CSKYSubtarget &STI)
static uint64_t align(uint64_t Size)
const HexagonInstrInfo * TII
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static constexpr MCPhysReg FPReg
static constexpr MCPhysReg SPReg
This file declares the machine register scavenger class.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool empty() const
Check if the array is empty.
bool test(unsigned Idx) const
Returns true if bit Idx is set.
BitVector & set()
Set all bits in the bitvector.
iterator_range< const_set_bits_iterator > set_bits() const
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS) const override
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg) const override
getFrameIndexReference - This method should return the base register and offset used to reference a f...
MachineBasicBlock::iterator eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const override
This method is called during prolog/epilog code insertion to eliminate call frame setup and destroy p...
bool hasReservedCallFrame(const MachineFunction &MF) const override
hasReservedCallFrame - Under normal circumstances, when a frame pointer is not required,...
bool hasFPImpl(const MachineFunction &MF) const override
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override
bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, MutableArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI) const override
restoreCalleeSavedRegisters - Issues instruction(s) to restore all callee saved registers and returns...
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override
emitProlog/emitEpilog - These methods insert prolog and epilog code into the function.
bool hasBP(const MachineFunction &MF) const
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, ArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI) const override
spillCalleeSavedRegisters - Issues instruction(s) to spill all callee saved registers and returns tru...
void setCalleeSaveAreaSize(int v)
int getCalleeSaveAreaSize() const
void setLRIsSpilled(bool s)
unsigned getVarArgsSaveSize() const
const CSKYRegisterInfo * getRegisterInfo() const override
const CSKYInstrInfo * getInstrInfo() const override
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register, SMLoc Loc={})
.cfi_def_cfa_register modifies a rule for computing CFA.
static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, int64_t Offset, SMLoc Loc={})
.cfi_offset Previous value of Register is saved at offset Offset from CFA.
static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int64_t Offset, SMLoc Loc={})
.cfi_def_cfa_offset modifies a rule for computing CFA.
Wrapper class representing physical registers. Should be passed by value.
MachineInstrBundleIterator< MachineInstr > iterator
const std::vector< MachineConstantPoolEntry > & getConstants() const
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
void setMaxCallFrameSize(uint64_t S)
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
bool hasCalls() const
Return true if the current function has any function calls.
bool isFrameAddressTaken() const
This method may be called any time after instruction selection is complete to determine if there is a...
Align getMaxAlign() const
Return alignment of this function's frame.
uint64_t getMaxCallFrameSize() const
Return the maximum size of a call frame that must be allocated for an outgoing function call.
LLVM_ABI uint64_t estimateStackSize(const MachineFunction &MF) const
Estimate and return the size of the stack frame.
LLVM_ABI int CreateSpillStackObject(uint64_t Size, Align Alignment, TargetStackID::Value StackID=TargetStackID::Default)
Create a new statically sized stack object that represents a spill slot, returning a nonnegative iden...
void setStackSize(uint64_t Size)
Set the size of the stack.
unsigned addFrameInst(const MCCFIInstruction &Inst)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
LLVM_ABI bool disableFramePointerElim() const
Returns true if frame pointer elimination should be disabled for this function.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
const MachineInstrBuilder & addCFIIndex(unsigned CFIIndex) const
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLVM_ABI const MCPhysReg * getCalleeSavedRegs() const
Returns list of callee saved registers.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
Wrapper class representing virtual and physical registers.
StackOffset holds a fixed and a scalable offset in bytes.
int64_t getFixed() const
Returns the fixed component of the stack.
bool hasFP(const MachineFunction &MF) const
hasFP - Return true if the specified function should have a dedicated frame pointer register.
virtual void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS=nullptr) const
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
Align getStackAlign() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
int alignSPAdjust(int SPAdj) const
alignSPAdjust - This method aligns the stack adjustment to the correct alignment.
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
bool hasStackRealignment(const MachineFunction &MF) const
True if stack realignment is required and still possible.
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
@ Kill
The last use of a register.
auto reverse(ContainerTy &&C)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
DWARFExpression::Operation Op
unsigned Log2(Align A)
Returns the log2 of the alignment.
constexpr bool isShiftedUInt(uint64_t x)
Checks if a unsigned integer is an N bit number shifted left by S.
MCRegisterClass TargetRegisterClass
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.