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