23#define DEBUG_TYPE "arc-frame-lowering"
29 cl::desc(
"Use arc callee save/restore functions"),
33 "__st_r13_to_r15",
"__st_r13_to_r16",
"__st_r13_to_r17",
"__st_r13_to_r18",
34 "__st_r13_to_r19",
"__st_r13_to_r20",
"__st_r13_to_r21",
"__st_r13_to_r22",
35 "__st_r13_to_r23",
"__st_r13_to_r24",
"__st_r13_to_r25",
39 "__ld_r13_to_r15",
"__ld_r13_to_r16",
"__ld_r13_to_r17",
"__ld_r13_to_r18",
40 "__ld_r13_to_r19",
"__ld_r13_to_r20",
"__ld_r13_to_r21",
"__ld_r13_to_r22",
41 "__ld_r13_to_r23",
"__ld_r13_to_r24",
"__ld_r13_to_r25",
47 int Amount,
int StackPtr) {
61 LLVM_DEBUG(
dbgs() <<
"Internal: adjust stack by: " << Amount <<
","
62 << AbsAmount <<
"\n");
64 assert((AbsAmount % 4 == 0) &&
"Stack adjustments must be 4-byte aligned.");
65 if (isUInt<6>(AbsAmount))
66 AdjOp = Positive ? ARC::ADD_rru6 : ARC::SUB_rru6;
67 else if (isInt<12>(AbsAmount))
68 AdjOp = Positive ? ARC::ADD_rrs12 : ARC::SUB_rrs12;
70 AdjOp = Positive ? ARC::ADD_rrlimm : ARC::SUB_rrlimm;
79 for (
auto Reg : CSI) {
80 assert(Reg.getReg() >= ARC::R13 && Reg.getReg() <= ARC::R25 &&
81 "Unexpected callee saved reg.");
82 if (Reg.getReg() >
Last)
93 SavedRegs.
set(ARC::BLINK);
96void ARCFrameLowering::adjustStackToMatchRecords(
98 bool Allocate)
const {
105 ScalarAlloc = -ScalarAlloc;
109 ScalarAlloc, ARC::SP);
129 unsigned StackSlotsUsedByFunclet = 0;
130 bool SavedBlink =
false;
131 unsigned AlreadyAdjusted = 0;
135 unsigned VarArgsBytes = MFI.
getObjectSize(AFI->getVarArgsFrameIndex());
136 unsigned Opc = ARC::SUB_rrlimm;
137 if (isUInt<6>(VarArgsBytes))
139 else if (isInt<12>(VarArgsBytes))
140 Opc = ARC::SUB_rrs12;
152 AlreadyAdjusted += 4;
157 StackSlotsUsedByFunclet =
Last - ARC::R12;
162 .
addImm(4 * StackSlotsUsedByFunclet);
166 AlreadyAdjusted += 4 * (StackSlotsUsedByFunclet + 1);
170 if (MFI.
hasCalls() && !SavedBlink) {
173 AlreadyAdjusted += 4;
175 if (AFI->MaxCallStackReq > 0)
206 nullptr,
MRI->getDwarfRegNum(ARC::FP,
true), CurOffset));
215 nullptr,
MRI->getDwarfRegNum(ARC::BLINK,
true), CurOffset));
221 for (
const auto &Entry : CSI) {
222 unsigned Reg = Entry.getReg();
223 int FI = Entry.getFrameIdx();
225 if ((
hasFP(MF) && Reg == ARC::FP) || (MFI.
hasCalls() && Reg == ARC::BLINK))
246 bool SavedBlink =
false;
247 unsigned AmountAboveFunclet = 0;
253 unsigned Opc = ARC::SUB_rrlimm;
254 if (isUInt<6>(StackSize))
259 AmountAboveFunclet += 4;
265 unsigned StackSlotsUsedByFunclet = 0;
269 StackSlotsUsedByFunclet =
Last - ARC::R12;
270 AmountAboveFunclet += 4 * (StackSlotsUsedByFunclet + 1);
274 if (MFI.
hasCalls() && !SavedBlink) {
275 AmountAboveFunclet += 4;
280 if (
unsigned MoveAmount = StackSize - AmountAboveFunclet) {
281 unsigned Opc = ARC::ADD_rrlimm;
282 if (isUInt<6>(MoveAmount))
284 else if (isInt<12>(MoveAmount))
285 Opc = ARC::ADD_rrs12;
288 .
addImm(StackSize - AmountAboveFunclet);
291 if (StackSlotsUsedByFunclet) {
296 unsigned Opc = ARC::ADD_rrlimm;
297 if (isUInt<6>(4 * StackSlotsUsedByFunclet))
299 else if (isInt<12>(4 * StackSlotsUsedByFunclet))
300 Opc = ARC::ADD_rrs12;
303 .
addImm(4 * (StackSlotsUsedByFunclet));
322 unsigned VarArgsBytes = MFI.
getObjectSize(AFI->getVarArgsFrameIndex());
323 unsigned Opc = ARC::ADD_rrlimm;
324 if (isUInt<6>(VarArgsBytes))
326 else if (isInt<12>(VarArgsBytes))
327 Opc = ARC::ADD_rrs12;
335static std::vector<CalleeSavedInfo>::iterator
337 for (
auto I = V.begin(), E = V.end();
I != E; ++
I) {
338 if (reg ==
I->getReg())
346 std::vector<CalleeSavedInfo> &CSI)
const {
356 LLVM_DEBUG(
dbgs() <<
"Creating fixed object (" << StackObj <<
") for FP at "
357 << CurOffset <<
"\n");
365 <<
") for BLINK at " << CurOffset <<
"\n");
371 for (
unsigned Which =
Last; Which > ARC::R12; Which--) {
373 if (RegI == CSI.end() || RegI->getFrameIdx() == 0) {
377 if (RegI != CSI.end())
378 RegI->setFrameIdx(FI);
383 for (
auto &
I : CSI) {
384 if (
I.getReg() > ARC::R12)
386 if (
I.getFrameIdx() == 0) {
389 <<
") for other register at " << CurOffset <<
"\n");
393 <<
") for other register at " << CurOffset <<
"\n");
444 LLVM_DEBUG(
dbgs() <<
"Created scavenging index RegScavFI=" << RegScavFI
451 unsigned Reg,
int NumBytes,
bool IsAdd,
454 if (isUInt<6>(NumBytes))
455 Opc = IsAdd ? ARC::ADD_rru6 : ARC::SUB_rru6;
456 else if (isInt<12>(NumBytes))
457 Opc = IsAdd ? ARC::ADD_rrs12 : ARC::SUB_rrs12;
459 Opc = IsAdd ? ARC::ADD_rrlimm : ARC::SUB_rrlimm;
476 if (Amt > AFI->MaxCallStackReq && Old.
getOpcode() == ARC::ADJCALLSTACKDOWN)
481 Old.
getOpcode() == ARC::ADJCALLSTACKUP) &&
482 "Unknown Frame Pseudo.");
483 bool IsAdd = (Old.
getOpcode() == ARC::ADJCALLSTACKUP);
unsigned const MachineRegisterInfo * MRI
static const char * load_funclet_name[]
static void emitRegUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, DebugLoc dl, unsigned Reg, int NumBytes, bool IsAdd, const ARCInstrInfo *TII)
static const char * store_funclet_name[]
static void generateStackAdjustment(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const ARCInstrInfo &TII, DebugLoc dl, int Amount, int StackPtr)
static std::vector< CalleeSavedInfo >::iterator getSavedReg(std::vector< CalleeSavedInfo > &V, unsigned reg)
static cl::opt< bool > UseSaveRestoreFunclet("arc-save-restore-funclet", cl::Hidden, cl::desc("Use arc callee save/restore functions"), cl::init(true))
static unsigned determineLastCalleeSave(ArrayRef< CalleeSavedInfo > CSI)
MachineBasicBlock MachineBasicBlock::iterator MBBI
const HexagonInstrInfo * TII
unsigned const TargetRegisterInfo * TRI
This file declares the machine register scavenger class.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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 processFunctionBeforeFrameFinalized(MachineFunction &MF, RegScavenger *RS) const override
processFunctionBeforeFrameFinalized - This method is called immediately before the specified function...
MachineBasicBlock::iterator eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const override
This method is called during prolog/epilog code insertion to eliminate call frame setup and destroy p...
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS) const override
Add explicit callee save registers.
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override
Insert Prologue into the function.
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override
Insert Epilogue into the function.
bool hasFP(const MachineFunction &MF) const override
hasFP - Return true if the specified function should have a dedicated frame pointer register.
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...
bool assignCalleeSavedSpillSlots(llvm::MachineFunction &, const llvm::TargetRegisterInfo *, std::vector< llvm::CalleeSavedInfo > &) const override
ARCFunctionInfo - This class is derived from MachineFunction private ARC target-specific information ...
const ARCInstrInfo * getInstrInfo() const override
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
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.
Context object for machine code objects.
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
DebugLoc findDebugLoc(instr_iterator MBBI)
Find the next valid DebugLoc starting at MBBI, skipping any debug instructions.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
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.
int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
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...
void setObjectOffset(int ObjectIdx, int64_t SPOffset)
Set the stack frame offset of the specified object.
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
const std::vector< CalleeSavedInfo > & getCalleeSavedInfo() const
Returns a reference to call saved info vector for the current function.
bool hasStackObjects() const
Return true if there are any stack objects in this function.
int CreateFixedSpillStackObject(uint64_t Size, int64_t SPOffset, bool IsImmutable=false)
Create a spill slot at a fixed location on the stack.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
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.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MCContext & getContext() const
Function & getFunction()
Return the LLVM function that this machine code represents.
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & addCFIIndex(unsigned CFIIndex) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
void addScavengingFrameIndex(int FI)
Add a scavenging frame index.
virtual void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS=nullptr) const
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
bool DisableFramePointerElim(const MachineFunction &MF) const
DisableFramePointerElim - This returns true if frame pointer elimination optimization should be disab...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Align getSpillAlign(const TargetRegisterClass &RC) const
Return the minimum required alignment in bytes for a spill slot for a register of this class.
bool hasStackRealignment(const MachineFunction &MF) const
True if stack realignment is required and still possible.
unsigned getSpillSize(const TargetRegisterClass &RC) const
Return the size in bytes of the stack slot allocated to hold a spilled copy of a register from class ...
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Define
Register definition.
@ Kill
The last use of a register.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.