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