xref: /freebsd/contrib/llvm-project/llvm/lib/Target/ARC/ARCFrameLowering.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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