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