[InstCombine] Signed saturation patterns
[llvm-core.git] / lib / Target / ARC / ARCFrameLowering.cpp
blobd8946d97deffd95e97e6b1bb502ec8b11545911b
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.
11 //===----------------------------------------------------------------------===//
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"
23 #define DEBUG_TYPE "arc-frame-lowering"
25 using namespace llvm;
27 static cl::opt<bool>
28 UseSaveRestoreFunclet("arc-save-restore-funclet", cl::Hidden,
29 cl::desc("Use arc callee save/restore functions"),
30 cl::init(true));
32 static 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",
38 static 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",
44 static 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;
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;
69 else
70 AdjOp = Positive ? ARC::ADD_rrlimm : ARC::SUB_rrlimm;
72 BuildMI(MBB, MBBI, dl, TII.get(AdjOp), StackPtr)
73 .addReg(StackPtr)
74 .addImm(AbsAmount);
77 static unsigned
78 determineLastCalleeSave(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();
86 return Last;
89 void 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);
97 void ARCFrameLowering::adjustStackToMatchRecords(
98 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
99 bool Allocate) const {
100 MachineFunction &MF = *MBB.getParent();
101 int ScalarAlloc = MF.getFrameInfo().getStackSize();
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;
109 generateStackAdjustment(MBB, MBBI, *ST.getInstrInfo(), DebugLoc(),
110 ScalarAlloc, ARC::SP);
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.
116 void 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);
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;
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;
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;
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);
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());
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);
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;
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);
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);
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.
240 void 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;
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;
276 if (MFI.hasCalls() && !SavedBlink) {
277 AmountAboveFunclet += 4;
278 SavedBlink = true;
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);
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));
307 // Now, pop blink if necessary.
308 if (SavedBlink) {
309 BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::POP_S_BLINK));
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);
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);
337 static std::vector<CalleeSavedInfo>::iterator
338 getSavedReg(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;
343 return V.end();
346 bool 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;
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;
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;
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");
397 CurOffset -= 4;
399 return true;
402 bool 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;
417 return false;
420 bool 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;
431 return false;
434 // Adjust local variables that are 4-bytes or larger to 4-byte boundary
435 void 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");
452 static 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;
464 BuildMI(MBB, MBBI, dl, TII->get(Opc), Reg)
465 .addReg(Reg, RegState::Kill)
466 .addImm(NumBytes);
469 MachineBasicBlock::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);
490 return MBB.erase(I);
493 bool 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;