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(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(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      MCCFIInstruction::cfiDefCfaOffset(nullptr, 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(MCCFIInstruction::createOffset(
229        nullptr, MRI->getDwarfRegNum(Reg, true), MFI.getObjectOffset(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(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(4, CurOffset, 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(4, CurOffset, 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(4, CurOffset, true));
389      LLVM_DEBUG(dbgs() << "Creating fixed object (" << I.getFrameIdx()
390                        << ") for other register at " << CurOffset << "\n");
391    } else {
392      MFI.setObjectOffset(I.getFrameIdx(), 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(RegInfo->getSpillSize(*RC),
443                                          RegInfo->getSpillAlign(*RC), false);
444    RS->addScavengingFrameIndex(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(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->needsStackRealignment(MF);
497  return HasFP;
498}
499