1//===- ARCFrameLowering.cpp - ARC Frame Information -------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains the ARC implementation of the TargetFrameLowering class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "ARCFrameLowering.h"
14#include "ARCMachineFunctionInfo.h"
15#include "ARCSubtarget.h"
16#include "llvm/CodeGen/MachineInstrBuilder.h"
17#include "llvm/CodeGen/MachineModuleInfo.h"
18#include "llvm/CodeGen/RegisterScavenging.h"
19#include "llvm/CodeGen/TargetRegisterInfo.h"
20#include "llvm/IR/Function.h"
21#include "llvm/Support/Debug.h"
22
23#define DEBUG_TYPE "arc-frame-lowering"
24
25using namespace llvm;
26
27static cl::opt<bool>
28 UseSaveRestoreFunclet("arc-save-restore-funclet", cl::Hidden,
29 cl::desc("Use arc callee save/restore functions"),
30 cl::init(Val: true));
31
32static const char *store_funclet_name[] = {
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",
36};
37
38static const char *load_funclet_name[] = {
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",
42};
43
44static void generateStackAdjustment(MachineBasicBlock &MBB,
45 MachineBasicBlock::iterator MBBI,
46 const ARCInstrInfo &TII, DebugLoc dl,
47 int Amount, int StackPtr) {
48 unsigned AdjOp;
49 if (!Amount)
50 return;
51 bool Positive;
52 unsigned AbsAmount;
53 if (Amount < 0) {
54 AbsAmount = -Amount;
55 Positive = false;
56 } else {
57 AbsAmount = Amount;
58 Positive = true;
59 }
60
61 LLVM_DEBUG(dbgs() << "Internal: adjust stack by: " << Amount << ","
62 << AbsAmount << "\n");
63
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;
69 else
70 AdjOp = Positive ? ARC::ADD_rrlimm : ARC::SUB_rrlimm;
71
72 BuildMI(MBB, MBBI, dl, TII.get(AdjOp), StackPtr)
73 .addReg(StackPtr)
74 .addImm(AbsAmount);
75}
76
77static unsigned determineLastCalleeSave(ArrayRef<CalleeSavedInfo> CSI) {
78 unsigned Last = 0;
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)
83 Last = Reg.getReg();
84 }
85 return Last;
86}
87
88void ARCFrameLowering::determineCalleeSaves(MachineFunction &MF,
89 BitVector &SavedRegs,
90 RegScavenger *RS) const {
91 LLVM_DEBUG(dbgs() << "Determine Callee Saves: " << MF.getName() << "\n");
92 TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
93 SavedRegs.set(ARC::BLINK);
94}
95
96void ARCFrameLowering::adjustStackToMatchRecords(
97 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
98 bool Allocate) const {
99 MachineFunction &MF = *MBB.getParent();
100 int ScalarAlloc = MF.getFrameInfo().getStackSize();
101
102 if (Allocate) {
103 // Allocate by adjusting by the negative of what the record holder tracked
104 // it tracked a positive offset in a downward growing stack.
105 ScalarAlloc = -ScalarAlloc;
106 }
107
108 generateStackAdjustment(MBB, MBBI, *ST.getInstrInfo(), DebugLoc(),
109 ScalarAlloc, ARC::SP);
110}
111
112/// Insert prolog code into the function.
113/// For ARC, this inserts a call to a function that puts required callee saved
114/// registers onto the stack, when enough callee saved registers are required.
115void ARCFrameLowering::emitPrologue(MachineFunction &MF,
116 MachineBasicBlock &MBB) const {
117 LLVM_DEBUG(dbgs() << "Emit Prologue: " << MF.getName() << "\n");
118 auto *AFI = MF.getInfo<ARCFunctionInfo>();
119 MachineModuleInfo &MMI = MF.getMMI();
120 MCContext &Context = MMI.getContext();
121 const MCRegisterInfo *MRI = Context.getRegisterInfo();
122 const ARCInstrInfo *TII = MF.getSubtarget<ARCSubtarget>().getInstrInfo();
123 MachineBasicBlock::iterator MBBI = MBB.begin();
124 // Debug location must be unknown since the first debug location is used
125 // to determine the end of the prologue.
126 DebugLoc dl;
127 MachineFrameInfo &MFI = MF.getFrameInfo();
128 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
129 unsigned Last = determineLastCalleeSave(CSI);
130 unsigned StackSlotsUsedByFunclet = 0;
131 bool SavedBlink = false;
132 unsigned AlreadyAdjusted = 0;
133 if (MF.getFunction().isVarArg()) {
134 // Add in the varargs area here first.
135 LLVM_DEBUG(dbgs() << "Varargs\n");
136 unsigned VarArgsBytes = MFI.getObjectSize(ObjectIdx: AFI->getVarArgsFrameIndex());
137 unsigned Opc = ARC::SUB_rrlimm;
138 if (isUInt<6>(VarArgsBytes))
139 Opc = ARC::SUB_rru6;
140 else if (isInt<12>(VarArgsBytes))
141 Opc = ARC::SUB_rrs12;
142 BuildMI(MBB, MBBI, dl, TII->get(Opc), ARC::SP)
143 .addReg(ARC::SP)
144 .addImm(VarArgsBytes);
145 }
146 if (hasFP(MF)) {
147 LLVM_DEBUG(dbgs() << "Saving FP\n");
148 BuildMI(MBB, MBBI, dl, TII->get(ARC::ST_AW_rs9))
149 .addReg(ARC::SP, RegState::Define)
150 .addReg(ARC::FP)
151 .addReg(ARC::SP)
152 .addImm(-4);
153 AlreadyAdjusted += 4;
154 }
155 if (UseSaveRestoreFunclet && Last > ARC::R14) {
156 LLVM_DEBUG(dbgs() << "Creating store funclet.\n");
157 // BL to __save_r13_to_<TRI->getRegAsmName()>
158 StackSlotsUsedByFunclet = Last - ARC::R12;
159 BuildMI(MBB, MBBI, dl, TII->get(ARC::PUSH_S_BLINK));
160 BuildMI(MBB, MBBI, dl, TII->get(ARC::SUB_rru6))
161 .addReg(ARC::SP)
162 .addReg(ARC::SP)
163 .addImm(4 * StackSlotsUsedByFunclet);
164 BuildMI(MBB, MBBI, dl, TII->get(ARC::BL))
165 .addExternalSymbol(store_funclet_name[Last - ARC::R15])
166 .addReg(ARC::BLINK, RegState::Implicit | RegState::Kill);
167 AlreadyAdjusted += 4 * (StackSlotsUsedByFunclet + 1);
168 SavedBlink = true;
169 }
170 // If we haven't saved BLINK, but we need to...do that now.
171 if (MFI.hasCalls() && !SavedBlink) {
172 LLVM_DEBUG(dbgs() << "Creating save blink.\n");
173 BuildMI(MBB, MBBI, dl, TII->get(ARC::PUSH_S_BLINK));
174 AlreadyAdjusted += 4;
175 }
176 if (AFI->MaxCallStackReq > 0)
177 MFI.setStackSize(MFI.getStackSize() + AFI->MaxCallStackReq);
178 // We have already saved some of the stack...
179 LLVM_DEBUG(dbgs() << "Adjusting stack by: "
180 << (MFI.getStackSize() - AlreadyAdjusted) << "\n");
181 generateStackAdjustment(MBB, MBBI, *ST.getInstrInfo(), dl,
182 -(MFI.getStackSize() - AlreadyAdjusted), ARC::SP);
183
184 if (hasFP(MF)) {
185 LLVM_DEBUG(dbgs() << "Setting FP from SP.\n");
186 BuildMI(MBB, MBBI, dl,
187 TII->get(isUInt<6>(MFI.getStackSize()) ? ARC::ADD_rru6
188 : ARC::ADD_rrlimm),
189 ARC::FP)
190 .addReg(ARC::SP)
191 .addImm(MFI.getStackSize());
192 }
193
194 // Emit CFI records:
195 // .cfi_def_cfa_offset StackSize
196 // .cfi_offset fp, -StackSize
197 // .cfi_offset blink, -StackSize+4
198 unsigned CFIIndex = MF.addFrameInst(
199 Inst: MCCFIInstruction::cfiDefCfaOffset(L: nullptr, Offset: MFI.getStackSize()));
200 BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION))
201 .addCFIIndex(CFIIndex)
202 .setMIFlags(MachineInstr::FrameSetup);
203
204 int CurOffset = -4;
205 if (hasFP(MF)) {
206 CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
207 nullptr, MRI->getDwarfRegNum(ARC::FP, true), CurOffset));
208 BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION))
209 .addCFIIndex(CFIIndex)
210 .setMIFlags(MachineInstr::FrameSetup);
211 CurOffset -= 4;
212 }
213
214 if (MFI.hasCalls()) {
215 CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
216 nullptr, MRI->getDwarfRegNum(ARC::BLINK, true), CurOffset));
217 BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION))
218 .addCFIIndex(CFIIndex)
219 .setMIFlags(MachineInstr::FrameSetup);
220 }
221 // CFI for the rest of the registers.
222 for (const auto &Entry : CSI) {
223 unsigned Reg = Entry.getReg();
224 int FI = Entry.getFrameIdx();
225 // Skip BLINK and FP.
226 if ((hasFP(MF) && Reg == ARC::FP) || (MFI.hasCalls() && Reg == ARC::BLINK))
227 continue;
228 CFIIndex = MF.addFrameInst(Inst: MCCFIInstruction::createOffset(
229 L: nullptr, Register: MRI->getDwarfRegNum(RegNum: Reg, isEH: true), Offset: MFI.getObjectOffset(ObjectIdx: FI)));
230 BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION))
231 .addCFIIndex(CFIIndex)
232 .setMIFlags(MachineInstr::FrameSetup);
233 }
234}
235
236/// Insert epilog code into the function.
237/// For ARC, this inserts a call to a function that restores callee saved
238/// registers onto the stack, when enough callee saved registers are required.
239void ARCFrameLowering::emitEpilogue(MachineFunction &MF,
240 MachineBasicBlock &MBB) const {
241 LLVM_DEBUG(dbgs() << "Emit Epilogue: " << MF.getName() << "\n");
242 auto *AFI = MF.getInfo<ARCFunctionInfo>();
243 const ARCInstrInfo *TII = MF.getSubtarget<ARCSubtarget>().getInstrInfo();
244 MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator();
245 MachineFrameInfo &MFI = MF.getFrameInfo();
246 uint64_t StackSize = MF.getFrameInfo().getStackSize();
247 bool SavedBlink = false;
248 unsigned AmountAboveFunclet = 0;
249 // If we have variable sized frame objects, then we have to move
250 // the stack pointer to a known spot (fp - StackSize).
251 // Then, replace the frame pointer by (new) [sp,StackSize-4].
252 // Then, move the stack pointer the rest of the way (sp = sp + StackSize).
253 if (hasFP(MF)) {
254 unsigned Opc = ARC::SUB_rrlimm;
255 if (isUInt<6>(StackSize))
256 Opc = ARC::SUB_rru6;
257 BuildMI(MBB, MBBI, DebugLoc(), TII->get(Opc), ARC::SP)
258 .addReg(ARC::FP)
259 .addImm(StackSize);
260 AmountAboveFunclet += 4;
261 }
262
263 // Now, move the stack pointer to the bottom of the save area for the funclet.
264 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
265 unsigned Last = determineLastCalleeSave(CSI);
266 unsigned StackSlotsUsedByFunclet = 0;
267 // Now, restore the callee save registers.
268 if (UseSaveRestoreFunclet && Last > ARC::R14) {
269 // BL to __ld_r13_to_<TRI->getRegAsmName()>
270 StackSlotsUsedByFunclet = Last - ARC::R12;
271 AmountAboveFunclet += 4 * (StackSlotsUsedByFunclet + 1);
272 SavedBlink = true;
273 }
274
275 if (MFI.hasCalls() && !SavedBlink) {
276 AmountAboveFunclet += 4;
277 SavedBlink = true;
278 }
279
280 // Move the stack pointer up to the point of the funclet.
281 if (unsigned MoveAmount = StackSize - AmountAboveFunclet) {
282 unsigned Opc = ARC::ADD_rrlimm;
283 if (isUInt<6>(MoveAmount))
284 Opc = ARC::ADD_rru6;
285 else if (isInt<12>(MoveAmount))
286 Opc = ARC::ADD_rrs12;
287 BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(Opc), ARC::SP)
288 .addReg(ARC::SP)
289 .addImm(StackSize - AmountAboveFunclet);
290 }
291
292 if (StackSlotsUsedByFunclet) {
293 // This part of the adjustment will always be < 64 bytes.
294 BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::BL))
295 .addExternalSymbol(load_funclet_name[Last - ARC::R15])
296 .addReg(ARC::BLINK, RegState::Implicit | RegState::Kill);
297 unsigned Opc = ARC::ADD_rrlimm;
298 if (isUInt<6>(4 * StackSlotsUsedByFunclet))
299 Opc = ARC::ADD_rru6;
300 else if (isInt<12>(4 * StackSlotsUsedByFunclet))
301 Opc = ARC::ADD_rrs12;
302 BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(Opc), ARC::SP)
303 .addReg(ARC::SP)
304 .addImm(4 * (StackSlotsUsedByFunclet));
305 }
306 // Now, pop blink if necessary.
307 if (SavedBlink) {
308 BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::POP_S_BLINK));
309 }
310 // Now, pop fp if necessary.
311 if (hasFP(MF)) {
312 BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::LD_AB_rs9))
313 .addReg(ARC::FP, RegState::Define)
314 .addReg(ARC::SP, RegState::Define)
315 .addReg(ARC::SP)
316 .addImm(4);
317 }
318
319 // Relieve the varargs area if necessary.
320 if (MF.getFunction().isVarArg()) {
321 // Add in the varargs area here first.
322 LLVM_DEBUG(dbgs() << "Varargs\n");
323 unsigned VarArgsBytes = MFI.getObjectSize(ObjectIdx: AFI->getVarArgsFrameIndex());
324 unsigned Opc = ARC::ADD_rrlimm;
325 if (isUInt<6>(VarArgsBytes))
326 Opc = ARC::ADD_rru6;
327 else if (isInt<12>(VarArgsBytes))
328 Opc = ARC::ADD_rrs12;
329 BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(Opc))
330 .addReg(ARC::SP)
331 .addReg(ARC::SP)
332 .addImm(VarArgsBytes);
333 }
334}
335
336static std::vector<CalleeSavedInfo>::iterator
337getSavedReg(std::vector<CalleeSavedInfo> &V, unsigned reg) {
338 for (auto I = V.begin(), E = V.end(); I != E; ++I) {
339 if (reg == I->getReg())
340 return I;
341 }
342 return V.end();
343}
344
345bool ARCFrameLowering::assignCalleeSavedSpillSlots(
346 MachineFunction &MF, const TargetRegisterInfo *TRI,
347 std::vector<CalleeSavedInfo> &CSI) const {
348 // Use this opportunity to assign the spill slots for all of the potential
349 // callee save registers (blink, fp, r13->r25) that we care about the
350 // placement for. We can calculate all of that data here.
351 int CurOffset = -4;
352 unsigned Last = determineLastCalleeSave(CSI);
353 MachineFrameInfo &MFI = MF.getFrameInfo();
354 if (hasFP(MF)) {
355 // Create a fixed slot at for FP
356 int StackObj = MFI.CreateFixedSpillStackObject(Size: 4, SPOffset: CurOffset, IsImmutable: true);
357 LLVM_DEBUG(dbgs() << "Creating fixed object (" << StackObj << ") for FP at "
358 << CurOffset << "\n");
359 (void)StackObj;
360 CurOffset -= 4;
361 }
362 if (MFI.hasCalls() || (UseSaveRestoreFunclet && Last > ARC::R14)) {
363 // Create a fixed slot for BLINK.
364 int StackObj = MFI.CreateFixedSpillStackObject(Size: 4, SPOffset: CurOffset, IsImmutable: true);
365 LLVM_DEBUG(dbgs() << "Creating fixed object (" << StackObj
366 << ") for BLINK at " << CurOffset << "\n");
367 (void)StackObj;
368 CurOffset -= 4;
369 }
370
371 // Create slots for last down to r13.
372 for (unsigned Which = Last; Which > ARC::R12; Which--) {
373 auto RegI = getSavedReg(CSI, Which);
374 if (RegI == CSI.end() || RegI->getFrameIdx() == 0) {
375 // Always create the stack slot. If for some reason the register isn't in
376 // the save list, then don't worry about it.
377 int FI = MFI.CreateFixedSpillStackObject(4, CurOffset, true);
378 if (RegI != CSI.end())
379 RegI->setFrameIdx(FI);
380 } else
381 MFI.setObjectOffset(RegI->getFrameIdx(), CurOffset);
382 CurOffset -= 4;
383 }
384 for (auto &I : CSI) {
385 if (I.getReg() > ARC::R12)
386 continue;
387 if (I.getFrameIdx() == 0) {
388 I.setFrameIdx(MFI.CreateFixedSpillStackObject(Size: 4, SPOffset: CurOffset, IsImmutable: true));
389 LLVM_DEBUG(dbgs() << "Creating fixed object (" << I.getFrameIdx()
390 << ") for other register at " << CurOffset << "\n");
391 } else {
392 MFI.setObjectOffset(ObjectIdx: I.getFrameIdx(), SPOffset: CurOffset);
393 LLVM_DEBUG(dbgs() << "Updating fixed object (" << I.getFrameIdx()
394 << ") for other register at " << CurOffset << "\n");
395 }
396 CurOffset -= 4;
397 }
398 return true;
399}
400
401bool ARCFrameLowering::spillCalleeSavedRegisters(
402 MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
403 ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
404 LLVM_DEBUG(dbgs() << "Spill callee saved registers: "
405 << MBB.getParent()->getName() << "\n");
406 // There are routines for saving at least 3 registers (r13 to r15, etc.)
407 unsigned Last = determineLastCalleeSave(CSI);
408 if (UseSaveRestoreFunclet && Last > ARC::R14) {
409 // Use setObjectOffset for these registers.
410 // Needs to be in or before processFunctionBeforeFrameFinalized.
411 // Or, do assignCalleeSaveSpillSlots?
412 // Will be handled in prolog.
413 return true;
414 }
415 return false;
416}
417
418bool ARCFrameLowering::restoreCalleeSavedRegisters(
419 MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
420 MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
421 LLVM_DEBUG(dbgs() << "Restore callee saved registers: "
422 << MBB.getParent()->getName() << "\n");
423 // There are routines for saving at least 3 registers (r13 to r15, etc.)
424 unsigned Last = determineLastCalleeSave(CSI);
425 if (UseSaveRestoreFunclet && Last > ARC::R14) {
426 // Will be handled in epilog.
427 return true;
428 }
429 return false;
430}
431
432// Adjust local variables that are 4-bytes or larger to 4-byte boundary
433void ARCFrameLowering::processFunctionBeforeFrameFinalized(
434 MachineFunction &MF, RegScavenger *RS) const {
435 const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
436 LLVM_DEBUG(dbgs() << "Process function before frame finalized: "
437 << MF.getName() << "\n");
438 MachineFrameInfo &MFI = MF.getFrameInfo();
439 LLVM_DEBUG(dbgs() << "Current stack size: " << MFI.getStackSize() << "\n");
440 const TargetRegisterClass *RC = &ARC::GPR32RegClass;
441 if (MFI.hasStackObjects()) {
442 int RegScavFI = MFI.CreateStackObject(Size: RegInfo->getSpillSize(RC: *RC),
443 Alignment: RegInfo->getSpillAlign(RC: *RC), isSpillSlot: false);
444 RS->addScavengingFrameIndex(FI: RegScavFI);
445 LLVM_DEBUG(dbgs() << "Created scavenging index RegScavFI=" << RegScavFI
446 << "\n");
447 }
448}
449
450static void emitRegUpdate(MachineBasicBlock &MBB,
451 MachineBasicBlock::iterator &MBBI, DebugLoc dl,
452 unsigned Reg, int NumBytes, bool IsAdd,
453 const ARCInstrInfo *TII) {
454 unsigned Opc;
455 if (isUInt<6>(NumBytes))
456 Opc = IsAdd ? ARC::ADD_rru6 : ARC::SUB_rru6;
457 else if (isInt<12>(NumBytes))
458 Opc = IsAdd ? ARC::ADD_rrs12 : ARC::SUB_rrs12;
459 else
460 Opc = IsAdd ? ARC::ADD_rrlimm : ARC::SUB_rrlimm;
461
462 BuildMI(MBB, MBBI, dl, TII->get(Opc), Reg)
463 .addReg(Reg, RegState::Kill)
464 .addImm(NumBytes);
465}
466
467MachineBasicBlock::iterator ARCFrameLowering::eliminateCallFramePseudoInstr(
468 MachineFunction &MF, MachineBasicBlock &MBB,
469 MachineBasicBlock::iterator I) const {
470 LLVM_DEBUG(dbgs() << "EmitCallFramePseudo: " << MF.getName() << "\n");
471 const ARCInstrInfo *TII = MF.getSubtarget<ARCSubtarget>().getInstrInfo();
472 MachineInstr &Old = *I;
473 DebugLoc dl = Old.getDebugLoc();
474 unsigned Amt = Old.getOperand(i: 0).getImm();
475 auto *AFI = MF.getInfo<ARCFunctionInfo>();
476 if (!hasFP(MF)) {
477 if (Amt > AFI->MaxCallStackReq && Old.getOpcode() == ARC::ADJCALLSTACKDOWN)
478 AFI->MaxCallStackReq = Amt;
479 } else {
480 if (Amt != 0) {
481 assert((Old.getOpcode() == ARC::ADJCALLSTACKDOWN ||
482 Old.getOpcode() == ARC::ADJCALLSTACKUP) &&
483 "Unknown Frame Pseudo.");
484 bool IsAdd = (Old.getOpcode() == ARC::ADJCALLSTACKUP);
485 emitRegUpdate(MBB, I, dl, ARC::SP, Amt, IsAdd, TII);
486 }
487 }
488 return MBB.erase(I);
489}
490
491bool ARCFrameLowering::hasFP(const MachineFunction &MF) const {
492 const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
493 bool HasFP = MF.getTarget().Options.DisableFramePointerElim(MF) ||
494 MF.getFrameInfo().hasVarSizedObjects() ||
495 MF.getFrameInfo().isFrameAddressTaken() ||
496 RegInfo->hasStackRealignment(MF);
497 return HasFP;
498}
499

source code of llvm/lib/Target/ARC/ARCFrameLowering.cpp