blob: 195a781950be544afb09f11334bd5e85af2de5a5 [file] [log] [blame]
Pete Couperus2d1f6d62017-08-24 15:40:33 +00001//===- ARCFrameLowering.cpp - ARC Frame Information -------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains the ARC implementation of the TargetFrameLowering class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "ARCFrameLowering.h"
15#include "ARCMachineFunctionInfo.h"
16#include "ARCSubtarget.h"
17#include "llvm/CodeGen/MachineInstrBuilder.h"
18#include "llvm/CodeGen/MachineModuleInfo.h"
19#include "llvm/CodeGen/RegisterScavenging.h"
David Blaikieb3bde2e2017-11-17 01:07:10 +000020#include "llvm/CodeGen/TargetRegisterInfo.h"
Pete Couperus2d1f6d62017-08-24 15:40:33 +000021#include "llvm/IR/Function.h"
22#include "llvm/Support/Debug.h"
Pete Couperus2d1f6d62017-08-24 15:40:33 +000023
24#define DEBUG_TYPE "arc-frame-lowering"
25
26using namespace llvm;
27
28static cl::opt<bool>
29 UseSaveRestoreFunclet("arc-save-restore-funclet", cl::Hidden,
30 cl::desc("Use arc callee save/restore functions"),
31 cl::init(true));
32
33static const char *store_funclet_name[] = {
34 "__st_r13_to_r15", "__st_r13_to_r16", "__st_r13_to_r17", "__st_r13_to_r18",
35 "__st_r13_to_r19", "__st_r13_to_r20", "__st_r13_to_r21", "__st_r13_to_r22",
36 "__st_r13_to_r23", "__st_r13_to_r24", "__st_r13_to_r25",
37};
38
39static const char *load_funclet_name[] = {
40 "__ld_r13_to_r15", "__ld_r13_to_r16", "__ld_r13_to_r17", "__ld_r13_to_r18",
41 "__ld_r13_to_r19", "__ld_r13_to_r20", "__ld_r13_to_r21", "__ld_r13_to_r22",
42 "__ld_r13_to_r23", "__ld_r13_to_r24", "__ld_r13_to_r25",
43};
44
45static void generateStackAdjustment(MachineBasicBlock &MBB,
46 MachineBasicBlock::iterator MBBI,
47 const ARCInstrInfo &TII, DebugLoc dl,
48 int Amount, int StackPtr) {
49 unsigned AdjOp;
50 if (!Amount)
51 return;
52 bool Positive;
53 unsigned AbsAmount;
54 if (Amount < 0) {
55 AbsAmount = -Amount;
56 Positive = false;
57 } else {
58 AbsAmount = Amount;
59 Positive = true;
60 }
61
62 DEBUG(dbgs() << "Internal: adjust stack by: " << Amount << "," << AbsAmount
63 << "\n");
64
65 assert((AbsAmount % 4 == 0) && "Stack adjustments must be 4-byte aligned.");
66 if (isUInt<6>(AbsAmount))
67 AdjOp = Positive ? ARC::ADD_rru6 : ARC::SUB_rru6;
68 else
69 AdjOp = Positive ? ARC::ADD_rrlimm : ARC::SUB_rrlimm;
70
71 BuildMI(MBB, MBBI, dl, TII.get(AdjOp), StackPtr)
72 .addReg(StackPtr)
73 .addImm(AbsAmount);
74}
75
76static unsigned
77determineLastCalleeSave(const std::vector<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 {
Matthias Braunf1caa282017-12-15 22:22:58 +000091 DEBUG(dbgs() << "Determine Callee Saves: " << MF.getName()
Pete Couperus2d1f6d62017-08-24 15:40:33 +000092 << "\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 {
Matthias Braunf1caa282017-12-15 22:22:58 +0000118 DEBUG(dbgs() << "Emit Prologue: " << MF.getName() << "\n");
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000119 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;
Matthias Braunf1caa282017-12-15 22:22:58 +0000134 if (MF.getFunction().isVarArg()) {
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000135 // Add in the varargs area here first.
136 DEBUG(dbgs() << "Varargs\n");
137 unsigned VarArgsBytes = MFI.getObjectSize(AFI->getVarArgsFrameIndex());
138 BuildMI(MBB, MBBI, dl, TII->get(ARC::SUB_rru6))
139 .addReg(ARC::SP)
140 .addReg(ARC::SP)
141 .addImm(VarArgsBytes);
142 }
143 if (hasFP(MF)) {
144 DEBUG(dbgs() << "Saving FP\n");
145 BuildMI(MBB, MBBI, dl, TII->get(ARC::ST_AW_rs9))
146 .addReg(ARC::SP, RegState::Define)
147 .addReg(ARC::FP)
148 .addReg(ARC::SP)
149 .addImm(-4);
150 AlreadyAdjusted += 4;
151 }
152 if (UseSaveRestoreFunclet && Last > ARC::R14) {
153 DEBUG(dbgs() << "Creating store funclet.\n");
154 // BL to __save_r13_to_<TRI->getRegAsmName()>
155 StackSlotsUsedByFunclet = Last - ARC::R12;
156 BuildMI(MBB, MBBI, dl, TII->get(ARC::PUSH_S_BLINK));
157 BuildMI(MBB, MBBI, dl, TII->get(ARC::SUB_rru6))
158 .addReg(ARC::SP)
159 .addReg(ARC::SP)
160 .addImm(4 * StackSlotsUsedByFunclet);
161 BuildMI(MBB, MBBI, dl, TII->get(ARC::BL))
162 .addExternalSymbol(store_funclet_name[Last - ARC::R15])
163 .addReg(ARC::BLINK, RegState::Implicit | RegState::Kill);
164 AlreadyAdjusted += 4 * (StackSlotsUsedByFunclet + 1);
165 SavedBlink = true;
166 }
167 // If we haven't saved BLINK, but we need to...do that now.
168 if (MFI.hasCalls() && !SavedBlink) {
169 DEBUG(dbgs() << "Creating save blink.\n");
170 BuildMI(MBB, MBBI, dl, TII->get(ARC::PUSH_S_BLINK));
171 AlreadyAdjusted += 4;
172 }
173 if (AFI->MaxCallStackReq > 0)
174 MFI.setStackSize(MFI.getStackSize() + AFI->MaxCallStackReq);
175 // We have already saved some of the stack...
176 DEBUG(dbgs() << "Adjusting stack by: "
177 << (MFI.getStackSize() - AlreadyAdjusted) << "\n");
178 generateStackAdjustment(MBB, MBBI, *ST.getInstrInfo(), dl,
179 -(MFI.getStackSize() - AlreadyAdjusted), ARC::SP);
180
181 if (hasFP(MF)) {
182 DEBUG(dbgs() << "Setting FP from SP.\n");
183 BuildMI(MBB, MBBI, dl,
184 TII->get(isUInt<6>(MFI.getStackSize()) ? ARC::ADD_rru6
185 : ARC::ADD_rrlimm),
186 ARC::FP)
187 .addReg(ARC::SP)
188 .addImm(MFI.getStackSize());
189 }
190
191 // Emit CFI records:
192 // .cfi_def_cfa_offset StackSize
193 // .cfi_offset fp, -StackSize
194 // .cfi_offset blink, -StackSize+4
195 unsigned CFIIndex = MF.addFrameInst(
196 MCCFIInstruction::createDefCfaOffset(nullptr, -MFI.getStackSize()));
197 BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION))
198 .addCFIIndex(CFIIndex)
199 .setMIFlags(MachineInstr::FrameSetup);
200
201 int CurOffset = -4;
202 if (hasFP(MF)) {
203 CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
204 nullptr, MRI->getDwarfRegNum(ARC::FP, true), CurOffset));
205 BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION))
206 .addCFIIndex(CFIIndex)
207 .setMIFlags(MachineInstr::FrameSetup);
208 CurOffset -= 4;
209 }
210
211 if (MFI.hasCalls()) {
212 CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
213 nullptr, MRI->getDwarfRegNum(ARC::BLINK, true), CurOffset));
214 BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION))
215 .addCFIIndex(CFIIndex)
216 .setMIFlags(MachineInstr::FrameSetup);
217 }
218 // CFI for the rest of the registers.
219 for (const auto &Entry : CSI) {
220 unsigned Reg = Entry.getReg();
221 int FI = Entry.getFrameIdx();
222 // Skip BLINK and FP.
223 if ((hasFP(MF) && Reg == ARC::FP) || (MFI.hasCalls() && Reg == ARC::BLINK))
224 continue;
225 CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
226 nullptr, MRI->getDwarfRegNum(Reg, true), MFI.getObjectOffset(FI)));
227 BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION))
228 .addCFIIndex(CFIIndex)
229 .setMIFlags(MachineInstr::FrameSetup);
230 }
231}
232
233/// Insert epilog code into the function.
234/// For ARC, this inserts a call to a function that restores callee saved
235/// registers onto the stack, when enough callee saved registers are required.
236void ARCFrameLowering::emitEpilogue(MachineFunction &MF,
237 MachineBasicBlock &MBB) const {
Matthias Braunf1caa282017-12-15 22:22:58 +0000238 DEBUG(dbgs() << "Emit Epilogue: " << MF.getName() << "\n");
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000239 auto *AFI = MF.getInfo<ARCFunctionInfo>();
240 const ARCInstrInfo *TII = MF.getSubtarget<ARCSubtarget>().getInstrInfo();
241 MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator();
242 MachineFrameInfo &MFI = MF.getFrameInfo();
243 uint64_t StackSize = MF.getFrameInfo().getStackSize();
244 bool SavedBlink = false;
245 unsigned AmountAboveFunclet = 0;
246 // If we have variable sized frame objects, then we have to move
247 // the stack pointer to a known spot (fp - StackSize).
248 // Then, replace the frame pointer by (new) [sp,StackSize-4].
249 // Then, move the stack pointer the rest of the way (sp = sp + StackSize).
250 if (hasFP(MF)) {
251 BuildMI(MBB, MBBI, DebugLoc(), TII->get(ARC::SUB_rru6), ARC::SP)
252 .addReg(ARC::FP)
253 .addImm(StackSize);
254 AmountAboveFunclet += 4;
255 }
256
257 // Now, move the stack pointer to the bottom of the save area for the funclet.
258 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
259 unsigned Last = determineLastCalleeSave(CSI);
260 unsigned StackSlotsUsedByFunclet = 0;
261 // Now, restore the callee save registers.
262 if (UseSaveRestoreFunclet && Last > ARC::R14) {
263 // BL to __ld_r13_to_<TRI->getRegAsmName()>
264 StackSlotsUsedByFunclet = Last - ARC::R12;
265 AmountAboveFunclet += 4 * (StackSlotsUsedByFunclet + 1);
266 SavedBlink = true;
267 }
268
269 if (MFI.hasCalls() && !SavedBlink) {
270 AmountAboveFunclet += 4;
271 SavedBlink = true;
272 }
273
274 // Move the stack pointer up to the point of the funclet.
275 if (StackSize - AmountAboveFunclet) {
276 BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::ADD_rru6))
277 .addReg(ARC::SP)
278 .addReg(ARC::SP)
279 .addImm(StackSize - AmountAboveFunclet);
280 }
281
282 if (StackSlotsUsedByFunclet) {
283 BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::BL))
284 .addExternalSymbol(load_funclet_name[Last - ARC::R15])
285 .addReg(ARC::BLINK, RegState::Implicit | RegState::Kill);
286 BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::ADD_rru6))
287 .addReg(ARC::SP)
288 .addReg(ARC::SP)
289 .addImm(4 * (StackSlotsUsedByFunclet));
290 }
291 // Now, pop blink if necessary.
292 if (SavedBlink) {
293 BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::POP_S_BLINK));
294 }
295 // Now, pop fp if necessary.
296 if (hasFP(MF)) {
297 BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::LD_AB_rs9))
298 .addReg(ARC::SP, RegState::Define)
299 .addReg(ARC::FP, RegState::Define)
300 .addReg(ARC::SP)
301 .addImm(4);
302 }
303
304 // Relieve the varargs area if necessary.
Matthias Braunf1caa282017-12-15 22:22:58 +0000305 if (MF.getFunction().isVarArg()) {
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000306 // Add in the varargs area here first.
307 DEBUG(dbgs() << "Varargs\n");
308 unsigned VarArgsBytes = MFI.getObjectSize(AFI->getVarArgsFrameIndex());
309 BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::ADD_rru6))
310 .addReg(ARC::SP)
311 .addReg(ARC::SP)
312 .addImm(VarArgsBytes);
313 }
314}
315
316static std::vector<CalleeSavedInfo>::iterator
317getSavedReg(std::vector<CalleeSavedInfo> &V, unsigned reg) {
318 for (auto I = V.begin(), E = V.end(); I != E; ++I) {
319 if (reg == I->getReg())
320 return I;
321 }
322 return V.end();
323}
324
325bool ARCFrameLowering::assignCalleeSavedSpillSlots(
326 MachineFunction &MF, const TargetRegisterInfo *TRI,
327 std::vector<CalleeSavedInfo> &CSI) const {
328 // Use this opportunity to assign the spill slots for all of the potential
329 // callee save registers (blink, fp, r13->r25) that we care about the
330 // placement for. We can calculate all of that data here.
331 int CurOffset = -4;
332 unsigned Last = determineLastCalleeSave(CSI);
333 MachineFrameInfo &MFI = MF.getFrameInfo();
334 if (hasFP(MF)) {
335 // Create a fixed slot at for FP
336 int StackObj = MFI.CreateFixedSpillStackObject(4, CurOffset, true);
337 DEBUG(dbgs() << "Creating fixed object (" << StackObj << ") for FP at "
338 << CurOffset << "\n");
339 (void)StackObj;
340 CurOffset -= 4;
341 }
342 if (MFI.hasCalls() || (UseSaveRestoreFunclet && Last > ARC::R14)) {
343 // Create a fixed slot for BLINK.
344 int StackObj = MFI.CreateFixedSpillStackObject(4, CurOffset, true);
345 DEBUG(dbgs() << "Creating fixed object (" << StackObj << ") for BLINK at "
346 << CurOffset << "\n");
347 (void)StackObj;
348 CurOffset -= 4;
349 }
350
351 // Create slots for last down to r13.
352 for (unsigned Which = Last; Which > ARC::R12; Which--) {
353 auto RegI = getSavedReg(CSI, Which);
354 if (RegI == CSI.end() || RegI->getFrameIdx() == 0) {
355 // Always create the stack slot. If for some reason the register isn't in
356 // the save list, then don't worry about it.
357 int FI = MFI.CreateFixedSpillStackObject(4, CurOffset, true);
358 if (RegI != CSI.end())
359 RegI->setFrameIdx(FI);
360 } else
361 MFI.setObjectOffset(RegI->getFrameIdx(), CurOffset);
362 CurOffset -= 4;
363 }
364 for (auto &I : CSI) {
365 if (I.getReg() > ARC::R12)
366 continue;
367 if (I.getFrameIdx() == 0) {
368 I.setFrameIdx(MFI.CreateFixedSpillStackObject(4, CurOffset, true));
369 DEBUG(dbgs() << "Creating fixed object (" << I.getFrameIdx()
370 << ") for other register at " << CurOffset << "\n");
371 } else {
372 MFI.setObjectOffset(I.getFrameIdx(), CurOffset);
373 DEBUG(dbgs() << "Updating fixed object (" << I.getFrameIdx()
374 << ") for other register at " << CurOffset << "\n");
375 }
376 CurOffset -= 4;
377 }
378 return true;
379}
380
381bool ARCFrameLowering::spillCalleeSavedRegisters(
382 MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
383 const std::vector<CalleeSavedInfo> &CSI,
384 const TargetRegisterInfo *TRI) const {
385 DEBUG(dbgs() << "Spill callee saved registers: "
Matthias Braunf1caa282017-12-15 22:22:58 +0000386 << MBB.getParent()->getName() << "\n");
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000387 // There are routines for saving at least 3 registers (r13 to r15, etc.)
388 unsigned Last = determineLastCalleeSave(CSI);
389 if (UseSaveRestoreFunclet && Last > ARC::R14) {
390 // Use setObjectOffset for these registers.
391 // Needs to be in or before processFunctionBeforeFrameFinalized.
392 // Or, do assignCalleeSaveSpillSlots?
393 // Will be handled in prolog.
394 return true;
395 }
396 return false;
397}
398
399bool ARCFrameLowering::restoreCalleeSavedRegisters(
400 MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
401 std::vector<CalleeSavedInfo> &CSI, const TargetRegisterInfo *TRI) const {
402 DEBUG(dbgs() << "Restore callee saved registers: "
Matthias Braunf1caa282017-12-15 22:22:58 +0000403 << MBB.getParent()->getName() << "\n");
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000404 // There are routines for saving at least 3 registers (r13 to r15, etc.)
405 unsigned Last = determineLastCalleeSave(CSI);
406 if (UseSaveRestoreFunclet && Last > ARC::R14) {
407 // Will be handled in epilog.
408 return true;
409 }
410 return false;
411}
412
413// Adjust local variables that are 4-bytes or larger to 4-byte boundary
414void ARCFrameLowering::processFunctionBeforeFrameFinalized(
415 MachineFunction &MF, RegScavenger *RS) const {
416 const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
417 DEBUG(dbgs() << "Process function before frame finalized: "
Matthias Braunf1caa282017-12-15 22:22:58 +0000418 << MF.getName() << "\n");
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000419 MachineFrameInfo &MFI = MF.getFrameInfo();
420 DEBUG(dbgs() << "Current stack size: " << MFI.getStackSize() << "\n");
421 const TargetRegisterClass *RC = &ARC::GPR32RegClass;
422 if (MFI.hasStackObjects()) {
423 int RegScavFI = MFI.CreateStackObject(
424 RegInfo->getSpillSize(*RC), RegInfo->getSpillAlignment(*RC), false);
425 RS->addScavengingFrameIndex(RegScavFI);
426 DEBUG(dbgs() << "Created scavenging index RegScavFI=" << RegScavFI << "\n");
427 }
428}
429
430static void emitRegUpdate(MachineBasicBlock &MBB,
431 MachineBasicBlock::iterator &MBBI, DebugLoc dl,
432 unsigned Reg, int NumBytes, bool IsAdd,
433 const ARCInstrInfo *TII) {
434 unsigned Opc = IsAdd ? ARC::ADD_rru6 : ARC::SUB_rru6;
435 BuildMI(MBB, MBBI, dl, TII->get(Opc), Reg)
436 .addReg(Reg, RegState::Kill)
437 .addImm(NumBytes);
438}
439
440MachineBasicBlock::iterator ARCFrameLowering::eliminateCallFramePseudoInstr(
441 MachineFunction &MF, MachineBasicBlock &MBB,
442 MachineBasicBlock::iterator I) const {
Matthias Braunf1caa282017-12-15 22:22:58 +0000443 DEBUG(dbgs() << "EmitCallFramePseudo: " << MF.getName() << "\n");
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000444 const ARCInstrInfo *TII = MF.getSubtarget<ARCSubtarget>().getInstrInfo();
445 MachineInstr &Old = *I;
446 DebugLoc dl = Old.getDebugLoc();
447 unsigned Amt = Old.getOperand(0).getImm();
448 auto *AFI = MF.getInfo<ARCFunctionInfo>();
449 if (!hasFP(MF)) {
450 if (Amt > AFI->MaxCallStackReq && Old.getOpcode() == ARC::ADJCALLSTACKDOWN)
451 AFI->MaxCallStackReq = Amt;
452 } else {
453 if (Amt != 0) {
454 assert((Old.getOpcode() == ARC::ADJCALLSTACKDOWN ||
455 Old.getOpcode() == ARC::ADJCALLSTACKUP) &&
456 "Unknown Frame Pseudo.");
457 bool IsAdd = (Old.getOpcode() == ARC::ADJCALLSTACKUP);
458 emitRegUpdate(MBB, I, dl, ARC::SP, Amt, IsAdd, TII);
459 }
460 }
461 return MBB.erase(I);
462}
463
464bool ARCFrameLowering::hasFP(const MachineFunction &MF) const {
465 const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
466 bool HasFP = MF.getTarget().Options.DisableFramePointerElim(MF) ||
467 MF.getFrameInfo().hasVarSizedObjects() ||
468 MF.getFrameInfo().isFrameAddressTaken() ||
469 RegInfo->needsStackRealignment(MF);
470 return HasFP;
471}